From 16f409856ef6f95791fe2f06f5d381d264ec4b13 Mon Sep 17 00:00:00 2001
From: Aleksandr Statciuk <free.arhey@gmail.com>
Date: Sun, 1 Aug 2021 19:45:15 +0300
Subject: [PATCH] Create /helpers directory

---
 scripts/{ => helpers}/blacklist.json  |   0
 scripts/{ => helpers}/categories.json |   0
 scripts/{ => helpers}/db.js           |   0
 scripts/{ => helpers}/log.js          |   4 +-
 scripts/helpers/parser.js             |  24 +++
 scripts/{ => helpers}/regions.json    |   0
 scripts/{ => helpers}/utils.js        | 104 ++---------
 scripts/parser.js                     | 244 --------------------------
 8 files changed, 41 insertions(+), 335 deletions(-)
 rename scripts/{ => helpers}/blacklist.json (100%)
 rename scripts/{ => helpers}/categories.json (100%)
 rename scripts/{ => helpers}/db.js (100%)
 rename scripts/{ => helpers}/log.js (76%)
 create mode 100644 scripts/helpers/parser.js
 rename scripts/{ => helpers}/regions.json (100%)
 rename scripts/{ => helpers}/utils.js (58%)
 delete mode 100644 scripts/parser.js

diff --git a/scripts/blacklist.json b/scripts/helpers/blacklist.json
similarity index 100%
rename from scripts/blacklist.json
rename to scripts/helpers/blacklist.json
diff --git a/scripts/categories.json b/scripts/helpers/categories.json
similarity index 100%
rename from scripts/categories.json
rename to scripts/helpers/categories.json
diff --git a/scripts/db.js b/scripts/helpers/db.js
similarity index 100%
rename from scripts/db.js
rename to scripts/helpers/db.js
diff --git a/scripts/log.js b/scripts/helpers/log.js
similarity index 76%
rename from scripts/log.js
rename to scripts/helpers/log.js
index a4b580cc8..a2e8fe0a2 100644
--- a/scripts/log.js
+++ b/scripts/helpers/log.js
@@ -6,11 +6,11 @@ log.print = function (string) {
 
 log.start = function () {
   this.print('Starting...\n')
-  console.time('\nDone in')
+  console.time('Done in')
 }
 
 log.finish = function () {
-  console.timeEnd('\nDone in')
+  console.timeEnd('Done in')
 }
 
 module.exports = log
diff --git a/scripts/helpers/parser.js b/scripts/helpers/parser.js
new file mode 100644
index 000000000..815c819ec
--- /dev/null
+++ b/scripts/helpers/parser.js
@@ -0,0 +1,24 @@
+const playlistParser = require('iptv-playlist-parser')
+const Playlist = require('./Playlist')
+const utils = require('./utils')
+const file = require('./file')
+
+const parser = {}
+
+parser.parseIndex = function () {
+  const content = file.read('index.m3u')
+  const result = playlistParser.parse(content)
+
+  return result.items
+}
+
+parser.parsePlaylist = async function (url) {
+  const content = file.read(url)
+  const result = playlistParser.parse(content)
+  const name = file.getFilename(url)
+  const country = utils.code2name(name)
+
+  return new Playlist({ header: result.header, items: result.items, url, country, name })
+}
+
+module.exports = parser
diff --git a/scripts/regions.json b/scripts/helpers/regions.json
similarity index 100%
rename from scripts/regions.json
rename to scripts/helpers/regions.json
diff --git a/scripts/utils.js b/scripts/helpers/utils.js
similarity index 58%
rename from scripts/utils.js
rename to scripts/helpers/utils.js
index 08465b4bd..7a2bae063 100644
--- a/scripts/utils.js
+++ b/scripts/helpers/utils.js
@@ -1,21 +1,15 @@
-const fs = require('fs')
-const path = require('path')
-const axios = require('axios')
-const zlib = require('zlib')
-const urlParser = require('url')
 const escapeStringRegexp = require('escape-string-regexp')
-const markdownInclude = require('markdown-include')
-const iso6393 = require('@freearhey/iso-639-3')
 const transliteration = require('transliteration')
-const regions = require('./regions')
+const iso6393 = require('@freearhey/iso-639-3')
 const categories = require('./categories')
+const regions = require('./regions')
+
+const utils = {}
 const intlDisplayNames = new Intl.DisplayNames(['en'], {
   style: 'narrow',
   type: 'region'
 })
 
-const utils = {}
-
 utils.name2id = function (name) {
   return transliteration
     .transliterate(name)
@@ -77,81 +71,10 @@ utils.sortBy = function (arr, fields) {
   })
 }
 
