mirror of
https://github.com/iptv-org/epg.git
synced 2025-05-10 00:50:09 -04:00
Merge pull request #484 from iptv-org/update-update-readme-js
Update update-readme.js
This commit is contained in:
commit
fd02200476
12 changed files with 79 additions and 137 deletions
|
@ -3,10 +3,11 @@
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"lint": "node scripts/commands/lint.js",
|
"lint": "node scripts/commands/lint.js",
|
||||||
"validate": "node scripts/commands/validate.js",
|
"validate": "node scripts/commands/validate.js",
|
||||||
"act": "act workflow_dispatch",
|
|
||||||
"test": "npx jest --runInBand",
|
"test": "npx jest --runInBand",
|
||||||
"test:commands": "npx jest --runInBand -- commands",
|
"test:commands": "npx jest --runInBand -- commands",
|
||||||
"test:sites": "npx jest --runInBand -- sites"
|
"test:sites": "npx jest --runInBand -- sites",
|
||||||
|
"act": "act workflow_dispatch",
|
||||||
|
"update-readme": "node scripts/commands/update-readme.js"
|
||||||
},
|
},
|
||||||
"private": true,
|
"private": true,
|
||||||
"author": "Arhey",
|
"author": "Arhey",
|
||||||
|
|
|
@ -1,37 +1,44 @@
|
||||||
const { file, markdown, parser, logger, api } = require('../core')
|
const { file, markdown, parser, logger, api, table } = require('../core')
|
||||||
const { program } = require('commander')
|
const { program } = require('commander')
|
||||||
const _ = require('lodash')
|
const _ = require('lodash')
|
||||||
|
|
||||||
const LOGS_DIR = process.env.LOGS_DIR || 'scripts/logs'
|
const CHANNELS_PATH = process.env.CHANNELS_PATH || 'sites/**/*.channels.xml'
|
||||||
|
|
||||||
const options = program
|
const options = program
|
||||||
.option('-c, --config <config>', 'Set path to config file', '.readme/config.json')
|
.option('-c, --config <config>', 'Set path to config file', '.readme/config.json')
|
||||||
.parse(process.argv)
|
.parse(process.argv)
|
||||||
.opts()
|
.opts()
|
||||||
|
|
||||||
const statuses = {
|
|
||||||
0: '🟢',
|
|
||||||
1: '🔴'
|
|
||||||
}
|
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
await api.countries.load()
|
await api.countries.load()
|
||||||
await api.subdivisions.load()
|
const files = await file.list(CHANNELS_PATH)
|
||||||
const records = await getLogRecords()
|
const items = []
|
||||||
await generateCountriesTable(records)
|
for (const filepath of files) {
|
||||||
await generateUSStatesTable(records)
|
const { site, channels } = await parser.parseChannels(filepath)
|
||||||
await generateCanadaProvincesTable(records)
|
const filename = file.basename(filepath)
|
||||||
|
const [__, suffix] = filename.match(/\_(.*)\.channels\.xml$/) || [null, null]
|
||||||
|
const [code] = suffix.split('-')
|
||||||
|
|
||||||
|
items.push({
|
||||||
|
code,
|
||||||
|
site,
|
||||||
|
count: channels.length,
|
||||||
|
group: `${suffix}/${site}`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
await generateCountriesTable(items)
|
||||||
await updateReadme()
|
await updateReadme()
|
||||||
}
|
}
|
||||||
|
|
||||||
main()
|
main()
|
||||||
|
|
||||||
async function generateCountriesTable(items = []) {
|
async function generateCountriesTable(items = []) {
|
||||||
logger.info('Generating countries table...')
|
logger.info('generating countries table...')
|
||||||
|
|
||||||
let rows = []
|
let rows = []
|
||||||
for (const item of items) {
|
for (const item of items) {
|
||||||
const country = api.countries.find({ code: item.code })
|
const country = api.countries.find({ code: item.code.toUpperCase() })
|
||||||
if (!country) continue
|
if (!country) continue
|
||||||
|
|
||||||
rows.push({
|
rows.push({
|
||||||
|
@ -39,70 +46,25 @@ async function generateCountriesTable(items = []) {
|
||||||
name: country.name,
|
name: country.name,
|
||||||
channels: item.count,
|
channels: item.count,
|
||||||
epg: `<code>https://iptv-org.github.io/epg/guides/${item.group}.epg.xml</code>`,
|
epg: `<code>https://iptv-org.github.io/epg/guides/${item.group}.epg.xml</code>`,
|
||||||
status: statuses[item.status]
|
status: `<a href="https://github.com/iptv-org/epg/actions/workflows/${item.site}.yml"><img src="https://github.com/iptv-org/epg/actions/workflows/${item.site}.yml/badge.svg" alt="${item.site}" style="max-width: 100%;"></a>`
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
rows = _.orderBy(rows, ['name', 'channels'], ['asc', 'desc'])
|
rows = _.orderBy(rows, ['name', 'channels'], ['asc', 'desc'])
|
||||||
rows = _.groupBy(rows, 'name')
|
rows = _.groupBy(rows, 'name')
|
||||||
|
|
||||||
const table = markdown.createTable(rows, ['Country', 'Channels', 'EPG', 'Status'])
|
const output = table.create(rows, [
|
||||||
|
'Country',
|
||||||
|
'Channels',
|
||||||
|
'EPG',
|
||||||
|
'Status '
|
||||||
|
])
|
||||||
|
|
||||||
await file.create('./.readme/_countries.md', table)
|
await file.create('./.readme/_countries.md', output)
|
||||||
}
|
|
||||||
|
|
||||||
async function generateUSStatesTable(items = []) {
|
|
||||||
logger.info('Generating US states table...')
|
|
||||||
|
|
||||||
let rows = []
|
|
||||||
for (const item of items) {
|
|
||||||
if (!item.code.startsWith('US-')) continue
|
|
||||||
const state = api.subdivisions.find({ code: item.code })
|
|
||||||
if (!state) continue
|
|
||||||
|
|
||||||
rows.push({
|
|
||||||
name: state.name,
|
|
||||||
channels: item.count,
|
|
||||||
epg: `<code>https://iptv-org.github.io/epg/guides/${item.group}.epg.xml</code>`,
|
|
||||||
status: statuses[item.status]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
rows = _.orderBy(rows, ['name', 'channels'], ['asc', 'desc'])
|
|
||||||
rows = _.groupBy(rows, 'name')
|
|
||||||
|
|
||||||
const table = markdown.createTable(rows, ['State', 'Channels', 'EPG', 'Status'])
|
|
||||||
|
|
||||||
await file.create('./.readme/_us-states.md', table)
|
|
||||||
}
|
|
||||||
|
|
||||||
async function generateCanadaProvincesTable(items = []) {
|
|
||||||
logger.info('Generating Canada provinces table...')
|
|
||||||
|
|
||||||
let rows = []
|
|
||||||
for (const item of items) {
|
|
||||||
if (!item.code.startsWith('CA-')) continue
|
|
||||||
const province = api.subdivisions.find({ code: item.code })
|
|
||||||
if (!province) continue
|
|
||||||
|
|
||||||
rows.push({
|
|
||||||
name: province.name,
|
|
||||||
channels: item.count,
|
|
||||||
epg: `<code>https://iptv-org.github.io/epg/guides/${item.group}.epg.xml</code>`,
|
|
||||||
status: statuses[item.status]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
rows = _.orderBy(rows, ['name', 'channels'], ['asc', 'desc'])
|
|
||||||
rows = _.groupBy(rows, 'name')
|
|
||||||
|
|
||||||
const table = markdown.createTable(rows, ['Province', 'Channels', 'EPG', 'Status'])
|
|
||||||
|
|
||||||
await file.create('./.readme/_ca-provinces.md', table)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function updateReadme() {
|
async function updateReadme() {
|
||||||
logger.info('Updating README.md...')
|
logger.info('updating readme.md...')
|
||||||
|
|
||||||
const config = require(file.resolve(options.config))
|
const config = require(file.resolve(options.config))
|
||||||
await file.createDir(file.dirname(config.build))
|
await file.createDir(file.dirname(config.build))
|
||||||
|
|
|
@ -6,3 +6,4 @@ exports.timer = require('./timer')
|
||||||
exports.markdown = require('./markdown')
|
exports.markdown = require('./markdown')
|
||||||
exports.api = require('./api')
|
exports.api = require('./api')
|
||||||
exports.date = require('./date')
|
exports.date = require('./date')
|
||||||
|
exports.table = require('./table')
|
||||||
|
|
|
@ -3,38 +3,6 @@ const file = require('./file')
|
||||||
|
|
||||||
const markdown = {}
|
const markdown = {}
|
||||||
|
|
||||||
markdown.createTable = function (data, cols) {
|
|
||||||
let output = '<table>\n'
|
|
||||||
|
|
||||||
output += ' <thead>\n <tr>'
|
|
||||||
for (let column of cols) {
|
|
||||||
output += `<th align="left">${column}</th>`
|
|
||||||
}
|
|
||||||
output += '</tr>\n </thead>\n'
|
|
||||||
|
|
||||||
output += ' <tbody>\n'
|
|
||||||
for (let groupId in data) {
|
|
||||||
const group = data[groupId]
|
|
||||||
for (let [i, item] of group.entries()) {
|
|
||||||
const rowspan = group.length > 1 ? ` rowspan="${group.length}"` : ''
|
|
||||||
output += ' <tr>'
|
|
||||||
if (i === 0) {
|
|
||||||
const name = item.flag ? `${item.flag} ${item.name}` : item.name
|
|
||||||
output += `<td align="left" valign="top" nowrap${rowspan}>${name}</td>`
|
|
||||||
}
|
|
||||||
output += `<td align="right">${item.channels}</td>`
|
|
||||||
output += `<td align="left" nowrap>${item.epg}</td>`
|
|
||||||
output += `<td align="center" nowrap>${item.status}</td>`
|
|
||||||
output += '</tr>\n'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
output += ' </tbody>\n'
|
|
||||||
|
|
||||||
output += '</table>'
|
|
||||||
|
|
||||||
return output
|
|
||||||
}
|
|
||||||
|
|
||||||
markdown.compile = function (filepath) {
|
markdown.compile = function (filepath) {
|
||||||
markdownInclude.compileFiles(file.resolve(filepath))
|
markdownInclude.compileFiles(file.resolve(filepath))
|
||||||
}
|
}
|
||||||
|
|
35
scripts/core/table.js
Normal file
35
scripts/core/table.js
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
const table = {}
|
||||||
|
|
||||||
|
table.create = function (data, cols) {
|
||||||
|
let output = '<table>\n'
|
||||||
|
|
||||||
|
output += ' <thead>\n <tr>'
|
||||||
|
for (let column of cols) {
|
||||||
|
output += `<th>${column}</th>`
|
||||||
|
}
|
||||||
|
output += '</tr>\n </thead>\n'
|
||||||
|
|
||||||
|
output += ' <tbody>\n'
|
||||||
|
for (let groupId in data) {
|
||||||
|
const group = data[groupId]
|
||||||
|
for (let [i, item] of group.entries()) {
|
||||||
|
const rowspan = group.length > 1 ? ` rowspan="${group.length}"` : ''
|
||||||
|
output += ' <tr>'
|
||||||
|
if (i === 0) {
|
||||||
|
const name = item.flag ? `${item.flag} ${item.name}` : item.name
|
||||||
|
output += `<td valign="top"${rowspan}>${name}</td>`
|
||||||
|
}
|
||||||
|
output += `<td align="right">${item.channels}</td>`
|
||||||
|
output += `<td nowrap>${item.epg}</td>`
|
||||||
|
output += `<td>${item.status}</td>`
|
||||||
|
output += '</tr>\n'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
output += ' </tbody>\n'
|
||||||
|
|
||||||
|
output += '</table>'
|
||||||
|
|
||||||
|
return output
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = table
|
|
@ -1,2 +1,2 @@
|
||||||
{"channel":{"lang":"ru","xmltv_id":"CNNInternationalEurope.us","site_id":"140","site":"example.com"},"configPath":"tests/__data__/input/sites/example.com.config.js","date":"2022-01-30T00:00:00.000Z","groups":["ca-nl/example.com"],"error":null,"cluster_id":1,"_id":"TYDwYLsrkmPtTLT2"}
|
{"channel":{"lang":"ru","xmltv_id":"CNNInternationalEurope.us","site_id":"140","site":"example.com"},"date":"2022-02-03T00:00:00.000Z","configPath":"tests/__data__/input/sites/example.com.config.js","groups":["ca/example.com"],"error":null,"cluster_id":1,"_id":"vOpwztzvJ5pFSVws"}
|
||||||
{"channel":{"lang":"ru","xmltv_id":"CNNInternationalEurope.us","site_id":"140","site":"example.com"},"configPath":"tests/__data__/input/sites/example.com.config.js","date":"2022-01-31T00:00:00.000Z","groups":["ca-nl/example.com"],"error":null,"cluster_id":1,"_id":"98cKRthEhMmKEnwx"}
|
{"channel":{"lang":"ru","xmltv_id":"CNNInternationalEurope.us","site_id":"140","site":"example.com"},"date":"2022-02-04T00:00:00.000Z","configPath":"tests/__data__/input/sites/example.com.config.js","groups":["ca/example.com"],"error":null,"cluster_id":1,"_id":"sP2A0zQSOoVg0BS1"}
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
# EPG
|
# EPG
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
EPG (Electronic Program Guide) for thousands of TV channels collected from different sources.
|
EPG (Electronic Program Guide) for thousands of TV channels collected from different sources.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
@ -11,40 +9,17 @@ To load a program guide, all you need to do is copy the link to one or more of t
|
||||||
<!-- prettier-ignore -->
|
<!-- prettier-ignore -->
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr><th align="left">Country</th><th align="left">Channels</th><th align="left">EPG</th><th align="left">Status</th></tr>
|
<tr><th>Country</th><th>Channels</th><th>EPG</th><th>Status </th></tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr><td align="left" valign="top" nowrap>🇿🇦 South Africa</td><td align="right">1</td><td align="left" nowrap><code>https://iptv-org.github.io/epg/guides/za/dstv.com.epg.xml</code></td><td align="center" nowrap>🟢</td></tr>
|
<tr><td valign="top">🇨🇦 Canada</td><td align="right">2</td><td nowrap><code>https://iptv-org.github.io/epg/guides/ca/example.com.epg.xml</code></td><td><a href="https://github.com/iptv-org/epg/actions/workflows/example.com.yml"><img src="https://github.com/iptv-org/epg/actions/workflows/example.com.yml/badge.svg" alt="example.com" style="max-width: 100%;"></a></td></tr>
|
||||||
<tr><td align="left" valign="top" nowrap rowspan="2">🇺🇸 United States</td><td align="right">372</td><td align="left" nowrap><code>https://iptv-org.github.io/epg/guides/us/tvtv.us.epg.xml</code></td><td align="center" nowrap>🟢</td></tr>
|
<tr><td valign="top">🇪🇪 Estonia</td><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/epg/guides/ee-en/ignore.com.epg.xml</code></td><td><a href="https://github.com/iptv-org/epg/actions/workflows/ignore.com.yml"><img src="https://github.com/iptv-org/epg/actions/workflows/ignore.com.yml/badge.svg" alt="ignore.com" style="max-width: 100%;"></a></td></tr>
|
||||||
<tr><td align="right">74</td><td align="left" nowrap><code>https://iptv-org.github.io/epg/guides/us/magticom.ge.epg.xml</code></td><td align="center" nowrap>🟢</td></tr>
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
### US States
|
## EPG Codes
|
||||||
|
|
||||||
<!-- prettier-ignore -->
|
📋 [iptv-org.github.io](https://iptv-org.github.io/)
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr><th align="left">State</th><th align="left">Channels</th><th align="left">EPG</th><th align="left">Status</th></tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr><td align="left" valign="top" nowrap rowspan="3">Puerto Rico</td><td align="right">14</td><td align="left" nowrap><code>https://iptv-org.github.io/epg/guides/us-pr/tvtv.us.epg.xml</code></td><td align="center" nowrap>🟢</td></tr>
|
|
||||||
<tr><td align="right">7</td><td align="left" nowrap><code>https://iptv-org.github.io/epg/guides/us-pr/gatotv.com.epg.xml</code></td><td align="center" nowrap>🔴</td></tr>
|
|
||||||
<tr><td align="right">0</td><td align="left" nowrap><code>https://iptv-org.github.io/epg/guides/us-pr/directv.com.epg.xml</code></td><td align="center" nowrap>🟢</td></tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
### Provinces of Canada
|
|
||||||
|
|
||||||
<!-- prettier-ignore -->
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr><th align="left">Province</th><th align="left">Channels</th><th align="left">EPG</th><th align="left">Status</th></tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr><td align="left" valign="top" nowrap>Newfoundland and Labrador</td><td align="right">1</td><td align="left" nowrap><code>https://iptv-org.github.io/epg/guides/ca-nl/tvtv.us.epg.xml</code></td><td align="center" nowrap>🟢</td></tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
## API
|
## API
|
||||||
|
|
||||||
|
|
|
@ -36,8 +36,8 @@ it('can create queue', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('can log errors', () => {
|
it('can log errors', () => {
|
||||||
let output = content('tests/__data__/output/logs/errors/ca-nl/example.com.log')
|
let output = content('tests/__data__/output/logs/errors/ca/example.com.log')
|
||||||
let expected = content('tests/__data__/expected/logs/errors/ca-nl/example.com.log')
|
let expected = content('tests/__data__/expected/logs/errors/ca/example.com.log')
|
||||||
|
|
||||||
expect(output).toEqual(expected)
|
expect(output).toEqual(expected)
|
||||||
})
|
})
|
||||||
|
|
|
@ -7,7 +7,7 @@ beforeEach(() => {
|
||||||
fs.mkdirSync('tests/__data__/output')
|
fs.mkdirSync('tests/__data__/output')
|
||||||
|
|
||||||
const stdout = execSync(
|
const stdout = execSync(
|
||||||
'LOGS_DIR=tests/__data__/input/logs DATA_DIR=tests/__data__/input/data node scripts/commands/update-readme.js --config=tests/__data__/input/_readme.json',
|
'CHANNELS_PATH=tests/__data__/input/sites/*.channels.xml DATA_DIR=tests/__data__/input/data node scripts/commands/update-readme.js --config=tests/__data__/input/_readme.json',
|
||||||
{ encoding: 'utf8' }
|
{ encoding: 'utf8' }
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue