epg/scripts/commands/channels/editor.js
2023-06-30 19:55:14 +03:00

125 lines
3.3 KiB
JavaScript

const { api, parser, xml, file, logger } = require('../../core')
const { transliterate } = require('transliteration')
const nodeCleanup = require('node-cleanup')
const { program } = require('commander')
const inquirer = require('inquirer')
program
.argument('<filepath>', 'Path to *.channels.xml file to edit')
.option('-c, --country <name>', 'Source country', 'us')
.parse(process.argv)
const filepath = program.args[0]
const options = program.opts()
const defaultCountry = options.country
const newLabel = ` [new]`
let site
let channels = []
async function main() {
if (!(await file.exists(filepath))) {
throw new Error(`File "${filepath}" does not exists`)
return
}
let result = await parser.parseChannels(filepath)
site = result.site
channels = result.channels
channels = channels.map(c => {
c.xmltv_id = c.xmltv_id
return c
})
await api.channels.load()
for (const channel of channels) {
if (channel.xmltv_id) continue
let choices = await getOptions(channel)
const question = {
name: 'option',
message: `Choose an option:`,
type: 'list',
choices,
pageSize: 10
}
await inquirer.prompt(question).then(async selected => {
switch (selected.option) {
case 'Overwrite...':
const input = await getInput(channel)
channel.xmltv_id = input.xmltv_id
break
case 'Skip...':
channel.xmltv_id = '-'
break
default:
const [name, xmltv_id] = selected.option
.replace(/ \[.*\]/, '')
.split('|')
.map(i => i.trim().replace(newLabel, ''))
channel.xmltv_id = xmltv_id
break
}
})
}
}
main()
function save() {
if (!file.existsSync(filepath)) return
const output = xml.create(channels, site)
file.writeSync(filepath, output)
logger.info(`\nFile '${filepath}' successfully saved`)
}
nodeCleanup(() => {
save()
})
async function getInput(channel) {
const name = channel.name.trim()
const input = await inquirer.prompt([
{
name: 'xmltv_id',
message: ' ID:',
type: 'input',
default: generateCode(name, defaultCountry)
}
])
return { name, xmltv_id: input['xmltv_id'] }
}
async function getOptions(channel) {
const channels = await api.channels.all()
const channelId = generateCode(channel.name, defaultCountry)
const similar = await getSimilar(channels, channelId)
let variants = []
variants.push(`${channel.name.trim()} | ${channelId}${newLabel}`)
similar.forEach(i => {
let alt_names = i.alt_names.length ? ` (${i.alt_names.join(',')})` : ''
let closed = i.closed ? `[closed:${i.closed}]` : ``
let replaced_by = i.replaced_by ? `[replaced_by:${i.replaced_by}]` : ''
variants.push(`${i.name}${alt_names} | ${i.id} ${closed}${replaced_by}[api]`)
})
variants.push(`Overwrite...`)
variants.push(`Skip...`)
return variants
}
async function getSimilar(list, channelId) {
const normChannelId = channelId.split('.')[0].slice(0, 8).toLowerCase()
return list.filter(i => i.id.split('.')[0].toLowerCase().startsWith(normChannelId))
}
function generateCode(name, country) {
const id = transliterate(name)
.replace(/\+/gi, 'Plus')
.replace(/^\&/gi, 'And')
.replace(/[^a-z\d]+/gi, '')
return `${id}.${country}`
}