-utils.getBasename = function (filename) {
-  return path.basename(filename, path.extname(filename))
-}
-
-utils.filterPlaylists = function (arr, include = '', exclude = '') {
-  if (include) {
-    const included = include.split(',').map(filename => `channels/${filename}.m3u`)
-
-    return arr.filter(i => included.indexOf(i.url) > -1)
-  }
-
-  if (exclude) {
-    const excluded = exclude.split(',').map(filename => `channels/${filename}.m3u`)
-
-    return arr.filter(i => excluded.indexOf(i.url) === -1)
-  }
-
-  return arr
-}
-
-utils.generateTable = function (data, options) {
-  let output = '<table>\n'
-
-  output += '\t<thead>\n\t\t<tr>'
-  for (let column of options.columns) {
-    output += `<th align="${column.align}">${column.name}</th>`
-  }
-  output += '</tr>\n\t</thead>\n'
-
-  output += '\t<tbody>\n'
-  for (let item of data) {
-    output += '\t\t<tr>'
-    let i = 0
-    for (let prop in item) {
-      const column = options.columns[i]
-      let nowrap = column.nowrap
-      let align = column.align
-      output += `<td align="${align}"${nowrap ? ' nowrap' : ''}>${item[prop]}</td>`
-      i++
-    }
-    output += '</tr>\n'
-  }
-  output += '\t</tbody>\n'
-
-  output += '</table>'
-
-  return output
-}
-
-utils.createDir = function (dir) {
-  if (!fs.existsSync(dir)) {
-    fs.mkdirSync(dir)
-  }
-}
-
-utils.readFile = function (filename) {
-  return fs.readFileSync(path.resolve(__dirname) + `/../${filename}`, { encoding: 'utf8' })
-}
-
-utils.appendToFile = function (filename, data) {
-  fs.appendFileSync(path.resolve(__dirname) + '/../' + filename, data)
-}
-
-utils.compileMarkdown = function (filepath) {
-  return markdownInclude.compileFiles(path.resolve(__dirname, filepath))
-}
-
 utils.escapeStringRegexp = function (scring) {
   return escapeStringRegexp(string)
 }
 
