Merge pull request #2745 from iptv-org/patch-2025.04.1

Patch 2025.04.1
This commit is contained in:
PopeyeTheSai10r 2025-04-06 14:53:04 -07:00 committed by GitHub
commit 7e1fbcbe15
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
90 changed files with 4458 additions and 4210 deletions

View file

@ -0,0 +1,24 @@
name: ✨ Feature request
description: Ask for a feature to be added to the guide
labels: ['feature request']
body:
- type: markdown
attributes:
value: |
Please fill out the issue template as much as you can so we could efficiently process your request.
- type: input
attributes:
label: Site
description: The name of the site
placeholder: 'guidatv.sky.it'
validations:
required: true
- type: textarea
attributes:
label: Description
description: Detailed description of the feature.
validations:
required: true

View file

@ -1,8 +1,5 @@
blank_issues_enabled: true blank_issues_enabled: true
contact_links: contact_links:
- name: 💡 Feature request
url: https://github.com/orgs/iptv-org/discussions/categories/ideas
about: For any ideas or feature requests
- name: ❓ Ask a question - name: ❓ Ask a question
url: https://github.com/orgs/iptv-org/discussions/categories/q-a url: https://github.com/orgs/iptv-org/discussions/categories/q-a
about: Ask questions about this project about: Ask questions about this project

View file

