This commit is contained in:
freearhey
2021-03-10 17:37:12 +03:00
parent df0819f1f1
commit ed1b894044
19 changed files with 597 additions and 1560 deletions

82
bin/epg-grabber/index.js Executable file
View File

@@ -0,0 +1,82 @@
#! /usr/bin/env node
const fs = require('fs')
const path = require('path')
const axios = require('axios')
const utils = require('./utils')
const { Command } = require('commander')
const program = new Command()
const dayjs = require('dayjs')
const utc = require('dayjs/plugin/utc')
dayjs.extend(utc)
program
.version('0.1.0', '-v, --version')
.name('epg-grabber')
.description('EPG grabber')
.usage('[options] [file-or-url]')
.option('-c, --config <config>', 'Path to config.xml file', './config.xml')
.option('-s, --sites <sites>', 'Path to /sites folder', './sites')
.parse(process.argv)
const options = program.opts()
const config = utils.parseConfig(options.config)
return console.log(config)
const sites = {
'tv.yandex.ru': {
url: function ({ date, channel }) {
return `https://tv.yandex.ru/channel/${channel.site_id}?date=${date.format('YYYY-MM-DD')}`
},
parser: function ({ channel, content }) {
const initialState = content.match(/window.__INITIAL_STATE__ = (.*);/i)[1]
const data = JSON.parse(initialState, null, 2)
const programs = data.channel.schedule.events.map(i => {
return {
title: i.title,
description: i.program.description,
start: i.start,
stop: i.finish,
lang: 'ru',
channel: channel['xmltv_id']
}
})
return programs
}
}
}
function main() {
const d = dayjs.utc()
const dates = Array.from({ length: config.days }, (_, i) => d.add(i, 'd'))
const channels = config.channels
const promises = []
channels.forEach(channel => {
const site = sites[channel.site]
dates.forEach(date => {
const url = site.url({ date, channel })
const promise = axios.get(url).then(response => {
return site.parser({ channel, content: response.data })
})
promises.push(promise)
})
})
Promise.allSettled(promises).then(results => {
let programs = []
results.forEach(result => {
if (result.status === 'fulfilled') {
programs = programs.concat(result.value)
}
})
const xml = utils.convertToXMLTV({ channels, programs })
fs.writeFileSync(path.resolve(__dirname, config.filename), xml)
})
}
main()

69
bin/epg-grabber/utils.js Normal file
View File

@@ -0,0 +1,69 @@
const fs = require('fs')
const path = require('path')
const convert = require('xml-js')
const dayjs = require('dayjs')
const utils = {}
utils.convertToXMLTV = function ({ channels, programs }) {
let output = `<?xml version="1.0" encoding="UTF-8" ?><tv>`
for (let channel of channels) {
output += `
<channel id="${channel['xmltv_id']}">
<display-name>${channel.name}</display-name>
</channel>`
}
for (let program of programs) {
const start = dayjs(program.start).format('YYYYMMDDHHmmss ZZ')
const stop = dayjs(program.stop).format('YYYYMMDDHHmmss ZZ')
output += `
<programme start="${start}" stop="${stop}" channel="${program.channel}">
<title lang="${program.lang}">${program.title}</title>`
if (program.category) {
output += `<category lang="${program.lang}">${program.category}</category>`
}
output += `</programme>`
}
output += '</tv>'
return output
}
utils.parseConfig = function (config) {
const xml = fs.readFileSync(path.resolve(process.cwd(), config), {
encoding: 'utf-8'
})
const result = convert.xml2js(xml)
const settings = result.elements.find(el => el.name === 'settings')
const filename = this.getElementText('filename', settings.elements)
const days = this.getElementText('days', settings.elements)
const userAgent = this.getElementText('user-agent', settings.elements)
const channels = settings.elements
.filter(el => el.name === 'channel')
.map(el => {
const channel = el.attributes
channel.name = el.elements.find(el => el.type === 'text').text
return channel
})
return {
filename,
days,
userAgent,
channels
}
}
utils.getElementText = function (name, elements) {
const el = elements.find(el => el.name === name)
return el ? el.elements.find(el => el.type === 'text').text : null
}
module.exports = utils