Initial Commit
This commit is contained in:
32
scripts/core/api.js
Normal file
32
scripts/core/api.js
Normal file
@@ -0,0 +1,32 @@
|
||||
const _ = require('lodash')
|
||||
const file = require('./file')
|
||||
|
||||
const DATA_DIR = process.env.DATA_DIR || './scripts/data'
|
||||
|
||||
class API {
|
||||
constructor(filepath) {
|
||||
this.filepath = file.resolve(filepath)
|
||||
}
|
||||
|
||||
async load() {
|
||||
const data = await file.read(this.filepath)
|
||||
this.collection = JSON.parse(data)
|
||||
}
|
||||
|
||||
find(query) {
|
||||
return _.find(this.collection, query)
|
||||
}
|
||||
|
||||
all() {
|
||||
return this.collection
|
||||
}
|
||||
}
|
||||
|
||||
const api = {}
|
||||
|
||||
api.channels = new API(`${DATA_DIR}/channels.json`)
|
||||
api.regions = new API(`${DATA_DIR}/regions.json`)
|
||||
api.countries = new API(`${DATA_DIR}/countries.json`)
|
||||
api.subdivisions = new API(`${DATA_DIR}/subdivisions.json`)
|
||||
|
||||
module.exports = api
|
||||
13
scripts/core/date.js
Normal file
13
scripts/core/date.js
Normal file
@@ -0,0 +1,13 @@
|
||||
const dayjs = require('dayjs')
|
||||
const utc = require('dayjs/plugin/utc')
|
||||
dayjs.extend(utc)
|
||||
|
||||
const date = {}
|
||||
|
||||
date.getUTC = function (d = null) {
|
||||
if (typeof d === 'string') return dayjs.utc(d).startOf('d')
|
||||
|
||||
return dayjs.utc().startOf('d')
|
||||
}
|
||||
|
||||
module.exports = date
|
||||
76
scripts/core/db.js
Normal file
76
scripts/core/db.js
Normal file
@@ -0,0 +1,76 @@
|
||||
const nedb = require('nedb-promises')
|
||||
const file = require('./file')
|
||||
|
||||
const DB_DIR = process.env.DB_DIR || './scripts/database'
|
||||
|
||||
class Database {
|
||||
constructor(filepath) {
|
||||
this.filepath = filepath
|
||||
}
|
||||
|
||||
load() {
|
||||
this.db = nedb.create({
|
||||
filename: file.resolve(this.filepath),
|
||||
autoload: true,
|
||||
onload: err => {
|
||||
if (err) console.error(err)
|
||||
},
|
||||
compareStrings: (a, b) => {
|
||||
a = a.replace(/\s/g, '_')
|
||||
b = b.replace(/\s/g, '_')
|
||||
|
||||
return a.localeCompare(b, undefined, {
|
||||
sensitivity: 'accent',
|
||||
numeric: true
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
removeIndex(field) {
|
||||
return this.db.removeIndex(field)
|
||||
}
|
||||
|
||||
addIndex(options) {
|
||||
return this.db.ensureIndex(options)
|
||||
}
|
||||
|
||||
compact() {
|
||||
return this.db.persistence.compactDatafile()
|
||||
}
|
||||
|
||||
stopAutocompact() {
|
||||
return this.db.persistence.stopAutocompaction()
|
||||
}
|
||||
|
||||
reset() {
|
||||
return file.clear(this.filepath)
|
||||
}
|
||||
|
||||
count(query) {
|
||||
return this.db.count(query)
|
||||
}
|
||||
|
||||
insert(doc) {
|
||||
return this.db.insert(doc)
|
||||
}
|
||||
|
||||
update(query, update) {
|
||||
return this.db.update(query, update)
|
||||
}
|
||||
|
||||
find(query) {
|
||||
return this.db.find(query)
|
||||
}
|
||||
|
||||
remove(query, options) {
|
||||
return this.db.remove(query, options)
|
||||
}
|
||||
}
|
||||
|
||||
const db = {}
|
||||
|
||||
db.queue = new Database(`${DB_DIR}/queue.db`)
|
||||
db.programs = new Database(`${DB_DIR}/programs.db`)
|
||||
|
||||
module.exports = db
|
||||
72
scripts/core/file.js
Normal file
72
scripts/core/file.js
Normal file
@@ -0,0 +1,72 @@
|
||||
const path = require('path')
|
||||
const glob = require('glob')
|
||||
const fs = require('fs-extra')
|
||||
|
||||
const file = {}
|
||||
|
||||
file.list = function (pattern) {
|
||||
return new Promise(resolve => {
|
||||
glob(pattern, function (err, files) {
|
||||
resolve(files)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
file.getFilename = function (filepath) {
|
||||
return path.parse(filepath).name
|
||||
}
|
||||
|
||||
file.createDir = async function (dir) {
|
||||
if (await file.exists(dir)) return
|
||||
|
||||
return fs.mkdir(dir, { recursive: true }).catch(console.error)
|
||||
}
|
||||
|
||||
file.exists = function (filepath) {
|
||||
return fs.exists(path.resolve(filepath))
|
||||
}
|
||||
|
||||
file.read = function (filepath) {
|
||||
return fs.readFile(path.resolve(filepath), { encoding: 'utf8' }).catch(console.error)
|
||||
}
|
||||
|
||||
file.append = function (filepath, data) {
|
||||
return fs.appendFile(path.resolve(filepath), data).catch(console.error)
|
||||
}
|
||||
|
||||
file.create = function (filepath, data = '') {
|
||||
filepath = path.resolve(filepath)
|
||||
const dir = path.dirname(filepath)
|
||||
|
||||
return file
|
||||
.createDir(dir)
|
||||
.then(() => file.write(filepath, data))
|
||||
.catch(console.error)
|
||||
}
|
||||
|
||||
file.write = function (filepath, data = '') {
|
||||
return fs.writeFile(path.resolve(filepath), data, { encoding: 'utf8' }).catch(console.error)
|
||||
}
|
||||
|
||||
file.writeSync = function (filepath, data = '') {
|
||||
return fs.writeFileSync(path.resolve(filepath), data, { encoding: 'utf8' })
|
||||
}
|
||||
|
||||
file.clear = async function (filepath) {
|
||||
if (await file.exists(filepath)) return file.write(filepath, '')
|
||||
return true
|
||||
}
|
||||
|
||||
file.resolve = function (filepath) {
|
||||
return path.resolve(filepath)
|
||||
}
|
||||
|
||||
file.dirname = function (filepath) {
|
||||
return path.dirname(filepath)
|
||||
}
|
||||
|
||||
file.basename = function (filepath) {
|
||||
return path.basename(filepath)
|
||||
}
|
||||
|
||||
module.exports = file
|
||||
11
scripts/core/index.js
Normal file
11
scripts/core/index.js
Normal file
@@ -0,0 +1,11 @@
|
||||
exports.db = require('./db')
|
||||
exports.logger = require('./logger')
|
||||
exports.file = require('./file')
|
||||
exports.parser = require('./parser')
|
||||
exports.timer = require('./timer')
|
||||
exports.markdown = require('./markdown')
|
||||
exports.api = require('./api')
|
||||
exports.date = require('./date')
|
||||
exports.table = require('./table')
|
||||
exports.xml = require('./xml')
|
||||
exports.zip = require('./zip')
|
||||
19
scripts/core/logger.js
Normal file
19
scripts/core/logger.js
Normal file
@@ -0,0 +1,19 @@
|
||||
const { Signale } = require('signale')
|
||||
|
||||
const options = {}
|
||||
|
||||
const logger = new Signale(options)
|
||||
|
||||
logger.config({
|
||||
displayLabel: false,
|
||||
displayScope: false,
|
||||
displayBadge: false
|
||||
})
|
||||
|
||||
logger.memoryUsage = function () {
|
||||
const used = process.memoryUsage().heapUsed / 1024 / 1024
|
||||
|
||||
logger.info(`memory: ${Math.round(used * 100) / 100} MB`)
|
||||
}
|
||||
|
||||
module.exports = logger
|
||||
10
scripts/core/markdown.js
Normal file
10
scripts/core/markdown.js
Normal file
@@ -0,0 +1,10 @@
|
||||
const markdownInclude = require('markdown-include')
|
||||
const file = require('./file')
|
||||
|
||||
const markdown = {}
|
||||
|
||||
markdown.compile = function (filepath) {
|
||||
markdownInclude.compileFiles(file.resolve(filepath))
|
||||
}
|
||||
|
||||
module.exports = markdown
|
||||
29
scripts/core/parser.js
Normal file
29
scripts/core/parser.js
Normal file
@@ -0,0 +1,29 @@
|
||||
const file = require('./file')
|
||||
const grabber = require('epg-grabber')
|
||||
|
||||
const parser = {}
|
||||
|
||||
parser.parseChannels = async function (filepath) {
|
||||
const content = await file.read(filepath)
|
||||
|
||||
return grabber.parseChannels(content)
|
||||
}
|
||||
|
||||
parser.parseLogs = async function (filepath) {
|
||||
const content = await file.read(filepath)
|
||||
if (!content) return []
|
||||
const lines = content.split('\n')
|
||||
|
||||
return lines.map(line => (line ? JSON.parse(line) : null)).filter(l => l)
|
||||
}
|
||||
|
||||
parser.parseNumber = function (string) {
|
||||
const parsed = parseInt(string)
|
||||
if (isNaN(parsed)) {
|
||||
throw new Error('scripts/core/parser.js:parseNumber() Input value is not a number')
|
||||
}
|
||||
|
||||
return parsed
|
||||
}
|
||||
|
||||
module.exports = parser
|
||||
47
scripts/core/table.js
Normal file
47
scripts/core/table.js
Normal file
@@ -0,0 +1,47 @@
|
||||
const table = {}
|
||||
|
||||
table.create = function (data, cols) {
|
||||
let output = '<table>\r\n'
|
||||
|
||||
output += ' <thead>\r\n <tr>'
|
||||
for (let column of cols) {
|
||||
output += `<th align="left">${column}</th>`
|
||||
}
|
||||
output += '</tr>\r\n </thead>\r\n'
|
||||
|
||||
output += ' <tbody>\r\n'
|
||||
output += getHTMLRows(data)
|
||||
output += ' </tbody>\r\n'
|
||||
|
||||
output += '</table>'
|
||||
|
||||
return output
|
||||
}
|
||||
|
||||
function getHTMLRows(data) {
|
||||
let output = ''
|
||||
for (let group of data) {
|
||||
let rowspan = group.length
|
||||
for (let [j, row] of group.entries()) {
|
||||
output += ' <tr>'
|
||||
for (let [i, value] of row.entries()) {
|
||||
if (i === 0 && j === 0) {
|
||||
output += `<td valign="top" rowspan="${rowspan}">${value}</td>`
|
||||
} else if (i > 0) {
|
||||
if (typeof value === 'number') {
|
||||
output += `<td align="right" nowrap>${value}</td>`
|
||||
} else {
|
||||
output += `<td nowrap>${value}</td>`
|
||||
}
|
||||
}
|
||||
}
|
||||
output += '</tr>\r\n'
|
||||
}
|
||||
}
|
||||
|
||||
return output
|
||||
}
|
||||
|
||||
function getSpan() {}
|
||||
|
||||
module.exports = table
|
||||
29
scripts/core/timer.js
Normal file
29
scripts/core/timer.js
Normal file
@@ -0,0 +1,29 @@
|
||||
const { performance } = require('perf_hooks')
|
||||
const dayjs = require('dayjs')
|
||||
const duration = require('dayjs/plugin/duration')
|
||||
const relativeTime = require('dayjs/plugin/relativeTime')
|
||||
|
||||
dayjs.extend(relativeTime)
|
||||
dayjs.extend(duration)
|
||||
|
||||
const timer = {}
|
||||
|
||||
let t0 = 0
|
||||
|
||||
timer.start = function () {
|
||||
t0 = performance.now()
|
||||
}
|
||||
|
||||
timer.format = function (f) {
|
||||
let t1 = performance.now()
|
||||
|
||||
return dayjs.duration(t1 - t0).format(f)
|
||||
}
|
||||
|
||||
timer.humanize = function (suffix = true) {
|
||||
let t1 = performance.now()
|
||||
|
||||
return dayjs.duration(t1 - t0).humanize(suffix)
|
||||
}
|
||||
|
||||
module.exports = timer
|
||||
49
scripts/core/xml.js
Normal file
49
scripts/core/xml.js
Normal file
@@ -0,0 +1,49 @@
|
||||
const xml = {}
|
||||
|
||||
xml.create = function (items, site) {
|
||||
let output = `<?xml version="1.0" encoding="UTF-8"?>\r\n<site site="${site}">\r\n <channels>\r\n`
|
||||
|
||||
items.forEach(channel => {
|
||||
const logo = channel.logo ? ` logo="${channel.logo}"` : ''
|
||||
const xmltv_id = channel.xmltv_id || ''
|
||||
const lang = channel.lang || ''
|
||||
const site_id = channel.site_id || ''
|
||||
output += ` <channel lang="${lang}" xmltv_id="${escapeString(
|
||||
xmltv_id
|
||||
)}" site_id="${site_id}"${logo}>${escapeString(channel.name)}</channel>\r\n`
|
||||
})
|
||||
|
||||
output += ` </channels>\r\n</site>\r\n`
|
||||
|
||||
return output
|
||||
}
|
||||
|
||||
function escapeString(string, defaultValue = '') {
|
||||
if (!string) return defaultValue
|
||||
|
||||
const regex = new RegExp(
|
||||
'((?:[\0-\x08\x0B\f\x0E-\x1F\uFFFD\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]))|([\\x7F-\\x84]|[\\x86-\\x9F]|[\\uFDD0-\\uFDEF]|(?:\\uD83F[\\uDFFE\\uDFFF])|(?:\\uD87F[\\uDF' +
|
||||
'FE\\uDFFF])|(?:\\uD8BF[\\uDFFE\\uDFFF])|(?:\\uD8FF[\\uDFFE\\uDFFF])|(?:\\uD93F[\\uDFFE\\uD' +
|
||||
'FFF])|(?:\\uD97F[\\uDFFE\\uDFFF])|(?:\\uD9BF[\\uDFFE\\uDFFF])|(?:\\uD9FF[\\uDFFE\\uDFFF])' +
|
||||
'|(?:\\uDA3F[\\uDFFE\\uDFFF])|(?:\\uDA7F[\\uDFFE\\uDFFF])|(?:\\uDABF[\\uDFFE\\uDFFF])|(?:\\' +
|
||||
'uDAFF[\\uDFFE\\uDFFF])|(?:\\uDB3F[\\uDFFE\\uDFFF])|(?:\\uDB7F[\\uDFFE\\uDFFF])|(?:\\uDBBF' +
|
||||
'[\\uDFFE\\uDFFF])|(?:\\uDBFF[\\uDFFE\\uDFFF])(?:[\\0-\\t\\x0B\\f\\x0E-\\u2027\\u202A-\\uD7FF\\' +
|
||||
'uE000-\\uFFFF]|[\\uD800-\\uDBFF][\\uDC00-\\uDFFF]|[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])|' +
|
||||
'(?:[^\\uD800-\\uDBFF]|^)[\\uDC00-\\uDFFF]))',
|
||||
'g'
|
||||
)
|
||||
|
||||
string = String(string || '').replace(regex, '')
|
||||
|
||||
return string
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, ''')
|
||||
.replace(/\n|\r/g, ' ')
|
||||
.replace(/ +/g, ' ')
|
||||
.trim()
|
||||
}
|
||||
|
||||
module.exports = xml
|
||||
13
scripts/core/zip.js
Normal file
13
scripts/core/zip.js
Normal file
@@ -0,0 +1,13 @@
|
||||
const { gzip, ungzip } = require('node-gzip')
|
||||
|
||||
const zip = {}
|
||||
|
||||
zip.compress = async function (string) {
|
||||
return gzip(string)
|
||||
}
|
||||
|
||||
zip.decompress = async function (string) {
|
||||
return ungzip(string)
|
||||
}
|
||||
|
||||
module.exports = zip
|
||||
Reference in New Issue
Block a user