diff --git a/.github/workflows/_update-readme.yml b/.github/workflows/_update-readme.yml
index 07f643da..41893691 100644
--- a/.github/workflows/_update-readme.yml
+++ b/.github/workflows/_update-readme.yml
@@ -8,7 +8,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- 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
- run: git config user.name 'iptv-bot[bot]'
- run: git config user.email '84861620+iptv-bot[bot]@users.noreply.github.com'
diff --git a/.github/workflows/_update-status.yml b/.github/workflows/_update-status.yml
new file mode 100644
index 00000000..c7f67177
--- /dev/null
+++ b/.github/workflows/_update-status.yml
@@ -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
diff --git a/.readme/_sites.md b/.readme/_sites.md
new file mode 100644
index 00000000..b28b5063
--- /dev/null
+++ b/.readme/_sites.md
@@ -0,0 +1,8 @@
+
+
+ Site | Status |
+
+
+ example.com |  |
+
+
\ No newline at end of file
diff --git a/.readme/config.json b/.readme/config.json
deleted file mode 100644
index 88556a84..00000000
--- a/.readme/config.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "build": "README.md",
- "files": ["./.readme/template.md"]
-}
diff --git a/.readme/readme.json b/.readme/readme.json
new file mode 100644
index 00000000..db539a62
--- /dev/null
+++ b/.readme/readme.json
@@ -0,0 +1,4 @@
+{
+ "build": "README.md",
+ "files": ["./.readme/readme.md"]
+}
diff --git a/.readme/template.md b/.readme/readme.md
similarity index 97%
rename from .readme/template.md
rename to .readme/readme.md
index a73700cb..2cd9f24a 100644
--- a/.readme/template.md
+++ b/.readme/readme.md
@@ -1,16 +1,16 @@
-# EPG
-
-EPG (Electronic Program Guide) for thousands of TV channels collected from different sources.
-
-## Usage
-
-To load a program guide, all you need to do is copy the link to one or more of the guides from the list below and paste it into your favorite player.
-
-
-#include "./.readme/_countries.md"
-
-All guides also have a compressed and JSON version. To download them, simply change the extension from `.xml` to `.xml.gz` or `.json` respectively.
-
-## Contribution
-
-If you find a bug or want to contribute to the code or documentation, you can help by submitting an [issue](https://github.com/iptv-org/epg/issues) or a [pull request](https://github.com/iptv-org/epg/pulls).
+# EPG
+
+EPG (Electronic Program Guide) for thousands of TV channels collected from different sources.
+
+## Usage
+
+To load a program guide, all you need to do is copy the link to one or more of the guides from the list below and paste it into your favorite player.
+
+
+#include "./.readme/_countries.md"
+
+All guides also have a compressed and JSON version. To download them, simply change the extension from `.xml` to `.xml.gz` or `.json` respectively.
+
+## Contribution
+
+If you find a bug or want to contribute to the code or documentation, you can help by submitting an [issue](https://github.com/iptv-org/epg/issues) or a [pull request](https://github.com/iptv-org/epg/pulls).
diff --git a/.readme/status.json b/.readme/status.json
new file mode 100644
index 00000000..1505b3a8
--- /dev/null
+++ b/.readme/status.json
@@ -0,0 +1,4 @@
+{
+ "build": "STATUS.md",
+ "files": ["./.readme/status.md"]
+}
\ No newline at end of file
diff --git a/.readme/status.md b/.readme/status.md
new file mode 100644
index 00000000..3ee20ea5
--- /dev/null
+++ b/.readme/status.md
@@ -0,0 +1,4 @@
+# Status
+
+
+#include "./.readme/_sites.md"
diff --git a/package.json b/package.json
index 4c643c29..d29da832 100644
--- a/package.json
+++ b/package.json
@@ -12,6 +12,7 @@
"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",
"readme:update": "node scripts/commands/readme/update.js",
+ "status:update": "node scripts/commands/status/update.js",
"lint": "npx eslint ./scripts/**/*.js",
"test": "TZ=Pacific/Nauru npx jest --runInBand",
"test:commands": "npx jest --runInBand -- commands",
@@ -19,6 +20,7 @@
"act:test": "act workflow_dispatch -W .github/workflows/_test.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-status": "act workflow_dispatch -W .github/workflows/_update-status.yml",
"act:update-api": "act workflow_dispatch -W .github/workflows/_update-api.yml"
},
"private": true,
diff --git a/scripts/commands/readme/update.js b/scripts/commands/readme/update.js
index 18f47c52..4ce5da4f 100644
--- a/scripts/commands/readme/update.js
+++ b/scripts/commands/readme/update.js
@@ -5,7 +5,7 @@ const _ = require('lodash')
const CHANNELS_PATH = process.env.CHANNELS_PATH || 'sites/**/*.channels.xml'
const options = program
- .option('-c, --config ', 'Set path to config file', '.readme/config.json')
+ .option('-c, --config ', 'Set path to config file', '.readme/readme.json')
.parse(process.argv)
.opts()
@@ -46,28 +46,30 @@ main()
async function generateCountriesTable(items = []) {
logger.info('generating countries table...')
- let rows = []
+ let data = []
for (const item of items) {
const country = api.countries.find({ code: item.code.toUpperCase() })
if (!country) continue
- rows.push({
- flag: country.flag,
- name: country.name,
- channels: item.count,
- epg: `https://iptv-org.github.io/epg/guides/${item.group}.epg.xml
`,
- status: `
`
- })
+ data.push([
+ country.name,
+ `${country.flag} ${country.name}`,
+ item.count,
+ `https://iptv-org.github.io/epg/guides/${item.group}.epg.xml
`
+ ])
}
- rows = _.orderBy(rows, ['name', 'channels'], ['asc', 'desc'])
- rows = _.groupBy(rows, 'name')
+ data = _.orderBy(data, [item => item[0], item => item[2]], ['asc', 'desc'])
+ 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 ',
'Channels',
- 'EPG',
- 'Status '
+ 'EPG'
])
await file.create('./.readme/_countries.md', output)
diff --git a/scripts/commands/status/update.js b/scripts/commands/status/update.js
new file mode 100644
index 00000000..9e3abdba
--- /dev/null
+++ b/scripts/commands/status/update.js
@@ -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 ', '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,
+ `
`
+ ])
+ } 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)
+}
diff --git a/scripts/core/table.js b/scripts/core/table.js
index f9315f1e..0c5d363f 100644
--- a/scripts/core/table.js
+++ b/scripts/core/table.js
@@ -1,35 +1,47 @@
const table = {}
table.create = function (data, cols) {
- let output = '\n'
+ let output = '\r\n'
- output += ' \n '
+ output += ' \r\n '
for (let column of cols) {
- output += `${column} | `
+ output += `${column} | `
}
- output += '
\n \n'
+ output += '
\r\n \r\n'
- output += ' \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 += ' '
- if (i === 0) {
- const name = item.flag ? `${item.flag} ${item.name}` : item.name
- output += `${name} | `
- }
- output += `${item.channels} | `
- output += `${item.epg} | `
- output += `${item.status} | `
- output += '
\n'
- }
- }
- output += ' \n'
+ output += ' \r\n'
+ output += getHTMLRows(data)
+ output += ' \r\n'
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 += ' '
+ for (let [i, value] of row.entries()) {
+ if (i === 0 && j === 0) {
+ output += `${value} | `
+ } else if (i > 0) {
+ if (typeof value === 'number') {
+ output += `${value} | `
+ } else {
+ output += `${value} | `
+ }
+ }
+ }
+ output += '
\r\n'
+ }
+ }
+
+ return output
+}
+
+function getSpan() {}
+
module.exports = table
diff --git a/tests/__data__/expected/_readme.md b/tests/__data__/expected/_readme.md
index 79027d19..5afa948d 100644
--- a/tests/__data__/expected/_readme.md
+++ b/tests/__data__/expected/_readme.md
@@ -1,24 +1,24 @@
-# EPG
-
-EPG (Electronic Program Guide) for thousands of TV channels collected from different sources.
-
-## Usage
-
-To load a program guide, all you need to do is copy the link to one or more of the guides from the list below and paste it into your favorite player.
-
-
-
-
- Country | Channels | EPG | Status |
-
-
- 🇨🇦 Canada | 2 | https://iptv-org.github.io/epg/guides/ca-en/example.com.epg.xml |  |
- 1 | https://iptv-org.github.io/epg/guides/ca-ru/example.com.epg.xml |  |
-
-
-
-All guides also have a compressed and JSON version. To download them, simply change the extension from `.xml` to `.xml.gz` or `.json` respectively.
-
-## Contribution
-
-If you find a bug or want to contribute to the code or documentation, you can help by submitting an [issue](https://github.com/iptv-org/epg/issues) or a [pull request](https://github.com/iptv-org/epg/pulls).
+# EPG
+
+EPG (Electronic Program Guide) for thousands of TV channels collected from different sources.
+
+## Usage
+
+To load a program guide, all you need to do is copy the link to one or more of the guides from the list below and paste it into your favorite player.
+
+
+
+
+ Country | Channels | EPG |
+
+
+ 🇨🇦 Canada | 2 | https://iptv-org.github.io/epg/guides/ca-en/example.com.epg.xml |
+ 1 | https://iptv-org.github.io/epg/guides/ca-ru/example.com.epg.xml |
+
+
+
+All guides also have a compressed and JSON version. To download them, simply change the extension from `.xml` to `.xml.gz` or `.json` respectively.
+
+## Contribution
+
+If you find a bug or want to contribute to the code or documentation, you can help by submitting an [issue](https://github.com/iptv-org/epg/issues) or a [pull request](https://github.com/iptv-org/epg/pulls).
diff --git a/tests/__data__/expected/_status.md b/tests/__data__/expected/_status.md
new file mode 100644
index 00000000..25e8e613
--- /dev/null
+++ b/tests/__data__/expected/_status.md
@@ -0,0 +1,11 @@
+# Status
+
+
+
+
+ Site | Status |
+
+
+ example.com |  |
+
+
diff --git a/tests/__data__/input/readme.json b/tests/__data__/input/readme.json
index d226f0e6..fc3d3668 100644
--- a/tests/__data__/input/readme.json
+++ b/tests/__data__/input/readme.json
@@ -1,4 +1,4 @@
{
"build" : "tests/__data__/output/readme.md",
- "files" : ["./.readme/template.md"]
+ "files" : ["./.readme/readme.md"]
}
\ No newline at end of file
diff --git a/tests/__data__/input/status.json b/tests/__data__/input/status.json
new file mode 100644
index 00000000..02392960
--- /dev/null
+++ b/tests/__data__/input/status.json
@@ -0,0 +1,4 @@
+{
+ "build" : "tests/__data__/output/status.md",
+ "files" : ["./.readme/status.md"]
+}
\ No newline at end of file
diff --git a/tests/commands/status/update.test.js b/tests/commands/status/update.test.js
new file mode 100644
index 00000000..568869b8
--- /dev/null
+++ b/tests/commands/status/update.test.js
@@ -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)
+}