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 a4b580cc87..a2e8fe0a2e 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 0000000000..815c819ec0
--- /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 08465b4bda..7a2bae0633 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,8 +71,18 @@ utils.sortBy = function (arr, fields) {
})
}
-utils.getBasename = function (filename) {
- return path.basename(filename, path.extname(filename))
+utils.escapeStringRegexp = function (scring) {
+ return escapeStringRegexp(string)
+}
+
+utils.sleep = function (ms) {
+ return function (x) {
+ return new Promise(resolve => setTimeout(() => resolve(x), ms))
+ }
+}
+
+utils.removeProtocol = function (string) {
+ return string.replace(/(^\w+:|^)\/\//, '')
}
utils.filterPlaylists = function (arr, include = '', exclude = '') {
@@ -97,82 +101,4 @@ utils.filterPlaylists = function (arr, include = '', exclude = '') {
return arr
}
-utils.generateTable = function (data, options) {
- let output = '
\n'
-
- output += '\t\n\t\t'
- for (let column of options.columns) {
- output += `${column.name} | `
- }
- output += '
\n\t\n'
-
- output += '\t\n'
- for (let item of data) {
- output += '\t\t'
- let i = 0
- for (let prop in item) {
- const column = options.columns[i]
- let nowrap = column.nowrap
- let align = column.align
- output += `${item[prop]} | `
- i++
- }
- output += '
\n'
- }
- output += '\t\n'
-
- output += '
'
-
- 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))
- }
-}
-
-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 })
-
- if (original === output) {
- return false
- } else {
- utils.createFile(playlist.url, output)
- }
-
- return true
-}
-
module.exports = utils
diff --git a/scripts/parser.js b/scripts/parser.js
deleted file mode 100644
index 0c86a02069..0000000000
--- 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