-utils.createFile = function (filename, data = '') {
-  fs.writeFileSync(path.resolve(__dirname) + '/../' + filename, data)
-}
-
 utils.sleep = function (ms) {
   return function (x) {
     return new Promise(resolve => setTimeout(() => resolve(x), ms))
@@ -162,17 +85,20 @@ utils.removeProtocol = function (string) {
   return string.replace(/(^\w+:|^)\/\//, '')
 }
 
-utils.savePlaylist = async function (playlist) {
-  const original = utils.readFile(playlist.url)
-  const output = playlist.toString({ raw: true })
+utils.filterPlaylists = function (arr, include = '', exclude = '') {
+  if (include) {
+    const included = include.split(',').map(filename => `channels/${filename}.m3u`)
+
+    return arr.filter(i => included.indexOf(i.url) > -1)
+  }
 
-  if (original === output) {
-    return false
-  } else {
-    utils.createFile(playlist.url, output)
+  if (exclude) {
+    const excluded = exclude.split(',').map(filename => `channels/${filename}.m3u`)
+
+    return arr.filter(i => excluded.indexOf(i.url) === -1)
   }
 
-  return true
+  return arr
 }
 
 module.exports = utils
diff --git a/scripts/parser.js b/scripts/parser.js
deleted file mode 100644
index 0c86a0206..000000000
--- a/scripts/parser.js
+++ /dev/null
@@ -1,244 +0,0 @@
-const playlistParser = require('iptv-playlist-parser')
-const utils = require('./utils')
-const categories = require('./categories')
-const path = require('path')
-
-const sfwCategories = categories.filter(c => !c.nsfw).map(c => c.name)
-const nsfwCategories = categories.filter(c => c.nsfw).map(c => c.name)
-
-const parser = {}
-
-parser.parseIndex = function () {
-  const content = utils.readFile('index.m3u')
-  const result = playlistParser.parse(content)
-
-  return result.items
-}
-
-parser.parsePlaylist = async function (filename) {
-  const content = utils.readFile(filename)
-  const result = playlistParser.parse(content)
-  const name = path.parse(filename).name
-  const country = utils.code2name(name)
-
-  return new Playlist({ header: result.header, items: result.items, url: filename, country, name })
-}
-
-class Playlist {
-  constructor({ header, items, url, name, country }) {
-    this.url = url
-    this.name = name
-    this.country = country
-    this.header = header
-    this.channels = items
-      .map(item => new Channel({ data: item, header, sourceUrl: url }))
-      .filter(channel => channel.url)
-  }
-
-  toString(options = {}) {
-    const config = { raw: false, ...options }
-    let parts = ['#EXTM3U']
-    for (let key in this.header.attrs) {
-      let value = this.header.attrs[key]
-      if (value) {
-        parts.push(`${key}="${value}"`)
-      }
-    }
-
-    let output = `${parts.join(' ')}\n`
-    for (let channel of this.channels) {
-      output += channel.toString(config.raw)
-    }
-
-    return output
-  }
-}
-
-class Channel {
-  constructor({ data, header, sourceUrl }) {
-    this.parseData(data)
-
-    this.filename = utils.getBasename(sourceUrl)
-    if (!this.countries.length) {
-      const countryName = utils.code2name(this.filename)
-      this.countries = countryName ? [{ code: this.filename, name: countryName }] : []
-      this.tvg.country = this.countries.map(c => c.code.toUpperCase()).join(';')
-    }
-  }
-
-  parseData(data) {
-    const title = this.parseTitle(data.name)
-
-    this.tvg = data.tvg
-    this.http = data.http
-    this.url = data.url
-    this.logo = data.tvg.logo
-    this.name = title.channelName
-    this.status = title.streamStatus
-    this.resolution = title.streamResolution
-    this.countries = this.parseCountries(data.tvg.country)
-    this.languages = this.parseLanguages(data.tvg.language)
-    this.category = this.parseCategory(data.group.title)
-    this.raw = data.raw
-  }
-
-  parseCountries(string) {
-    let arr = string
-      .split(';')
-      .reduce((acc, curr) => {
-        const codes = utils.region2codes(curr)
-        if (codes.length) {
-          for (let code of codes) {
-            if (!acc.includes(code)) {
-              acc.push(code)
-            }
-          }
-        } else {
-          acc.push(curr)
-        }
-
-        return acc
-      }, [])
-      .filter(code => code && utils.code2name(code))
-
-    return arr.map(code => {
-      return { code: code.toLowerCase(), name: utils.code2name(code) }
-    })
-  }
-
-  parseLanguages(string) {
-    return string
-      .split(';')
-      .map(name => {
-        const code = name ? utils.language2code(name) : null
-        if (!code) return null
-
-        return {
-          code,
-          name
-        }
-      })
-      .filter(l => l)
-  }
-
-  parseCategory(string) {
-    const category = categories.find(c => c.id === string.toLowerCase())
-
-    return category ? category.name : ''
-  }
-
-  parseTitle(title) {
-    const channelName = title
-      .trim()
-      .split(' ')
-      .map(s => s.trim())
-      .filter(s => {
-        return !/\[|\]/i.test(s) && !/\((\d+)P\)/i.test(s)
-      })
-      .join(' ')
-
-    const streamStatusMatch = title.match(/\[(.*)\]/i)
-    const streamStatus = streamStatusMatch ? streamStatusMatch[1] : null
-
-    const streamResolutionMatch = title.match(/\((\d+)P\)/i)
-    const streamResolutionHeight = streamResolutionMatch ? parseInt(streamResolutionMatch[1]) : null
-    const streamResolution = { width: null, height: streamResolutionHeight }
-
-    return { channelName, streamStatus, streamResolution }
-  }
-
-  get tvgCountry() {
-    return this.tvg.country
-      .split(';')
-      .map(code => utils.code2name(code))
-      .join(';')
-  }
-
-  get tvgLanguage() {
-    return this.tvg.language
-  }
-
-  get tvgUrl() {
-    return this.tvg.id && this.tvg.url ? this.tvg.url : ''
-  }
-
-  get tvgId() {
-    if (this.tvg.id) {
-      return this.tvg.id
-    } else if (this.filename !== 'unsorted') {
-      const id = utils.name2id(this.tvgName)
-
-      return id ? `${id}.${this.filename}` : ''
-    }
-
-    return ''
-  }
-
-  get tvgName() {
-    if (this.tvg.name) {
-      return this.tvg.name
-    } else if (this.filename !== 'unsorted') {
-      return this.name.replace(/\"/gi, '')
-    }
-
-    return ''
-  }
-
-  getInfo() {
-    this.tvg.country = this.tvg.country.toUpperCase()
-
-    let info = `-1 tvg-id="${this.tvgId}" tvg-name="${this.tvgName}" tvg-country="${this.tvg.country}" tvg-language="${this.tvg.language}" tvg-logo="${this.logo}"`
-
-    info += ` group-title="${this.category}",${this.name}`
-
-    if (this.resolution.height) {
-      info += ` (${this.resolution.height}p)`
-    }
-
-    if (this.status) {
-      info += ` [${this.status}]`
-    }
-
-    if (this.http['referrer']) {
-      info += `\n#EXTVLCOPT:http-referrer=${this.http['referrer']}`
-    }
-
-    if (this.http['user-agent']) {
-      info += `\n#EXTVLCOPT:http-user-agent=${this.http['user-agent']}`
-    }
-
-    return info
-  }
-
-  toString(raw = false) {
-    if (raw) return this.raw + '\n'
-
-    return '#EXTINF:' + this.getInfo() + '\n' + this.url + '\n'
-  }
-
-  toObject() {
-    return {
-      name: this.name,
-      logo: this.logo || null,
-      url: this.url,
-      category: this.category || null,
-      languages: this.languages,
-      countries: this.countries,
-      tvg: {
-        id: this.tvgId || null,
-        name: this.tvgName || null,
-        url: this.tvgUrl || null
-      }
-    }
-  }
-
-  isSFW() {
-    return sfwCategories.includes(this.category)
-  }
-
-  isNSFW() {
-    return nsfwCategories.includes(this.category)
-  }
-}
-
-module.exports = parser