mirror of
https://github.com/iptv-org/epg.git
synced 2025-05-10 09:00:07 -04:00
Merge pull request #1203 from iptv-org/create-status-md
Create STATUS.md
This commit is contained in:
commit
bf94743137
17 changed files with 259 additions and 81 deletions
2
.github/workflows/_update-readme.yml
vendored
2
.github/workflows/_update-readme.yml
vendored
|
@ -8,7 +8,7 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- run: echo "BRANCH_NAME=$(date +'bot/auto-update-%s')" >> $GITHUB_OUTPUT
|
- run: echo "BRANCH_NAME=$(date +'bot/update-readme-%s')" >> $GITHUB_OUTPUT
|
||||||
id: create-branch-name
|
id: create-branch-name
|
||||||
- run: git config user.name 'iptv-bot[bot]'
|
- run: git config user.name 'iptv-bot[bot]'
|
||||||
- run: git config user.email '84861620+iptv-bot[bot]@users.noreply.github.com'
|
- run: git config user.email '84861620+iptv-bot[bot]@users.noreply.github.com'
|
||||||
|
|
53
.github/workflows/_update-status.yml
vendored
Normal file
53
.github/workflows/_update-status.yml
vendored
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
name: _update-status
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 9 * * *'
|
||||||
|
jobs:
|
||||||
|
update:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- run: echo "BRANCH_NAME=$(date +'bot/update-status-%s')" >> $GITHUB_OUTPUT
|
||||||
|
id: create-branch-name
|
||||||
|
- run: git config user.name 'iptv-bot[bot]'
|
||||||
|
- run: git config user.email '84861620+iptv-bot[bot]@users.noreply.github.com'
|
||||||
|
- run: git checkout -b ${{ steps.create-branch-name.outputs.BRANCH_NAME }}
|
||||||
|
- uses: actions/setup-node@v3
|
||||||
|
if: ${{ !env.ACT }}
|
||||||
|
with:
|
||||||
|
node-version: 16
|
||||||
|
cache: 'npm'
|
||||||
|
- run: npm install
|
||||||
|
- run: npm run status:update
|
||||||
|
- name: Commit Changes
|
||||||
|
if: ${{ !env.ACT }}
|
||||||
|
run: |
|
||||||
|
git add STATUS.md
|
||||||
|
git commit -m "[Bot] Update STATUS.md"
|
||||||
|
git status
|
||||||
|
git push -u origin ${{ steps.create-branch-name.outputs.BRANCH_NAME }}
|
||||||
|
- uses: tibdex/github-app-token@v1
|
||||||
|
if: ${{ !env.ACT }}
|
||||||
|
id: create-app-token
|
||||||
|
with:
|
||||||
|
app_id: ${{ secrets.APP_ID }}
|
||||||
|
private_key: ${{ secrets.APP_PRIVATE_KEY }}
|
||||||
|
- uses: repo-sync/pull-request@v2
|
||||||
|
if: ${{ !env.ACT && github.ref == 'refs/heads/master' }}
|
||||||
|
id: pull-request
|
||||||
|
with:
|
||||||
|
github_token: ${{ steps.create-app-token.outputs.token }}
|
||||||
|
source_branch: ${{ steps.create-branch-name.outputs.BRANCH_NAME }}
|
||||||
|
destination_branch: 'master'
|
||||||
|
pr_title: '[Bot] Update STATUS.md'
|
||||||
|
pr_body: |
|
||||||
|
This pull request is created via [update-status][1] workflow.
|
||||||
|
|
||||||
|
[1]: https://github.com/iptv-org/epg/actions/runs/${{ github.run_id }}
|
||||||
|
- uses: juliangruber/merge-pull-request-action@v1
|
||||||
|
if: ${{ !env.ACT && github.ref == 'refs/heads/master' }}
|
||||||
|
with:
|
||||||
|
github-token: ${{ secrets.PAT }}
|
||||||
|
number: ${{ steps.pull-request.outputs.pr_number }}
|
||||||
|
method: squash
|
8
.readme/_sites.md
Normal file
8
.readme/_sites.md
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr><th align="left">Site</th><th align="left">Status </th></tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td valign="top" rowspan="1">example.com</td><td nowrap><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>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
|
@ -1,4 +0,0 @@
|
||||||
{
|
|
||||||
"build": "README.md",
|
|
||||||
"files": ["./.readme/template.md"]
|
|
||||||
}
|
|
4
.readme/readme.json
Normal file
4
.readme/readme.json
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"build": "README.md",
|
||||||
|
"files": ["./.readme/readme.md"]
|
||||||
|
}
|
4
.readme/status.json
Normal file
4
.readme/status.json
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"build": "STATUS.md",
|
||||||
|
"files": ["./.readme/status.md"]
|
||||||
|
}
|
4
.readme/status.md
Normal file
4
.readme/status.md
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
# Status
|
||||||
|
|
||||||
|
<!-- prettier-ignore -->
|
||||||
|
#include "./.readme/_sites.md"
|
|
@ -12,6 +12,7 @@
|
||||||
"api:update": "node scripts/commands/api/update.js",
|
"api:update": "node scripts/commands/api/update.js",
|
||||||
"api:load": "mkdir -p scripts/data && curl -L -o scripts/data/channels.json https://iptv-org.github.io/api/channels.json && curl -L -o scripts/data/countries.json https://iptv-org.github.io/api/countries.json",
|
"api:load": "mkdir -p scripts/data && curl -L -o scripts/data/channels.json https://iptv-org.github.io/api/channels.json && curl -L -o scripts/data/countries.json https://iptv-org.github.io/api/countries.json",
|
||||||
"readme:update": "node scripts/commands/readme/update.js",
|
"readme:update": "node scripts/commands/readme/update.js",
|
||||||
|
"status:update": "node scripts/commands/status/update.js",
|
||||||
"lint": "npx eslint ./scripts/**/*.js",
|
"lint": "npx eslint ./scripts/**/*.js",
|
||||||
"test": "TZ=Pacific/Nauru npx jest --runInBand",
|
"test": "TZ=Pacific/Nauru npx jest --runInBand",
|
||||||
"test:commands": "npx jest --runInBand -- commands",
|
"test:commands": "npx jest --runInBand -- commands",
|
||||||
|
@ -19,6 +20,7 @@
|
||||||
"act:test": "act workflow_dispatch -W .github/workflows/_test.yml",
|
"act:test": "act workflow_dispatch -W .github/workflows/_test.yml",
|
||||||
"act:check": "act workflow_dispatch -W .github/workflows/_check.yml",
|
"act:check": "act workflow_dispatch -W .github/workflows/_check.yml",
|
||||||
"act:update-readme": "act workflow_dispatch -W .github/workflows/_update-readme.yml",
|
"act:update-readme": "act workflow_dispatch -W .github/workflows/_update-readme.yml",
|
||||||
|
"act:update-status": "act workflow_dispatch -W .github/workflows/_update-status.yml",
|
||||||
"act:update-api": "act workflow_dispatch -W .github/workflows/_update-api.yml"
|
"act:update-api": "act workflow_dispatch -W .github/workflows/_update-api.yml"
|
||||||
},
|
},
|
||||||
"private": true,
|
"private": true,
|
||||||
|
|
|
@ -5,7 +5,7 @@ const _ = require('lodash')
|
||||||
const CHANNELS_PATH = process.env.CHANNELS_PATH || 'sites/**/*.channels.xml'
|
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/readme.json')
|
||||||
.parse(process.argv)
|
.parse(process.argv)
|
||||||
.opts()
|
.opts()
|
||||||
|
|
||||||
|
@ -46,28 +46,30 @@ main()
|
||||||
async function generateCountriesTable(items = []) {
|
async function generateCountriesTable(items = []) {
|
||||||
logger.info('generating countries table...')
|
logger.info('generating countries table...')
|
||||||
|
|
||||||
let rows = []
|
let data = []
|
||||||
for (const item of items) {
|
for (const item of items) {
|
||||||
const country = api.countries.find({ code: item.code.toUpperCase() })
|
const country = api.countries.find({ code: item.code.toUpperCase() })
|
||||||
if (!country) continue
|
if (!country) continue
|
||||||
|
|
||||||
rows.push({
|
data.push([
|
||||||
flag: country.flag,
|
country.name,
|
||||||
name: country.name,
|
`${country.flag} ${country.name}`,
|
||||||
channels: item.count,
|
item.count,
|
||||||
epg: `<code>https://iptv-org.github.io/epg/guides/${item.group}.epg.xml</code>`,
|
`<code>https://iptv-org.github.io/epg/guides/${item.group}.epg.xml</code>`
|
||||||
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'])
|
data = _.orderBy(data, [item => item[0], item => item[2]], ['asc', 'desc'])
|
||||||
rows = _.groupBy(rows, 'name')
|
data = data.map(i => {
|
||||||
|
i.shift()
|
||||||
|
return i
|
||||||
|
})
|
||||||
|
data = Object.values(_.groupBy(data, item => item[0]))
|
||||||
|
|
||||||
const output = table.create(rows, [
|
const output = table.create(data, [
|
||||||
'Country ',
|
'Country ',
|
||||||
'Channels',
|
'Channels',
|
||||||
'EPG',
|
'EPG'
|
||||||
'Status '
|
|
||||||
])
|
])
|
||||||
|
|
||||||
await file.create('./.readme/_countries.md', output)
|
await file.create('./.readme/_countries.md', output)
|
||||||
|
|
52
scripts/commands/status/update.js
Normal file
52
scripts/commands/status/update.js
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
const { file, markdown, logger, table } = require('../../core')
|
||||||
|
const { program } = require('commander')
|
||||||
|
const _ = require('lodash')
|
||||||
|
|
||||||
|
const CONFIGS_PATH = process.env.CONFIGS_PATH || 'sites/**/*.config.js'
|
||||||
|
|
||||||
|
const options = program
|
||||||
|
.option('-c, --config <config>', 'Set path to config file', '.readme/status.json')
|
||||||
|
.parse(process.argv)
|
||||||
|
.opts()
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
let data = []
|
||||||
|
|
||||||
|
const files = await file.list(CONFIGS_PATH).catch(console.error)
|
||||||
|
for (const filepath of files) {
|
||||||
|
try {
|
||||||
|
const { site, ignore } = require(file.resolve(filepath))
|
||||||
|
|
||||||
|
if (ignore) continue
|
||||||
|
|
||||||
|
data.push([
|
||||||
|
site,
|
||||||
|
`<a href="https://github.com/iptv-org/epg/actions/workflows/${site}.yml"><img src="https://github.com/iptv-org/epg/actions/workflows/${site}.yml/badge.svg" alt="${site}" style="max-width: 100%;"></a>`
|
||||||
|
])
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data = Object.values(_.groupBy(data, item => item[0]))
|
||||||
|
|
||||||
|
const output = table.create(data, [
|
||||||
|
'Site',
|
||||||
|
'Status '
|
||||||
|
])
|
||||||
|
|
||||||
|
await file.create('./.readme/_sites.md', output)
|
||||||
|
|
||||||
|
await updateMarkdown()
|
||||||
|
}
|
||||||
|
|
||||||
|
main()
|
||||||
|
|
||||||
|
async function updateMarkdown() {
|
||||||
|
logger.info('updating status.md...')
|
||||||
|
|
||||||
|
const config = require(file.resolve(options.config))
|
||||||
|
await file.createDir(file.dirname(config.build))
|
||||||
|
await markdown.compile(options.config)
|
||||||
|
}
|
|
@ -1,35 +1,47 @@
|
||||||
const table = {}
|
const table = {}
|
||||||
|
|
||||||
table.create = function (data, cols) {
|
table.create = function (data, cols) {
|
||||||
let output = '<table>\n'
|
let output = '<table>\r\n'
|
||||||
|
|
||||||
output += ' <thead>\n <tr>'
|
output += ' <thead>\r\n <tr>'
|
||||||
for (let column of cols) {
|
for (let column of cols) {
|
||||||
output += `<th>${column}</th>`
|
output += `<th align="left">${column}</th>`
|
||||||
}
|
}
|
||||||
output += '</tr>\n </thead>\n'
|
output += '</tr>\r\n </thead>\r\n'
|
||||||
|
|
||||||
output += ' <tbody>\n'
|
output += ' <tbody>\r\n'
|
||||||
for (let groupId in data) {
|
output += getHTMLRows(data)
|
||||||
const group = data[groupId]
|
output += ' </tbody>\r\n'
|
||||||
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>'
|
output += '</table>'
|
||||||
|
|
||||||
return output
|
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
|
module.exports = table
|
||||||
|
|
|
@ -9,11 +9,11 @@ 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>Country </th><th>Channels</th><th>EPG</th><th>Status </th></tr>
|
<tr><th align="left">Country </th><th align="left">Channels</th><th align="left">EPG</th></tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr><td valign="top" rowspan="2">🇨🇦 Canada</td><td align="right">2</td><td nowrap><code>https://iptv-org.github.io/epg/guides/ca-en/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 valign="top" rowspan="2">🇨🇦 Canada</td><td align="right" nowrap>2</td><td nowrap><code>https://iptv-org.github.io/epg/guides/ca-en/example.com.epg.xml</code></td></tr>
|
||||||
<tr><td align="right">1</td><td nowrap><code>https://iptv-org.github.io/epg/guides/ca-ru/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="right" nowrap>1</td><td nowrap><code>https://iptv-org.github.io/epg/guides/ca-ru/example.com.epg.xml</code></td></tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
|
11
tests/__data__/expected/_status.md
Normal file
11
tests/__data__/expected/_status.md
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
# Status
|
||||||
|
|
||||||
|
<!-- prettier-ignore -->
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr><th align="left">Site</th><th align="left">Status </th></tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr><td valign="top" rowspan="1">example.com</td><td nowrap><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>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
|
@ -1,4 +1,4 @@
|
||||||
{
|
{
|
||||||
"build" : "tests/__data__/output/readme.md",
|
"build" : "tests/__data__/output/readme.md",
|
||||||
"files" : ["./.readme/template.md"]
|
"files" : ["./.readme/readme.md"]
|
||||||
}
|
}
|
4
tests/__data__/input/status.json
Normal file
4
tests/__data__/input/status.json
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"build" : "tests/__data__/output/status.md",
|
||||||
|
"files" : ["./.readme/status.md"]
|
||||||
|
}
|
26
tests/commands/status/update.test.js
Normal file
26
tests/commands/status/update.test.js
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
const { execSync } = require('child_process')
|
||||||
|
const fs = require('fs-extra')
|
||||||
|
const path = require('path')
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fs.emptyDirSync('tests/__data__/output')
|
||||||
|
|
||||||
|
const stdout = execSync(
|
||||||
|
'CONFIGS_PATH=tests/__data__/input/sites/example.com.config.js DATA_DIR=tests/__data__/input/data npm run status:update -- --config=tests/__data__/input/status.json',
|
||||||
|
{ encoding: 'utf8' }
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('can update status.md', () => {
|
||||||
|
expect(content('tests/__data__/output/status.md')).toBe(
|
||||||
|
content('tests/__data__/expected/_status.md')
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
function content(filepath) {
|
||||||
|
const data = fs.readFileSync(path.resolve(filepath), {
|
||||||
|
encoding: 'utf8'
|
||||||
|
})
|
||||||
|
|
||||||
|
return JSON.stringify(data)
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue