mirror of
https://github.com/iptv-org/iptv
synced 2026-11-01 06:44:15 -05:00
Merge pull request #55984 from iptv-org/patch-2026.10.1
Patch 2026.10.1
This commit is contained in:
14 files changed
+807
-466
No files matched your search
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"discussion": {
|
||||||
|
"number": 19956,
|
||||||
|
"body": "### Channel ID\n\nCNBCe.tr@SD",
|
||||||
|
"category": {
|
||||||
|
"name": "Channel Search"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
name: Validate Discussions
|
||||||
|
|
||||||
|
on:
|
||||||
|
discussion:
|
||||||
|
types: [created, edited]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
validate:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: github.event.discussion.category.name == 'Channel Search'
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository code
|
||||||
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||||
|
|
||||||
|
- uses: tibdex/github-app-token@0d49dd721133f900ebd5e0dff2810704e8defbc6 # v1.8.2
|
||||||
|
if: ${{ !env.ACT }}
|
||||||
|
id: create-app-token
|
||||||
|
with:
|
||||||
|
app_id: ${{ secrets.APP_ID }}
|
||||||
|
private_key: ${{ secrets.APP_PRIVATE_KEY }}
|
||||||
|
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
||||||
|
with:
|
||||||
|
node-version: 22
|
||||||
|
cache: 'npm'
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm ci
|
||||||
|
|
||||||
|
- name: Run discussion:validate
|
||||||
|
id: validator
|
||||||
|
continue-on-error: true
|
||||||
|
env:
|
||||||
|
RAW_BODY: ${{ github.event.discussion.body }}
|
||||||
|
DISC_NUMBER: ${{ github.event.discussion.number }}
|
||||||
|
GITHUB_TOKEN: ${{ steps.create-app-token.outputs.token || secrets.GITHUB_TOKEN }}
|
||||||
|
run: |
|
||||||
|
npm run discussion:validate -- \
|
||||||
|
--number "$DISC_NUMBER" \
|
||||||
|
--body "$RAW_BODY"
|
||||||
|
|
||||||
|
- name: Handle Discussion Result
|
||||||
|
if: always() && hashFiles('temp/logs/result.json') != ''
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ steps.create-app-token.outputs.token }}
|
||||||
|
DISC_NUMBER: ${{ github.event.discussion.number }}
|
||||||
|
run: |
|
||||||
|
COMMENT=$(jq -r '.comment // empty' temp/logs/result.json)
|
||||||
|
LABEL=$(jq -r '.label // empty' temp/logs/result.json)
|
||||||
|
|
||||||
|
if [ "${{ env.ACT }}" = "true" ]; then
|
||||||
|
echo "[MOCK] Comment: $COMMENT"
|
||||||
|
echo "[MOCK] Label: $LABEL"
|
||||||
|
else
|
||||||
|
if [ -n "$COMMENT" ] && [ "$COMMENT" != "null" ]; then
|
||||||
|
gh discussion comment $DISC_NUMBER --body "$COMMENT"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$LABEL" ] && [ "$LABEL" != "null" ]; then
|
||||||
|
gh discussion edit $DISC_NUMBER --add-label "$LABEL"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
@@ -7,9 +7,11 @@ For the scripts to work, you must have [Node.js](https://nodejs.org/en) installe
|
|||||||
- [act:check](#actcheck)
|
- [act:check](#actcheck)
|
||||||
- [act:format](#actformat)
|
- [act:format](#actformat)
|
||||||
- [act:update](#actupdate)
|
- [act:update](#actupdate)
|
||||||
|
- [act:validate_discussion](#actvalidate_discussion)
|
||||||
- [act:validate_issue](#actvalidate_issue)
|
- [act:validate_issue](#actvalidate_issue)
|
||||||
- [act:validate_label](#actvalidate_label)
|
- [act:validate_label](#actvalidate_label)
|
||||||
- [api:load](#apiload)
|
- [api:load](#apiload)
|
||||||
|
- [discussion:validate](#discussionvalidate)
|
||||||
- [issue:validate](#issuevalidate)
|
- [issue:validate](#issuevalidate)
|
||||||
- [playlist:format](#playlistformat)
|
- [playlist:format](#playlistformat)
|
||||||
- [playlist:update](#playlistupdate)
|
- [playlist:update](#playlistupdate)
|
||||||
@@ -48,6 +50,14 @@ Runs the [update](./workflows.md#update) workflow locally. Depends on [nektos/gh
|
|||||||
npm run act:update
|
npm run act:update
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## act:validate_discussion
|
||||||
|
|
||||||
|
Runs the [validate_discussion](./workflows.md#validate_discussion) workflow locally. Depends on [nektos/gh-act](https://github.com/nektos/gh-act).
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm run act:validate_discussion -- -e .github/mocks/events/discussion_opened.json -s GITHUB_TOKEN=github_pat_***
|
||||||
|
```
|
||||||
|
|
||||||
## act:validate_issue
|
## act:validate_issue
|
||||||
|
|
||||||
Runs the [validate_issue](./workflows.md#validate_issue) workflow locally. Depends on [nektos/gh-act](https://github.com/nektos/gh-act).
|
Runs the [validate_issue](./workflows.md#validate_issue) workflow locally. Depends on [nektos/gh-act](https://github.com/nektos/gh-act).
|
||||||
@@ -72,6 +82,14 @@ Downloads the latest channel and stream data from the [iptv-org/api](https://git
|
|||||||
npm run api:load
|
npm run api:load
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## discussion:validate
|
||||||
|
|
||||||
|
Checks the request for errors and saves the result to the file `temp/logs/result.json`
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm run discussion:validate --number=123 --body="### Stream URL..."
|
||||||
|
```
|
||||||
|
|
||||||
## issue:validate
|
## issue:validate
|
||||||
|
|
||||||
Checks the request for errors and, if any are found, saves a list of them to the file `temp/logs/errors.txt`
|
Checks the request for errors and, if any are found, saves a list of them to the file `temp/logs/errors.txt`
|
||||||
|
|||||||
@@ -16,6 +16,10 @@ Sequentially runs the `api:load`, `playlist:format`, `playlist:lint`, and `playl
|
|||||||
|
|
||||||
Runs every day at 0:00 UTC. It sequentially executes the `api:load`, `playlist:update`, `playlist:lint`, `playlist:validate`, `playlist:generate`, `playlist:export`, and `readme:update` scripts, then automatically deploys the updated files if successful.
|
Runs every day at 0:00 UTC. It sequentially executes the `api:load`, `playlist:update`, `playlist:lint`, `playlist:validate`, `playlist:generate`, `playlist:export`, and `readme:update` scripts, then automatically deploys the updated files if successful.
|
||||||
|
|
||||||
|
## validate_discussion
|
||||||
|
|
||||||
|
Runs when an discussion is opened or edited. It checks the requests for errors using `discussion:validate` script and, if any are found, the bot posts them in the comments.
|
||||||
|
|
||||||
## validate_issue
|
## validate_issue
|
||||||
|
|
||||||
Runs when an issue is opened or edited. It checks the requests for errors using `issue:validate` script and, if any are found, the bot posts them in the comments.
|
Runs when an issue is opened or edited. It checks the requests for errors using `issue:validate` script and, if any are found, the bot posts them in the comments.
|
||||||
|
|||||||
Generated
+423
-459
File diff suppressed because it is too large.
Load diff
@@ -4,10 +4,12 @@
|
|||||||
"act:check": "gh act pull_request -W .github/workflows/check.yml",
|
"act:check": "gh act pull_request -W .github/workflows/check.yml",
|
||||||
"act:format": "gh act workflow_dispatch -W .github/workflows/format.yml",
|
"act:format": "gh act workflow_dispatch -W .github/workflows/format.yml",
|
||||||
"act:update": "gh act workflow_dispatch -W .github/workflows/update.yml",
|
"act:update": "gh act workflow_dispatch -W .github/workflows/update.yml",
|
||||||
|
"act:validate_discussion": "gh act discussion -W .github/workflows/validate_discussion.yml",
|
||||||
"act:validate_issue": "gh act issues -W .github/workflows/validate_issue.yml",
|
"act:validate_issue": "gh act issues -W .github/workflows/validate_issue.yml",
|
||||||
"act:validate_label": "gh act issues -W .github/workflows/validate_label.yml",
|
"act:validate_label": "gh act issues -W .github/workflows/validate_label.yml",
|
||||||
"api:load": "tsx scripts/commands/api/load.ts",
|
"api:load": "tsx scripts/commands/api/load.ts",
|
||||||
"issue:validate": "tsx scripts/commands/issue/validate.ts",
|
"issue:validate": "tsx scripts/commands/issue/validate.ts",
|
||||||
|
"discussion:validate": "tsx scripts/commands/discussion/validate.ts",
|
||||||
"playlist:format": "tsx scripts/commands/playlist/format.ts",
|
"playlist:format": "tsx scripts/commands/playlist/format.ts",
|
||||||
"playlist:update": "tsx scripts/commands/playlist/update.ts",
|
"playlist:update": "tsx scripts/commands/playlist/update.ts",
|
||||||
"playlist:generate": "tsx scripts/commands/playlist/generate.ts",
|
"playlist:generate": "tsx scripts/commands/playlist/generate.ts",
|
||||||
|
|||||||
@@ -0,0 +1,130 @@
|
|||||||
|
import { LOGS_DIR, OWNER, REPO, STREAMS_DIR } from '../../constants'
|
||||||
|
import { loadData, data as apiData } from '../../api'
|
||||||
|
import { Logger } from '@freearhey/core'
|
||||||
|
import { Storage } from '@freearhey/storage-js'
|
||||||
|
import { PlaylistParser } from '../../core'
|
||||||
|
import { Discussion, Stream } from '../../models'
|
||||||
|
import { loadDiscussions, parseIssueBody } from '../../utils'
|
||||||
|
import { program } from 'commander'
|
||||||
|
|
||||||
|
program
|
||||||
|
.requiredOption('--number <number>', 'The discussion number')
|
||||||
|
.requiredOption('--body <body>', 'The full markdown body text of the discussion')
|
||||||
|
.parse(process.argv)
|
||||||
|
|
||||||
|
const { number: discussionNumberStr, body } = program.opts()
|
||||||
|
const targetDiscussionNumber = parseInt(discussionNumberStr, 10)
|
||||||
|
|
||||||
|
const logsStorage = new Storage(LOGS_DIR)
|
||||||
|
|
||||||
|
const status = {
|
||||||
|
OK: 'ok',
|
||||||
|
FULFILLED: 'fulfilled',
|
||||||
|
INVALID_CHANNEL_ID: 'invalid_channel_id',
|
||||||
|
MISSING_FEED_ID: 'missing_feed_id',
|
||||||
|
DUPLICATE_REQUEST: 'duplicate_request'
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
const logger = new Logger()
|
||||||
|
|
||||||
|
logger.info('loading discussions...')
|
||||||
|
const discussions = await loadDiscussions()
|
||||||
|
|
||||||
|
logger.info('loading data from api...')
|
||||||
|
await loadData()
|
||||||
|
|
||||||
|
logger.info('loading streams...')
|
||||||
|
const streamsStorage = new Storage(STREAMS_DIR)
|
||||||
|
const parser = new PlaylistParser({ storage: streamsStorage })
|
||||||
|
const files = await streamsStorage.list('**/*.m3u')
|
||||||
|
const streams = await parser.parse(files)
|
||||||
|
const streamsGroupedById = streams.groupBy((stream: Stream) => stream.getId())
|
||||||
|
|
||||||
|
const discussionData = parseIssueBody(body)
|
||||||
|
const streamId =
|
||||||
|
discussionData.getString('stream_id') ||
|
||||||
|
discussionData.getString('channel_id') ||
|
||||||
|
''
|
||||||
|
const [channelId, feedId] = streamId.split('@')
|
||||||
|
|
||||||
|
const priorDiscussions = discussions.filter(
|
||||||
|
(d: Discussion) => d.number < targetDiscussionNumber && d.category === 'Channel Search'
|
||||||
|
)
|
||||||
|
const seenStreamIds = new Set<string>()
|
||||||
|
let originalDiscussionNumber: number | null = null
|
||||||
|
|
||||||
|
priorDiscussions.forEach((d: Discussion) => {
|
||||||
|
const existingId = d.data.getString('stream_id') || d.data.getString('channel_id') || ''
|
||||||
|
if (existingId) {
|
||||||
|
seenStreamIds.add(existingId)
|
||||||
|
if (existingId === streamId && !originalDiscussionNumber) {
|
||||||
|
originalDiscussionNumber = d.number
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
let finalStatus = status.OK
|
||||||
|
if (!channelId || apiData.channelsKeyById.missing(channelId)) {
|
||||||
|
finalStatus = status.INVALID_CHANNEL_ID
|
||||||
|
} else if (!feedId) {
|
||||||
|
finalStatus = status.MISSING_FEED_ID
|
||||||
|
} else if (streamId && seenStreamIds.has(streamId)) {
|
||||||
|
finalStatus = status.DUPLICATE_REQUEST
|
||||||
|
} else if (streamsGroupedById.has(streamId)) {
|
||||||
|
finalStatus = status.FULFILLED
|
||||||
|
}
|
||||||
|
|
||||||
|
const repo = process.env.GITHUB_REPOSITORY || OWNER + '/' + REPO
|
||||||
|
const sha = process.env.GITHUB_SHA || 'master'
|
||||||
|
|
||||||
|
let comment = ''
|
||||||
|
let label = 'check:passed'
|
||||||
|
let close = 'false'
|
||||||
|
|
||||||
|
if (finalStatus === status.FULFILLED) {
|
||||||
|
for (const filePath of files) {
|
||||||
|
const content = await streamsStorage.load(filePath)
|
||||||
|
const lines = content.split(/\r?\n/)
|
||||||
|
const lineIndex = lines.findIndex(line => line.includes(streamId))
|
||||||
|
if (lineIndex !== -1) {
|
||||||
|
const permalink = `https://github.com/${repo}/blob/${sha}/streams/${filePath}#L${lineIndex + 1}-L${lineIndex + 2}`
|
||||||
|
comment = `A link to the "${streamId}" stream is already in the playlist: ${permalink}`
|
||||||
|
label = 'check:failed'
|
||||||
|
close = 'true'
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (finalStatus === status.DUPLICATE_REQUEST) {
|
||||||
|
comment = `Duplicate of #${originalDiscussionNumber}.`
|
||||||
|
label = 'check:failed'
|
||||||
|
close = 'true'
|
||||||
|
} else if (finalStatus === status.INVALID_CHANNEL_ID) {
|
||||||
|
comment = `There is no channel with the ID "${channelId}" in the database.`
|
||||||
|
label = 'check:failed'
|
||||||
|
close = 'true'
|
||||||
|
} else if (finalStatus === status.MISSING_FEED_ID) {
|
||||||
|
comment = 'The request is missing the feed ID.'
|
||||||
|
label = 'check:failed'
|
||||||
|
close = 'true'
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = {
|
||||||
|
number: targetDiscussionNumber,
|
||||||
|
streamId: streamId,
|
||||||
|
status: finalStatus,
|
||||||
|
label: label,
|
||||||
|
comment: comment,
|
||||||
|
close: close
|
||||||
|
}
|
||||||
|
|
||||||
|
logsStorage.saveSync('result.json', JSON.stringify(result, null, 2))
|
||||||
|
|
||||||
|
if (finalStatus !== status.FULFILLED) {
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
process.exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
main()
|
||||||
@@ -604,5 +604,13 @@
|
|||||||
"country": "BR",
|
"country": "BR",
|
||||||
"categories": [],
|
"categories": [],
|
||||||
"is_nsfw": false
|
"is_nsfw": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "CNBCe.tr",
|
||||||
|
"name": "CNBCe",
|
||||||
|
"network": null,
|
||||||
|
"country": "TR",
|
||||||
|
"categories": [],
|
||||||
|
"is_nsfw": false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -889,5 +889,21 @@
|
|||||||
"America/New_York"
|
"America/New_York"
|
||||||
],
|
],
|
||||||
"video_format": "576i"
|
"video_format": "576i"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"channel": "CNBCe.tr",
|
||||||
|
"id": "SD",
|
||||||
|
"name": "SD",
|
||||||
|
"is_main": true,
|
||||||
|
"broadcast_area": [
|
||||||
|
"c/TR"
|
||||||
|
],
|
||||||
|
"languages": [
|
||||||
|
"eng"
|
||||||
|
],
|
||||||
|
"timezones": [
|
||||||
|
"America/New_York"
|
||||||
|
],
|
||||||
|
"video_format": "576i"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
#EXTM3U
|
||||||
|
#EXTINF:-1 tvg-id="CNBCe.tr@SD",CNBCe
|
||||||
|
https://ythls.onrender.com/channel/UC40TUSUx490U5uR1lZt3Ajg.m3u8
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
module.exports = [
|
module.exports = [
|
||||||
{
|
{
|
||||||
number: 19956,
|
number: 19956,
|
||||||
body: '### Stream ID (required)\r\n\r\nCNBCe.tr\r\n\r\n### Notes\r\n\r\n_No response_',
|
body: '### Stream ID (required)\r\n\r\nCNBCe.tr@SD\r\n\r\n### Notes\r\n\r\n_No response_',
|
||||||
category: { name: 'Channel Search' }
|
category: { name: 'Channel Search' }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -9,6 +9,21 @@ module.exports = [
|
|||||||
body: '### Stream ID (required)\r\n\r\n13thStreet.au\r\n\r\n### Notes\r\n\r\nI need Disney Channel East Stream m3u Url please\r\n\r\n### Contributing Guide\r\n\r\n- [x] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md)',
|
body: '### Stream ID (required)\r\n\r\n13thStreet.au\r\n\r\n### Notes\r\n\r\nI need Disney Channel East Stream m3u Url please\r\n\r\n### Contributing Guide\r\n\r\n- [x] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md)',
|
||||||
category: { name: 'Channel Search' }
|
category: { name: 'Channel Search' }
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
number: 19958,
|
||||||
|
body: '### Stream ID (required)\r\n\r\nCNBCe.tr@SD\r\n\r\n### Notes\r\n\r\n_No response_',
|
||||||
|
category: { name: 'Channel Search' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
number: 19959,
|
||||||
|
body: '### Stream ID (required)\r\n\r\nCNBCe.com\r\n\r\n### Notes\r\n\r\n_No response_',
|
||||||
|
category: { name: 'Channel Search' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
number: 19960,
|
||||||
|
body: '### Stream ID (required)\r\n\r\nCNBCe.tr\r\n\r\n### Notes\r\n\r\n_No response_',
|
||||||
|
category: { name: 'Channel Search' }
|
||||||
|
},
|
||||||
{
|
{
|
||||||
number: 20956,
|
number: 20956,
|
||||||
body: '### Stream ID (required)\r\n\r\nIONTV.us\r\n\r\n### Notes\r\n\r\nI need it fast please thank you\r\n\r\n### Contributing Guide\r\n\r\n- [x] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md)',
|
body: '### Stream ID (required)\r\n\r\nIONTV.us\r\n\r\n### Notes\r\n\r\nI need it fast please thank you\r\n\r\n### Contributing Guide\r\n\r\n- [x] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md)',
|
||||||
|
|||||||
@@ -0,0 +1,104 @@
|
|||||||
|
import { describe, beforeEach, it, expect } from 'vitest'
|
||||||
|
import { pathToFileURL } from 'node:url'
|
||||||
|
import { execFileSync } from 'child_process'
|
||||||
|
import * as fs from 'fs-extra'
|
||||||
|
|
||||||
|
const ENV = {
|
||||||
|
...process.env,
|
||||||
|
DATA_DIR: 'tests/__data__/input/data',
|
||||||
|
STREAMS_DIR: 'tests/__data__/output/streams',
|
||||||
|
LOGS_DIR: 'tests/__data__/output/logs',
|
||||||
|
GITHUB_REPOSITORY: 'test-owner/test-repo',
|
||||||
|
GITHUB_SHA: 'main'
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fs.emptyDirSync('tests/__data__/output')
|
||||||
|
fs.copySync('tests/__data__/input/discussion_validate/streams', 'tests/__data__/output/streams')
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('discussion:validate', () => {
|
||||||
|
it('can handle fulfilled channel search request', () => {
|
||||||
|
const discussionNumber = 19956
|
||||||
|
const body = '### Channel ID\n\nCNBCe.tr@SD'
|
||||||
|
|
||||||
|
const stdout = runDiscussionValidate(discussionNumber, body)
|
||||||
|
if (process.env.DEBUG === 'true') console.log(stdout)
|
||||||
|
|
||||||
|
const result = readResultJson()
|
||||||
|
expect(result.status).toBe('fulfilled')
|
||||||
|
expect(result.label).toBe('check:failed')
|
||||||
|
expect(result.comment).toContain('https://github.com/test-owner/test-repo/blob/main/')
|
||||||
|
expect(result.close).toBe('true')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('can handle duplicate channel search request', () => {
|
||||||
|
const discussionNumber = 19958
|
||||||
|
const body = '### Channel ID\n\nCNBCe.tr@SD'
|
||||||
|
|
||||||
|
try {
|
||||||
|
runDiscussionValidate(discussionNumber, body)
|
||||||
|
throw new Error('Expected process to fail for duplicate request')
|
||||||
|
} catch {
|
||||||
|
const result = readResultJson()
|
||||||
|
expect(result.status).toBe('duplicate_request')
|
||||||
|
expect(result.label).toBe('check:failed')
|
||||||
|
expect(result.comment).toContain('Duplicate of #19956.')
|
||||||
|
expect(result.close).toBe('true')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('can handle invalid channel id request', () => {
|
||||||
|
const discussionNumber = 19959
|
||||||
|
const body = '### Channel ID\n\nCNBCe.com@SD'
|
||||||
|
|
||||||
|
try {
|
||||||
|
runDiscussionValidate(discussionNumber, body)
|
||||||
|
throw new Error('Expected process to fail for invalid channel ID')
|
||||||
|
} catch {
|
||||||
|
const result = readResultJson()
|
||||||
|
expect(result.status).toBe('invalid_channel_id')
|
||||||
|
expect(result.label).toBe('check:failed')
|
||||||
|
expect(result.comment).toContain('There is no channel with the ID "CNBCe.com" in the database.')
|
||||||
|
expect(result.close).toBe('true')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
it('can handle missing feed id request', () => {
|
||||||
|
const discussionNumber = 19960
|
||||||
|
const body = '### Channel ID\n\nCNBCe.tr'
|
||||||
|
|
||||||
|
try {
|
||||||
|
runDiscussionValidate(discussionNumber, body)
|
||||||
|
throw new Error('Expected process to fail for missing feed ID')
|
||||||
|
} catch {
|
||||||
|
const result = readResultJson()
|
||||||
|
expect(result.status).toBe('missing_feed_id')
|
||||||
|
expect(result.label).toBe('check:failed')
|
||||||
|
expect(result.comment).toContain('The request is missing the feed ID.')
|
||||||
|
expect(result.close).toBe('true')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
function runDiscussionValidate(number: number, body: string) {
|
||||||
|
return execFileSync(
|
||||||
|
process.execPath,
|
||||||
|
[
|
||||||
|
'--import',
|
||||||
|
'tsx',
|
||||||
|
'scripts/commands/discussion/validate.ts',
|
||||||
|
'--number',
|
||||||
|
`${number}`,
|
||||||
|
'--body',
|
||||||
|
body
|
||||||
|
],
|
||||||
|
{ encoding: 'utf8', env: ENV }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function readResultJson() {
|
||||||
|
const filepath = 'tests/__data__/output/logs/result.json'
|
||||||
|
const raw = fs.readFileSync(pathToFileURL(filepath), { encoding: 'utf8' })
|
||||||
|
return JSON.parse(raw)
|
||||||
|
}
|
||||||
@@ -134,7 +134,7 @@ describe('playlist:validate', () => {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (process.env.DEBUG === 'true') console.log(cmd, error)
|
if (process.env.DEBUG === 'true') console.log(cmd, error)
|
||||||
expect((error as ExecError).stdout).toContain(
|
expect((error as ExecError).stdout).toContain(
|
||||||
'log_level.m3u\n 2 error \"new: https://streamer2.nexgen.bz/07-CHANNEL7/index.m3u8\" is not a valid URL\n\n1 problems (1 errors, 0 warnings)\n'
|
'log_level.m3u\n 2 error "new: https://streamer2.nexgen.bz/07-CHANNEL7/index.m3u8" is not a valid URL\n\n1 problems (1 errors, 0 warnings)\n'
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -23,11 +23,13 @@ describe('report:create', () => {
|
|||||||
│ 4 │ 14179 │ 'streams:add' │ 'ManoramaNews.in' │ '(https://mitelefe.com/Api/Videos/GetSourceUrl/694564/0/HLS / https://ssl.cloud.telefe.com/Api/Vid...' │ 'invalid_stream_url' │
|
│ 4 │ 14179 │ 'streams:add' │ 'ManoramaNews.in' │ '(https://mitelefe.com/Api/Videos/GetSourceUrl/694564/0/HLS / https://ssl.cloud.telefe.com/Api/Vid...' │ 'invalid_stream_url' │
|
||||||
│ 5 │ 15175 │ 'streams:add' │ 'Channel7.bz@SD' │ 'new: https://streamer2.nexgen.bz/07-CHANNEL7/index.m3u8' │ 'invalid_stream_url' │
|
│ 5 │ 15175 │ 'streams:add' │ 'Channel7.bz@SD' │ 'new: https://streamer2.nexgen.bz/07-CHANNEL7/index.m3u8' │ 'invalid_stream_url' │
|
||||||
│ 6 │ 16120 │ 'streams:remove' │ undefined │ 'http://190.61.102.67:2000/play/a038/index.m3u8' │ 'nonexistent_link' │
|
│ 6 │ 16120 │ 'streams:remove' │ undefined │ 'http://190.61.102.67:2000/play/a038/index.m3u8' │ 'nonexistent_link' │
|
||||||
│ 7 │ 19956 │ 'channel search' │ 'CNBCe.tr' │ undefined │ 'invalid_channel_id' │
|
│ 7 │ 19957 │ 'channel search' │ '13thStreet.au' │ undefined │ 'channel_closed' │
|
||||||
│ 8 │ 19957 │ 'channel search' │ '13thStreet.au' │ undefined │ 'channel_closed' │
|
│ 8 │ 19958 │ 'channel search' │ 'CNBCe.tr@SD' │ undefined │ 'duplicate_request' │
|
||||||
│ 9 │ 20956 │ 'channel search' │ 'IONTV.us' │ undefined │ 'fulfilled' │
|
│ 9 │ 19959 │ 'channel search' │ 'CNBCe.com' │ undefined │ 'invalid_channel_id' │
|
||||||
│ 10 │ 25157 │ 'streams:add' │ 'OnTimeSports.eg@SD' │ 'OnTime Sports SD.mu38' │ 'invalid_stream_url' │
|
│ 10 │ 19960 │ 'channel search' │ 'CNBCe.tr' │ undefined │ 'duplicate_request' │
|
||||||
│ 11 │ 39097 │ 'streams:edit' │ '~' │ 'https://jmp2.uk/plu-5a74b8e1e22a61737979c6bf.m3u8' │ 'nonexistent_link' │
|
│ 11 │ 20956 │ 'channel search' │ 'IONTV.us' │ undefined │ 'fulfilled' │
|
||||||
|
│ 12 │ 25157 │ 'streams:add' │ 'OnTimeSports.eg@SD' │ 'OnTime Sports SD.mu38' │ 'invalid_stream_url' │
|
||||||
|
│ 13 │ 39097 │ 'streams:edit' │ '~' │ 'https://jmp2.uk/plu-5a74b8e1e22a61737979c6bf.m3u8' │ 'nonexistent_link' │
|
||||||
└─────────┴─────────────┴──────────────────┴─────────────────────────────┴────────────────────────────────────────────────────────────────────────────────────────────────────────┴──────────────────────┘`).trim()
|
└─────────┴─────────────┴──────────────────┴─────────────────────────────┴────────────────────────────────────────────────────────────────────────────────────────────────────────┴──────────────────────┘`).trim()
|
||||||
)
|
)
|
||||||
).toBe(true)
|
).toBe(true)
|
||||||
|
|||||||
Reference in new issue
Block a user