@ -8,7 +8,11 @@
### How to add a channel to the guide? ### How to add a channel to the guide?
First, select a site from the [SITES.md](SITES.md) that you know has a guide for the channel you need. Then go to the folder with its config and open the file `*.channels.xml`. To ask for help with adding a channel simply fill out this [form](https://github.com/iptv-org/epg/issues/new?assignees=&labels=channel+request&projects=&template=2_channel-request.yml).
If you want to add a channel to the list yourself, here are the instructions on how to do it.
First select the site from [SITES.md](SITES.md) that you know has a guide for the channel you need. Then go to the folder with its config and open the file `*.channels.xml`.
Make sure that the desired channel is not already in the list. If it is not, simply add its description to the end of the list as shown here: Make sure that the desired channel is not already in the list. If it is not, simply add its description to the end of the list as shown here:
@ -20,43 +24,25 @@ Make sure that the desired channel is not already in the list. If it is not, sim
</channels> </channels>
``` ```
| Attribute | Description | Example | | Attribute | Description | Example |
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------- | | ------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | ------------- |
| SITE | Site domain name. | `example.com` | | SITE | Site domain name. | `example.com` |
| LANGUAGE_CODE | Language of the guide ([ISO 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) code). | `en` | | LANGUAGE_CODE | Language of the guide ([ISO 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) code). | `en` |
| CHANNEL_ID | Channel ID from [iptv-org/database](https://github.com/iptv-org/database). A complete list of supported channels can also be found at https://iptv-org.github.io/. | `BBCOne.uk` | | CHANNEL_ID | ID of the channel. Full list of supported channels with corresponding ID could be found on [iptv-org.github.io](https://iptv-org.github.io/). | `HBO.us@East` |
| SITE_ID | Unique ID of the channel used in the source. | `bbc1` | | SITE_ID | Unique ID of the channel used in the source. | `hbo` |
| CHANNEL_NAME | Name of the channel used in the source. | `BBC One` | | CHANNEL_NAME | Name of the channel used in the source. | `HBO East` |
After that just [commit](https://docs.github.com/en/pull-requests/committing-changes-to-your-project/creating-and-editing-commits/about-commits) all changes and send a [pull request](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests). After that just [commit](https://docs.github.com/en/pull-requests/committing-changes-to-your-project/creating-and-editing-commits/about-commits) all changes and send a [pull request](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests).
### How to map the channels? ### How to report broken guide?
In order for the guides to be linked with playlists from [iptv-org/iptv](https://github.com/iptv-org/iptv) and also with our other projects, each channel must have the same ID in the description as in our [iptv-org/database](https://github.com/iptv-org/database). If you start to get errors when downloading the guide or if nothing loads at all, please let us know via this [form](https://github.com/iptv-org/epg/issues/new?assignees=&labels=broken+guide&projects=&template=3_broken-guide.yml).
To check this, select one of the sites in the [SITES.md](SITES.md), open its `*.channels.xml` file and check that all channels have a valid `xmltv_id`. If it is missing somewhere, just copy the matching ID from the [iptv-org.github.io](https://iptv-org.github.io/). If the channel is not in our database yet, you can add it to it through this [form](https://github.com/iptv-org/database/issues/new?assignees=&labels=channels%3Aadd&projects=&template=__channels_add.yml&title=Add%3A+).
If the `*.channels.xml` file contains many channels without `xmltv_id`, you can speed up the process by running the command in the [Console](https://en.wikipedia.org/wiki/Windows_Console) (or [Terminal](<https://en.wikipedia.org/wiki/Terminal_(macOS)>) if you have macOS):
```sh
npm run channels:edit path/to/channels.xml
```
This way, you can map channels by simply selecting the proper ID from the list:
```sh
? Select xmltv_id for "BBC One" (bbc1): (Use arrow keys)
BBC One (BBC1, BBC Television, BBC Television Service) | BBCOne.uk
BBC One HD | BBCOneHD.uk
Type...
Skip
```
Once complete, [commit](https://docs.github.com/en/pull-requests/committing-changes-to-your-project/creating-and-editing-commits/about-commits) all changes and send a [pull request](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests).
### How to add a new source to the repository? ### How to add a new source to the repository?
To do this, you will need to create a new folder in the [/sites](/sites) directory with at least 4 files: If you are not familiar with javascript programming, you can ask for help from other community members through this [form](https://github.com/iptv-org/epg/issues/new?assignees=&labels=source+request&projects=&template=1_source-request.yml). Otherwise, below are the instructions for you.
To start with, you need to create a new folder in the [/sites](/sites) folder and put at least 4 files in it:
<details> <details>
<summary>example.com.config.js</summary> <summary>example.com.config.js</summary>
@ -70,9 +56,9 @@ module.exports = {
url({ channel, date }) { url({ channel, date }) {
return `https://example.com/api/${channel.site_id}/${date.format('YYYY-MM-DD')}` return `https://example.com/api/${channel.site_id}/${date.format('YYYY-MM-DD')}`
}, },
parser({ content }) { parser(context) {
try { try {
return JSON.parse(content) return JSON.parse(context.content)
} catch { } catch {
return [] return []
} }
@ -80,7 +66,189 @@ module.exports = {
} }
``` ```
More detailed instructions for this file can be found here: https://github.com/freearhey/epg-grabber#site-config ### Context Object
From each function in `config.js` you can access a `context` object containing the following data:
- `channel`: The object describing the current channel (xmltv_id, site_id, name, lang)
- `date`: The 'dayjs' instance with the requested date
- `content`: The response data as a String
- `buffer`: The response data as an ArrayBuffer
- `headers`: The response headers
- `request`: The request config
- `cached`: A boolean to check whether this request was cached or not
### Program Properties
List of properties that can be assigned to each program during parsing.
| Property | Aliases | Type | Required |
| --------------- | -------------------------------- | ------------------------------------------ | -------- |
| start | | `String \| Number \| Date()` | true |
| stop | | `String \| Number \| Date()` | true |
| title | titles | `String \| Object \| String[] \| Object[]` | true |
| subTitle | subTitles, sub_title, sub_titles | `String \| Object \| String[] \| Object[]` | false |
| description | desc, descriptions | `String \| Object \| String[] \| Object[]` | false |
| date | | `String \| Number \| Date()` | false |
| category | categories | `String \| Object \| String[] \| Object[]` | false |
| keyword | keywords | `String \| Object \| String[] \| Object[]` | false |
| language | languages | `String \| Object \| String[] \| Object[]` | false |
| origLanguage | origLanguages | `String \| Object \| String[] \| Object[]` | false |
| length | | `String \| Object \| String[] \| Object[]` | false |
| url | urls | `String \| Object \| String[] \| Object[]` | false |
| country | countries | `String \| Object \| String[] \| Object[]` | false |
| video | | `Object` | false |
| audio | | `Object` | false |
| season | | `String \| Number` | false |
| episode | | `String \| Number` | false |
| episodeNumber | episodeNum, episodeNumbers | `Object` | false |
| previouslyShown | | `String \| Object \| String[] \| Object[]` | false |
| premiere | | `String \| Object \| String[] \| Object[]` | false |
| lastChance | | `String \| Object \| String[] \| Object[]` | false |
| new | | `Boolean` | false |
| subtitles | | `Object \| Object[]` | false |
| rating | ratings | `String \| Object \| String[] \| Object[]` | false |
| starRating | starRatings | `String \| Object \| String[] \| Object[]` | false |
| review | reviews | `String \| Object \| String[] \| Object[]` | false |
| director | directors | `String \| Object \| String[] \| Object[]` | false |
| actor | actors | `String \| Object \| String[] \| Object[]` | false |
| writer | writers | `String \| Object \| String[] \| Object[]` | false |
| adapter | adapters | `String \| Object \| String[] \| Object[]` | false |
| producer | producers | `String \| Object \| String[] \| Object[]` | false |
| presenter | presenters | `String \| Object \| String[] \| Object[]` | false |
| composer | composers | `String \| Object \| String[] \| Object[]` | false |
| editor | editors | `String \| Object \| String[] \| Object[]` | false |
| commentator | commentators | `String \| Object \| String[] \| Object[]` | false |
| guest | guests | `String \| Object \| String[] \| Object[]` | false |
| image | images | `String \| Object \| String[] \| Object[]` | false |
| icon | icons | `String \| Object \| String[] \| Object[]` | false |
Example:
```js
{
start: '2021-03-19T06:00:00.000Z',
stop: '2021-03-19T06:30:00.000Z',
title: 'Program 1',
subTitle: 'Sub-title & 1',
description: 'Description for Program 1',
date: '2022-05-06',
categories: ['Comedy', 'Drama'],
keywords: [
{ lang: 'en', value: 'physical-comedy' },
{ lang: 'en', value: 'romantic' }
],
language: 'English',
origLanguage: { lang: 'en', value: 'French' },
length: { units: 'minutes', value: '60' },
url: 'http://example.com/title.html',
country: 'US',
video: {
present: 'yes',
colour: 'no',
aspect: '16:9',
quality: 'HDTV'
},
audio: {
present: 'yes',
stereo: 'Dolby Digital'
},
season: 9,
episode: 239,
previouslyShown: [{ start: '20080711000000', channel: 'channel-two.tv' }],
premiere: 'First time on British TV',
lastChance: [{ lang: 'en', value: 'Last time on this channel' }],
new: true,
subtitles: [
{ type: 'teletext', language: 'English' },
{ type: 'onscreen', language: [{ lang: 'en', value: 'Spanish' }] }
],
rating: {
system: 'MPAA',
value: 'P&G',
icon: 'http://example.com/pg_symbol.png'
},
starRatings: [
{
system: 'TV Guide',
value: '4/5',
icon: [{ src: 'stars.png', width: 100, height: 100 }]
},
{
system: 'IMDB',
value: '8/10'
}
],
reviews: [
{
type: 'text',
source: 'Rotten Tomatoes',
reviewer: 'Joe Bloggs',
lang: 'en',
value: 'This is a fantastic show!'
},
{
type: 'text',
source: 'IDMB',
reviewer: 'Jane Doe',
lang: 'en',
value: 'I love this show!'
},
{
type: 'url',
source: 'Rotten Tomatoes',
reviewer: 'Joe Bloggs',
lang: 'en',
value: 'https://example.com/programme_one_review'
}
],
directors: [
{
value: 'Director 1',
url: { value: 'http://example.com/director1.html', system: 'TestSystem' },
image: [
'https://example.com/image1.jpg',
{
value: 'https://example.com/image2.jpg',
type: 'person',
size: '2',
system: 'TestSystem',
orient: 'P'
}
]
},
'Director 2'
],
actors: ['Actor 1', 'Actor 2'],
writer: 'Writer 1',
producers: 'Roger Dobkowitz',
presenters: 'Drew Carey',
images: [
{
type: 'poster',
size: '1',
orient: 'P',
system: 'tvdb',
value: 'https://tvdb.com/programme_one_poster_1.jpg'
},
{
type: 'poster',
size: '2',
orient: 'P',
system: 'tmdb',
value: 'https://tmdb.com/programme_one_poster_2.jpg'
},
{
type: 'backdrop',
size: '3',
orient: 'L',
system: 'tvdb',
value: 'https://tvdb.com/programme_one_backdrop_3.jpg'
}
],
icon: 'https://example.com/images/Program1.png?x=шеллы&sid=777'
}
```
</details> </details>
@ -135,12 +303,6 @@ it('can handle empty guide', () => {
}) })
``` ```
To run all of these tests use the following command:
```sh
npm test --- example.com
```
Detailed documentation for the tests can be found here: https://jestjs.io/docs/using-matchers Detailed documentation for the tests can be found here: https://jestjs.io/docs/using-matchers
</details> </details>
@ -192,7 +354,51 @@ The fastest way to create all these files is to use the command:
npm run sites:init --- example.com npm run sites:init --- example.com
``` ```
Once you are done working on the config make sure the tests pass, the guide downloads correctly, [commit](https://docs.github.com/en/pull-requests/committing-changes-to-your-project/creating-and-editing-commits/about-commits) all changes and send us a [pull request](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests). After you finish working on the files you can make sure that everything works by running the config test:
```
npm test --- example.com
```
Then check that all channels have the correct `xmltv-id`:
```
npm run channels:validate sites/example.com/example.com.channels.xml
```
And then try downloading the guide itself:
```
npm run grab --- example.com
```
If everything goes well just [commit](https://docs.github.com/en/pull-requests/committing-changes-to-your-project/creating-and-editing-commits/about-commits) all changes and send us a [pull request](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests).
### How to map the channels?
In order for the guides to be linked with playlists from [iptv-org/iptv](https://github.com/iptv-org/iptv) and also with our other projects, each channel must have the same ID in the description as in our [iptv-org/database](https://github.com/iptv-org/database).
To check this, select one of the sites in the [SITES.md](SITES.md), open its `*.channels.xml` file and check that all channels have a valid `xmltv_id`. A list of all channels with corresponding IDs can be found at [iptv-org.github.io](https://iptv-org.github.io/).
If the channel is not in our database yet, you can add it to it through this [form](https://github.com/iptv-org/database/issues/new?assignees=&labels=channels%3Aadd&projects=&template=1_channels_add.yml&title=Add%3A+).
If the `*.channels.xml` file contains many channels without `xmltv_id`, you can speed up the process by running the command in the [Console](https://en.wikipedia.org/wiki/Windows_Console) (or [Terminal](<https://en.wikipedia.org/wiki/Terminal_(macOS)>) if you have macOS):
```sh
npm run channels:edit path/to/channels.xml
```
This way, you can map channels by simply selecting the proper ID from the list:
```sh
? Select xmltv_id for "BBC One" (bbc1): (Use arrow keys)
BBC One (BBC1, BBC Television, BBC Television Service) | BBCOne.uk
BBC One HD | BBCOneHD.uk
Type...
Skip
```
Once complete, [commit](https://docs.github.com/en/pull-requests/committing-changes-to-your-project/creating-and-editing-commits/about-commits) all changes and send a [pull request](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests).
## Project Structure ## Project Structure

View file

@ -146,10 +146,6 @@ And then update all the dependencies:
npm install npm install
``` ```
## Playlists
Playlists with already linked guides can be found in the [iptv-org/iptv](https://github.com/iptv-org/iptv) repository.
## Database ## Database
All channel data is taken from the [iptv-org/database](https://github.com/iptv-org/database) repository. If you find any errors please open a new [issue](https://github.com/iptv-org/database/issues) there. All channel data is taken from the [iptv-org/database](https://github.com/iptv-org/database) repository. If you find any errors please open a new [issue](https://github.com/iptv-org/database/issues) there.

1921
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -33,13 +33,16 @@
"<rootDir>/sites/**/*.test.(js|ts)", "<rootDir>/sites/**/*.test.(js|ts)",
"<rootDir>/tests/commands/**/*.test.(js|ts)" "<rootDir>/tests/commands/**/*.test.(js|ts)"
], ],
"testTimeout": 10000 "testTimeout": 10000,
"transformIgnorePatterns": [
"<rootDir>/node_modules/(?!parse-duration/.*)"
]
}, },
"dependencies": { "dependencies": {
"@alex_neo/jest-expect-message": "^1.0.5", "@alex_neo/jest-expect-message": "^1.0.5",
"@eslint/eslintrc": "^3.2.0", "@eslint/eslintrc": "^3.2.0",
"@eslint/js": "^9.17.0", "@eslint/js": "^9.17.0",
"@freearhey/core": "^0.5.1", "@freearhey/core": "^0.7.0",
"@ntlab/sfetch": "^1.2.0", "@ntlab/sfetch": "^1.2.0",
"@octokit/core": "^6.1.3", "@octokit/core": "^6.1.3",
"@octokit/plugin-paginate-rest": "^11.3.6", "@octokit/plugin-paginate-rest": "^11.3.6",
@ -76,7 +79,7 @@
"globals": "^15.14.0", "globals": "^15.14.0",
"husky": "^9.1.7", "husky": "^9.1.7",
"iconv-lite": "^0.4.24", "iconv-lite": "^0.4.24",
"inquirer": "^8.2.6", "inquirer": "^12.5.0",
"jest": "^29.7.0", "jest": "^29.7.0",
"jest-offline": "^1.0.1", "jest-offline": "^1.0.1",
"langs": "^2.0.0", "langs": "^2.0.0",
@ -89,7 +92,7 @@
"node-gzip": "^1.1.2", "node-gzip": "^1.1.2",
"numeral": "^2.0.6", "numeral": "^2.0.6",
"pako": "^2.1.0", "pako": "^2.1.0",
"parse-duration": "^1.0.0", "parse-duration": "^2.1.3",
"pdf-parse": "^1.1.1", "pdf-parse": "^1.1.1",
"pm2": "^5.4.3", "pm2": "^5.4.3",
"readline": "^1.3.0", "readline": "^1.3.0",

View file

@ -2,10 +2,11 @@ import { Logger, Storage, Collection } from '@freearhey/core'
import { ChannelsParser } from '../../core' import { ChannelsParser } from '../../core'
import path from 'path' import path from 'path'
import { SITES_DIR, API_DIR } from '../../constants' import { SITES_DIR, API_DIR } from '../../constants'
import { Channel } from 'epg-grabber' import epgGrabber from 'epg-grabber'
type OutputItem = { type OutputItem = {
channel: string | null channel: string | null
feed: string | null
site: string site: string
site_id: string site_id: string
site_name: string site_name: string
@ -31,9 +32,13 @@ async function main() {
logger.info(` found ${parsedChannels.count()} channel(s)`) logger.info(` found ${parsedChannels.count()} channel(s)`)
const output = parsedChannels.map((channel: Channel): OutputItem => { const output = parsedChannels.map((channel: epgGrabber.Channel): OutputItem => {
const xmltv_id = channel.xmltv_id || ''
const [channelId, feedId] = xmltv_id.split('@')
return { return {
channel: channel.xmltv_id || null, channel: channelId || null,
feed: feedId || null,
site: channel.site || '', site: channel.site || '',
site_id: channel.site_id || '', site_id: channel.site_id || '',
site_name: channel.name, site_name: channel.name,

View file

@ -7,6 +7,7 @@ async function main() {
const requests = [ const requests = [
client.download('channels.json'), client.download('channels.json'),
client.download('feeds.json'),
client.download('countries.json'), client.download('countries.json'),
client.download('regions.json'), client.download('regions.json'),
client.download('subdivisions.json') client.download('subdivisions.json')

View file

@ -1 +0,0 @@
/replace.ts

View file

@ -1,12 +1,16 @@
import { Storage, Collection, Logger, Dictionary } from '@freearhey/core'
import { select, input } from '@inquirer/prompts'
import { ChannelsParser, XML } from '../../core'
import { Channel, Feed } from '../../models'
import { DATA_DIR } from '../../constants' import { DATA_DIR } from '../../constants'
import { Storage, Collection, Logger } from '@freearhey/core'
import { ChannelsParser, XML, ApiChannel } from '../../core'
import { Channel } from 'epg-grabber'
import nodeCleanup from 'node-cleanup' import nodeCleanup from 'node-cleanup'
import { program } from 'commander' import epgGrabber from 'epg-grabber'
import inquirer, { QuestionCollection } from 'inquirer' import { Command } from 'commander'
import Fuse from 'fuse.js'
import readline from 'readline' import readline from 'readline'
import Fuse from 'fuse.js'
type ChoiceValue = { type: string; value?: Feed | Channel }
type Choice = { name: string; short?: string; value: ChoiceValue }
if (process.platform === 'win32') { if (process.platform === 'win32') {
readline readline
@ -19,105 +23,159 @@ if (process.platform === 'win32') {
}) })
} }
const program = new Command()
program.argument('<filepath>', 'Path to *.channels.xml file to edit').parse(process.argv) program.argument('<filepath>', 'Path to *.channels.xml file to edit').parse(process.argv)
const filepath = program.args[0] const filepath = program.args[0]
const logger = new Logger() const logger = new Logger()
const storage = new Storage() const storage = new Storage()
let channels = new Collection() let parsedChannels = new Collection()
async function main() { main(filepath)
nodeCleanup(() => {
save(filepath)
})
export default async function main(filepath: string) {
if (!(await storage.exists(filepath))) { if (!(await storage.exists(filepath))) {
throw new Error(`File "${filepath}" does not exists`) throw new Error(`File "${filepath}" does not exists`)
} }
const parser = new ChannelsParser({ storage }) const parser = new ChannelsParser({ storage })
channels = await parser.parse(filepath) parsedChannels = await parser.parse(filepath)
const dataStorage = new Storage(DATA_DIR) const dataStorage = new Storage(DATA_DIR)
const channelsContent = await dataStorage.json('channels.json') const channelsData = await dataStorage.json('channels.json')
const searchIndex = new Fuse(channelsContent, { keys: ['name', 'alt_names'], threshold: 0.4 }) const channels = new Collection(channelsData).map(data => new Channel(data))
const feedsData = await dataStorage.json('feeds.json')
const feeds = new Collection(feedsData).map(data => new Feed(data))
const feedsGroupedByChannelId = feeds.groupBy((feed: Feed) => feed.channelId)
for (const channel of channels.all()) { const searchIndex: Fuse<Channel> = new Fuse(channels.all(), {
keys: ['name', 'alt_names'],
threshold: 0.4
})
for (const channel of parsedChannels.all()) {
if (channel.xmltv_id) continue if (channel.xmltv_id) continue
const question: QuestionCollection = { try {
name: 'option', channel.xmltv_id = await selectChannel(channel, searchIndex, feedsGroupedByChannelId)
message: `Select xmltv_id for "${channel.name}" (${channel.site_id}):`, } catch {
type: 'list', break
choices: getOptions(searchIndex, channel),
pageSize: 10
} }
await inquirer.prompt(question).then(async selected => {
switch (selected.option) {
case 'Type...':
const input = await getInput(channel)
channel.xmltv_id = input.xmltv_id
break
case 'Skip':
channel.xmltv_id = '-'
break
default:
const [, xmltv_id] = selected.option
.replace(/ \[.*\]/, '')
.split('|')
.map((i: string) => i.trim())
channel.xmltv_id = xmltv_id
break
}
})
} }
channels.forEach((channel: Channel) => { parsedChannels.forEach((channel: epgGrabber.Channel) => {
if (channel.xmltv_id === '-') { if (channel.xmltv_id === '-') {
channel.xmltv_id = '' channel.xmltv_id = ''
} }
}) })
} }
main() async function selectChannel(
channel: epgGrabber.Channel,
searchIndex: Fuse<Channel>,
feedsGroupedByChannelId: Dictionary
): Promise<string> {
const similarChannels = searchIndex
.search(channel.name)
.map((result: { item: Channel }) => result.item)
function save() { const selected: ChoiceValue = await select({
message: `Select channel ID for "${channel.name}" (${channel.site_id}):`,
choices: getChannelChoises(new Collection(similarChannels)),
pageSize: 10
})
switch (selected.type) {
case 'skip':
return '-'
case 'type': {
const typedChannelId = await input({ message: ' Channel ID:' })
const typedFeedId = await input({ message: ' Feed ID:', default: 'SD' })
return [typedChannelId, typedFeedId].join('@')
}
case 'channel': {
const selectedChannel = selected.value
if (!selectedChannel) return ''
const selectedFeedId = await selectFeed(selectedChannel.id, feedsGroupedByChannelId)
return [selectedChannel.id, selectedFeedId].join('@')
}
}
return ''
}
async function selectFeed(channelId: string, feedsGroupedByChannelId: Dictionary): Promise<string> {
const channelFeeds = feedsGroupedByChannelId.get(channelId) || []
if (channelFeeds.length <= 1) return ''
const selected: ChoiceValue = await select({
message: `Select feed ID for "${channelId}":`,
choices: getFeedChoises(channelFeeds),
pageSize: 10
})
switch (selected.type) {
case 'type':
return await input({ message: ' Feed ID:' })
case 'feed':
const selectedFeed = selected.value
if (!selectedFeed) return ''
return selectedFeed.id
}
return ''
}
function getChannelChoises(channels: Collection): Choice[] {
const choises: Choice[] = []
channels.forEach((channel: Channel) => {
const names = [channel.name, ...channel.altNames.all()].join(', ')
choises.push({
value: {
type: 'channel',
value: channel
},
name: `${channel.id} (${names})`,
short: `${channel.id}`
})
})
choises.push({ name: 'Type...', value: { type: 'type' } })
choises.push({ name: 'Skip', value: { type: 'skip' } })
return choises
}
function getFeedChoises(feeds: Collection): Choice[] {
const choises: Choice[] = []
feeds.forEach((feed: Feed) => {
let name = `${feed.id} (${feed.name})`
if (feed.isMain) name += ' [main]'
choises.push({
value: {
type: 'feed',
value: feed
},
name,
short: feed.id
})
})
choises.push({ name: 'Type...', value: { type: 'type' } })
return choises
}
function save(filepath: string) {
if (!storage.existsSync(filepath)) return if (!storage.existsSync(filepath)) return
const xml = new XML(parsedChannels)
const xml = new XML(channels)
storage.saveSync(filepath, xml.toString()) storage.saveSync(filepath, xml.toString())
logger.info(`\nFile '${filepath}' successfully saved`) logger.info(`\nFile '${filepath}' successfully saved`)
} }
nodeCleanup(() => {
save()
})
async function getInput(channel: Channel) {
const name = channel.name.trim()
const input = await inquirer.prompt([
{
name: 'xmltv_id',
message: ' xmltv_id:',
type: 'input'
}
])
return { name, xmltv_id: input['xmltv_id'] }
}
function getOptions(index, channel: Channel) {
const similar = index.search(channel.name).map(result => new ApiChannel(result.item))
const variants = new Collection()
similar.forEach((_channel: ApiChannel) => {
const altNames = _channel.altNames.notEmpty() ? ` (${_channel.altNames.join(',')})` : ''
const closed = _channel.closed ? ` [closed:${_channel.closed}]` : ''
const replacedBy = _channel.replacedBy ? `[replaced_by:${_channel.replacedBy}]` : ''
variants.add(`${_channel.name}${altNames} | ${_channel.id}${closed}${replacedBy}`)
})
variants.add('Type...')
variants.add('Skip')
return variants.all()
}

View file

@ -1,10 +1,11 @@
import { Storage, Collection, Dictionary, File } from '@freearhey/core' import { Storage, Collection, Dictionary, File } from '@freearhey/core'
import { ChannelsParser, ApiChannel } from '../../core' import { ChannelsParser } from '../../core'
import { Channel } from '../../models'
import { program } from 'commander' import { program } from 'commander'
import chalk from 'chalk' import chalk from 'chalk'
import langs from 'langs' import langs from 'langs'
import { DATA_DIR } from '../../constants' import { DATA_DIR } from '../../constants'
import { Channel } from 'epg-grabber' import epgGrabber from 'epg-grabber'
program.argument('[filepath]', 'Path to *.channels.xml files to validate').parse(process.argv) program.argument('[filepath]', 'Path to *.channels.xml files to validate').parse(process.argv)
@ -21,8 +22,9 @@ async function main() {
const parser = new ChannelsParser({ storage: new Storage() }) const parser = new ChannelsParser({ storage: new Storage() })
const dataStorage = new Storage(DATA_DIR) const dataStorage = new Storage(DATA_DIR)
const channelsContent = await dataStorage.json('channels.json') const channelsData = await dataStorage.json('channels.json')
const channels = new Collection(channelsContent).map(data => new ApiChannel(data)) const channels = new Collection(channelsData).map(data => new Channel(data))
const channelsGroupedById = channels.groupBy((channel: Channel) => channel.id)
let totalFiles = 0 let totalFiles = 0
let totalErrors = 0 let totalErrors = 0
@ -37,7 +39,7 @@ async function main() {
const bufferBySiteId = new Dictionary() const bufferBySiteId = new Dictionary()
const errors: ValidationError[] = [] const errors: ValidationError[] = []
parsedChannels.forEach((channel: Channel) => { parsedChannels.forEach((channel: epgGrabber.Channel) => {
const bufferId: string = channel.site_id const bufferId: string = channel.site_id
if (bufferBySiteId.missing(bufferId)) { if (bufferBySiteId.missing(bufferId)) {
bufferBySiteId.set(bufferId, true) bufferBySiteId.set(bufferId, true)
@ -52,10 +54,8 @@ async function main() {
} }
if (!channel.xmltv_id) return if (!channel.xmltv_id) return
const [channelId] = channel.xmltv_id.split('@')
const foundChannel = channels.first( const foundChannel = channelsGroupedById.get(channelId)
(_channel: ApiChannel) => _channel.id === channel.xmltv_id
)
if (!foundChannel) { if (!foundChannel) {
errors.push({ type: 'wrong_xmltv_id', ...channel }) errors.push({ type: 'wrong_xmltv_id', ...channel })
totalErrors++ totalErrors++

View file

@ -1,8 +1,8 @@
import { Logger, Storage } from '@freearhey/core' import { Logger, Storage } from '@freearhey/core'
import { program } from 'commander'
import { SITES_DIR } from '../../constants' import { SITES_DIR } from '../../constants'
import fs from 'fs-extra'
import { pathToFileURL } from 'node:url' import { pathToFileURL } from 'node:url'
import { program } from 'commander'
import fs from 'fs-extra'
program.argument('<site>', 'Domain name of the site').parse(process.argv) program.argument('<site>', 'Domain name of the site').parse(process.argv)

View file

@ -1,8 +1,8 @@
import { Channel } from 'epg-grabber'
import { Logger, Storage, Collection } from '@freearhey/core'
import { IssueLoader, HTMLTable, ChannelsParser } from '../../core' import { IssueLoader, HTMLTable, ChannelsParser } from '../../core'
import { Issue, Site } from '../../models' import { Logger, Storage, Collection } from '@freearhey/core'
import { SITES_DIR, ROOT_DIR } from '../../constants' import { SITES_DIR, ROOT_DIR } from '../../constants'
import { Issue, Site } from '../../models'
import { Channel } from 'epg-grabber'
async function main() { async function main() {
const logger = new Logger({ disabled: true }) const logger = new Logger({ disabled: true })
@ -15,11 +15,17 @@ async function main() {
const folders = await sitesStorage.list('*/') const folders = await sitesStorage.list('*/')
logger.info('loading issues...') logger.info('loading issues...')
const issues = await loadIssues(loader) const issues = await loader.load()
logger.info('putting the data together...') logger.info('putting the data together...')
const brokenGuideReports = issues.filter(issue =>
issue.labels.find((label: string) => label === 'broken guide')
)
for (const domain of folders) { for (const domain of folders) {
const filteredIssues = issues.filter((issue: Issue) => domain === issue.data.get('site')) const filteredIssues = brokenGuideReports.filter(
(issue: Issue) => domain === issue.data.get('site')
)
const site = new Site({ const site = new Site({
domain, domain,
issues: filteredIssues issues: filteredIssues
@ -62,10 +68,3 @@ async function main() {
} }
main() main()
async function loadIssues(loader: IssueLoader) {
const issuesWithStatusWarning = await loader.load({ labels: ['broken guide', 'status:warning'] })
const issuesWithStatusDown = await loader.load({ labels: ['broken guide', 'status:down'] })
return issuesWithStatusWarning.concat(issuesWithStatusDown)
}

View file

@ -1,79 +0,0 @@
import { Collection } from '@freearhey/core'
type ApiChannelProps = {
id: string
name: string
alt_names: string[]
network: string
owners: string[]
country: string
subdivision: string
city: string
broadcast_area: string[]
languages: string[]
categories: string[]
is_nsfw: boolean
launched: string
closed: string
replaced_by: string
website: string
logo: string
}
export class ApiChannel {
id: string
name: string
altNames: Collection
network: string
owners: Collection
country: string
subdivision: string
city: string
broadcastArea: Collection
languages: Collection
categories: Collection
isNSFW: boolean
launched: string
closed: string
replacedBy: string
website: string
logo: string
constructor({
id,
name,
alt_names,
network,
owners,
country,
subdivision,
city,
broadcast_area,
languages,
categories,
is_nsfw,
launched,
closed,
replaced_by,
website,
logo
}: ApiChannelProps) {
this.id = id
this.name = name
this.altNames = new Collection(alt_names)
this.network = network
this.owners = new Collection(owners)
this.country = country
this.subdivision = subdivision
this.city = city
this.broadcastArea = new Collection(broadcast_area)
this.languages = new Collection(languages)
this.categories = new Collection(categories)
this.isNSFW = is_nsfw
this.launched = launched
this.closed = closed
this.replacedBy = replaced_by
this.website = website
this.logo = logo
}
}

View file

@ -7,7 +7,6 @@ export * from './job'
export * from './queue' export * from './queue'
export * from './guideManager' export * from './guideManager'
export * from './guide' export * from './guide'
export * from './apiChannel'
export * from './apiClient' export * from './apiClient'
export * from './queueCreator' export * from './queueCreator'
export * from './issueLoader' export * from './issueLoader'

View file

@ -1,27 +1,22 @@
import { Collection } from '@freearhey/core'
import { restEndpointMethods } from '@octokit/plugin-rest-endpoint-methods' import { restEndpointMethods } from '@octokit/plugin-rest-endpoint-methods'
import { paginateRest } from '@octokit/plugin-paginate-rest' import { paginateRest } from '@octokit/plugin-paginate-rest'
import { TESTING, OWNER, REPO } from '../constants'
import { Collection } from '@freearhey/core'
import { Octokit } from '@octokit/core' import { Octokit } from '@octokit/core'
import { IssueParser } from './' import { IssueParser } from './'
import { TESTING, OWNER, REPO } from '../constants'
const CustomOctokit = Octokit.plugin(paginateRest, restEndpointMethods) const CustomOctokit = Octokit.plugin(paginateRest, restEndpointMethods)
const octokit = new CustomOctokit() const octokit = new CustomOctokit()
export class IssueLoader { export class IssueLoader {
async load({ labels }: { labels: string[] | string }) { async load(props?: { labels: string[] | string }) {
labels = Array.isArray(labels) ? labels.join(',') : labels let labels = ''
if (props && props.labels) {
labels = Array.isArray(props.labels) ? props.labels.join(',') : props.labels
}
let issues: object[] = [] let issues: object[] = []
if (TESTING) { if (TESTING) {
switch (labels) { issues = (await import('../../tests/__data__/input/sites_update/issues.mjs')).default
case 'broken guide,status:warning':
issues = (await import('../../tests/__data__/input/issues/broken_guide_warning.mjs'))
.default
break
case 'broken guide,status:down':
issues = (await import('../../tests/__data__/input/issues/broken_guide_down.mjs')).default
break
}
} else { } else {
issues = await octokit.paginate(octokit.rest.issues.listForRepo, { issues = await octokit.paginate(octokit.rest.issues.listForRepo, {
owner: OWNER, owner: OWNER,

View file

@ -1,9 +1,10 @@
import { Storage, Collection, DateTime, Logger } from '@freearhey/core' import { Storage, Collection, DateTime, Logger } from '@freearhey/core'
import { ChannelsParser, ConfigLoader, ApiChannel, Queue } from './' import { ChannelsParser, ConfigLoader, Queue } from './'
import { SITES_DIR, DATA_DIR } from '../constants' import { SITES_DIR, DATA_DIR } from '../constants'
import { SiteConfig } from 'epg-grabber' import { SiteConfig } from 'epg-grabber'
import path from 'path' import path from 'path'
import { GrabOptions } from '../commands/epg/grab' import { GrabOptions } from '../commands/epg/grab'
import { Channel } from '../models'
type QueueCreatorProps = { type QueueCreatorProps = {
logger: Logger logger: Logger
@ -32,7 +33,7 @@ export class QueueCreator {
async create(): Promise<Queue> { async create(): Promise<Queue> {
const channelsContent = await this.dataStorage.json('channels.json') const channelsContent = await this.dataStorage.json('channels.json')
const channels = new Collection(channelsContent).map(data => new ApiChannel(data)) const channels = new Collection(channelsContent).map(data => new Channel(data))
const queue = new Queue() const queue = new Queue()
for (const channel of this.parsedChannels.all()) { for (const channel of this.parsedChannels.all()) {
@ -44,8 +45,8 @@ export class QueueCreator {
if (channel.xmltv_id) { if (channel.xmltv_id) {
if (!channel.icon) { if (!channel.icon) {
const found: ApiChannel = channels.first( const found: Channel = channels.first(
(_channel: ApiChannel) => _channel.id === channel.xmltv_id (_channel: Channel) => _channel.id === channel.xmltv_id
) )
if (found) { if (found) {

56
scripts/models/channel.ts Normal file
View file

@ -0,0 +1,56 @@
import { Collection } from '@freearhey/core'
type ChannelData = {
id: string
name: string
alt_names: string[]
network: string
owners: Collection
country: string
subdivision: string
city: string
categories: Collection
is_nsfw: boolean
launched: string
closed: string
replaced_by: string
website: string
logo: string
}
export class Channel {
id: string
name: string
altNames: Collection
network?: string
owners: Collection
countryCode: string
subdivisionCode?: string
cityName?: string
categoryIds: Collection
categories?: Collection
isNSFW: boolean
launched?: string
closed?: string
replacedBy?: string
website?: string
logo: string
constructor(data: ChannelData) {
this.id = data.id
this.name = data.name
this.altNames = new Collection(data.alt_names)
this.network = data.network || undefined
this.owners = new Collection(data.owners)
this.countryCode = data.country
this.subdivisionCode = data.subdivision || undefined
this.cityName = data.city || undefined
this.categoryIds = new Collection(data.categories)
this.isNSFW = data.is_nsfw
this.launched = data.launched || undefined
this.closed = data.closed || undefined
this.replacedBy = data.replaced_by || undefined
this.website = data.website || undefined
this.logo = data.logo
}
}

34
scripts/models/feed.ts Normal file
View file

@ -0,0 +1,34 @@
import { Collection } from '@freearhey/core'
type FeedData = {
channel: string
id: string
name: string
is_main: boolean
broadcast_area: Collection
languages: Collection
timezones: Collection
video_format: string
}
export class Feed {
channelId: string
id: string
name: string
isMain: boolean
broadcastAreaCodes: Collection
languageCodes: Collection
timezoneIds: Collection
videoFormat: string
constructor(data: FeedData) {
this.channelId = data.channel
this.id = data.id
this.name = data.name
this.isMain = data.is_main
this.broadcastAreaCodes = new Collection(data.broadcast_area)
this.languageCodes = new Collection(data.languages)
this.timezoneIds = new Collection(data.timezones)
this.videoFormat = data.video_format
}
}

View file

@ -1,2 +1,4 @@
export * from './issue' export * from './issue'
export * from './site' export * from './site'
export * from './channel'
export * from './feed'

View file

@ -1,6 +1,6 @@
# <DOMAIN> # <DOMAIN>
https://example.com https://<DOMAIN>
### Download the guide ### Download the guide

View file

@ -1,7 +1,7 @@
const axios = require('axios') const axios = require('axios')
const dayjs = require('dayjs') const dayjs = require('dayjs')
const utc = require('dayjs/plugin/utc') const utc = require('dayjs/plugin/utc')
const parseDuration = require('parse-duration') const parseDuration = require('parse-duration').default
dayjs.extend(utc) dayjs.extend(utc)

View file

@ -1,4 +1,4 @@
const durationParser = require('parse-duration') const durationParser = require('parse-duration').default
const cheerio = require('cheerio') const cheerio = require('cheerio')
const srcset = require('srcset') const srcset = require('srcset')
const dayjs = require('dayjs') const dayjs = require('dayjs')

View file

@ -0,0 +1 @@
[{"channel":"Channel1.us","feed":"SD","site":"example.com","site_id":"140","site_name":"Channel 1","lang":"en"},{"channel":"Channel2.us","feed":null,"site":"example.com","site_id":"142","site_name":"Channel 2","lang":"en"},{"channel":"Channel1.us","feed":"HD","site":"example.com","site_id":"140","site_name":"Channel 1","lang":"fr"},{"channel":"Channel3.us","feed":"HD","site":"example2.com","site_id":"150","site_name":"Channel 3","lang":"en"},{"channel":"Channel4.us","feed":null,"site":"example2.com","site_id":"152","site_name":"Channel 4","lang":"en"},{"channel":"Channel1.us","feed":null,"site":"example2.com","site_id":"140","site_name":"Channel 1","lang":"fr"}]

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<channels>
<channel site="example.com" lang="" xmltv_id="CNNInternational.us@Europe" site_id="140">CNN International</channel>
</channels>

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<channels>
<channel site="example.com" lang="en" xmltv_id="" site_id="240">BBC World News</channel>
<channel site="example.com" lang="en" xmltv_id="CNNInternational.us@Europe" site_id="140">CNN International</channel>
</channels>

View file

@ -1 +0,0 @@
[{"channel":"Channel1.us","site":"example.com","site_id":"140","site_name":"Channel 1","lang":"en"},{"channel":"Channel2.us","site":"example.com","site_id":"142","site_name":"Channel 2","lang":"en"},{"channel":"Channel1.us","site":"example.com","site_id":"140","site_name":"Channel 1","lang":"fr"},{"channel":"Channel3.us","site":"example2.com","site_id":"150","site_name":"Channel 3","lang":"en"},{"channel":"Channel4.us","site":"example2.com","site_id":"152","site_name":"Channel 4","lang":"en"},{"channel":"Channel1.us","site":"example2.com","site_id":"140","site_name":"Channel 1","lang":"fr"}]

View file

@ -1,4 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<channels>
<channel site="example.com" lang="" xmltv_id="" site_id="140">CNN International</channel>
</channels>

View file

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<channels>
<channel site="parse-channels.com" lang="en" xmltv_id="" site_id="140">CNN International</channel>
<channel site="parse-channels.com" lang="en" xmltv_id="" site_id="240">BBC World News</channel>
</channels>

View file

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<channels>
<channel site="parse-channels.com" lang="en" xmltv_id="" site_id="240">BBC World News</channel>
<channel site="parse-channels.com" lang="en" xmltv_id="CNNInternational.us" site_id="140">CNN International</channel>
</channels>

View file

@ -1,34 +1,36 @@
[ [
{ {
"id": "BravoEast.us", "id": "Bravo.us",
"name": "Bravo East", "name": "Bravo",
"network": null,
"country": "US",
"subdivision": null,
"city": null,
"categories": [],
"is_nsfw": false,
"closed": "2020-01-01",
"replaced_by": "R6.co",
"logo": "https://www.directv.com/images/logos/channels/dark/large/579.png"
},
{
"id": "Bravos.us",
"name": "Bravos",
"network": null, "network": null,
"country": "US", "country": "US",
"subdivision": null, "subdivision": null,
"city": null, "city": null,
"broadcast_area": [
"c/US"
],
"languages": [
"eng"
],
"categories": [], "categories": [],
"is_nsfw": false, "is_nsfw": false,
"logo": "https://www.directv.com/images/logos/channels/dark/large/579.png" "logo": "https://www.directv.com/images/logos/channels/dark/large/579.png"
}, },
{ {
"id": "CNNInternationalEurope.us", "id": "CNNInternational.us",
"name": "CNN International Europe", "name": "CNN International",
"alt_names": ["CNN", "CNN Int"],
"network": null, "network": null,
"country": "US", "country": "US",
"subdivision": null, "subdivision": null,
"city": null, "city": null,
"broadcast_area": [
"r/EUR"
],
"languages": [
"eng"
],
"categories": [ "categories": [
"news" "news"
], ],
@ -42,12 +44,6 @@
"country": "ZA", "country": "ZA",
"subdivision": null, "subdivision": null,
"city": null, "city": null,
"broadcast_area": [
"c/ZA"
],
"languages": [
"afr"
],
"categories": [], "categories": [],
"is_nsfw": false, "is_nsfw": false,
"logo": "https://rndcdn.dstv.com/dstvcms/2020/08/31/M-Net_Movies_2_Logo_4-3_lightbackground_xlrg.png" "logo": "https://rndcdn.dstv.com/dstvcms/2020/08/31/M-Net_Movies_2_Logo_4-3_lightbackground_xlrg.png"
@ -61,12 +57,6 @@
"country": "US", "country": "US",
"subdivision": null, "subdivision": null,
"city": null, "city": null,
"broadcast_area": [
"c/US"
],
"languages": [
"eng"
],
"categories": [], "categories": [],
"is_nsfw": false, "is_nsfw": false,
"logo": "https://www.directv.com/images/logos/channels/dark/large/579.png" "logo": "https://www.directv.com/images/logos/channels/dark/large/579.png"

View file

@ -0,0 +1,30 @@
[
{
"channel": "CNNInternational.us",
"id": "SD",
"name": "SD",
"is_main": true,
"broadcast_area": [
"r/INT"
],
"timezones": [
"America/New_York"
],
"languages": [],
"video_format": "480i"
},
{
"channel": "CNNInternational.us",
"id": "Europe",
"name": "Europe",
"is_main": false,
"broadcast_area": [
"r/EUR"
],
"timezones": [
"America/New_York"
],
"languages": [],
"video_format": "480i"
}
]

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<channels site="example.com">
<channel lang="en" xmltv_id="Channel1.us@SD" site_id="140">Channel 1</channel>
<channel lang="en" xmltv_id="Channel2.us" site_id="142" logo="https://i.imgur.com/qmRnD0M.png">Channel 2</channel>
<channel lang="fr" xmltv_id="Channel1.us@HD" site_id="140">Channel 1</channel>
</channels>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<channels site="example2.com">
<channel lang="en" xmltv_id="Channel3.us@HD" site_id="150">Channel 3</channel>
<channel lang="en" xmltv_id="Channel4.us" site_id="152">Channel 4</channel>
<channel lang="fr" xmltv_id="Channel1.us" site_id="140">Channel 1</channel>
</channels>

View file

@ -1,4 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<channels site="example.com">
<channel lang="" xmltv_id="" site_id="140">CNN International</channel>
</channels>

View file

@ -1,4 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<channels>
<channel site="lint.com" xmltv_id="CNNInternationalEurope.us" site_id="140">CNN International</channel>
</channels>

View file

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<channels site="lint.com">
<channel lang="en" xmltv_id="BravoEast.us" site_id="140">Bravo</channel>
</channels>

View file

@ -1,4 +0,0 @@
<?xml version='1.0' encoding="UTF-8"?>
<channels>
<channel site="singlequotes.com" lang="en" xmltv_id="" site_id="140">Bravo 2</channel>
</channels>

View file

@ -1,4 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<channels>
<channel site="valid.com" lang="en" xmltv_id="BravoEast.us" site_id="140#Tes't">Bravo's</channel>
</channels>

View file

@ -1,4 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<channels site="parse-channels.com">
<channel lang="en" xmltv_id="CNNInternational.us" site_id="140">CNN International</channel>
</channels>

View file

@ -1,4 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<channels site="wrong_xmltv_id.com">
<channel lang="en" xmltv_id="CNNInternational" site_id="140">CNN International</channel>
</channels>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<channels>
<channel site="example.com" lang="" xmltv_id="" site_id="140">CNN International</channel>
<channel site="example.com" lang="" xmltv_id="" site_id="141">CNN International</channel>
<channel site="example.com" lang="" xmltv_id="" site_id="142">Bravo</channel>
</channels>

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<channels>
<channel site="example.com" xmltv_id="CNNInternational.us@Europe" site_id="140">CNN International</channel>
</channels>

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<channels site="example.com">
<channel lang="en" xmltv_id="Bravo.us@East" site_id="140">Bravo</channel>
</channels>

View file

@ -0,0 +1,4 @@
<?xml version='1.0' encoding="UTF-8"?>
<channels>
<channel site="example.com" lang="en" xmltv_id="" site_id="140">Bravo 2</channel>
</channels>

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<channels>
<channel site="example.com" lang="en" xmltv_id="Bravo.us@East" site_id="140#Tes't">Bravo's</channel>
</channels>

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<channels site="example.com">
<channel lang="en" xmltv_id="CNNInternational.us@Europe" site_id="140">CNN International</channel>
</channels>

View file

@ -1,6 +1,6 @@
module.exports = { module.exports = {
site: 'parse-channels.com', site: 'example.com',
url: 'https://parse-channels.com', url: 'https://example.com',
parser() { parser() {
return [] return []
}, },

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<channels site="duplicate.com"> <channels site="example.com">
<channel lang="en" xmltv_id="" site_id="140">Bravo 2</channel> <channel lang="en" xmltv_id="" site_id="140">Bravo 2</channel>
<channel lang="en" xmltv_id="BravoEast.us" site_id="140">Bravo</channel> <channel lang="en" xmltv_id="Bravo.us@East" site_id="140">Bravo</channel>
</channels> </channels>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<channels site="example.com">
<channel lang="en" xmltv_id="CNNInternational" site_id="140">CNN International</channel>
<channel lang="en" xmltv_id="Bravo.us@East" site_id="150">Bravo</channel>
<channel lang="en" xmltv_id="Bravo.us@West" site_id="151">Bravo</channel>
</channels>

View file

@ -1,974 +0,0 @@
export default [
{
url: 'https://api.github.com/repos/iptv-org/epg/issues/2543',
repository_url: 'https://api.github.com/repos/iptv-org/epg',
labels_url: 'https://api.github.com/repos/iptv-org/epg/issues/2543/labels{/name}',
comments_url: 'https://api.github.com/repos/iptv-org/epg/issues/2543/comments',
events_url: 'https://api.github.com/repos/iptv-org/epg/issues/2543/events',
html_url: 'https://github.com/iptv-org/epg/issues/2543',
id: 2759693796,
node_id: 'I_kwDOFLVvtM6kfZXk',
number: 2543,
title: 'flixed.io is downloding old programming',
user: {
login: 'SiWafer',
id: 10903014,
node_id: 'MDQ6VXNlcjEwOTAzMDE0',
avatar_url: 'https://avatars.githubusercontent.com/u/10903014?v=4',
gravatar_id: '',
url: 'https://api.github.com/users/SiWafer',
html_url: 'https://github.com/SiWafer',
followers_url: 'https://api.github.com/users/SiWafer/followers',
following_url: 'https://api.github.com/users/SiWafer/following{/other_user}',
gists_url: 'https://api.github.com/users/SiWafer/gists{/gist_id}',
starred_url: 'https://api.github.com/users/SiWafer/starred{/owner}{/repo}',
subscriptions_url: 'https://api.github.com/users/SiWafer/subscriptions',
organizations_url: 'https://api.github.com/users/SiWafer/orgs',
repos_url: 'https://api.github.com/users/SiWafer/repos',
events_url: 'https://api.github.com/users/SiWafer/events{/privacy}',
received_events_url: 'https://api.github.com/users/SiWafer/received_events',
type: 'User',
user_view_type: 'public',
site_admin: false
},
labels: [
{
id: 4542348869,
node_id: 'LA_kwDOFLVvtM8AAAABDr6-RQ',
url: 'https://api.github.com/repos/iptv-org/epg/labels/broken%20guide',
name: 'broken guide',
color: 'eaeaea',
default: false,
description: "There's a problem with the guide"
},
{
id: 7932710318,
node_id: 'LA_kwDOFLVvtM8AAAAB2NONrg',
url: 'https://api.github.com/repos/iptv-org/epg/labels/status:warning',
name: 'status:warning',
color: 'fbca06',
default: false,
description: 'The guide downloads, but contains errors'
}
],
state: 'open',
locked: false,
assignee: null,
assignees: [],
milestone: null,
comments: 0,
created_at: '2024-12-26T12:09:43Z',
updated_at: '2024-12-27T05:29:58Z',
closed_at: null,
author_association: 'NONE',
active_lock_reason: null,
body: '### Describe your issue\r\n\r\nJust ran and updated, and seems the output is loading old programming and it also is not complete\r\n\r\nExample is Bravo channel\r\n\r\n```\r\nepg@rpi:~/epg$ npm run grab --- --site=flixed.io --maxConnections=10 -o "flixed.xml"\r\n\r\n> grab\r\n> npx tsx scripts/commands/epg/grab.ts --site=flixed.io --maxConnections=10 -o flixed.xml\r\n\r\nstarting...\r\nconfig:\r\n output: flixed.xml\r\n maxConnections: 10\r\n gzip: false\r\n site: flixed.io\r\nloading channels...\r\n found 94 channel(s)\r\nrun #1:\r\n [1/94] flixed.io (en) - BravoEast.us - Dec 26, 2024 (2 programs)\r\n [2/94] flixed.io (en) - ComedyCentralEast.us - Dec 26, 2024 (5 programs)\r\n [3/94] flixed.io (en) - ACCNetwork.us - Dec 26, 2024 (26 programs)\r\n [4/94] flixed.io (en) - CNN.us - Dec 26, 2024 (25 programs)\r\n [5/94] flixed.io (en) - BloombergTV.us - Dec 26, 2024 (21 programs)\r\n [6/94] flixed.io (en) - AEEast.us - Dec 26, 2024 (6 programs)\r\n [7/94] flixed.io (en) - CNBC.us - Dec 26, 2024 (3 programs)\r\n [8/94] flixed.io (en) - CinemaxEast.us - Dec 26, 2024 (14 programs)\r\n [9/94] flixed.io (en) - AMCEast.us - Dec 26, 2024 (19 programs)\r\n [10/94] flixed.io (en) - BigTenNetwork.us - Dec 26, 2024 (3 programs)\r\n [11/94] flixed.io (en) - FoxWest.us - Dec 26, 2024 (8 programs)\r\n [12/94] flixed.io (en) - FreeformEast.us - Dec 26, 2024 (2 programs)\r\n [13/94] flixed.io (en) - FoxSports2.us - Dec 26, 2024 (2 programs)\r\n [14/94] flixed.io (en) - FoodNetworkEast.us - Dec 26, 2024 (3 programs)\r\n...\r\n...\r\n...\r\n\r\n```\r\nSnip from xml file out\r\n![image](https://github.com/user-attachments/assets/5ed6d7eb-df59-4951-9b2c-5214e24d24ac)\r\n\r\nThe date is September 26, 2024, 01:00:00 for Bravo\r\n\r\n',
closed_by: null,
reactions: {
url: 'https://api.github.com/repos/iptv-org/epg/issues/2543/reactions',
total_count: 0,
'+1': 0,
'-1': 0,
laugh: 0,
hooray: 0,
confused: 0,
heart: 0,
rocket: 0,
eyes: 0
},
timeline_url: 'https://api.github.com/repos/iptv-org/epg/issues/2543/timeline',
performed_via_github_app: null,
state_reason: null
},
{
url: 'https://api.github.com/repos/iptv-org/epg/issues/2516',
repository_url: 'https://api.github.com/repos/iptv-org/epg',
labels_url: 'https://api.github.com/repos/iptv-org/epg/issues/2516/labels{/name}',
comments_url: 'https://api.github.com/repos/iptv-org/epg/issues/2516/comments',
events_url: 'https://api.github.com/repos/iptv-org/epg/issues/2516/events',
html_url: 'https://github.com/iptv-org/epg/issues/2516',
id: 2745387354,
node_id: 'I_kwDOFLVvtM6jo0la',
number: 2516,
title: 'Duplicate programmes with sky.com grab',
user: {
login: 'misar1',
id: 69795879,
node_id: 'MDQ6VXNlcjY5Nzk1ODc5',
avatar_url: 'https://avatars.githubusercontent.com/u/69795879?v=4',
gravatar_id: '',
url: 'https://api.github.com/users/misar1',
html_url: 'https://github.com/misar1',
followers_url: 'https://api.github.com/users/misar1/followers',
following_url: 'https://api.github.com/users/misar1/following{/other_user}',
gists_url: 'https://api.github.com/users/misar1/gists{/gist_id}',
starred_url: 'https://api.github.com/users/misar1/starred{/owner}{/repo}',
subscriptions_url: 'https://api.github.com/users/misar1/subscriptions',
organizations_url: 'https://api.github.com/users/misar1/orgs',
repos_url: 'https://api.github.com/users/misar1/repos',
events_url: 'https://api.github.com/users/misar1/events{/privacy}',
received_events_url: 'https://api.github.com/users/misar1/received_events',
type: 'User',
user_view_type: 'public',
site_admin: false
},
labels: [
{
id: 4542348869,
node_id: 'LA_kwDOFLVvtM8AAAABDr6-RQ',
url: 'https://api.github.com/repos/iptv-org/epg/labels/broken%20guide',
name: 'broken guide',
color: 'eaeaea',
default: false,
description: "There's a problem with the guide"
},
{
id: 7932710318,
node_id: 'LA_kwDOFLVvtM8AAAAB2NONrg',
url: 'https://api.github.com/repos/iptv-org/epg/labels/status:warning',
name: 'status:warning',
color: 'fbca06',
default: false,
description: 'The guide downloads, but contains errors'
}
],
state: 'open',
locked: false,
assignee: null,
assignees: [],
milestone: null,
comments: 1,
created_at: '2024-12-17T16:19:36Z',
updated_at: '2024-12-27T05:27:44Z',
closed_at: null,
author_association: 'NONE',
active_lock_reason: null,
body: '### Site\n\nsky.com\n\n### Description\n\n\r\nI changed to the recently updated sky.com script a couple of days ago (using a completely new install as in the readme) and have found an anomaly. This does not occur with an identical grab using my previous installation. The grabs are for about 60 UK FTA channels which I can list if it would be helpful.\r\n\r\nA number of programmes have two identical blocks in the XML, including their start and finish times. This occurs only from around approximately 22:00 each day and up to about midnight GMT. During this period most channels are affected and it is consistent between successive grabs. In case of a timing issue I tested delays of 100, 1000, 3000 and 5000 msec but the XML was unchanged.',
closed_by: null,
reactions: {
url: 'https://api.github.com/repos/iptv-org/epg/issues/2516/reactions',
total_count: 0,
'+1': 0,
'-1': 0,
laugh: 0,
hooray: 0,
confused: 0,
heart: 0,
rocket: 0,
eyes: 0
},
timeline_url: 'https://api.github.com/repos/iptv-org/epg/issues/2516/timeline',
performed_via_github_app: null,
state_reason: null
},
{
url: 'https://api.github.com/repos/iptv-org/epg/issues/2501',
repository_url: 'https://api.github.com/repos/iptv-org/epg',
labels_url: 'https://api.github.com/repos/iptv-org/epg/issues/2501/labels{/name}',
comments_url: 'https://api.github.com/repos/iptv-org/epg/issues/2501/comments',
events_url: 'https://api.github.com/repos/iptv-org/epg/issues/2501/events',
html_url: 'https://github.com/iptv-org/epg/issues/2501',
id: 2738899005,
node_id: 'I_kwDOFLVvtM6jQEg9',
number: 2501,
title: 'Sky.com',
user: {
login: 'Chris230291',
id: 5328818,
node_id: 'MDQ6VXNlcjUzMjg4MTg=',
avatar_url: 'https://avatars.githubusercontent.com/u/5328818?v=4',
gravatar_id: '',
url: 'https://api.github.com/users/Chris230291',
html_url: 'https://github.com/Chris230291',
followers_url: 'https://api.github.com/users/Chris230291/followers',
following_url: 'https://api.github.com/users/Chris230291/following{/other_user}',
gists_url: 'https://api.github.com/users/Chris230291/gists{/gist_id}',
starred_url: 'https://api.github.com/users/Chris230291/starred{/owner}{/repo}',
subscriptions_url: 'https://api.github.com/users/Chris230291/subscriptions',
organizations_url: 'https://api.github.com/users/Chris230291/orgs',
repos_url: 'https://api.github.com/users/Chris230291/repos',
events_url: 'https://api.github.com/users/Chris230291/events{/privacy}',
received_events_url: 'https://api.github.com/users/Chris230291/received_events',
type: 'User',
user_view_type: 'public',
site_admin: false
},
labels: [
{
id: 4542348869,
node_id: 'LA_kwDOFLVvtM8AAAABDr6-RQ',
url: 'https://api.github.com/repos/iptv-org/epg/labels/broken%20guide',
name: 'broken guide',
color: 'eaeaea',
default: false,
description: "There's a problem with the guide"
},
{
id: 7932710318,
node_id: 'LA_kwDOFLVvtM8AAAAB2NONrg',
url: 'https://api.github.com/repos/iptv-org/epg/labels/status:warning',
name: 'status:warning',
color: 'fbca06',
default: false,
description: 'The guide downloads, but contains errors'
}
],
state: 'open',
locked: false,
assignee: null,
assignees: [],
milestone: null,
comments: 2,
created_at: '2024-12-13T17:45:02Z',
updated_at: '2024-12-27T05:25:49Z',
closed_at: null,
author_association: 'NONE',
active_lock_reason: null,
body: '### Site\n\nsky.com\n\n### Description\n\n```\r\n <channel site="sky.com" lang="en" xmltv_id="ViaplaySports1.uk" site_id="1289">Viaplay 1 HD</channel>\r\n <channel site="sky.com" lang="en" xmltv_id="ViaplaySports2.uk" site_id="1290">Viaplay 2 HD</channel>\r\n```\r\n\r\nThese should be "Premier Sports 1 HD" and "Premier Sports 2 HD".\r\nAlso, the UK and ROI have different schedules for these 2 channels.',
closed_by: null,
reactions: {
url: 'https://api.github.com/repos/iptv-org/epg/issues/2501/reactions',
total_count: 0,
'+1': 0,
'-1': 0,
laugh: 0,
hooray: 0,
confused: 0,
heart: 0,
rocket: 0,
eyes: 0
},
timeline_url: 'https://api.github.com/repos/iptv-org/epg/issues/2501/timeline',
performed_via_github_app: null,
state_reason: null
},
{
url: 'https://api.github.com/repos/iptv-org/epg/issues/2446',
repository_url: 'https://api.github.com/repos/iptv-org/epg',
labels_url: 'https://api.github.com/repos/iptv-org/epg/issues/2446/labels{/name}',
comments_url: 'https://api.github.com/repos/iptv-org/epg/issues/2446/comments',
events_url: 'https://api.github.com/repos/iptv-org/epg/issues/2446/events',
html_url: 'https://github.com/iptv-org/epg/issues/2446',
id: 2568624116,
node_id: 'I_kwDOFLVvtM6ZGhf0',
number: 2446,
title: 'Eleven channels returning 0 programs on meo.pt',
user: {
login: 'jonatasgz',
id: 78122211,
node_id: 'MDQ6VXNlcjc4MTIyMjEx',
avatar_url: 'https://avatars.githubusercontent.com/u/78122211?v=4',
gravatar_id: '',
url: 'https://api.github.com/users/jonatasgz',
html_url: 'https://github.com/jonatasgz',
followers_url: 'https://api.github.com/users/jonatasgz/followers',
following_url: 'https://api.github.com/users/jonatasgz/following{/other_user}',
gists_url: 'https://api.github.com/users/jonatasgz/gists{/gist_id}',
starred_url: 'https://api.github.com/users/jonatasgz/starred{/owner}{/repo}',
subscriptions_url: 'https://api.github.com/users/jonatasgz/subscriptions',
organizations_url: 'https://api.github.com/users/jonatasgz/orgs',
repos_url: 'https://api.github.com/users/jonatasgz/repos',
events_url: 'https://api.github.com/users/jonatasgz/events{/privacy}',
received_events_url: 'https://api.github.com/users/jonatasgz/received_events',
type: 'User',
user_view_type: 'public',
site_admin: false
},
labels: [
{
id: 4542348869,
node_id: 'LA_kwDOFLVvtM8AAAABDr6-RQ',
url: 'https://api.github.com/repos/iptv-org/epg/labels/broken%20guide',
name: 'broken guide',
color: 'eaeaea',
default: false,
description: "There's a problem with the guide"
},
{
id: 7932710318,
node_id: 'LA_kwDOFLVvtM8AAAAB2NONrg',
url: 'https://api.github.com/repos/iptv-org/epg/labels/status:warning',
name: 'status:warning',
color: 'fbca06',
default: false,
description: 'The guide downloads, but contains errors'
}
],
state: 'open',
locked: false,
assignee: null,
assignees: [],
milestone: null,
comments: 2,
created_at: '2024-10-06T12:00:48Z',
updated_at: '2024-12-27T05:23:16Z',
closed_at: null,
author_association: 'NONE',
active_lock_reason: null,
body: '### Site\n\nmeo.pt\n\n### Description\n\nEleven (DAZN) channels return 0 programs.',
closed_by: null,
reactions: {
url: 'https://api.github.com/repos/iptv-org/epg/issues/2446/reactions',
total_count: 0,
'+1': 0,
'-1': 0,
laugh: 0,
hooray: 0,
confused: 0,
heart: 0,
rocket: 0,
eyes: 0
},
timeline_url: 'https://api.github.com/repos/iptv-org/epg/issues/2446/timeline',
performed_via_github_app: null,
state_reason: null
},
{
url: 'https://api.github.com/repos/iptv-org/epg/issues/2400',
repository_url: 'https://api.github.com/repos/iptv-org/epg',
labels_url: 'https://api.github.com/repos/iptv-org/epg/issues/2400/labels{/name}',
comments_url: 'https://api.github.com/repos/iptv-org/epg/issues/2400/comments',
events_url: 'https://api.github.com/repos/iptv-org/epg/issues/2400/events',
html_url: 'https://github.com/iptv-org/epg/issues/2400',
id: 2370209498,
node_id: 'I_kwDOFLVvtM6NRoba',
number: 2400,
title: 'tvgids.nl',
user: {
login: 'freearhey',
id: 7253922,
node_id: 'MDQ6VXNlcjcyNTM5MjI=',
avatar_url: 'https://avatars.githubusercontent.com/u/7253922?v=4',
gravatar_id: '',
url: 'https://api.github.com/users/freearhey',
html_url: 'https://github.com/freearhey',
followers_url: 'https://api.github.com/users/freearhey/followers',
following_url: 'https://api.github.com/users/freearhey/following{/other_user}',
gists_url: 'https://api.github.com/users/freearhey/gists{/gist_id}',
starred_url: 'https://api.github.com/users/freearhey/starred{/owner}{/repo}',
subscriptions_url: 'https://api.github.com/users/freearhey/subscriptions',
organizations_url: 'https://api.github.com/users/freearhey/orgs',
repos_url: 'https://api.github.com/users/freearhey/repos',
events_url: 'https://api.github.com/users/freearhey/events{/privacy}',
received_events_url: 'https://api.github.com/users/freearhey/received_events',
type: 'User',
user_view_type: 'public',
site_admin: false
},
labels: [
{
id: 4542348869,
node_id: 'LA_kwDOFLVvtM8AAAABDr6-RQ',
url: 'https://api.github.com/repos/iptv-org/epg/labels/broken%20guide',
name: 'broken guide',
color: 'eaeaea',
default: false,
description: "There's a problem with the guide"
},
{
id: 7932710318,
node_id: 'LA_kwDOFLVvtM8AAAAB2NONrg',
url: 'https://api.github.com/repos/iptv-org/epg/labels/status:warning',
name: 'status:warning',
color: 'fbca06',
default: false,
description: 'The guide downloads, but contains errors'
}
],
state: 'open',
locked: false,
assignee: null,
assignees: [],
milestone: null,
comments: 0,
created_at: '2024-06-24T13:05:05Z',
updated_at: '2024-12-27T05:19:25Z',
closed_at: null,
author_association: 'COLLABORATOR',
active_lock_reason: null,
body: "### Site\n\ntvgids.nl\n\n### Description\n\nTest failed:\r\n\r\n```sh\r\nnpm test -- tvgids.nl \r\n\r\n> test\r\n> run-script-os tvgids.nl\r\n\r\n\r\n> test:default\r\n> TZ=Pacific/Nauru npx jest --runInBand tvgids.nl\r\n\r\n FAIL sites/tvgids.nl/tvgids.nl.test.js\r\n ✓ can generate valid url (29 ms)\r\n ✕ can generate valid url for today (4 ms)\r\n ✓ can parse response (307 ms)\r\n ✓ can handle empty guide (3 ms)\r\n\r\n ● can generate valid url for today\r\n\r\n expect(received).toBe(expected) // Object.is equality\r\n\r\n Expected: \"https://www.tvgids.nl/gids/npo1\"\r\n Received: \"https://www.tvgids.nl/gids/25-06-2024/npo1\"\r\n\r\n 21 | const today = dayjs().startOf('d')\r\n 22 |\r\n > 23 | expect(url({ date: today, channel })).toBe('https://www.tvgids.nl/gids/npo1')\r\n | ^\r\n 24 | })\r\n 25 |\r\n 26 | it('can parse response', () => {\r\n\r\n at Object.<anonymous> (sites/tvgids.nl/tvgids.nl.test.js:23:41)\r\n\r\nTest Suites: 1 failed, 1 total\r\nTests: 1 failed, 3 passed, 4 total\r\nSnapshots: 0 total\r\nTime: 3.52 s\r\nRan all test suites matching /tvgids.nl/i.\r\n```",
closed_by: null,
reactions: {
url: 'https://api.github.com/repos/iptv-org/epg/issues/2400/reactions',
total_count: 0,
'+1': 0,
'-1': 0,
laugh: 0,
hooray: 0,
confused: 0,
heart: 0,
rocket: 0,
eyes: 0
},
timeline_url: 'https://api.github.com/repos/iptv-org/epg/issues/2400/timeline',
performed_via_github_app: null,
state_reason: null
},
{
url: 'https://api.github.com/repos/iptv-org/epg/issues/2399',
repository_url: 'https://api.github.com/repos/iptv-org/epg',
labels_url: 'https://api.github.com/repos/iptv-org/epg/issues/2399/labels{/name}',
comments_url: 'https://api.github.com/repos/iptv-org/epg/issues/2399/comments',
events_url: 'https://api.github.com/repos/iptv-org/epg/issues/2399/events',
html_url: 'https://github.com/iptv-org/epg/issues/2399',
id: 2370207356,
node_id: 'I_kwDOFLVvtM6NRn58',
number: 2399,
title: 'tvprofil.com',
user: {
login: 'freearhey',
id: 7253922,
node_id: 'MDQ6VXNlcjcyNTM5MjI=',
avatar_url: 'https://avatars.githubusercontent.com/u/7253922?v=4',
gravatar_id: '',
url: 'https://api.github.com/users/freearhey',
html_url: 'https://github.com/freearhey',
followers_url: 'https://api.github.com/users/freearhey/followers',
following_url: 'https://api.github.com/users/freearhey/following{/other_user}',
gists_url: 'https://api.github.com/users/freearhey/gists{/gist_id}',
starred_url: 'https://api.github.com/users/freearhey/starred{/owner}{/repo}',
subscriptions_url: 'https://api.github.com/users/freearhey/subscriptions',
organizations_url: 'https://api.github.com/users/freearhey/orgs',
repos_url: 'https://api.github.com/users/freearhey/repos',
events_url: 'https://api.github.com/users/freearhey/events{/privacy}',
received_events_url: 'https://api.github.com/users/freearhey/received_events',
type: 'User',
user_view_type: 'public',
site_admin: false
},
labels: [
{
id: 4542348869,
node_id: 'LA_kwDOFLVvtM8AAAABDr6-RQ',
url: 'https://api.github.com/repos/iptv-org/epg/labels/broken%20guide',
name: 'broken guide',
color: 'eaeaea',
default: false,
description: "There's a problem with the guide"
},
{
id: 7932710318,
node_id: 'LA_kwDOFLVvtM8AAAAB2NONrg',
url: 'https://api.github.com/repos/iptv-org/epg/labels/status:warning',
name: 'status:warning',
color: 'fbca06',
default: false,
description: 'The guide downloads, but contains errors'
}
],
state: 'open',
locked: false,
assignee: null,
assignees: [],
milestone: null,
comments: 1,
created_at: '2024-06-24T13:04:08Z',
updated_at: '2024-12-27T05:18:50Z',
closed_at: null,
author_association: 'COLLABORATOR',
active_lock_reason: null,
body: '### Site\n\ntvprofil.com\n\n### Description\n\nTest failed:\r\n\r\n```sh\r\nnpm test -- tvprofil.com\r\n\r\n> test\r\n> run-script-os tvprofil.com\r\n\r\n\r\n> test:default\r\n> TZ=Pacific/Nauru npx jest --runInBand tvprofil.com\r\n\r\n FAIL sites/tvprofil.com/tvprofil.com.test.js\r\n ✕ can generate valid url (14 ms)\r\n ✓ can generate valid request headers (1 ms)\r\n ✓ can parse response (76 ms)\r\n ✓ can handle empty guide (2 ms)\r\n\r\n ● can generate valid url\r\n\r\n expect(received).toBe(expected) // Object.is equality\r\n\r\n Expected: "https://tvprofil.com/bg/tv-programa/program/?datum=2023-01-12&kanal=24kitchen-bg&callback=cb&b51=818933"\r\n Received: "https://tvprofil.com/bg/tv-programa/program/?datum=2023-01-12&kanal=24kitchen-bg&callback=cb&b49=819461"\r\n\r\n 15 |\r\n 16 | it(\'can generate valid url\', () => {\r\n > 17 | expect(url({ channel, date })).toBe(\r\n | ^\r\n 18 | \'https://tvprofil.com/bg/tv-programa/program/?datum=2023-01-12&kanal=24kitchen-bg&callback=cb&b51=818933\'\r\n 19 | )\r\n 20 | })\r\n\r\n at Object.<anonymous> (sites/tvprofil.com/tvprofil.com.test.js:17:34)\r\n\r\nTest Suites: 1 failed, 1 total\r\nTests: 1 failed, 3 passed, 4 total\r\nSnapshots: 0 total\r\nTime: 3.307 s\r\nRan all test suites matching /tvprofil.com/i.\r\n```',
closed_by: null,
reactions: {
url: 'https://api.github.com/repos/iptv-org/epg/issues/2399/reactions',
total_count: 0,
'+1': 0,
'-1': 0,
laugh: 0,
hooray: 0,
confused: 0,
heart: 0,
rocket: 0,
eyes: 0
},
timeline_url: 'https://api.github.com/repos/iptv-org/epg/issues/2399/timeline',
performed_via_github_app: null,
state_reason: null
},
{
url: 'https://api.github.com/repos/iptv-org/epg/issues/2396',
repository_url: 'https://api.github.com/repos/iptv-org/epg',
labels_url: 'https://api.github.com/repos/iptv-org/epg/issues/2396/labels{/name}',
comments_url: 'https://api.github.com/repos/iptv-org/epg/issues/2396/comments',
events_url: 'https://api.github.com/repos/iptv-org/epg/issues/2396/events',
html_url: 'https://github.com/iptv-org/epg/issues/2396',
id: 2370189473,
node_id: 'I_kwDOFLVvtM6NRjih',
number: 2396,
title: 'iltalehti.fi',
user: {
login: 'freearhey',
id: 7253922,
node_id: 'MDQ6VXNlcjcyNTM5MjI=',
avatar_url: 'https://avatars.githubusercontent.com/u/7253922?v=4',
gravatar_id: '',
url: 'https://api.github.com/users/freearhey',
html_url: 'https://github.com/freearhey',
followers_url: 'https://api.github.com/users/freearhey/followers',
following_url: 'https://api.github.com/users/freearhey/following{/other_user}',
gists_url: 'https://api.github.com/users/freearhey/gists{/gist_id}',
starred_url: 'https://api.github.com/users/freearhey/starred{/owner}{/repo}',
subscriptions_url: 'https://api.github.com/users/freearhey/subscriptions',
organizations_url: 'https://api.github.com/users/freearhey/orgs',
repos_url: 'https://api.github.com/users/freearhey/repos',
events_url: 'https://api.github.com/users/freearhey/events{/privacy}',
received_events_url: 'https://api.github.com/users/freearhey/received_events',
type: 'User',
user_view_type: 'public',
site_admin: false
},
labels: [
{
id: 4542348869,
node_id: 'LA_kwDOFLVvtM8AAAABDr6-RQ',
url: 'https://api.github.com/repos/iptv-org/epg/labels/broken%20guide',
name: 'broken guide',
color: 'eaeaea',
default: false,
description: "There's a problem with the guide"
},
{
id: 7932710318,
node_id: 'LA_kwDOFLVvtM8AAAAB2NONrg',
url: 'https://api.github.com/repos/iptv-org/epg/labels/status:warning',
name: 'status:warning',
color: 'fbca06',
default: false,
description: 'The guide downloads, but contains errors'
}
],
state: 'open',
locked: false,
assignee: null,
assignees: [],
milestone: null,
comments: 0,
created_at: '2024-06-24T12:56:45Z',
updated_at: '2024-12-27T05:18:16Z',
closed_at: null,
author_association: 'COLLABORATOR',
active_lock_reason: null,
body: '### Site\n\niltalehti.fi\n\n### Description\n\nTest failed:\r\n\r\n```sh\r\nnpm test -- iltalehti.fi \r\n\r\n> test\r\n> run-script-os iltalehti.fi\r\n\r\n\r\n> test:default\r\n> TZ=Pacific/Nauru npx jest --runInBand iltalehti.fi\r\n\r\n FAIL sites/iltalehti.fi/iltalehti.fi.test.js\r\n ✕ can generate valid url (10 ms)\r\n ✓ can parse response (28 ms)\r\n ✓ can handle empty guide (1 ms)\r\n\r\n ● can generate valid url\r\n\r\n expect(received).toBe(expected) // Object.is equality\r\n\r\n Expected: "https://telkku.com/api/channel-groups/default_builtin_channelgroup1/offering?startTime=00%3A00%3A00.000&duration=PT24H&inclusionPolicy=IncludeOngoingAlso&limit=1000&tvDate=2022-10-29&view=PublicationDetails"\r\n Received: "https://telkku.com/api/channel-groups/default_builtin_channelgroupdefault_builtin_channelgroup1/offering?startTime=00%3A00%3A00.000&duration=PT24H&inclusionPolicy=IncludeOngoingAlso&limit=1000&tvDate=2022-10-29&view=PublicationDetails"\r\n\r\n 15 |\r\n 16 | it(\'can generate valid url\', () => {\r\n > 17 | expect(url({ channel, date })).toBe(\r\n | ^\r\n 18 | \'https://telkku.com/api/channel-groups/default_builtin_channelgroup1/offering?startTime=00%3A00%3A00.000&duration=PT24H&inclusionPolicy=IncludeOngoingAlso&limit=1000&tvDate=2022-10-29&view=PublicationDetails\'\r\n 19 | )\r\n 20 | })\r\n\r\n at Object.<anonymous> (sites/iltalehti.fi/iltalehti.fi.test.js:17:34)\r\n\r\nTest Suites: 1 failed, 1 total\r\nTests: 1 failed, 2 passed, 3 total\r\nSnapshots: 0 total\r\nTime: 3.193 s\r\nRan all test suites matching /iltalehti.fi/i.\r\n```',
closed_by: null,
reactions: {
url: 'https://api.github.com/repos/iptv-org/epg/issues/2396/reactions',
total_count: 0,
'+1': 0,
'-1': 0,
laugh: 0,
hooray: 0,
confused: 0,
heart: 0,
rocket: 0,
eyes: 0
},
timeline_url: 'https://api.github.com/repos/iptv-org/epg/issues/2396/timeline',
performed_via_github_app: null,
state_reason: null
},
{
url: 'https://api.github.com/repos/iptv-org/epg/issues/2395',
repository_url: 'https://api.github.com/repos/iptv-org/epg',
labels_url: 'https://api.github.com/repos/iptv-org/epg/issues/2395/labels{/name}',
comments_url: 'https://api.github.com/repos/iptv-org/epg/issues/2395/comments',
events_url: 'https://api.github.com/repos/iptv-org/epg/issues/2395/events',
html_url: 'https://github.com/iptv-org/epg/issues/2395',
id: 2370186157,
node_id: 'I_kwDOFLVvtM6NRiut',
number: 2395,
title: 'chaines-tv.orange.fr',
user: {
login: 'freearhey',
id: 7253922,
node_id: 'MDQ6VXNlcjcyNTM5MjI=',
avatar_url: 'https://avatars.githubusercontent.com/u/7253922?v=4',
gravatar_id: '',
url: 'https://api.github.com/users/freearhey',
html_url: 'https://github.com/freearhey',
followers_url: 'https://api.github.com/users/freearhey/followers',
following_url: 'https://api.github.com/users/freearhey/following{/other_user}',
gists_url: 'https://api.github.com/users/freearhey/gists{/gist_id}',
starred_url: 'https://api.github.com/users/freearhey/starred{/owner}{/repo}',
subscriptions_url: 'https://api.github.com/users/freearhey/subscriptions',
organizations_url: 'https://api.github.com/users/freearhey/orgs',
repos_url: 'https://api.github.com/users/freearhey/repos',
events_url: 'https://api.github.com/users/freearhey/events{/privacy}',
received_events_url: 'https://api.github.com/users/freearhey/received_events',
type: 'User',
user_view_type: 'public',
site_admin: false
},
labels: [
{
id: 4542348869,
node_id: 'LA_kwDOFLVvtM8AAAABDr6-RQ',
url: 'https://api.github.com/repos/iptv-org/epg/labels/broken%20guide',
name: 'broken guide',
color: 'eaeaea',
default: false,
description: "There's a problem with the guide"
},
{
id: 7932710318,
node_id: 'LA_kwDOFLVvtM8AAAAB2NONrg',
url: 'https://api.github.com/repos/iptv-org/epg/labels/status:warning',
name: 'status:warning',
color: 'fbca06',
default: false,
description: 'The guide downloads, but contains errors'
}
],
state: 'open',
locked: false,
assignee: null,
assignees: [],
milestone: null,
comments: 2,
created_at: '2024-06-24T12:55:21Z',
updated_at: '2024-12-27T05:17:25Z',
closed_at: null,
author_association: 'COLLABORATOR',
active_lock_reason: null,
body: '### Site\r\n\r\nchaines-tv.orange.fr\r\n\r\n### Description\r\n\r\nTest failed:\r\n\r\n```sh\r\nnpm test -- chaines-tv.orange.fr\r\n\r\n> test\r\n> run-script-os chaines-tv.orange.fr\r\n\r\n\r\n> test:default\r\n> TZ=Pacific/Nauru npx jest --runInBand chaines-tv.orange.fr\r\n\r\n FAIL sites/chaines-tv.orange.fr/chaines-tv.orange.fr.test.js\r\n ✓ can generate valid url (5 ms)\r\n ✕ can parse response (12 ms)\r\n ✓ can handle empty guide (1 ms)\r\n\r\n ● can parse response\r\n\r\n expect(received).toMatchObject(expected)\r\n\r\n - Expected - 1\r\n + Received + 1\r\n\r\n @@ -3,8 +3,8 @@\r\n "category": "Série Suspense",\r\n "description": "Un tueur en série prend un plaisir pervers à prévenir les autorités de Tallahassee avant chaque nouveau meurtre. Rossi apprend le décès d\'un de ses vieux amis.",\r\n "icon": "https://proxymedia.woopic.com/340/p/169_EMI_9697669.jpg",\r\n "start": "2021-11-07T23:35:00.000Z",\r\n "stop": "2021-11-08T00:20:00.000Z",\r\n - "title": "Tête de liste",\r\n + "title": "Esprits criminels",\r\n },\r\n ]\r\n\r\n 23 | it(\'can parse response\', () => {\r\n 24 | const result = parser({ date, channel, content })\r\n > 25 | expect(result).toMatchObject([\r\n | ^\r\n 26 | {\r\n 27 | start: \'2021-11-07T23:35:00.000Z\',\r\n 28 | stop: \'2021-11-08T00:20:00.000Z\',\r\n\r\n at Object.<anonymous> (sites/chaines-tv.orange.fr/chaines-tv.orange.fr.test.js:25:18)\r\n\r\nTest Suites: 1 failed, 1 total\r\nTests: 1 failed, 2 passed, 3 total\r\nSnapshots: 0 total\r\nTime: 4.003 s\r\nRan all test suites matching /chaines-tv.orange.fr/i.\r\n```',
closed_by: null,
reactions: {
url: 'https://api.github.com/repos/iptv-org/epg/issues/2395/reactions',
total_count: 0,
'+1': 0,
'-1': 0,
laugh: 0,
hooray: 0,
confused: 0,
heart: 0,
rocket: 0,
eyes: 0
},
timeline_url: 'https://api.github.com/repos/iptv-org/epg/issues/2395/timeline',
performed_via_github_app: null,
state_reason: null
},
{
url: 'https://api.github.com/repos/iptv-org/epg/issues/2304',
repository_url: 'https://api.github.com/repos/iptv-org/epg',
labels_url: 'https://api.github.com/repos/iptv-org/epg/issues/2304/labels{/name}',
comments_url: 'https://api.github.com/repos/iptv-org/epg/issues/2304/comments',
events_url: 'https://api.github.com/repos/iptv-org/epg/issues/2304/events',
html_url: 'https://github.com/iptv-org/epg/issues/2304',
id: 2064638324,
node_id: 'I_kwDOFLVvtM57D-F0',
number: 2304,
title: 'digiturk.com.tr Missing Channel Identifications',
user: {
login: 'UzunMuhalefet',
id: 80906858,
node_id: 'MDQ6VXNlcjgwOTA2ODU4',
avatar_url: 'https://avatars.githubusercontent.com/u/80906858?v=4',
gravatar_id: '',
url: 'https://api.github.com/users/UzunMuhalefet',
html_url: 'https://github.com/UzunMuhalefet',
followers_url: 'https://api.github.com/users/UzunMuhalefet/followers',
following_url: 'https://api.github.com/users/UzunMuhalefet/following{/other_user}',
gists_url: 'https://api.github.com/users/UzunMuhalefet/gists{/gist_id}',
starred_url: 'https://api.github.com/users/UzunMuhalefet/starred{/owner}{/repo}',
subscriptions_url: 'https://api.github.com/users/UzunMuhalefet/subscriptions',
organizations_url: 'https://api.github.com/users/UzunMuhalefet/orgs',
repos_url: 'https://api.github.com/users/UzunMuhalefet/repos',
events_url: 'https://api.github.com/users/UzunMuhalefet/events{/privacy}',
received_events_url: 'https://api.github.com/users/UzunMuhalefet/received_events',
type: 'User',
user_view_type: 'public',
site_admin: false
},
labels: [
{
id: 4542348869,
node_id: 'LA_kwDOFLVvtM8AAAABDr6-RQ',
url: 'https://api.github.com/repos/iptv-org/epg/labels/broken%20guide',
name: 'broken guide',
color: 'eaeaea',
default: false,
description: "There's a problem with the guide"
},
{
id: 7932710318,
node_id: 'LA_kwDOFLVvtM8AAAAB2NONrg',
url: 'https://api.github.com/repos/iptv-org/epg/labels/status:warning',
name: 'status:warning',
color: 'fbca06',
default: false,
description: 'The guide downloads, but contains errors'
}
],
state: 'open',
locked: false,
assignee: null,
assignees: [],
milestone: null,
comments: 0,
created_at: '2024-01-03T20:57:58Z',
updated_at: '2024-12-27T05:32:37Z',
closed_at: null,
author_association: 'NONE',
active_lock_reason: null,
body: '### Site\r\n\r\ndigiturk.com.tr\r\n\r\n### Describe your issue\r\n\r\nThe following channels can be corrected as follows. (I added the TVG-IDs if they exist in https://iptv-org.github.io/)\r\n\r\n```\r\n<channel site="digiturk.com.tr" lang="tr" xmltv_id="24TV.tr" site_id="40">KANAL 24 HD</channel>\r\n<channel site="digiturk.com.tr" lang="tr" xmltv_id="TarihTV.tr" site_id="184">TARIH TV HD</channel>\r\n<channel site="digiturk.com.tr" lang="tr" xmltv_id="SozcuTV.tr" site_id="60">SÖZCÜ TV HD</channel>\r\n```\r\n\r\nLet me clarify the cases:\r\n- SZC changed its name to Sözcü TV\r\n- 24 TV often called as Kanal (Channel) 24\r\n- Tarih TV is straightforward.\r\n',
closed_by: null,
reactions: {
url: 'https://api.github.com/repos/iptv-org/epg/issues/2304/reactions',
total_count: 0,
'+1': 0,
'-1': 0,
laugh: 0,
hooray: 0,
confused: 0,
heart: 0,
rocket: 0,
eyes: 0
},
timeline_url: 'https://api.github.com/repos/iptv-org/epg/issues/2304/timeline',
performed_via_github_app: null,
state_reason: null
},
{
url: 'https://api.github.com/repos/iptv-org/epg/issues/2303',
repository_url: 'https://api.github.com/repos/iptv-org/epg',
labels_url: 'https://api.github.com/repos/iptv-org/epg/issues/2303/labels{/name}',
comments_url: 'https://api.github.com/repos/iptv-org/epg/issues/2303/comments',
events_url: 'https://api.github.com/repos/iptv-org/epg/issues/2303/events',
html_url: 'https://github.com/iptv-org/epg/issues/2303',
id: 2064633657,
node_id: 'I_kwDOFLVvtM57D885',
number: 2303,
title: 'dsmart.com.tr Channel Identifications',
user: {
login: 'UzunMuhalefet',
id: 80906858,
node_id: 'MDQ6VXNlcjgwOTA2ODU4',
avatar_url: 'https://avatars.githubusercontent.com/u/80906858?v=4',
gravatar_id: '',
url: 'https://api.github.com/users/UzunMuhalefet',
html_url: 'https://github.com/UzunMuhalefet',
followers_url: 'https://api.github.com/users/UzunMuhalefet/followers',
following_url: 'https://api.github.com/users/UzunMuhalefet/following{/other_user}',
gists_url: 'https://api.github.com/users/UzunMuhalefet/gists{/gist_id}',
starred_url: 'https://api.github.com/users/UzunMuhalefet/starred{/owner}{/repo}',
subscriptions_url: 'https://api.github.com/users/UzunMuhalefet/subscriptions',
organizations_url: 'https://api.github.com/users/UzunMuhalefet/orgs',
repos_url: 'https://api.github.com/users/UzunMuhalefet/repos',
events_url: 'https://api.github.com/users/UzunMuhalefet/events{/privacy}',
received_events_url: 'https://api.github.com/users/UzunMuhalefet/received_events',
type: 'User',
user_view_type: 'public',
site_admin: false
},
labels: [
{
id: 4542348869,
node_id: 'LA_kwDOFLVvtM8AAAABDr6-RQ',
url: 'https://api.github.com/repos/iptv-org/epg/labels/broken%20guide',
name: 'broken guide',
color: 'eaeaea',
default: false,
description: "There's a problem with the guide"
},
{
id: 7932710318,
node_id: 'LA_kwDOFLVvtM8AAAAB2NONrg',
url: 'https://api.github.com/repos/iptv-org/epg/labels/status:warning',
name: 'status:warning',
color: 'fbca06',
default: false,
description: 'The guide downloads, but contains errors'
}
],
state: 'open',
locked: false,
assignee: null,
assignees: [],
milestone: null,
comments: 1,
created_at: '2024-01-03T20:53:34Z',
updated_at: '2024-12-27T05:44:16Z',
closed_at: null,
author_association: 'NONE',
active_lock_reason: null,
body: '### Describe your issue\r\n\r\nThe following channels can be corrected as follows. (I added the TVG-IDs if they exist in https://iptv-org.github.io/)\r\n\r\n```\r\n<channel site="dsmart.com.tr" lang="tr" xmltv_id="Number1TV.tr" site_id="102#58d29bb0eefad3db9c60623c">NR1</channel>\r\n<channel site="dsmart.com.tr" lang="tr" xmltv_id="Number1Turk.tr" site_id="104#58d29bb0eefad3db9c606245">NR1 Türk</channel>\r\n<channel site="dsmart.com.tr" lang="tr" xmltv_id="EBATVIlkokul.tr" site_id="123#5e75c6f5cfef0b15938bc9b9">TRT EBA TV İlkokul</channel>\r\n<channel site="dsmart.com.tr" lang="tr" xmltv_id="EBATVOrtaokul.tr" site_id="124#5e75c923cfef0b15938bc9cc">TRT EBA TV Ortaokul</channel>\r\n<channel site="dsmart.com.tr" lang="tr" xmltv_id="EBATVLise.tr" site_id="125#5e75c9d1cfef0b15938bc9d1">TRT EBA TV Lise</channel>\r\n<channel site="dsmart.com.tr" lang="tr" xmltv_id="CiftciTV.tr" site_id="139#59dcaaaccfef0b4d80a47d7e">Çifçi TV</channel>\r\n<channel site="dsmart.com.tr" lang="tr" xmltv_id="On6.tr" site_id="150#59dcbc42cfef0b4d80a49628">Kanal 16</channel>\r\n<channel site="dsmart.com.tr" lang="tr" xmltv_id="FlashTV.tr" site_id="163#6163ee3dcfef0b1593d572b0">Flash Haber</channel>\r\n<channel site="dsmart.com.tr" lang="tr" xmltv_id="KocaeliTV.tr" site_id="168#59dcbe7dcfef0b4d80a4964c">Yeni Kocaeli TV</channel>\r\n<channel site="dsmart.com.tr" lang="tr" xmltv_id="ATV.tr" site_id="198#58d29bb0eefad3db9c606247">ATV Turkiye SD</channel>\r\n<channel site="dsmart.com.tr" lang="tr" xmltv_id="EBATVIlkokul" site_id="207#5e7865eacfef0b15938c1bb0">TRT EBA TV İlkokul SD</channel>\r\n<channel site="dsmart.com.tr" lang="tr" xmltv_id="EBATVOrtaokul" site_id="208#5e78662ecfef0b15938c1c03">TRT EBA TV Ortaokul SD</channel>\r\n<channel site="dsmart.com.tr" lang="tr" xmltv_id="EBATVLise" site_id="209#5e7866dfcfef0b15938c1c1b">TRT EBA TV Lise SD</channel>\r\n<channel site="dsmart.com.tr" lang="tr" xmltv_id="TarihTV.tr" site_id="63#64edfc67cfef0b02d2c038c5">Tarih Tv</channel>\r\n<channel site="dsmart.com.tr" lang="tr" xmltv_id="SozcuTV.tr" site_id="87#63ecd91acfef0b02d2687aed">SZC</channel>\r\n<channel site="dsmart.com.tr" lang="tr" xmltv_id="TRT3.tr" site_id="93#58d29bb0eefad3db9c606231">TRT 3 Spor</channel>\r\n``` \r\n\r\nLet me clarify the cases: \r\n\r\n- NR1 stands for Number One\r\n- Cifci TV - Çiftçi TV - misspelling\r\n- The number 16 is spelled as onaltı (on -> 10, altı->6, on6 -> 16) in Turkish so on6 - Kanal 16\r\n- Flash TV changed its name to Flash Haber TV\r\n- SZC changed its name to Sözcü TV\r\n- TRT 3 is a strange channel that usually streams the same content as TRT Spor but when there is a Turkish parliament event it switches to that event. So, the channel is both called TRT 3 and TRT 3 Spor.\r\n',
closed_by: null,
reactions: {
url: 'https://api.github.com/repos/iptv-org/epg/issues/2303/reactions',
total_count: 0,
'+1': 0,
'-1': 0,
laugh: 0,
hooray: 0,
confused: 0,
heart: 0,
rocket: 0,
eyes: 0
},
timeline_url: 'https://api.github.com/repos/iptv-org/epg/issues/2303/timeline',
performed_via_github_app: null,
state_reason: null
},
{
url: 'https://api.github.com/repos/iptv-org/epg/issues/2272',
repository_url: 'https://api.github.com/repos/iptv-org/epg',
labels_url: 'https://api.github.com/repos/iptv-org/epg/issues/2272/labels{/name}',
comments_url: 'https://api.github.com/repos/iptv-org/epg/issues/2272/comments',
events_url: 'https://api.github.com/repos/iptv-org/epg/issues/2272/events',
html_url: 'https://github.com/iptv-org/epg/issues/2272',
id: 2022135766,
node_id: 'I_kwDOFLVvtM54h1fW',
number: 2272,
title: 'Film titles with numbers only in the title (as in "1900" or "1917") don\'t show up',
user: {
login: 'GlamoramaAttack',
id: 116585465,
node_id: 'U_kgDOBvLz-Q',
avatar_url: 'https://avatars.githubusercontent.com/u/116585465?v=4',
gravatar_id: '',
url: 'https://api.github.com/users/GlamoramaAttack',
html_url: 'https://github.com/GlamoramaAttack',
followers_url: 'https://api.github.com/users/GlamoramaAttack/followers',
following_url: 'https://api.github.com/users/GlamoramaAttack/following{/other_user}',
gists_url: 'https://api.github.com/users/GlamoramaAttack/gists{/gist_id}',
starred_url: 'https://api.github.com/users/GlamoramaAttack/starred{/owner}{/repo}',
subscriptions_url: 'https://api.github.com/users/GlamoramaAttack/subscriptions',
organizations_url: 'https://api.github.com/users/GlamoramaAttack/orgs',
repos_url: 'https://api.github.com/users/GlamoramaAttack/repos',
events_url: 'https://api.github.com/users/GlamoramaAttack/events{/privacy}',
received_events_url: 'https://api.github.com/users/GlamoramaAttack/received_events',
type: 'User',
user_view_type: 'public',
site_admin: false
},
labels: [
{
id: 4542348869,
node_id: 'LA_kwDOFLVvtM8AAAABDr6-RQ',
url: 'https://api.github.com/repos/iptv-org/epg/labels/broken%20guide',
name: 'broken guide',
color: 'eaeaea',
default: false,
description: "There's a problem with the guide"
},
{
id: 7932710318,
node_id: 'LA_kwDOFLVvtM8AAAAB2NONrg',
url: 'https://api.github.com/repos/iptv-org/epg/labels/status:warning',
name: 'status:warning',
color: 'fbca06',
default: false,
description: 'The guide downloads, but contains errors'
}
],
state: 'open',
locked: false,
assignee: null,
assignees: [],
milestone: null,
comments: 2,
created_at: '2023-12-02T17:29:50Z',
updated_at: '2024-12-27T05:02:05Z',
closed_at: null,
author_association: 'NONE',
active_lock_reason: null,
body: '### Site\r\n\r\ntvpassport.com\r\n\r\n### Describe your issue\r\n\r\nFilm titles with numbers only in the title -as in "1900" or "1917"- don\'t show up at all.\r\n\r\nSorry, I don\'t understand anything about how to write a script or fix it but I see there is notable difference in the **guide.xml** file - the examples are excerpts from tvpassport.com. This isn\'t a new bug I think, it\'s just that I thought for a long time it\'s a Kodi problem before looking into the guide.xml file...\r\n\r\n```\r\nchannel="Showtime2East.us"><title lang="en">The Caine Mutiny Court-Martial</title><desc lang="en">A \r\nchannel="Showtime2East.us"><desc lang="en">Two British soldiers receive seemingly impossible orders \r\nchannel="Showtime2East.us"><title lang="en">There Will Be Blood</title><desc lang="en">Daniel \r\n```\r\nor:\r\n\r\n```\r\nchannel="MGMPlusEast.us"><title lang="en">A Fistful of Dynamite</title><desc lang="en">A thief \r\nchannel="MGMPlusEast.us"><desc lang="en">The son (Robert De Niro) of a landowner and the son \r\nchannel="MGMPlusEast.us"><title lang="en">Indecent Proposal</title><desc lang="en">A Las Vegas \r\n```\r\n\r\nFor some reason "title lang" gets replaced by "desc lang" and the film title is nowhere displayed.\r\n\r\nOn Kodi it looks like this for the films and you can also see it\'s not a problem if the film title includes more than numbers (see "88 Minutes" or "Resistance: 1942"). But titles as "1900", "1917" or "1408" (Horror with John Cusack) appear blank.\r\n\r\n![NoTitleWithNumbers](https://github.com/iptv-org/epg/assets/116585465/155f98f8-8529-4c42-af3c-def1edcf5651)\r\n\r\nI\'m not sure whether the problem also exists with other sources than tvpassport.com because I use only two other (German language) EPG sources that have currently no film titles with numbers only. But I assume it\'s a bug if it\'s not reduced to tvpassport.',
closed_by: null,
reactions: {
url: 'https://api.github.com/repos/iptv-org/epg/issues/2272/reactions',
total_count: 0,
'+1': 0,
'-1': 0,
laugh: 0,
hooray: 0,
confused: 0,
heart: 0,
rocket: 0,
eyes: 0
},
timeline_url: 'https://api.github.com/repos/iptv-org/epg/issues/2272/timeline',
performed_via_github_app: null,
state_reason: null
},
{
url: 'https://api.github.com/repos/iptv-org/epg/issues/2176',
repository_url: 'https://api.github.com/repos/iptv-org/epg',
labels_url: 'https://api.github.com/repos/iptv-org/epg/issues/2176/labels{/name}',
comments_url: 'https://api.github.com/repos/iptv-org/epg/issues/2176/comments',
events_url: 'https://api.github.com/repos/iptv-org/epg/issues/2176/events',
html_url: 'https://github.com/iptv-org/epg/issues/2176',
id: 1915947653,
node_id: 'I_kwDOFLVvtM5yMwqF',
number: 2176,
title: 'tvtv',
user: {
login: 'jvdillon',
id: 1137078,
node_id: 'MDQ6VXNlcjExMzcwNzg=',
avatar_url: 'https://avatars.githubusercontent.com/u/1137078?v=4',
gravatar_id: '',
url: 'https://api.github.com/users/jvdillon',
html_url: 'https://github.com/jvdillon',
followers_url: 'https://api.github.com/users/jvdillon/followers',
following_url: 'https://api.github.com/users/jvdillon/following{/other_user}',
gists_url: 'https://api.github.com/users/jvdillon/gists{/gist_id}',
starred_url: 'https://api.github.com/users/jvdillon/starred{/owner}{/repo}',
subscriptions_url: 'https://api.github.com/users/jvdillon/subscriptions',
organizations_url: 'https://api.github.com/users/jvdillon/orgs',
repos_url: 'https://api.github.com/users/jvdillon/repos',
events_url: 'https://api.github.com/users/jvdillon/events{/privacy}',
received_events_url: 'https://api.github.com/users/jvdillon/received_events',
type: 'User',
user_view_type: 'public',
site_admin: false
},
labels: [
{
id: 4542348869,
node_id: 'LA_kwDOFLVvtM8AAAABDr6-RQ',
url: 'https://api.github.com/repos/iptv-org/epg/labels/broken%20guide',
name: 'broken guide',
color: 'eaeaea',
default: false,
description: "There's a problem with the guide"
},
{
id: 7932710318,
node_id: 'LA_kwDOFLVvtM8AAAAB2NONrg',
url: 'https://api.github.com/repos/iptv-org/epg/labels/status:warning',
name: 'status:warning',
color: 'fbca06',
default: false,
description: 'The guide downloads, but contains errors'
}
],
state: 'open',
locked: false,
assignee: null,
assignees: [],
milestone: null,
comments: 6,
created_at: '2023-09-27T16:34:00Z',
updated_at: '2024-12-27T04:55:00Z',
closed_at: null,
author_association: 'NONE',
active_lock_reason: null,
body: '### Site\r\n\r\ntvtv.us\r\n\r\n### Description\r\n\r\nStarts getting error 429 after several 100 scrapes. I tried setting the delay to 1000ms, 1500ms, and 2000ms but keep seeing the issue.\r\n\r\nIt almost appears to happen after a sequence of 0 program scrapes. I wonder if the delay is not happening when nothing is downloaded which causes tvtv.us to throttle which triggers 0 programs downloaded. (Ie a feedback loop)',
closed_by: null,
reactions: {
url: 'https://api.github.com/repos/iptv-org/epg/issues/2176/reactions',
total_count: 0,
'+1': 0,
'-1': 0,
laugh: 0,
hooray: 0,
confused: 0,
heart: 0,
rocket: 0,
eyes: 0
},
timeline_url: 'https://api.github.com/repos/iptv-org/epg/issues/2176/timeline',
performed_via_github_app: null,
state_reason: null
}
]

View file

@ -3,10 +3,10 @@ import fs from 'fs-extra'
import { pathToFileURL } from 'node:url' import { pathToFileURL } from 'node:url'
import os from 'os' import os from 'os'
let ENV_VAR = 'SITES_DIR=tests/__data__/input/epg-grab/sites API_DIR=tests/__data__/output' let ENV_VAR = 'SITES_DIR=tests/__data__/input/api_generate/sites API_DIR=tests/__data__/output'
if (os.platform() === 'win32') { if (os.platform() === 'win32') {
ENV_VAR = ENV_VAR =
'SET "SITES_DIR=tests/__data__/input/epg-grab/sites" && SET "API_DIR=tests/__data__/output" &&' 'SET "SITES_DIR=tests/__data__/input/api_generate/sites" && SET "API_DIR=tests/__data__/output" &&'
} }
beforeEach(() => { beforeEach(() => {
@ -20,7 +20,7 @@ describe('api:generate', () => {
if (process.env.DEBUG === 'true') console.log(cmd, stdout) if (process.env.DEBUG === 'true') console.log(cmd, stdout)
expect(content('tests/__data__/output/guides.json')).toEqual( expect(content('tests/__data__/output/guides.json')).toEqual(
content('tests/__data__/expected/guides.json') content('tests/__data__/expected/api_generate/guides.json')
) )
}) })
}) })

View file

@ -1,22 +1,21 @@
import fs from 'fs-extra'
import { execSync } from 'child_process' import { execSync } from 'child_process'
import fs from 'fs-extra'
import os from 'os' import os from 'os'
import { pathToFileURL } from 'node:url'
type ExecError = { type ExecError = {
status: number status: number
stdout: string stdout: string
} }
let ENV_VAR = 'DATA_DIR=tests/__data__/input/temp/data' let ENV_VAR = 'DATA_DIR=tests/__data__/input/__data__'
if (os.platform() === 'win32') { if (os.platform() === 'win32') {
ENV_VAR = 'SET "DATA_DIR=tests/__data__/input/temp/data" &&' ENV_VAR = 'SET "DATA_DIR=tests/__data__/input/__data__" &&'
} }
beforeEach(() => { beforeEach(() => {
fs.emptyDirSync('tests/__data__/output') fs.emptyDirSync('tests/__data__/output')
fs.copySync( fs.copySync(
'tests/__data__/input/channels-edit/example.com.channels.xml', 'tests/__data__/input/channels_edit/example.com.channels.xml',
'tests/__data__/output/channels.xml' 'tests/__data__/output/channels.xml'
) )
}) })
@ -28,29 +27,17 @@ describe('channels:edit', () => {
const stdout = execSync(cmd, { encoding: 'utf8' }) const stdout = execSync(cmd, { encoding: 'utf8' })
if (process.env.DEBUG === 'true') console.log(cmd, stdout) if (process.env.DEBUG === 'true') console.log(cmd, stdout)
checkStdout(stdout) checkStdout(stdout)
expect(content('tests/__data__/output/channels.xml')).toEqual(
content('tests/__data__/expected/sites/channels-edit/example.com.channels.xml')
)
} catch (error) { } catch (error) {
// NOTE: for Windows only // NOTE: for Windows only
if (process.env.DEBUG === 'true') console.log(cmd, error) if (process.env.DEBUG === 'true') console.log(cmd, error)
checkStdout((error as ExecError).stdout) checkStdout((error as ExecError).stdout)
expect(content('tests/__data__/output/channels.xml')).toEqual(
content('tests/__data__/expected/sites/channels-edit/example.com.channels.xml')
)
} }
}) })
}) })
function checkStdout(stdout: string) { function checkStdout(stdout: string) {
expect(stdout).toContain('CNN International Europe | CNNInternationalEurope.us') expect(stdout).toContain('CNNInternational.us (CNN International, CNN, CNN Int)')
expect(stdout).toContain('Type...') expect(stdout).toContain('Type...')
expect(stdout).toContain('Skip') expect(stdout).toContain('Skip')
expect(stdout).toContain("File 'tests/__data__/output/channels.xml' successfully saved") expect(stdout).toContain("File 'tests/__data__/output/channels.xml' successfully saved")
} }
function content(filepath: string) {
return fs.readFileSync(pathToFileURL(filepath), {
encoding: 'utf8'
})
}

View file

@ -8,7 +8,7 @@ type ExecError = {
describe('channels:lint', () => { describe('channels:lint', () => {
it('will show a message if the file contains a syntax error', () => { it('will show a message if the file contains a syntax error', () => {
try { try {
const cmd = 'npm run channels:lint --- tests/__data__/input/channels-lint/error.channels.xml' const cmd = 'npm run channels:lint --- tests/__data__/input/channels_lint/error.channels.xml'
const stdout = execSync(cmd, { encoding: 'utf8' }) const stdout = execSync(cmd, { encoding: 'utf8' })
if (process.env.DEBUG === 'true') console.log(cmd, stdout) if (process.env.DEBUG === 'true') console.log(cmd, stdout)
process.exit(1) process.exit(1)
@ -23,7 +23,7 @@ describe('channels:lint', () => {
it('will show a message if an error occurred while parsing an xml file', () => { it('will show a message if an error occurred while parsing an xml file', () => {
try { try {
const cmd = const cmd =
'npm run channels:lint --- tests/__data__/input/channels-lint/invalid.channels.xml' 'npm run channels:lint --- tests/__data__/input/channels_lint/invalid.channels.xml'
const stdout = execSync(cmd, { encoding: 'utf8' }) const stdout = execSync(cmd, { encoding: 'utf8' })
if (process.env.DEBUG === 'true') console.log(cmd, stdout) if (process.env.DEBUG === 'true') console.log(cmd, stdout)
process.exit(1) process.exit(1)
@ -38,7 +38,7 @@ describe('channels:lint', () => {
it('can test multiple files at ones', () => { it('can test multiple files at ones', () => {
try { try {
const cmd = const cmd =
'npm run channels:lint --- tests/__data__/input/channels-lint/error.channels.xml tests/__data__/input/channels-lint/invalid.channels.xml' 'npm run channels:lint --- tests/__data__/input/channels_lint/error.channels.xml tests/__data__/input/channels_lint/invalid.channels.xml'
const stdout = execSync(cmd, { encoding: 'utf8' }) const stdout = execSync(cmd, { encoding: 'utf8' })
if (process.env.DEBUG === 'true') console.log(cmd, stdout) if (process.env.DEBUG === 'true') console.log(cmd, stdout)
process.exit(1) process.exit(1)
@ -57,7 +57,7 @@ describe('channels:lint', () => {
it('will show a message if the file contains single quotes', () => { it('will show a message if the file contains single quotes', () => {
try { try {
const cmd = const cmd =
'npm run channels:lint --- tests/__data__/input/channels-lint/single_quotes.channels.xml' 'npm run channels:lint --- tests/__data__/input/channels_lint/single_quotes.channels.xml'
const stdout = execSync(cmd, { encoding: 'utf8' }) const stdout = execSync(cmd, { encoding: 'utf8' })
if (process.env.DEBUG === 'true') console.log(cmd, stdout) if (process.env.DEBUG === 'true') console.log(cmd, stdout)
process.exit(1) process.exit(1)
@ -72,7 +72,7 @@ describe('channels:lint', () => {
it('does not display errors if there are none', () => { it('does not display errors if there are none', () => {
try { try {
const cmd = 'npm run channels:lint --- tests/__data__/input/channels-lint/valid.channels.xml' const cmd = 'npm run channels:lint --- tests/__data__/input/channels_lint/valid.channels.xml'
const stdout = execSync(cmd, { encoding: 'utf8' }) const stdout = execSync(cmd, { encoding: 'utf8' })
if (process.env.DEBUG === 'true') console.log(cmd, stdout) if (process.env.DEBUG === 'true') console.log(cmd, stdout)
} catch (error) { } catch (error) {

View file

@ -5,20 +5,20 @@ import { pathToFileURL } from 'node:url'
beforeEach(() => { beforeEach(() => {
fs.emptyDirSync('tests/__data__/output') fs.emptyDirSync('tests/__data__/output')
fs.copySync( fs.copySync(
'tests/__data__/input/channels-parse/channels-parse.channels.xml', 'tests/__data__/input/channels_parse/example.com.channels.xml',
'tests/__data__/output/channels.xml' 'tests/__data__/output/example.com.channels.xml'
) )
}) })
describe('channels:parse', () => { describe('channels:parse', () => {
it('can parse channels', () => { it('can parse channels', () => {
const cmd = const cmd =
'npm run channels:parse --- --config=tests/__data__/input/channels-parse/channels-parse.config.js --output=tests/__data__/output/channels.xml' 'npm run channels:parse --- --config=tests/__data__/input/channels_parse/example.com.config.js --output=tests/__data__/output/example.com.channels.xml'
const stdout = execSync(cmd, { encoding: 'utf8' }) const stdout = execSync(cmd, { encoding: 'utf8' })
if (process.env.DEBUG === 'true') console.log(cmd, stdout) if (process.env.DEBUG === 'true') console.log(cmd, stdout)
expect(content('tests/__data__/output/channels.xml')).toEqual( expect(content('tests/__data__/output/example.com.channels.xml')).toEqual(
content('tests/__data__/expected/sites/channels-parse/channels-parse.channels.xml') content('tests/__data__/expected/channels_parse/example.com.channels.xml')
) )
}) })
}) })

View file

@ -6,26 +6,26 @@ type ExecError = {
stdout: string stdout: string
} }
let ENV_VAR = 'DATA_DIR=tests/__data__/input/temp/data' let ENV_VAR = 'DATA_DIR=tests/__data__/input/__data__'
if (os.platform() === 'win32') { if (os.platform() === 'win32') {
ENV_VAR = 'SET "DATA_DIR=tests/__data__/input/temp/data" &&' ENV_VAR = 'SET "DATA_DIR=tests/__data__/input/__data__" &&'
} }
describe('channels:validate', () => { describe('channels:validate', () => {
it('will show a message if the file contains a duplicate', () => { it('will show a message if the file contains a duplicate', () => {
try { try {
const cmd = `${ENV_VAR} npm run channels:validate --- tests/__data__/input/channels-validate/duplicate.channels.xml` const cmd = `${ENV_VAR} npm run channels:validate --- tests/__data__/input/channels_validate/duplicate.channels.xml`
const stdout = execSync(cmd, { encoding: 'utf8' }) const stdout = execSync(cmd, { encoding: 'utf8' })
if (process.env.DEBUG === 'true') console.log(cmd, stdout) if (process.env.DEBUG === 'true') console.log(cmd, stdout)
process.exit(1) process.exit(1)
} catch (error) { } catch (error) {
expect((error as ExecError).status).toBe(1) expect((error as ExecError).status).toBe(1)
expect((error as ExecError).stdout).toContain(` expect((error as ExecError).stdout).toContain(`
(index) type lang xmltv_id site_id name (index) type lang xmltv_id site_id name
0 'duplicate' 'en' 'BravoEast.us' '140' 'Bravo' 0 'duplicate' 'en' 'Bravo.us@East' '140' 'Bravo'
1 error(s) in 1 file(s) 1 error(s) in 1 file(s)
`) `)
@ -34,7 +34,7 @@ describe('channels:validate', () => {
it('will show a message if the file contains a channel with wrong xmltv_id', () => { it('will show a message if the file contains a channel with wrong xmltv_id', () => {
try { try {
const cmd = `${ENV_VAR} npm run channels:validate --- tests/__data__/input/channels-validate/wrong_xmltv_id.channels.xml` const cmd = `${ENV_VAR} npm run channels:validate --- tests/__data__/input/channels_validate/wrong_xmltv_id.channels.xml`
const stdout = execSync(cmd, { encoding: 'utf8' }) const stdout = execSync(cmd, { encoding: 'utf8' })
if (process.env.DEBUG === 'true') console.log(cmd, stdout) if (process.env.DEBUG === 'true') console.log(cmd, stdout)
process.exit(1) process.exit(1)

View file

@ -1,15 +1,15 @@
import { execSync } from 'child_process'
import fs from 'fs-extra'
import { pathToFileURL } from 'node:url' import { pathToFileURL } from 'node:url'
import { execSync } from 'child_process'
import { Zip } from '@freearhey/core'
import fs from 'fs-extra'
import path from 'path' import path from 'path'
import os from 'os' import os from 'os'
import { Zip } from '@freearhey/core'
let ENV_VAR = let ENV_VAR =
'SITES_DIR=tests/__data__/input/epg-grab/sites CURR_DATE=2022-10-20 DATA_DIR=tests/__data__/input/temp/data' 'SITES_DIR=tests/__data__/input/epg_grab/sites CURR_DATE=2022-10-20 DATA_DIR=tests/__data__/input/__data__'
if (os.platform() === 'win32') { if (os.platform() === 'win32') {
ENV_VAR = ENV_VAR =
'SET "SITES_DIR=tests/__data__/input/epg-grab/sites" && SET "CURR_DATE=2022-10-20" && SET "DATA_DIR=tests/__data__/input/temp/data" &&' 'SET "SITES_DIR=tests/__data__/input/epg_grab/sites" && SET "CURR_DATE=2022-10-20" && SET "DATA_DIR=tests/__data__/input/__data__" &&'
} }
beforeEach(() => { beforeEach(() => {
@ -25,73 +25,75 @@ describe('epg:grab', () => {
if (process.env.DEBUG === 'true') console.log(cmd, stdout) if (process.env.DEBUG === 'true') console.log(cmd, stdout)
expect(content('tests/__data__/output/guide.xml')).toEqual( expect(content('tests/__data__/output/guide.xml')).toEqual(
content('tests/__data__/expected/guide2.xml') content('tests/__data__/expected/epg_grab/guide_2.xml')
) )
}) })
it('can grab epg with multiple channels.xml files', () => { it('can grab epg with multiple channels.xml files', () => {
const cmd = `${ENV_VAR} npm run grab --- --channels=tests/__data__/input/epg-grab/sites/**/*.channels.xml --output=tests/__data__/output/guide.xml` const cmd = `${ENV_VAR} npm run grab --- --channels=tests/__data__/input/epg_grab/sites/**/*.channels.xml --output=tests/__data__/output/guide.xml`
const stdout = execSync(cmd, { encoding: 'utf8' }) const stdout = execSync(cmd, { encoding: 'utf8' })
if (process.env.DEBUG === 'true') console.log(cmd, stdout) if (process.env.DEBUG === 'true') console.log(cmd, stdout)
expect(content('tests/__data__/output/guide.xml')).toEqual( expect(content('tests/__data__/output/guide.xml')).toEqual(
content('tests/__data__/expected/guide.xml') content('tests/__data__/expected/epg_grab/guide.xml')
) )
}) })
it('can grab epg with gzip option enabled', async () => { it('can grab epg with gzip option enabled', async () => {
const cmd = `${ENV_VAR} npm run grab --- --channels=tests/__data__/input/epg-grab/sites/**/*.channels.xml --output="${path.resolve( const cmd = `${ENV_VAR} npm run grab --- --channels=tests/__data__/input/epg_grab/sites/**/*.channels.xml --output="${path.resolve(
'tests/__data__/output/guide.xml' 'tests/__data__/output/guide.xml'
)}" --gzip` )}" --gzip`
const stdout = execSync(cmd, { encoding: 'utf8' }) const stdout = execSync(cmd, { encoding: 'utf8' })
if (process.env.DEBUG === 'true') console.log(cmd, stdout) if (process.env.DEBUG === 'true') console.log(cmd, stdout)
expect(content('tests/__data__/output/guide.xml')).toEqual( expect(content('tests/__data__/output/guide.xml')).toEqual(
content('tests/__data__/expected/guide.xml') content('tests/__data__/expected/epg_grab/guide.xml')
) )
const zip = new Zip() const zip = new Zip()
const expected = await zip.decompress(fs.readFileSync('tests/__data__/output/guide.xml.gz')) const expected = await zip.decompress(fs.readFileSync('tests/__data__/output/guide.xml.gz'))
const result = await zip.decompress(fs.readFileSync('tests/__data__/expected/guide.xml.gz')) const result = await zip.decompress(
fs.readFileSync('tests/__data__/expected/epg_grab/guide.xml.gz')
)
expect(expected).toEqual(result) expect(expected).toEqual(result)
}, 30000) }, 30000)
it('can grab epg with wildcard as output', () => { it('can grab epg with wildcard as output', () => {
const cmd = `${ENV_VAR} npm run grab --- --channels=tests/__data__/input/epg-grab/sites/example.com/example.com.channels.xml --output=tests/__data__/output/guides/{lang}/{site}.xml` const cmd = `${ENV_VAR} npm run grab --- --channels=tests/__data__/input/epg_grab/sites/example.com/example.com.channels.xml --output=tests/__data__/output/guides/{lang}/{site}.xml`
const stdout = execSync(cmd, { encoding: 'utf8' }) const stdout = execSync(cmd, { encoding: 'utf8' })
if (process.env.DEBUG === 'true') console.log(cmd, stdout) if (process.env.DEBUG === 'true') console.log(cmd, stdout)
expect(content('tests/__data__/output/guides/en/example.com.xml')).toEqual( expect(content('tests/__data__/output/guides/en/example.com.xml')).toEqual(
content('tests/__data__/expected/guides/en/example.com.xml') content('tests/__data__/expected/epg_grab/guides/en/example.com.xml')
) )
expect(content('tests/__data__/output/guides/fr/example.com.xml')).toEqual( expect(content('tests/__data__/output/guides/fr/example.com.xml')).toEqual(
content('tests/__data__/expected/guides/fr/example.com.xml') content('tests/__data__/expected/epg_grab/guides/fr/example.com.xml')
) )
}) })
it('can grab epg then language filter enabled', () => { it('can grab epg then language filter enabled', () => {
const cmd = `${ENV_VAR} npm run grab --- --channels=tests/__data__/input/epg-grab/sites/example.com/example.com.channels.xml --output=tests/__data__/output/guides/{lang}/{site}.xml --lang=fr` const cmd = `${ENV_VAR} npm run grab --- --channels=tests/__data__/input/epg_grab/sites/example.com/example.com.channels.xml --output=tests/__data__/output/guides/{lang}/{site}.xml --lang=fr`
const stdout = execSync(cmd, { encoding: 'utf8' }) const stdout = execSync(cmd, { encoding: 'utf8' })
if (process.env.DEBUG === 'true') console.log(cmd, stdout) if (process.env.DEBUG === 'true') console.log(cmd, stdout)
expect(content('tests/__data__/output/guides/fr/example.com.xml')).toEqual( expect(content('tests/__data__/output/guides/fr/example.com.xml')).toEqual(
content('tests/__data__/expected/guides/fr/example.com.xml') content('tests/__data__/expected/epg_grab/guides/fr/example.com.xml')
) )
}) })
it('can grab epg using custom channels list', () => { it('can grab epg using custom channels list', () => {
const cmd = `${ENV_VAR} npm run grab --- --channels=tests/__data__/input/epg-grab/custom.channels.xml --output=tests/__data__/output/guide.xml` const cmd = `${ENV_VAR} npm run grab --- --channels=tests/__data__/input/epg_grab/custom.channels.xml --output=tests/__data__/output/guide.xml`
const stdout = execSync(cmd, { encoding: 'utf8' }) const stdout = execSync(cmd, { encoding: 'utf8' })
if (process.env.DEBUG === 'true') console.log(cmd, stdout) if (process.env.DEBUG === 'true') console.log(cmd, stdout)
expect(content('tests/__data__/output/guide.xml')).toEqual( expect(content('tests/__data__/output/guide.xml')).toEqual(
content('tests/__data__/expected/custom_guide.xml') content('tests/__data__/expected/epg_grab/guide_3.xml')
) )
}) })
it('it will raise an error if the timeout is exceeded', () => { it('it will raise an error if the timeout is exceeded', () => {
const cmd = `${ENV_VAR} npm run grab --- --channels=tests/__data__/input/epg-grab/custom.channels.xml --output=tests/__data__/output/guide.xml --timeout=0` const cmd = `${ENV_VAR} npm run grab --- --channels=tests/__data__/input/epg_grab/custom.channels.xml --output=tests/__data__/output/guide.xml --timeout=0`
const stdout = execSync(cmd, { encoding: 'utf8' }) const stdout = execSync(cmd, { encoding: 'utf8' })
if (process.env.DEBUG === 'true') console.log(cmd, stdout) if (process.env.DEBUG === 'true') console.log(cmd, stdout)
@ -106,7 +108,7 @@ describe('epg:grab', () => {
if (process.env.DEBUG === 'true') console.log(cmd, stdout) if (process.env.DEBUG === 'true') console.log(cmd, stdout)
expect(content('tests/__data__/output/guide.xml')).toEqual( expect(content('tests/__data__/output/guide.xml')).toEqual(
content('tests/__data__/expected/guide2.xml') content('tests/__data__/expected/epg_grab/guide_2.xml')
) )
}) })
@ -118,7 +120,7 @@ describe('epg:grab', () => {
if (process.env.DEBUG === 'true') console.log(cmd, stdout) if (process.env.DEBUG === 'true') console.log(cmd, stdout)
expect(content('tests/__data__/output/guide.xml')).toEqual( expect(content('tests/__data__/output/guide.xml')).toEqual(
content('tests/__data__/expected/guide2.xml') content('tests/__data__/expected/epg_grab/guide_2.xml')
) )
}) })
}) })

View file

@ -24,13 +24,13 @@ it('can create new site config from template', () => {
expect(exists('tests/__data__/output/sites/example.com/example.com.config.js')).toBe(true) expect(exists('tests/__data__/output/sites/example.com/example.com.config.js')).toBe(true)
expect(exists('tests/__data__/output/sites/example.com/readme.md')).toBe(true) expect(exists('tests/__data__/output/sites/example.com/readme.md')).toBe(true)
expect(content('tests/__data__/output/sites/example.com/example.com.test.js')).toEqual( expect(content('tests/__data__/output/sites/example.com/example.com.test.js')).toEqual(
content('tests/__data__/expected/sites/sites-init/example.com.test.js') content('tests/__data__/expected/sites_init/example.com.test.js')
) )
expect(content('tests/__data__/output/sites/example.com/example.com.config.js')).toEqual( expect(content('tests/__data__/output/sites/example.com/example.com.config.js')).toEqual(
content('tests/__data__/expected/sites/sites-init/example.com.config.js') content('tests/__data__/expected/sites_init/example.com.config.js')
) )
expect(content('tests/__data__/output/sites/example.com/readme.md')).toEqual( expect(content('tests/__data__/output/sites/example.com/readme.md')).toEqual(
content('tests/__data__/expected/sites/sites-init/readme.md') content('tests/__data__/expected/sites_init/readme.md')
) )
}) })

View file

@ -3,10 +3,10 @@ import fs from 'fs-extra'
import { pathToFileURL } from 'node:url' import { pathToFileURL } from 'node:url'
import os from 'os' import os from 'os'
let ENV_VAR = 'SITES_DIR=tests/__data__/input/sites-update/sites ROOT_DIR=tests/__data__/output' let ENV_VAR = 'SITES_DIR=tests/__data__/input/sites_update/sites ROOT_DIR=tests/__data__/output'
if (os.platform() === 'win32') { if (os.platform() === 'win32') {
ENV_VAR = ENV_VAR =
'SET "SITES_DIR=tests/__data__/input/sites-update/sites" && SET "ROOT_DIR=tests/__data__/output" &&' 'SET "SITES_DIR=tests/__data__/input/sites_update/sites" && SET "ROOT_DIR=tests/__data__/output" &&'
} }
beforeEach(() => { beforeEach(() => {
@ -20,7 +20,7 @@ it('can update SITES.md', () => {
if (process.env.DEBUG === 'true') console.log(cmd, stdout) if (process.env.DEBUG === 'true') console.log(cmd, stdout)
expect(content('tests/__data__/output/SITES.md')).toEqual( expect(content('tests/__data__/output/SITES.md')).toEqual(
content('tests/__data__/expected/SITES.md') content('tests/__data__/expected/sites_update/SITES.md')
) )
}) })

581
yarn.lock
View file

@ -20,13 +20,14 @@
"@jridgewell/gen-mapping" "^0.3.0" "@jridgewell/gen-mapping" "^0.3.0"
"@jridgewell/trace-mapping" "^0.3.9" "@jridgewell/trace-mapping" "^0.3.9"
"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.22.13", "@babel/code-frame@^7.22.5": "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.22.13", "@babel/code-frame@^7.22.5", "@babel/code-frame@^7.26.2":
version "7.22.13" version "7.26.2"
resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz" resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz"
integrity sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w== integrity sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==
dependencies: dependencies:
"@babel/highlight" "^7.22.13" "@babel/helper-validator-identifier" "^7.25.9"
chalk "^2.4.2" js-tokens "^4.0.0"
picocolors "^1.0.0"
"@babel/compat-data@^7.22.6": "@babel/compat-data@^7.22.6":
version "7.22.6" version "7.22.6"
@ -135,15 +136,15 @@
dependencies: dependencies:
"@babel/types" "^7.22.5" "@babel/types" "^7.22.5"
"@babel/helper-string-parser@^7.22.5": "@babel/helper-string-parser@^7.25.9":
version "7.22.5" version "7.25.9"
resolved "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz" resolved "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz"
integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw== integrity sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==
"@babel/helper-validator-identifier@^7.22.20", "@babel/helper-validator-identifier@^7.22.5": "@babel/helper-validator-identifier@^7.22.5", "@babel/helper-validator-identifier@^7.25.9":
version "7.22.20" version "7.25.9"
resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz" resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz"
integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== integrity sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==
"@babel/helper-validator-option@^7.22.5": "@babel/helper-validator-option@^7.22.5":
version "7.22.5" version "7.22.5"
@ -151,27 +152,19 @@
integrity sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw== integrity sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==
"@babel/helpers@^7.22.6": "@babel/helpers@^7.22.6":
version "7.22.6" version "7.27.0"
resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.6.tgz" resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.0.tgz"
integrity sha512-YjDs6y/fVOYFV8hAf1rxd1QvR9wJe1pDBZ2AREKq/SDayfPzgk0PBnVuTCE5X1acEpMMNOVUqoe+OwiZGJ+OaA== integrity sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==
dependencies: dependencies:
"@babel/template" "^7.22.5" "@babel/template" "^7.27.0"
"@babel/traverse" "^7.22.6" "@babel/types" "^7.27.0"
"@babel/types" "^7.22.5"
"@babel/highlight@^7.22.13": "@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.22.7", "@babel/parser@^7.23.3", "@babel/parser@^7.27.0":
version "7.22.20" version "7.27.0"
resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz" resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz"
integrity sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg== integrity sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==
dependencies: dependencies:
"@babel/helper-validator-identifier" "^7.22.20" "@babel/types" "^7.27.0"
chalk "^2.4.2"
js-tokens "^4.0.0"
"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.22.15", "@babel/parser@^7.22.7", "@babel/parser@^7.23.3":
version "7.23.3"
resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.23.3.tgz"
integrity sha512-uVsWNvlVsIninV2prNz/3lHCb+5CJ+e+IUBfbjToAHODtfGYLfCFuY4AU7TskI+dAKk+njsPiBjq1gKTvZOBaw==
"@babel/plugin-syntax-async-generators@^7.8.4": "@babel/plugin-syntax-async-generators@^7.8.4":
version "7.8.4" version "7.8.4"
@ -271,16 +264,16 @@
dependencies: dependencies:
"@babel/helper-plugin-utils" "^7.22.5" "@babel/helper-plugin-utils" "^7.22.5"
"@babel/template@^7.22.15", "@babel/template@^7.22.5", "@babel/template@^7.3.3": "@babel/template@^7.22.15", "@babel/template@^7.22.5", "@babel/template@^7.27.0", "@babel/template@^7.3.3":
version "7.22.15" version "7.27.0"
resolved "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz" resolved "https://registry.npmjs.org/@babel/template/-/template-7.27.0.tgz"
integrity sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w== integrity sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==
dependencies: dependencies:
"@babel/code-frame" "^7.22.13" "@babel/code-frame" "^7.26.2"
"@babel/parser" "^7.22.15" "@babel/parser" "^7.27.0"
"@babel/types" "^7.22.15" "@babel/types" "^7.27.0"
"@babel/traverse@^7.22.5", "@babel/traverse@^7.22.6", "@babel/traverse@^7.22.8": "@babel/traverse@^7.22.5", "@babel/traverse@^7.22.8":
version "7.23.3" version "7.23.3"
resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.3.tgz" resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.3.tgz"
integrity sha512-+K0yF1/9yR0oHdE0StHuEj3uTPzwwbrLGfNOndVJVV2TqA5+j3oljJUb4nmB954FLGjNem976+B+eDuLIjesiQ== integrity sha512-+K0yF1/9yR0oHdE0StHuEj3uTPzwwbrLGfNOndVJVV2TqA5+j3oljJUb4nmB954FLGjNem976+B+eDuLIjesiQ==
@ -296,14 +289,13 @@
debug "^4.1.0" debug "^4.1.0"
globals "^11.1.0" globals "^11.1.0"
"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.22.15", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.23.3", "@babel/types@^7.3.3": "@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.23.3", "@babel/types@^7.27.0", "@babel/types@^7.3.3":
version "7.23.3" version "7.27.0"
resolved "https://registry.npmjs.org/@babel/types/-/types-7.23.3.tgz" resolved "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz"
integrity sha512-OZnvoH2l8PK5eUvEcUyCt/sXgr/h+UWpVuBbOljwcrAgUl6lpchoQ++PHGyQy1AtYnVA6CEq3y5xeEI10brpXw== integrity sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==
dependencies: dependencies:
"@babel/helper-string-parser" "^7.22.5" "@babel/helper-string-parser" "^7.25.9"
"@babel/helper-validator-identifier" "^7.22.20" "@babel/helper-validator-identifier" "^7.25.9"
to-fast-properties "^2.0.0"
"@bcoe/v8-coverage@^0.2.3": "@bcoe/v8-coverage@^0.2.3":
version "0.2.3" version "0.2.3"
@ -331,10 +323,10 @@
enabled "2.0.x" enabled "2.0.x"
kuler "^2.0.0" kuler "^2.0.0"
"@esbuild/darwin-x64@0.23.1": "@esbuild/darwin-x64@0.25.2":
version "0.23.1" version "0.25.2"
resolved "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.1.tgz" resolved "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.2.tgz"
integrity sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw== integrity sha512-5eRPrTX7wFyuWe8FqEFPG2cU0+butQQVNcT4sVipqjLYQjjh8a8+vUTfgBKM88ObB85ahsnTwF7PSIt6PG+QkA==
"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0":
version "4.4.1" version "4.4.1"
@ -396,10 +388,10 @@
dependencies: dependencies:
levn "^0.4.1" levn "^0.4.1"
"@freearhey/core@^0.5.1": "@freearhey/core@^0.7.0":
version "0.5.1" version "0.7.0"
resolved "https://registry.npmjs.org/@freearhey/core/-/core-0.5.1.tgz" resolved "https://registry.npmjs.org/@freearhey/core/-/core-0.7.0.tgz"
integrity sha512-UDKIOyrtcUXaiAeIvjNFTI6DlempiOQaRB83CqHNF1VPRHNBiNhGhERWyInHE2cjLp/cc0CA/IykOYS39kBK7Q== integrity sha512-HXkKPYGY7ife7JAc1q/Qxzy0WUdSnyt3rHThCShZHgnH3rz0tpkjHFW7LNegB3he0IKn/Zc95/YSOQ97Fq8ctA==
dependencies: dependencies:
"@types/fs-extra" "^11.0.2" "@types/fs-extra" "^11.0.2"
"@types/lodash" "^4.14.198" "@types/lodash" "^4.14.198"
@ -443,6 +435,138 @@
resolved "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz" resolved "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz"
integrity sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA== integrity sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==
"@inquirer/checkbox@^4.1.4":
version "4.1.4"
resolved "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-4.1.4.tgz"
integrity sha512-d30576EZdApjAMceijXA5jDzRQHT/MygbC+J8I7EqA6f/FRpYxlRtRJbHF8gHeWYeSdOuTEJqonn7QLB1ELezA==
dependencies:
"@inquirer/core" "^10.1.9"
"@inquirer/figures" "^1.0.11"
"@inquirer/type" "^3.0.5"
ansi-escapes "^4.3.2"
yoctocolors-cjs "^2.1.2"
"@inquirer/confirm@^5.1.8":
version "5.1.8"
resolved "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.8.tgz"
integrity sha512-dNLWCYZvXDjO3rnQfk2iuJNL4Ivwz/T2+C3+WnNfJKsNGSuOs3wAo2F6e0p946gtSAk31nZMfW+MRmYaplPKsg==
dependencies:
"@inquirer/core" "^10.1.9"
"@inquirer/type" "^3.0.5"
"@inquirer/core@^10.1.9":
version "10.1.9"
resolved "https://registry.npmjs.org/@inquirer/core/-/core-10.1.9.tgz"
integrity sha512-sXhVB8n20NYkUBfDYgizGHlpRVaCRjtuzNZA6xpALIUbkgfd2Hjz+DfEN6+h1BRnuxw0/P4jCIMjMsEOAMwAJw==
dependencies:
"@inquirer/figures" "^1.0.11"
"@inquirer/type" "^3.0.5"
ansi-escapes "^4.3.2"
cli-width "^4.1.0"
mute-stream "^2.0.0"
signal-exit "^4.1.0"
wrap-ansi "^6.2.0"
yoctocolors-cjs "^2.1.2"
"@inquirer/editor@^4.2.9":
version "4.2.9"
resolved "https://registry.npmjs.org/@inquirer/editor/-/editor-4.2.9.tgz"
integrity sha512-8HjOppAxO7O4wV1ETUlJFg6NDjp/W2NP5FB9ZPAcinAlNT4ZIWOLe2pUVwmmPRSV0NMdI5r/+lflN55AwZOKSw==
dependencies:
"@inquirer/core" "^10.1.9"
"@inquirer/type" "^3.0.5"
external-editor "^3.1.0"
"@inquirer/expand@^4.0.11":
version "4.0.11"
resolved "https://registry.npmjs.org/@inquirer/expand/-/expand-4.0.11.tgz"
integrity sha512-OZSUW4hFMW2TYvX/Sv+NnOZgO8CHT2TU1roUCUIF2T+wfw60XFRRp9MRUPCT06cRnKL+aemt2YmTWwt7rOrNEA==
dependencies:
"@inquirer/core" "^10.1.9"
"@inquirer/type" "^3.0.5"
yoctocolors-cjs "^2.1.2"
"@inquirer/figures@^1.0.11":
version "1.0.11"
resolved "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.11.tgz"
integrity sha512-eOg92lvrn/aRUqbxRyvpEWnrvRuTYRifixHkYVpJiygTgVSBIHDqLh0SrMQXkafvULg3ck11V7xvR+zcgvpHFw==
"@inquirer/input@^4.1.8":
version "4.1.8"
resolved "https://registry.npmjs.org/@inquirer/input/-/input-4.1.8.tgz"
integrity sha512-WXJI16oOZ3/LiENCAxe8joniNp8MQxF6Wi5V+EBbVA0ZIOpFcL4I9e7f7cXse0HJeIPCWO8Lcgnk98juItCi7Q==
dependencies:
"@inquirer/core" "^10.1.9"
"@inquirer/type" "^3.0.5"
"@inquirer/number@^3.0.11":
version "3.0.11"
resolved "https://registry.npmjs.org/@inquirer/number/-/number-3.0.11.tgz"
integrity sha512-pQK68CsKOgwvU2eA53AG/4npRTH2pvs/pZ2bFvzpBhrznh8Mcwt19c+nMO7LHRr3Vreu1KPhNBF3vQAKrjIulw==
dependencies:
"@inquirer/core" "^10.1.9"
"@inquirer/type" "^3.0.5"
"@inquirer/password@^4.0.11":
version "4.0.11"
resolved "https://registry.npmjs.org/@inquirer/password/-/password-4.0.11.tgz"
integrity sha512-dH6zLdv+HEv1nBs96Case6eppkRggMe8LoOTl30+Gq5Wf27AO/vHFgStTVz4aoevLdNXqwE23++IXGw4eiOXTg==
dependencies:
"@inquirer/core" "^10.1.9"
"@inquirer/type" "^3.0.5"
ansi-escapes "^4.3.2"
"@inquirer/prompts@^7.4.0":
version "7.4.0"
resolved "https://registry.npmjs.org/@inquirer/prompts/-/prompts-7.4.0.tgz"
integrity sha512-EZiJidQOT4O5PYtqnu1JbF0clv36oW2CviR66c7ma4LsupmmQlUwmdReGKRp456OWPWMz3PdrPiYg3aCk3op2w==
dependencies:
"@inquirer/checkbox" "^4.1.4"
"@inquirer/confirm" "^5.1.8"
"@inquirer/editor" "^4.2.9"
"@inquirer/expand" "^4.0.11"
"@inquirer/input" "^4.1.8"
"@inquirer/number" "^3.0.11"
"@inquirer/password" "^4.0.11"
"@inquirer/rawlist" "^4.0.11"
"@inquirer/search" "^3.0.11"
"@inquirer/select" "^4.1.0"
"@inquirer/rawlist@^4.0.11":
version "4.0.11"
resolved "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-4.0.11.tgz"
integrity sha512-uAYtTx0IF/PqUAvsRrF3xvnxJV516wmR6YVONOmCWJbbt87HcDHLfL9wmBQFbNJRv5kCjdYKrZcavDkH3sVJPg==
dependencies:
"@inquirer/core" "^10.1.9"
"@inquirer/type" "^3.0.5"
yoctocolors-cjs "^2.1.2"
"@inquirer/search@^3.0.11":
version "3.0.11"
resolved "https://registry.npmjs.org/@inquirer/search/-/search-3.0.11.tgz"
integrity sha512-9CWQT0ikYcg6Ls3TOa7jljsD7PgjcsYEM0bYE+Gkz+uoW9u8eaJCRHJKkucpRE5+xKtaaDbrND+nPDoxzjYyew==
dependencies:
"@inquirer/core" "^10.1.9"
"@inquirer/figures" "^1.0.11"
"@inquirer/type" "^3.0.5"
yoctocolors-cjs "^2.1.2"
"@inquirer/select@^4.1.0":
version "4.1.0"
resolved "https://registry.npmjs.org/@inquirer/select/-/select-4.1.0.tgz"
integrity sha512-z0a2fmgTSRN+YBuiK1ROfJ2Nvrpij5lVN3gPDkQGhavdvIVGHGW29LwYZfM/j42Ai2hUghTI/uoBuTbrJk42bA==
dependencies:
"@inquirer/core" "^10.1.9"
"@inquirer/figures" "^1.0.11"
"@inquirer/type" "^3.0.5"
ansi-escapes "^4.3.2"
yoctocolors-cjs "^2.1.2"
"@inquirer/type@^3.0.5":
version "3.0.5"
resolved "https://registry.npmjs.org/@inquirer/type/-/type-3.0.5.tgz"
integrity sha512-ZJpeIYYueOz/i/ONzrfof8g89kNdO2hjGuvULROo3O8rlB2CRtSseE5KeirnyE4t/thAn/EwvS/vuQeJCn+NZg==
"@isaacs/cliui@^8.0.2": "@isaacs/cliui@^8.0.2":
version "8.0.2" version "8.0.2"
resolved "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz" resolved "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz"
@ -766,10 +890,10 @@
before-after-hook "^3.0.2" before-after-hook "^3.0.2"
universal-user-agent "^7.0.0" universal-user-agent "^7.0.0"
"@octokit/endpoint@^10.0.0": "@octokit/endpoint@^10.1.3":
version "10.1.2" version "10.1.3"
resolved "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-10.1.2.tgz" resolved "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-10.1.3.tgz"
integrity sha512-XybpFv9Ms4hX5OCHMZqyODYqGTZ3H6K6Vva+M9LR7ib/xr1y1ZnlChYv9H680y77Vd/i/k+thXApeRASBQkzhA== integrity sha512-nBRBMpKPhQUxCsQQeW+rCJ/OPSMcj3g0nfHn01zGYZXuNDvvXudF/TYY6APj5THlurerpFN4a/dQAIAaM6BYhA==
dependencies: dependencies:
"@octokit/types" "^13.6.2" "@octokit/types" "^13.6.2"
universal-user-agent "^7.0.2" universal-user-agent "^7.0.2"
@ -783,17 +907,17 @@
"@octokit/types" "^13.6.2" "@octokit/types" "^13.6.2"
universal-user-agent "^7.0.0" universal-user-agent "^7.0.0"
"@octokit/openapi-types@^22.2.0": "@octokit/openapi-types@^24.2.0":
version "22.2.0" version "24.2.0"
resolved "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-22.2.0.tgz" resolved "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz"
integrity sha512-QBhVjcUa9W7Wwhm6DBFu6ZZ+1/t/oYxqc2tp81Pi41YNuJinbFRx8B133qVOrAaBbF7D/m0Et6f9/pZt9Rc+tg== integrity sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==
"@octokit/plugin-paginate-rest@^11.3.6": "@octokit/plugin-paginate-rest@^11.3.6":
version "11.3.6" version "11.6.0"
resolved "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-11.3.6.tgz" resolved "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-11.6.0.tgz"
integrity sha512-zcvqqf/+TicbTCa/Z+3w4eBJcAxCFymtc0UAIsR3dEVoNilWld4oXdscQ3laXamTszUZdusw97K8+DrbFiOwjw== integrity sha512-n5KPteiF7pWKgBIBJSk8qzoZWcUkza2O6A0za97pMGVrGfPdltxrfmfF5GucHYvHGZD8BdaZmmHGz5cX/3gdpw==
dependencies: dependencies:
"@octokit/types" "^13.6.2" "@octokit/types" "^13.10.0"
"@octokit/plugin-rest-endpoint-methods@^13.2.6": "@octokit/plugin-rest-endpoint-methods@^13.2.6":
version "13.2.6" version "13.2.6"
@ -802,30 +926,30 @@
dependencies: dependencies:
"@octokit/types" "^13.6.1" "@octokit/types" "^13.6.1"
"@octokit/request-error@^6.0.1", "@octokit/request-error@^6.1.6": "@octokit/request-error@^6.1.6", "@octokit/request-error@^6.1.7":
version "6.1.6" version "6.1.7"
resolved "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.6.tgz" resolved "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.7.tgz"
integrity sha512-pqnVKYo/at0NuOjinrgcQYpEbv4snvP3bKMRqHaD9kIsk9u1LCpb2smHZi8/qJfgeNqLo5hNW4Z7FezNdEo0xg== integrity sha512-69NIppAwaauwZv6aOzb+VVLwt+0havz9GT5YplkeJv7fG7a40qpLt/yZKyiDxAhgz0EtgNdNcb96Z0u+Zyuy2g==
dependencies: dependencies:
"@octokit/types" "^13.6.2" "@octokit/types" "^13.6.2"
"@octokit/request@^9.1.4": "@octokit/request@^9.1.4":
version "9.2.0" version "9.2.2"
resolved "https://registry.npmjs.org/@octokit/request/-/request-9.2.0.tgz" resolved "https://registry.npmjs.org/@octokit/request/-/request-9.2.2.tgz"
integrity sha512-kXLfcxhC4ozCnAXy2ff+cSxpcF0A1UqxjvYMqNuPIeOAzJbVWQ+dy5G2fTylofB/gTbObT8O6JORab+5XtA1Kw== integrity sha512-dZl0ZHx6gOQGcffgm1/Sf6JfEpmh34v3Af2Uci02vzUYz6qEN6zepoRtmybWXIGXFIK8K9ylE3b+duCWqhArtg==
dependencies: dependencies:
"@octokit/endpoint" "^10.0.0" "@octokit/endpoint" "^10.1.3"
"@octokit/request-error" "^6.0.1" "@octokit/request-error" "^6.1.7"
"@octokit/types" "^13.6.2" "@octokit/types" "^13.6.2"
fast-content-type-parse "^2.0.0" fast-content-type-parse "^2.0.0"
universal-user-agent "^7.0.2" universal-user-agent "^7.0.2"
"@octokit/types@^13.6.1", "@octokit/types@^13.6.2": "@octokit/types@^13.10.0", "@octokit/types@^13.6.1", "@octokit/types@^13.6.2":
version "13.6.2" version "13.10.0"
resolved "https://registry.npmjs.org/@octokit/types/-/types-13.6.2.tgz" resolved "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz"
integrity sha512-WpbZfZUcZU77DrSW4wbsSgTPfKcp286q3ItaIgvSbBpZJlu6mnYXAkjZz6LVZPXkEvLIM8McanyZejKTYUHipA== integrity sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==
dependencies: dependencies:
"@octokit/openapi-types" "^22.2.0" "@octokit/openapi-types" "^24.2.0"
"@pkgjs/parseargs@^0.11.0": "@pkgjs/parseargs@^0.11.0":
version "0.11.0" version "0.11.0"
@ -1142,7 +1266,7 @@
resolved "https://registry.npmjs.org/@types/node-cleanup/-/node-cleanup-2.1.2.tgz" resolved "https://registry.npmjs.org/@types/node-cleanup/-/node-cleanup-2.1.2.tgz"
integrity sha512-HTksao/sZs9nqxKD/vWOR3WxSrQsyJlBPEFFCgq9lMmhRsuQF+2p6hy+7FaCYn6lOeiDc3ywI8jDQ2bz5y6m8w== integrity sha512-HTksao/sZs9nqxKD/vWOR3WxSrQsyJlBPEFFCgq9lMmhRsuQF+2p6hy+7FaCYn6lOeiDc3ywI8jDQ2bz5y6m8w==
"@types/node@*": "@types/node@*", "@types/node@>=18":
version "20.7.1" version "20.7.1"
resolved "https://registry.npmjs.org/@types/node/-/node-20.7.1.tgz" resolved "https://registry.npmjs.org/@types/node/-/node-20.7.1.tgz"
integrity sha512-LT+OIXpp2kj4E2S/p91BMe+VgGX2+lfO+XTpfXhh+bCk2LkQtHZSub8ewFBMGP5ClysPjTDFa4sMI8Q3n4T0wg== integrity sha512-LT+OIXpp2kj4E2S/p91BMe+VgGX2+lfO+XTpfXhh+bCk2LkQtHZSub8ewFBMGP5ClysPjTDFa4sMI8Q3n4T0wg==
@ -1376,7 +1500,7 @@ ansi-colors@^4.1.1:
resolved "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz" resolved "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz"
integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw== integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==
ansi-escapes@^4.2.1: ansi-escapes@^4.2.1, ansi-escapes@^4.3.2:
version "4.3.2" version "4.3.2"
resolved "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz" resolved "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz"
integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==
@ -1524,9 +1648,9 @@ axios-mock-adapter@^1.20.0:
is-buffer "^2.0.5" is-buffer "^2.0.5"
axios@^1.5.1, axios@^1.6.1, axios@^1.7.9, "axios@>= 0.9.0", axios@>=0.20.0: axios@^1.5.1, axios@^1.6.1, axios@^1.7.9, "axios@>= 0.9.0", axios@>=0.20.0:
version "1.7.9" version "1.8.4"
resolved "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz" resolved "https://registry.npmjs.org/axios/-/axios-1.8.4.tgz"
integrity sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw== integrity sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw==
dependencies: dependencies:
follow-redirects "^1.15.6" follow-redirects "^1.15.6"
form-data "^4.0.0" form-data "^4.0.0"
@ -1597,11 +1721,6 @@ balanced-match@^1.0.0:
resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz"
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
base64-js@^1.3.1:
version "1.5.1"
resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz"
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
basic-ftp@^5.0.2: basic-ftp@^5.0.2:
version "5.0.5" version "5.0.5"
resolved "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz" resolved "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz"
@ -1617,15 +1736,6 @@ binary-extensions@^2.0.0:
resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz" resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz"
integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==
bl@^4.1.0:
version "4.1.0"
resolved "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz"
integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==
dependencies:
buffer "^5.5.0"
inherits "^2.0.4"
readable-stream "^3.4.0"
blessed@0.1.81: blessed@0.1.81:
version "0.1.81" version "0.1.81"
resolved "https://registry.npmjs.org/blessed/-/blessed-0.1.81.tgz" resolved "https://registry.npmjs.org/blessed/-/blessed-0.1.81.tgz"
@ -1699,14 +1809,6 @@ buffer-from@^1.0.0:
resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz" resolved "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz"
integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==
buffer@^5.5.0:
version "5.7.1"
resolved "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz"
integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==
dependencies:
base64-js "^1.3.1"
ieee754 "^1.1.13"
bytes@3.0.0: bytes@3.0.0:
version "3.0.0" version "3.0.0"
resolved "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz" resolved "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz"
@ -1781,16 +1883,7 @@ chalk@^2.3.2:
escape-string-regexp "^1.0.5" escape-string-regexp "^1.0.5"
supports-color "^5.3.0" supports-color "^5.3.0"
chalk@^2.4.2: chalk@^4.0.0, chalk@^4.1.2:
version "2.4.2"
resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz"
integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
dependencies:
ansi-styles "^3.2.1"
escape-string-regexp "^1.0.5"
supports-color "^5.3.0"
chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1, chalk@^4.1.2:
version "4.1.2" version "4.1.2"
resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz"
integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
@ -1894,13 +1987,6 @@ cli-boxes@^3.0.0:
resolved "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz" resolved "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz"
integrity sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g== integrity sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==
cli-cursor@^3.1.0:
version "3.1.0"
resolved "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz"
integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==
dependencies:
restore-cursor "^3.1.0"
cli-progress@^3.12.0: cli-progress@^3.12.0:
version "3.12.0" version "3.12.0"
resolved "https://registry.npmjs.org/cli-progress/-/cli-progress-3.12.0.tgz" resolved "https://registry.npmjs.org/cli-progress/-/cli-progress-3.12.0.tgz"
@ -1908,11 +1994,6 @@ cli-progress@^3.12.0:
dependencies: dependencies:
string-width "^4.2.3" string-width "^4.2.3"
cli-spinners@^2.5.0:
version "2.9.1"
resolved "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.1.tgz"
integrity sha512-jHgecW0pxkonBJdrKsqxgRX9AcG+u/5k0Q7WPDfi8AogLAdwxEkyYYNWwZ5GvVFoFx2uiY1eNcSK00fh+1+FyQ==
cli-tableau@^2.0.0: cli-tableau@^2.0.0:
version "2.0.1" version "2.0.1"
resolved "https://registry.npmjs.org/cli-tableau/-/cli-tableau-2.0.1.tgz" resolved "https://registry.npmjs.org/cli-tableau/-/cli-tableau-2.0.1.tgz"
@ -1920,10 +2001,10 @@ cli-tableau@^2.0.0:
dependencies: dependencies:
chalk "3.0.0" chalk "3.0.0"
cli-width@^3.0.0: cli-width@^4.1.0:
version "3.0.0" version "4.1.0"
resolved "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz" resolved "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz"
integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw== integrity sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==
clipboardy@3.0.0: clipboardy@3.0.0:
version "3.0.0" version "3.0.0"
@ -1959,11 +2040,6 @@ clone-response@^1.0.2:
dependencies: dependencies:
mimic-response "^1.0.0" mimic-response "^1.0.0"
clone@^1.0.2:
version "1.0.4"
resolved "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz"
integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==
co@^4.6.0: co@^4.6.0:
version "4.6.0" version "4.6.0"
resolved "https://registry.npmjs.org/co/-/co-4.6.0.tgz" resolved "https://registry.npmjs.org/co/-/co-4.6.0.tgz"
@ -2003,7 +2079,7 @@ color-name@^1.0.0, color-name@~1.1.4:
color-name@1.1.3: color-name@1.1.3:
version "1.1.3" version "1.1.3"
resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz"
integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
color-string@^1.6.0: color-string@^1.6.0:
version "1.9.1" version "1.9.1"
@ -2245,13 +2321,6 @@ deepmerge@^4.2.2:
resolved "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz" resolved "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz"
integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==
defaults@^1.0.3:
version "1.0.4"
resolved "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz"
integrity sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==
dependencies:
clone "^1.0.2"
defer-to-connect@^2.0.0: defer-to-connect@^2.0.0:
version "2.0.1" version "2.0.1"
resolved "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz" resolved "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz"
@ -2411,35 +2480,36 @@ error-ex@^1.3.1:
dependencies: dependencies:
is-arrayish "^0.2.1" is-arrayish "^0.2.1"
esbuild@~0.23.0: esbuild@~0.25.0:
version "0.23.1" version "0.25.2"
resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.23.1.tgz" resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.25.2.tgz"
integrity sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg== integrity sha512-16854zccKPnC+toMywC+uKNeYSv+/eXkevRAfwRD/G9Cleq66m8XFIrigkbvauLLlCfDL45Q2cWegSg53gGBnQ==
optionalDependencies: optionalDependencies:
"@esbuild/aix-ppc64" "0.23.1" "@esbuild/aix-ppc64" "0.25.2"
"@esbuild/android-arm" "0.23.1" "@esbuild/android-arm" "0.25.2"
"@esbuild/android-arm64" "0.23.1" "@esbuild/android-arm64" "0.25.2"
"@esbuild/android-x64" "0.23.1" "@esbuild/android-x64" "0.25.2"
"@esbuild/darwin-arm64" "0.23.1" "@esbuild/darwin-arm64" "0.25.2"
"@esbuild/darwin-x64" "0.23.1" "@esbuild/darwin-x64" "0.25.2"
"@esbuild/freebsd-arm64" "0.23.1" "@esbuild/freebsd-arm64" "0.25.2"
"@esbuild/freebsd-x64" "0.23.1" "@esbuild/freebsd-x64" "0.25.2"
"@esbuild/linux-arm" "0.23.1" "@esbuild/linux-arm" "0.25.2"
"@esbuild/linux-arm64" "0.23.1" "@esbuild/linux-arm64" "0.25.2"
"@esbuild/linux-ia32" "0.23.1" "@esbuild/linux-ia32" "0.25.2"
"@esbuild/linux-loong64" "0.23.1" "@esbuild/linux-loong64" "0.25.2"
"@esbuild/linux-mips64el" "0.23.1" "@esbuild/linux-mips64el" "0.25.2"
"@esbuild/linux-ppc64" "0.23.1" "@esbuild/linux-ppc64" "0.25.2"
"@esbuild/linux-riscv64" "0.23.1" "@esbuild/linux-riscv64" "0.25.2"
"@esbuild/linux-s390x" "0.23.1" "@esbuild/linux-s390x" "0.25.2"
"@esbuild/linux-x64" "0.23.1" "@esbuild/linux-x64" "0.25.2"
"@esbuild/netbsd-x64" "0.23.1" "@esbuild/netbsd-arm64" "0.25.2"
"@esbuild/openbsd-arm64" "0.23.1" "@esbuild/netbsd-x64" "0.25.2"
"@esbuild/openbsd-x64" "0.23.1" "@esbuild/openbsd-arm64" "0.25.2"
"@esbuild/sunos-x64" "0.23.1" "@esbuild/openbsd-x64" "0.25.2"
"@esbuild/win32-arm64" "0.23.1" "@esbuild/sunos-x64" "0.25.2"
"@esbuild/win32-ia32" "0.23.1" "@esbuild/win32-arm64" "0.25.2"
"@esbuild/win32-x64" "0.23.1" "@esbuild/win32-ia32" "0.25.2"
"@esbuild/win32-x64" "0.25.2"
escalade@^3.1.1: escalade@^3.1.1:
version "3.1.1" version "3.1.1"
@ -2619,7 +2689,7 @@ expect@^29.0.0, expect@^29.7.0:
jest-message-util "^29.7.0" jest-message-util "^29.7.0"
jest-util "^29.7.0" jest-util "^29.7.0"
external-editor@^3.0.3: external-editor@^3.1.0:
version "3.1.0" version "3.1.0"
resolved "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz" resolved "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz"
integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==
@ -2707,13 +2777,6 @@ figures@^2.0.0:
dependencies: dependencies:
escape-string-regexp "^1.0.5" escape-string-regexp "^1.0.5"
figures@^3.0.0:
version "3.2.0"
resolved "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz"
integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==
dependencies:
escape-string-regexp "^1.0.5"
file-entry-cache@^8.0.0: file-entry-cache@^8.0.0:
version "8.0.0" version "8.0.0"
resolved "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz" resolved "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz"
@ -2971,7 +3034,7 @@ graphemer@^1.4.0:
has-flag@^3.0.0: has-flag@^3.0.0:
version "3.0.0" version "3.0.0"
resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz"
integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
has-flag@^4.0.0: has-flag@^4.0.0:
version "4.0.0" version "4.0.0"
@ -3053,11 +3116,6 @@ iconv-lite@^0.4.24, iconv-lite@^0.4.4:
dependencies: dependencies:
safer-buffer ">= 2.1.2 < 3" safer-buffer ">= 2.1.2 < 3"
ieee754@^1.1.13:
version "1.2.1"
resolved "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz"
integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
ignore@^5.2.0, ignore@^5.3.1: ignore@^5.2.0, ignore@^5.3.1:
version "5.3.2" version "5.3.2"
resolved "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz" resolved "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz"
@ -3097,7 +3155,7 @@ inflight@^1.0.4:
once "^1.3.0" once "^1.3.0"
wrappy "1" wrappy "1"
inherits@^2.0.3, inherits@^2.0.4, inherits@2: inherits@^2.0.3, inherits@2:
version "2.0.4" version "2.0.4"
resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
@ -3107,26 +3165,18 @@ ini@^1.3.5, ini@~1.3.0:
resolved "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz" resolved "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz"
integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==
inquirer@^8.2.6: inquirer@^12.5.0:
version "8.2.6" version "12.5.0"
resolved "https://registry.npmjs.org/inquirer/-/inquirer-8.2.6.tgz" resolved "https://registry.npmjs.org/inquirer/-/inquirer-12.5.0.tgz"
integrity sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg== integrity sha512-aiBBq5aKF1k87MTxXDylLfwpRwToShiHrSv4EmB07EYyLgmnjEz5B3rn0aGw1X3JA/64Ngf2T54oGwc+BCsPIQ==
dependencies: dependencies:
ansi-escapes "^4.2.1" "@inquirer/core" "^10.1.9"
chalk "^4.1.1" "@inquirer/prompts" "^7.4.0"
cli-cursor "^3.1.0" "@inquirer/type" "^3.0.5"
cli-width "^3.0.0" ansi-escapes "^4.3.2"
external-editor "^3.0.3" mute-stream "^2.0.0"
figures "^3.0.0" run-async "^3.0.0"
lodash "^4.17.21" rxjs "^7.8.2"
mute-stream "0.0.8"
ora "^5.4.1"
run-async "^2.4.0"
rxjs "^7.5.5"
string-width "^4.1.0"
strip-ansi "^6.0.0"
through "^2.3.6"
wrap-ansi "^6.0.1"
ip-address@^9.0.5: ip-address@^9.0.5:
version "9.0.5" version "9.0.5"
@ -3197,11 +3247,6 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1:
dependencies: dependencies:
is-extglob "^2.1.1" is-extglob "^2.1.1"
is-interactive@^1.0.0:
version "1.0.0"
resolved "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz"
integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==
is-number@^7.0.0: is-number@^7.0.0:
version "7.0.0" version "7.0.0"
resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz" resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz"
@ -3217,11 +3262,6 @@ is-stream@^2.0.0:
resolved "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz" resolved "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz"
integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==
is-unicode-supported@^0.1.0:
version "0.1.0"
resolved "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz"
integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==
is-wsl@^2.2.0: is-wsl@^2.2.0:
version "2.2.0" version "2.2.0"
resolved "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz" resolved "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz"
@ -3868,14 +3908,6 @@ lodash@^4.17.14, lodash@^4.17.21:
resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz" resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
log-symbols@^4.1.0:
version "4.1.0"
resolved "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz"
integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==
dependencies:
chalk "^4.1.0"
is-unicode-supported "^0.1.0"
logform@^2.3.2, logform@^2.4.0: logform@^2.3.2, logform@^2.4.0:
version "2.4.0" version "2.4.0"
resolved "https://registry.npmjs.org/logform/-/logform-2.4.0.tgz" resolved "https://registry.npmjs.org/logform/-/logform-2.4.0.tgz"
@ -4070,7 +4102,12 @@ ms@2.1.2:
resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz"
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
mute-stream@~0.0.4, mute-stream@0.0.8: mute-stream@^2.0.0:
version "2.0.0"
resolved "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz"
integrity sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==
mute-stream@~0.0.4:
version "0.0.8" version "0.0.8"
resolved "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz" resolved "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz"
integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==
@ -4202,7 +4239,7 @@ one-time@^1.0.0:
dependencies: dependencies:
fn.name "1.x.x" fn.name "1.x.x"
onetime@^5.1.0, onetime@^5.1.2: onetime@^5.1.2:
version "5.1.2" version "5.1.2"
resolved "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz" resolved "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz"
integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==
@ -4221,21 +4258,6 @@ optionator@^0.9.3:
prelude-ls "^1.2.1" prelude-ls "^1.2.1"
type-check "^0.4.0" type-check "^0.4.0"
ora@^5.4.1:
version "5.4.1"
resolved "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz"
integrity sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==
dependencies:
bl "^4.1.0"
chalk "^4.1.0"
cli-cursor "^3.1.0"
cli-spinners "^2.5.0"
is-interactive "^1.0.0"
is-unicode-supported "^0.1.0"
log-symbols "^4.1.0"
strip-ansi "^6.0.0"
wcwidth "^1.0.1"
os-tmpdir@~1.0.2: os-tmpdir@~1.0.2:
version "1.0.2" version "1.0.2"
resolved "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz" resolved "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz"
@ -4337,10 +4359,10 @@ parent-module@^1.0.0:
dependencies: dependencies:
callsites "^3.0.0" callsites "^3.0.0"
parse-duration@^1.0.0: parse-duration@^2.1.3:
version "1.0.2" version "2.1.3"
resolved "https://registry.npmjs.org/parse-duration/-/parse-duration-1.0.2.tgz" resolved "https://registry.npmjs.org/parse-duration/-/parse-duration-2.1.3.tgz"
integrity sha512-Dg27N6mfok+ow1a2rj/nRjtCfaKrHUZV2SJpEn/s8GaVUSlf4GGRCRP1c13Hj+wfPKVMrFDqLMLITkYKgKxyyg== integrity sha512-MtbharL7Bets65qDBXuDOHHWyY1BxTJZmJ/xGmS90iEbKE0gZ6yZpZtCda7O79GeOi/f0NwBaplIuReExIoVsw==
parse-json@^4.0.0: parse-json@^4.0.0:
version "4.0.0" version "4.0.0"
@ -4761,23 +4783,15 @@ responselike@^2.0.0:
dependencies: dependencies:
lowercase-keys "^2.0.0" lowercase-keys "^2.0.0"
restore-cursor@^3.1.0:
version "3.1.0"
resolved "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz"
integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==
dependencies:
onetime "^5.1.0"
signal-exit "^3.0.2"
reusify@^1.0.4: reusify@^1.0.4:
version "1.0.4" version "1.0.4"
resolved "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz" resolved "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz"
integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
run-async@^2.4.0: run-async@^3.0.0:
version "2.4.1" version "3.0.0"
resolved "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz" resolved "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz"
integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== integrity sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==
run-parallel@^1.1.9: run-parallel@^1.1.9:
version "1.2.0" version "1.2.0"
@ -4796,10 +4810,10 @@ run-series@^1.1.8:
resolved "https://registry.npmjs.org/run-series/-/run-series-1.1.9.tgz" resolved "https://registry.npmjs.org/run-series/-/run-series-1.1.9.tgz"
integrity sha512-Arc4hUN896vjkqCYrUXquBFtRZdv1PfLbTYP71efP6butxyQ0kWpiNJyAgsxscmQg1cqvHY32/UCBzXedTpU2g== integrity sha512-Arc4hUN896vjkqCYrUXquBFtRZdv1PfLbTYP71efP6butxyQ0kWpiNJyAgsxscmQg1cqvHY32/UCBzXedTpU2g==
rxjs@^7.2.0, rxjs@^7.5.5: rxjs@^7.2.0, rxjs@^7.8.2:
version "7.8.1" version "7.8.2"
resolved "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz" resolved "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz"
integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== integrity sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==
dependencies: dependencies:
tslib "^2.1.0" tslib "^2.1.0"
@ -4928,7 +4942,7 @@ shimmer@^1.2.0:
resolved "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz" resolved "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz"
integrity sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw== integrity sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==
signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: signal-exit@^3.0.3, signal-exit@^3.0.7:
version "3.0.7" version "3.0.7"
resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz" resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz"
integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==
@ -4938,6 +4952,11 @@ signal-exit@^4.0.1:
resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz" resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz"
integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==
signal-exit@^4.1.0:
version "4.1.0"
resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz"
integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==
signale@^1.4.0: signale@^1.4.0:
version "1.4.0" version "1.4.0"
resolved "https://registry.npmjs.org/signale/-/signale-1.4.0.tgz" resolved "https://registry.npmjs.org/signale/-/signale-1.4.0.tgz"
@ -5192,11 +5211,6 @@ text-hex@1.0.x:
resolved "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz" resolved "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz"
integrity sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg== integrity sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==
through@^2.3.6:
version "2.3.8"
resolved "https://registry.npmjs.org/through/-/through-2.3.8.tgz"
integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==
tldts-core@^6.1.68: tldts-core@^6.1.68:
version "6.1.68" version "6.1.68"
resolved "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.68.tgz" resolved "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.68.tgz"
@ -5221,11 +5235,6 @@ tmpl@1.0.5:
resolved "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz" resolved "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz"
integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==
to-fast-properties@^2.0.0:
version "2.0.0"
resolved "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz"
integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==
to-regex-range@^5.0.1: to-regex-range@^5.0.1:
version "5.0.1" version "5.0.1"
resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz" resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz"
@ -5292,11 +5301,11 @@ tslib@1.9.3:
integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ== integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==
tsx@^4.19.2: tsx@^4.19.2:
version "4.19.2" version "4.19.3"
resolved "https://registry.npmjs.org/tsx/-/tsx-4.19.2.tgz" resolved "https://registry.npmjs.org/tsx/-/tsx-4.19.3.tgz"
integrity sha512-pOUl6Vo2LUq/bSa8S5q7b91cgNSjctn9ugq/+Mvow99qW6x/UZYwzxy/3NmqoT66eHYfCVvFvACC58UBPFf28g== integrity sha512-4H8vUNGNjQ4V2EOoGw005+c+dGuPSnhpPBPHBtsZdGZBk/iJb4kguGlPWaZTZ3q5nMtFOEsY0nRDlh9PJyd6SQ==
dependencies: dependencies:
esbuild "~0.23.0" esbuild "~0.25.0"
get-tsconfig "^4.7.5" get-tsconfig "^4.7.5"
optionalDependencies: optionalDependencies:
fsevents "~2.3.3" fsevents "~2.3.3"
@ -5426,13 +5435,6 @@ walker@^1.0.8:
dependencies: dependencies:
makeerror "1.0.12" makeerror "1.0.12"
wcwidth@^1.0.1:
version "1.0.1"
resolved "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz"
integrity sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==
dependencies:
defaults "^1.0.3"
which@^2.0.1: which@^2.0.1:
version "2.0.2" version "2.0.2"
resolved "https://registry.npmjs.org/which/-/which-2.0.2.tgz" resolved "https://registry.npmjs.org/which/-/which-2.0.2.tgz"
@ -5486,7 +5488,7 @@ winston@^3.3.3:
string-width "^4.1.0" string-width "^4.1.0"
strip-ansi "^6.0.0" strip-ansi "^6.0.0"
wrap-ansi@^6.0.1: wrap-ansi@^6.2.0:
version "6.2.0" version "6.2.0"
resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz" resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz"
integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==
@ -5607,3 +5609,8 @@ yocto-queue@^0.1.0:
version "0.1.0" version "0.1.0"
resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz" resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz"
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
yoctocolors-cjs@^2.1.2:
version "2.1.2"
resolved "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.2.tgz"
integrity sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==