diff --git a/.github/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md index 760ee26d2c..91ec0a38e8 100644 --- a/.github/CODE_OF_CONDUCT.md +++ b/.github/CODE_OF_CONDUCT.md @@ -1,13 +1,13 @@ -# Contributor Code of Conduct - -As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities. - -We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion. - -Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct. - -Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team. - -Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers. - -This Code of Conduct is adapted from the [Contributor Covenant](http:contributor-covenant.org), version 1.0.0, available at https://www.contributor-covenant.org/version/1/0/0/code-of-conduct.html +# Contributor Code of Conduct + +As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities. + +We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion. + +Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct. + +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team. + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers. + +This Code of Conduct is adapted from the [Contributor Covenant](http:contributor-covenant.org), version 1.0.0, available at https://www.contributor-covenant.org/version/1/0/0/code-of-conduct.html diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 7d4c3fe13e..0e164e4b09 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,12 +1,12 @@ -# These are supported funding model platforms - -github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] -patreon: # Replace with a single Patreon username -open_collective: iptv-org -ko_fi: # Replace with a single Ko-fi username -tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel -community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry -liberapay: # Replace with a single Liberapay username -issuehunt: # Replace with a single IssueHunt username -otechie: # Replace with a single Otechie username -custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] +# These are supported funding model platforms + +github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] +patreon: # Replace with a single Patreon username +open_collective: iptv-org +ko_fi: # Replace with a single Ko-fi username +tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +otechie: # Replace with a single Otechie username +custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] diff --git a/.github/ISSUE_TEMPLATE/1_streams_add.yml b/.github/ISSUE_TEMPLATE/1_streams_add.yml index 6a49621a26..6c54d31493 100644 --- a/.github/ISSUE_TEMPLATE/1_streams_add.yml +++ b/.github/ISSUE_TEMPLATE/1_streams_add.yml @@ -1,82 +1,82 @@ -name: ➕ Add stream -description: Request to add a new stream link into the playlist -title: 'Add: ' -labels: ['streams:add'] - -body: - - type: input - id: stream_id - attributes: - label: Stream ID (required) - description: "ID of the stream consisting of `` or `@`. Full list of supported channels with corresponding ID could be found on [iptv-org.github.io](https://iptv-org.github.io/). If you can't find the channel you want in the list, please let us know through this [form](https://github.com/iptv-org/database/issues/new?assignees=&labels=channels%3Aadd&projects=&template=channels_add.yml&title=Add%3A+) before posting your request." - placeholder: 'BBCAmerica.us@East' - validations: - required: true - - - type: input - id: stream_url - attributes: - label: Stream URL (required) - description: Link to be added to the playlist - placeholder: 'https://example.com/playlist.m3u8' - validations: - required: true - - - type: dropdown - id: quality - attributes: - label: Quality - description: Maximum video resolution available on the link - options: - - 2160p - - 1280p - - 1080p - - 1080i - - 720p - - 576p - - 576i - - 480p - - 480i - - 360p - - - type: dropdown - id: label - attributes: - label: Label - description: Is there any reason why the broadcast may not work? - options: - - 'Not 24/7' - - 'Geo-blocked' - - - type: input - id: http_user_agent - attributes: - label: HTTP User Agent - placeholder: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36 Edge/12.246' - - - type: input - id: http_referrer - attributes: - label: HTTP Referrer - placeholder: 'https://example.com/' - - - type: textarea - id: directives - attributes: - label: Directives - description: 'List of directives telling players how to play the stream. Supported `#KODIPROP` and `#VLCOPT`.' - placeholder: '#KODIPROP:inputstream=inputstream.adaptive' - - - type: textarea - id: notes - attributes: - label: Notes - description: 'Anything else we should know about this broadcast?' - - - type: checkboxes - attributes: - label: Contributing Guide - description: 'Please read this guide before posting your request' - options: - - label: I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md) - required: true +name: ➕ Add stream +description: Request to add a new stream link into the playlist +title: 'Add: ' +labels: ['streams:add'] + +body: + - type: input + id: stream_id + attributes: + label: Stream ID (required) + description: "ID of the stream consisting of `` or `@`. Full list of supported channels with corresponding ID could be found on [iptv-org.github.io](https://iptv-org.github.io/). If you can't find the channel you want in the list, please let us know through this [form](https://github.com/iptv-org/database/issues/new?assignees=&labels=channels%3Aadd&projects=&template=channels_add.yml&title=Add%3A+) before posting your request." + placeholder: 'BBCAmerica.us@East' + validations: + required: true + + - type: input + id: stream_url + attributes: + label: Stream URL (required) + description: Link to be added to the playlist + placeholder: 'https://example.com/playlist.m3u8' + validations: + required: true + + - type: dropdown + id: quality + attributes: + label: Quality + description: Maximum video resolution available on the link + options: + - 2160p + - 1280p + - 1080p + - 1080i + - 720p + - 576p + - 576i + - 480p + - 480i + - 360p + + - type: dropdown + id: label + attributes: + label: Label + description: Is there any reason why the broadcast may not work? + options: + - 'Not 24/7' + - 'Geo-blocked' + + - type: input + id: http_user_agent + attributes: + label: HTTP User Agent + placeholder: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36 Edge/12.246' + + - type: input + id: http_referrer + attributes: + label: HTTP Referrer + placeholder: 'https://example.com/' + + - type: textarea + id: directives + attributes: + label: Directives + description: 'List of directives telling players how to play the stream. Supported `#KODIPROP` and `#EXTVLCOPT`.' + placeholder: '#KODIPROP:inputstream=inputstream.adaptive' + + - type: textarea + id: notes + attributes: + label: Notes + description: 'Anything else we should know about this broadcast?' + + - type: checkboxes + attributes: + label: Contributing Guide + description: 'Please read this guide before posting your request' + options: + - label: I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md) + required: true diff --git a/.github/ISSUE_TEMPLATE/2_streams_edit.yml b/.github/ISSUE_TEMPLATE/2_streams_edit.yml index ece9afd024..7cd0b8a9f0 100644 --- a/.github/ISSUE_TEMPLATE/2_streams_edit.yml +++ b/.github/ISSUE_TEMPLATE/2_streams_edit.yml @@ -1,94 +1,94 @@ -name: ✏️ Edit stream -description: Request to edit stream description -title: 'Edit: ' -labels: ['streams:edit'] - -body: - - type: input - id: stream_url - attributes: - label: Stream URL (required) - description: Link to the stream to be updated - placeholder: 'https://lnc-kdfw-fox-aws.tubi.video/index.m3u8' - validations: - required: true - - - type: markdown - attributes: - value: | - What exactly needs to be changed? To delete an existing value without replacement use the `~` symbol. - - - type: input - id: new_stream_url - attributes: - label: New Stream URL - description: New link to the stream - placeholder: 'https://servilive.com:3126/live/tele2000live.m3u8' - - - type: input - id: stream_id - attributes: - label: Stream ID - description: "ID of the stream consisting of `` or `@`. Full list of supported channels with corresponding ID could be found on [iptv-org.github.io](https://iptv-org.github.io/). If you can't find the channel you want in the list, please let us know through this [form](https://github.com/iptv-org/database/issues/new?assignees=&labels=channels%3Aadd&projects=&template=channels_add.yml&title=Add%3A+) before posting your request." - placeholder: 'BBCAmerica.us@East' - - - type: dropdown - id: quality - attributes: - label: Quality - description: Maximum video resolution available on the link - options: - - 2160p - - 1280p - - 1080p - - 1080i - - 720p - - 576p - - 576i - - 480p - - 480i - - 360p - - '~' - - - type: dropdown - id: label - attributes: - label: Label - description: Is there any reason why the broadcast may not work? - options: - - 'Not 24/7' - - 'Geo-blocked' - - '~' - - - type: input - id: http_user_agent - attributes: - label: HTTP User Agent - placeholder: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36 Edge/12.246' - - - type: input - id: http_referrer - attributes: - label: HTTP Referrer - placeholder: 'https://example.com/' - - - type: textarea - id: directives - attributes: - label: Directives - description: 'List of directives telling players how to play the stream. Supported `#KODIPROP` and `#VLCOPT`.' - placeholder: '#KODIPROP:inputstream=inputstream.adaptive' - - - type: textarea - id: notes - attributes: - label: Notes - placeholder: 'Anything else we should know?' - - - type: checkboxes - attributes: - label: Contributing Guide - description: 'Please read this guide before posting your request' - options: - - label: I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md) - required: true +name: ✏️ Edit stream +description: Request to edit stream description +title: 'Edit: ' +labels: ['streams:edit'] + +body: + - type: input + id: stream_url + attributes: + label: Stream URL (required) + description: Link to the stream to be updated + placeholder: 'https://lnc-kdfw-fox-aws.tubi.video/index.m3u8' + validations: + required: true + + - type: markdown + attributes: + value: | + What exactly needs to be changed? To delete an existing value without replacement use the `~` symbol. + + - type: input + id: new_stream_url + attributes: + label: New Stream URL + description: New link to the stream + placeholder: 'https://servilive.com:3126/live/tele2000live.m3u8' + + - type: input + id: stream_id + attributes: + label: Stream ID + description: "ID of the stream consisting of `` or `@`. Full list of supported channels with corresponding ID could be found on [iptv-org.github.io](https://iptv-org.github.io/). If you can't find the channel you want in the list, please let us know through this [form](https://github.com/iptv-org/database/issues/new?assignees=&labels=channels%3Aadd&projects=&template=channels_add.yml&title=Add%3A+) before posting your request." + placeholder: 'BBCAmerica.us@East' + + - type: dropdown + id: quality + attributes: + label: Quality + description: Maximum video resolution available on the link + options: + - 2160p + - 1280p + - 1080p + - 1080i + - 720p + - 576p + - 576i + - 480p + - 480i + - 360p + - '~' + + - type: dropdown + id: label + attributes: + label: Label + description: Is there any reason why the broadcast may not work? + options: + - 'Not 24/7' + - 'Geo-blocked' + - '~' + + - type: input + id: http_user_agent + attributes: + label: HTTP User Agent + placeholder: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36 Edge/12.246' + + - type: input + id: http_referrer + attributes: + label: HTTP Referrer + placeholder: 'https://example.com/' + + - type: textarea + id: directives + attributes: + label: Directives + description: 'List of directives telling players how to play the stream. Supported `#KODIPROP` and `#EXTVLCOPT`.' + placeholder: '#KODIPROP:inputstream=inputstream.adaptive' + + - type: textarea + id: notes + attributes: + label: Notes + placeholder: 'Anything else we should know?' + + - type: checkboxes + attributes: + label: Contributing Guide + description: 'Please read this guide before posting your request' + options: + - label: I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md) + required: true diff --git a/.github/ISSUE_TEMPLATE/3_streams_report.yml b/.github/ISSUE_TEMPLATE/3_streams_report.yml index 8ed86525f0..b55918cfc7 100644 --- a/.github/ISSUE_TEMPLATE/3_streams_report.yml +++ b/.github/ISSUE_TEMPLATE/3_streams_report.yml @@ -1,49 +1,49 @@ -name: 🚧 Report a stream -description: Report a broken or unstable stream -title: 'Report: ' -labels: ['streams:remove'] - -body: - - type: markdown - attributes: - value: | - Please fill out the form as much as you can so we could efficiently process your request. To suggest a new replacement link, use this [form](https://github.com/iptv-org/iptv/issues/new?assignees=&labels=streams:add&projects=&template=1_streams_add.yml&title=Add%3A+). - - - type: textarea - id: stream_url - attributes: - label: Stream URL - description: List all links in question (one per line) - placeholder: 'https://lnc-kdfw-fox-aws.tubi.video/index.m3u8' - validations: - required: true - - - type: dropdown - id: reason - attributes: - label: What happened to the stream? - options: - - Not loading - - Constantly interrupts/lagging - - Stuck at a single frame - - I see visual artifacts - - Shows looped video - - No sound - - Displays a message asking to renew subscription - - Other - validations: - required: true - - - type: textarea - id: notes - attributes: - label: Notes (optional) - placeholder: 'Anything else we should know?' - - - type: checkboxes - attributes: - label: Contributing Guide - description: 'Please read this guide before posting your request' - options: - - label: I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md) - required: true +name: 🚧 Report a stream +description: Report a broken or unstable stream +title: 'Report: ' +labels: ['streams:remove'] + +body: + - type: markdown + attributes: + value: | + Please fill out the form as much as you can so we could efficiently process your request. To suggest a new replacement link, use this [form](https://github.com/iptv-org/iptv/issues/new?assignees=&labels=streams:add&projects=&template=1_streams_add.yml&title=Add%3A+). + + - type: textarea + id: stream_url + attributes: + label: Stream URL + description: List all links in question (one per line) + placeholder: 'https://lnc-kdfw-fox-aws.tubi.video/index.m3u8' + validations: + required: true + + - type: dropdown + id: reason + attributes: + label: What happened to the stream? + options: + - Not loading + - Constantly interrupts/lagging + - Stuck at a single frame + - I see visual artifacts + - Shows looped video + - No sound + - Displays a message asking to renew subscription + - Other + validations: + required: true + + - type: textarea + id: notes + attributes: + label: Notes (optional) + placeholder: 'Anything else we should know?' + + - type: checkboxes + attributes: + label: Contributing Guide + description: 'Please read this guide before posting your request' + options: + - label: I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md) + required: true diff --git a/.github/ISSUE_TEMPLATE/4_channel-search.yml b/.github/ISSUE_TEMPLATE/4_channel-search.yml index 26b4f6a220..9d6888c507 100644 --- a/.github/ISSUE_TEMPLATE/4_channel-search.yml +++ b/.github/ISSUE_TEMPLATE/4_channel-search.yml @@ -1,28 +1,28 @@ -name: 🔍 Channel search -description: Ask for help in finding a link to the channel stream. -title: 'Find: ' -labels: ['channel search'] - -body: - - type: input - id: stream_id - attributes: - label: Channel ID (required) - description: Unique channel ID from [iptv-org.github.io](https://iptv-org.github.io/). If you can't find the channel you want in the list, please let us know through this [form](https://github.com/iptv-org/database/issues/new?assignees=&labels=channels%3Aadd&projects=&template=channels_add.yml&title=Add%3A+) before posting your request. - placeholder: 'BBCAmericaEast.us' - validations: - required: true - - - type: textarea - id: notes - attributes: - label: Notes - description: 'Any additional information that may help find a link to the stream faster?' - - - type: checkboxes - attributes: - label: Contributing Guide - description: 'Please read this guide before posting your request' - options: - - label: I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md) - required: true +name: 🔍 Channel search +description: Ask for help in finding a link to the channel stream. +title: 'Find: ' +labels: ['channel search'] + +body: + - type: input + id: stream_id + attributes: + label: Stream ID (required) + description: Unique ID of the channel and feed from [iptv-org.github.io](https://iptv-org.github.io/). If you cannot find the channel or feed you are looking for in the list, please let us know via one of the [forms](https://github.com/iptv-org/database/issues/new/choose) before posting your request. + placeholder: 'BBCAmerica.us@East' + validations: + required: true + + - type: textarea + id: notes + attributes: + label: Notes + description: 'Any additional information that may help find a link to the stream faster?' + + - type: checkboxes + attributes: + label: Contributing Guide + description: 'Please read this guide before posting your request' + options: + - label: I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md) + required: true diff --git a/.github/ISSUE_TEMPLATE/5_bug-report.yml b/.github/ISSUE_TEMPLATE/5_bug-report.yml index d93ed317ed..d0a4f81d7f 100644 --- a/.github/ISSUE_TEMPLATE/5_bug-report.yml +++ b/.github/ISSUE_TEMPLATE/5_bug-report.yml @@ -1,19 +1,19 @@ -name: 🐞 Bug report -description: Report an error in this repository -labels: ['bug'] - -body: - - type: textarea - attributes: - label: Describe your issue - description: Please describe the error in as much detail as possible so that we can fix it quickly. - validations: - required: true - - - type: checkboxes - attributes: - label: Contributing Guide - description: 'Please read this guide before posting your request' - options: - - label: I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md) +name: 🐞 Bug report +description: Report an error in this repository +labels: ['bug'] + +body: + - type: textarea + attributes: + label: Describe your issue + description: Please describe the error in as much detail as possible so that we can fix it quickly. + validations: + required: true + + - type: checkboxes + attributes: + label: Contributing Guide + description: 'Please read this guide before posting your request' + options: + - label: I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md) required: true \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/6_copyright-claim.yml b/.github/ISSUE_TEMPLATE/6_copyright-claim.yml index 4e3d779567..4265fc342f 100644 --- a/.github/ISSUE_TEMPLATE/6_copyright-claim.yml +++ b/.github/ISSUE_TEMPLATE/6_copyright-claim.yml @@ -1,50 +1,50 @@ -name: ©️ Copyright removal request -description: Request to remove content -labels: ['removal request'] -body: - - type: input - attributes: - label: Your full legal name - validations: - required: true - - - type: dropdown - attributes: - label: Are you the copyright holder or authorized to act on the copyright owner's behalf? - description: We cannot process your request unless it is submitted by the copyright owner or an agent authorized to act on behalf of the copyright owner. - options: - - Yes, I am the copyright holder. - - Yes, I am authorized to act on the copyright owner's behalf. - - No. - validations: - required: true - - - type: textarea - attributes: - label: Please describe the nature of your copyright ownership or authorization to act on the owner's behalf. - validations: - required: true - - - type: textarea - attributes: - label: Please provide a detailed description of the original copyrighted work that has allegedly been infringed. If possible, include a URL to where it is posted online. - validations: - required: true - - - type: textarea - attributes: - label: What content should be removed? Please specify the URL for each item or, if it is an entire file, the file's URL. - validations: - required: true - - - type: textarea - attributes: - label: Any additional information we need to know? - - - type: checkboxes - attributes: - label: Contributing Guide - description: 'Please read this guide before posting your request' - options: - - label: I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md) - required: true +name: ©️ Copyright removal request +description: Request to remove content +labels: ['removal request'] +body: + - type: input + attributes: + label: Your full legal name + validations: + required: true + + - type: dropdown + attributes: + label: Are you the copyright holder or authorized to act on the copyright owner's behalf? + description: We cannot process your request unless it is submitted by the copyright owner or an agent authorized to act on behalf of the copyright owner. + options: + - Yes, I am the copyright holder. + - Yes, I am authorized to act on the copyright owner's behalf. + - No. + validations: + required: true + + - type: textarea + attributes: + label: Please describe the nature of your copyright ownership or authorization to act on the owner's behalf. + validations: + required: true + + - type: textarea + attributes: + label: Please provide a detailed description of the original copyrighted work that has allegedly been infringed. If possible, include a URL to where it is posted online. + validations: + required: true + + - type: textarea + attributes: + label: What content should be removed? Please specify the URL for each item or, if it is an entire file, the file's URL. + validations: + required: true + + - type: textarea + attributes: + label: Any additional information we need to know? + + - type: checkboxes + attributes: + label: Contributing Guide + description: 'Please read this guide before posting your request' + options: + - label: I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md) + required: true diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index d42fd2acbf..b837a3ab6c 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,11 +1,11 @@ -blank_issues_enabled: false -contact_links: - - name: 💡 Ideas - url: https://github.com/orgs/iptv-org/discussions/categories/ideas - about: Share ideas for new features - - name: 🙌 Show and tell - url: https://github.com/orgs/iptv-org/discussions/categories/show-and-tell - about: Show off something you've made - - name: ❓ Q&A - url: https://github.com/orgs/iptv-org/discussions/categories/q-a - about: Ask the community for help +blank_issues_enabled: false +contact_links: + - name: 💡 Ideas + url: https://github.com/orgs/iptv-org/discussions/categories/ideas + about: Share ideas for new features + - name: 🙌 Show and tell + url: https://github.com/orgs/iptv-org/discussions/categories/show-and-tell + about: Show off something you've made + - name: ❓ Q&A + url: https://github.com/orgs/iptv-org/discussions/categories/q-a + about: Ask the community for help diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 62d0f58eac..b741e6c988 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -1,37 +1,42 @@ -name: check -on: - workflow_dispatch: - pull_request: - types: [opened, synchronize, reopened] -concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} - cancel-in-progress: true -jobs: - check: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: changed files - id: files - run: | - git fetch origin master:master - ANY_CHANGED=false - ALL_CHANGED_FILES=$(git diff --name-only master -- streams/ | tr '\n' ' ') - if [ -n "${ALL_CHANGED_FILES}" ]; then - ANY_CHANGED=true - fi - echo "all_changed_files=$ALL_CHANGED_FILES" >> "$GITHUB_OUTPUT" - echo "any_changed=$ANY_CHANGED" >> "$GITHUB_OUTPUT" - - uses: actions/setup-node@v4 - if: ${{ !env.ACT && steps.files.outputs.any_changed == 'true' }} - with: - node-version: 22 - cache: 'npm' - - name: install dependencies - if: steps.files.outputs.any_changed == 'true' - run: npm install - - name: validate - if: steps.files.outputs.any_changed == 'true' - run: | - npm run playlist:lint -- ${{ steps.files.outputs.all_changed_files }} +name: check +on: + workflow_dispatch: + pull_request: + types: [opened, synchronize, reopened] +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true +jobs: + check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Get list of changed files + id: files + run: | + git fetch origin master:master + ANY_CHANGED=false + ALL_CHANGED_FILES=$(git diff --name-only master -- streams/ | tr '\n' ' ') + if [ -n "${ALL_CHANGED_FILES}" ]; then + ANY_CHANGED=true + fi + echo "all_changed_files=$ALL_CHANGED_FILES" >> "$GITHUB_OUTPUT" + echo "any_changed=$ANY_CHANGED" >> "$GITHUB_OUTPUT" + - uses: actions/setup-node@v4 + if: steps.files.outputs.any_changed == 'true' + with: + node-version: 22 + cache: 'npm' + - name: Setup .npmrc for GitHub Packages + run: | + echo "//npm.pkg.github.com/:_authToken=$GITHUB_TOKEN" >> .npmrc + echo "@iptv-org:registry=https://npm.pkg.github.com/" >> .npmrc + echo "always-auth=true" >> .npmrc + - name: Install dependencies + if: steps.files.outputs.any_changed == 'true' + run: npm install + - name: Validate changed files + if: steps.files.outputs.any_changed == 'true' + run: | + npm run playlist:lint -- ${{ steps.files.outputs.all_changed_files }} npm run playlist:validate -- ${{ steps.files.outputs.all_changed_files }} \ No newline at end of file diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml index 439c21e9eb..7b7a5b82b4 100644 --- a/.github/workflows/format.yml +++ b/.github/workflows/format.yml @@ -1,131 +1,62 @@ -name: format -on: - workflow_dispatch: - # pull_request: - # types: [closed] - # branches: - # - master - # schedule: - # - cron: "0 12 * * *" -jobs: - on_trigger: - # if: ${{ github.event_name == 'workflow_dispatch' || github.event_name == 'schedule' }} - if: ${{ github.event_name == 'workflow_dispatch' }} - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: tibdex/github-app-token@v1.8.2 - if: ${{ !env.ACT }} - id: create-app-token - with: - app_id: ${{ secrets.APP_ID }} - private_key: ${{ secrets.APP_PRIVATE_KEY }} - - uses: actions/checkout@v4 - if: ${{ !env.ACT }} - with: - token: ${{ steps.create-app-token.outputs.token }} - - uses: actions/setup-node@v4 - with: - node-version: 22 - cache: 'npm' - - name: setup git - run: | - git config user.name "iptv-bot[bot]" - git config user.email "84861620+iptv-bot[bot]@users.noreply.github.com" - - name: install dependencies - run: npm install - - name: format internal playlists - run: npm run playlist:format - - name: check internal playlists - run: | - npm run playlist:lint - npm run playlist:validate - - name: changed files - id: files_after - run: | - ANY_CHANGED=false - ALL_CHANGED_FILES=$(git diff --name-only master -- streams/ | tr '\n' ' ') - if [ -n "${ALL_CHANGED_FILES}" ]; then - ANY_CHANGED=true - fi - echo "all_changed_files=$ALL_CHANGED_FILES" >> "$GITHUB_OUTPUT" - echo "any_changed=$ANY_CHANGED" >> "$GITHUB_OUTPUT" - - name: git status - run: git status - - name: commit changes - if: steps.files_after.outputs.any_changed == 'true' - run: | - git add streams - git status - git commit -m "[Bot] Format /streams" -m "Committed by [iptv-bot](https://github.com/apps/iptv-bot) via [format](https://github.com/iptv-org/iptv/actions/runs/${{ github.run_id }}) workflow." --no-verify - - name: push all changes to the repository - if: ${{ !env.ACT && github.ref == 'refs/heads/master' && steps.files_after.outputs.any_changed == 'true' }} - run: git push - on_merge: - if: github.event.pull_request.merged == true - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: tibdex/github-app-token@v1.8.2 - if: ${{ !env.ACT }} - id: create-app-token - with: - app_id: ${{ secrets.APP_ID }} - private_key: ${{ secrets.APP_PRIVATE_KEY }} - - uses: actions/checkout@v4 - if: ${{ !env.ACT }} - with: - token: ${{ steps.create-app-token.outputs.token }} - - name: changed files - id: files - run: | - ANY_CHANGED=false - ALL_CHANGED_FILES=$(git diff --name-only master -- streams/ | tr '\n' ' ') - if [ -n "${ALL_CHANGED_FILES}" ]; then - ANY_CHANGED=true - fi - echo "all_changed_files=$ALL_CHANGED_FILES" >> "$GITHUB_OUTPUT" - echo "any_changed=$ANY_CHANGED" >> "$GITHUB_OUTPUT" - - uses: actions/setup-node@v4 - if: ${{ steps.files.outputs.any_changed == 'true' }} - with: - node-version: 22 - cache: 'npm' - - name: setup git - if: steps.files.outputs.any_changed == 'true' - run: | - git config user.name "iptv-bot[bot]" - git config user.email "84861620+iptv-bot[bot]@users.noreply.github.com" - - name: install dependencies - if: steps.files.outputs.any_changed == 'true' - run: npm install - - name: format internal playlists - if: steps.files.outputs.any_changed == 'true' - run: npm run playlist:format -- ${{ steps.files.outputs.all_changed_files }} - - name: check internal playlists - if: steps.files.outputs.any_changed == 'true' - run: | - npm run playlist:lint -- ${{ steps.files.outputs.all_changed_files }} - npm run playlist:validate -- ${{ steps.files.outputs.all_changed_files }} - - name: git status - if: steps.files.outputs.any_changed == 'true' - run: git status - - name: changed files - id: files_after - run: | - ANY_CHANGED=false - ALL_CHANGED_FILES=$(git diff --name-only master -- streams/ | tr '\n' ' ') - if [ -n "${ALL_CHANGED_FILES}" ]; then - ANY_CHANGED=true - fi - echo "all_changed_files=$ALL_CHANGED_FILES" >> "$GITHUB_OUTPUT" - echo "any_changed=$ANY_CHANGED" >> "$GITHUB_OUTPUT" - - name: commit changes - if: steps.files_after.outputs.any_changed == 'true' - run: | - git add streams - git status - git commit -m "[Bot] Format /streams" -m "Committed by [iptv-bot](https://github.com/apps/iptv-bot) via [format](https://github.com/iptv-org/iptv/actions/runs/${{ github.run_id }}) workflow." --no-verify - - name: push all changes to the repository - if: ${{ !env.ACT && github.ref == 'refs/heads/master' && steps.files_after.outputs.any_changed == 'true' }} - run: git push +name: format +on: + workflow_dispatch: + # schedule: + # - cron: "0 12 * * *" +jobs: + on_trigger: + # if: ${{ github.event_name == 'workflow_dispatch' || github.event_name == 'schedule' }} + if: ${{ github.event_name == 'workflow_dispatch' }} + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: tibdex/github-app-token@v1.8.2 + if: ${{ !env.ACT }} + id: create-app-token + with: + app_id: ${{ secrets.APP_ID }} + private_key: ${{ secrets.APP_PRIVATE_KEY }} + - uses: actions/checkout@v4 + if: ${{ !env.ACT }} + with: + token: ${{ steps.create-app-token.outputs.token }} + - uses: actions/setup-node@v4 + with: + node-version: 22 + cache: 'npm' + - name: Setup .npmrc for GitHub Packages + run: | + echo "//npm.pkg.github.com/:_authToken=$GITHUB_TOKEN" >> .npmrc + echo "@iptv-org:registry=https://npm.pkg.github.com/" >> .npmrc + echo "always-auth=true" >> .npmrc + - name: Install dependencies + run: npm install + - name: Format internal playlists + run: npm run playlist:format + - name: Check internal playlists + run: | + npm run playlist:lint + npm run playlist:validate + - name: Get list of changed files + id: files_after + run: | + ANY_CHANGED=false + ALL_CHANGED_FILES=$(git diff --name-only master -- streams/ | tr '\n' ' ') + if [ -n "${ALL_CHANGED_FILES}" ]; then + ANY_CHANGED=true + fi + echo "all_changed_files=$ALL_CHANGED_FILES" >> "$GITHUB_OUTPUT" + echo "any_changed=$ANY_CHANGED" >> "$GITHUB_OUTPUT" + - name: Setup git + run: | + git config user.name "iptv-bot[bot]" + git config user.email "84861620+iptv-bot[bot]@users.noreply.github.com" + - name: Commit changes to /streams + if: steps.files_after.outputs.any_changed == 'true' + run: | + git add streams + git status + git commit -m "[Bot] Format /streams" -m "Committed by [iptv-bot](https://github.com/apps/iptv-bot) via [format](https://github.com/iptv-org/iptv/actions/runs/${{ github.run_id }}) workflow." --no-verify + - name: Push all changes to the repository + if: ${{ !env.ACT && github.ref == 'refs/heads/master' && steps.files_after.outputs.any_changed == 'true' }} + run: git push \ No newline at end of file diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 4bf3b0fae0..f305a4fd75 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -1,25 +1,26 @@ -name: stale -on: - workflow_dispatch: - schedule: - - cron: '0 0 * * *' -permissions: - issues: write -jobs: - stale: - runs-on: ubuntu-latest - steps: - - uses: tibdex/github-app-token@v1.8.2 - id: create-app-token - with: - app_id: ${{ secrets.APP_ID }} - private_key: ${{ secrets.APP_PRIVATE_KEY }} - - uses: actions/stale@v9 - with: - repo-token: ${{ steps.create-app-token.outputs.token }} - days-before-stale: 180 - days-before-close: 7 - operations-per-run: 500 - stale-issue-label: 'stale' - any-of-issue-labels: 'channel search' +name: stale +on: + workflow_dispatch: + schedule: + - cron: '0 0 * * *' +permissions: + actions: write + issues: write +jobs: + stale: + runs-on: ubuntu-latest + steps: + - uses: tibdex/github-app-token@v1.8.2 + id: create-app-token + with: + app_id: ${{ secrets.APP_ID }} + private_key: ${{ secrets.APP_PRIVATE_KEY }} + - uses: actions/stale@v9 + with: + repo-token: ${{ steps.create-app-token.outputs.token }} + days-before-stale: 180 + days-before-close: 7 + operations-per-run: 500 + stale-issue-label: 'stale' + any-of-issue-labels: 'channel search' close-issue-message: 'This request has been closed because it has been inactive for more than 180 days.' \ No newline at end of file diff --git a/.github/workflows/update.yml b/.github/workflows/update.yml index a44b59538b..82928fac93 100644 --- a/.github/workflows/update.yml +++ b/.github/workflows/update.yml @@ -1,82 +1,85 @@ -name: update -on: - workflow_dispatch: - schedule: - - cron: '0 0 * * *' -jobs: - main: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: tibdex/github-app-token@v1.8.2 - if: ${{ !env.ACT }} - id: create-app-token - with: - app_id: ${{ secrets.APP_ID }} - private_key: ${{ secrets.APP_PRIVATE_KEY }} - - uses: actions/checkout@v3 - if: ${{ !env.ACT }} - with: - token: ${{ steps.create-app-token.outputs.token }} - - name: setup git - run: | - git config user.name "iptv-bot[bot]" - git config user.email "84861620+iptv-bot[bot]@users.noreply.github.com" - - uses: actions/setup-node@v3 - if: ${{ !env.ACT }} - with: - node-version: 20 - cache: 'npm' - - name: install dependencies - run: npm install - - name: update internal playlists - run: npm run playlist:update --silent >> $GITHUB_OUTPUT - id: playlist-update - - name: check internal playlists - run: | - npm run playlist:lint - npm run playlist:validate - - name: generate public playlists - run: npm run playlist:generate - - name: generate .api/streams.json - run: npm run api:generate - - name: update readme - run: npm run readme:update - - run: git status - - name: commit changes to /streams - run: | - git add streams - git status - git commit --allow-empty -m "[Bot] Update /streams" -m "Committed by [iptv-bot](https://github.com/apps/iptv-bot) via [update](https://github.com/iptv-org/iptv/actions/runs/${{ github.run_id }}) workflow." -m "${{ steps.playlist-update.outputs.OUTPUT }}" --no-verify - - name: commit changes to playlists.md - run: | - git add PLAYLISTS.md - git status - git commit --allow-empty -m "[Bot] Update PLAYLISTS.md" -m "Committed by [iptv-bot](https://github.com/apps/iptv-bot) via [update](https://github.com/iptv-org/iptv/actions/runs/${{ github.run_id }}) workflow." --no-verify - - name: push all changes to the repository - if: ${{ !env.ACT && github.ref == 'refs/heads/master' }} - run: git push - - name: deploy public playlists to github pages - uses: JamesIves/github-pages-deploy-action@4.1.1 - if: ${{ !env.ACT && github.ref == 'refs/heads/master' }} - with: - repository-name: iptv-org/iptv - branch: gh-pages - folder: .gh-pages - token: ${{ steps.create-app-token.outputs.token }} - git-config-name: iptv-bot[bot] - git-config-email: 84861620+iptv-bot[bot]@users.noreply.github.com - commit-message: '[Bot] Deploy to GitHub Pages' - clean: true - - name: move .api/streams.json to iptv-org/api - uses: JamesIves/github-pages-deploy-action@4.1.1 - if: ${{ !env.ACT && github.ref == 'refs/heads/master' }} - with: - repository-name: iptv-org/api - branch: gh-pages - folder: .api - token: ${{ steps.create-app-token.outputs.token }} - git-config-name: iptv-bot[bot] - git-config-email: 84861620+iptv-bot[bot]@users.noreply.github.com - commit-message: '[Bot] Deploy to iptv-org/api' - clean: false +name: update +on: + workflow_dispatch: + schedule: + - cron: '0 0 * * *' +jobs: + main: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: tibdex/github-app-token@v1.8.2 + if: ${{ !env.ACT }} + id: create-app-token + with: + app_id: ${{ secrets.APP_ID }} + private_key: ${{ secrets.APP_PRIVATE_KEY }} + - uses: actions/checkout@v4 + if: ${{ !env.ACT }} + with: + token: ${{ steps.create-app-token.outputs.token }} + - uses: actions/setup-node@v4 + with: + node-version: 22 + cache: 'npm' + - name: Setup .npmrc for GitHub Packages + run: | + echo "//npm.pkg.github.com/:_authToken=$GITHUB_TOKEN" >> .npmrc + echo "@iptv-org:registry=https://npm.pkg.github.com/" >> .npmrc + echo "always-auth=true" >> .npmrc + - name: Install dependencies + run: npm install + - name: Update internal playlists + run: npm run playlist:update --silent >> $GITHUB_OUTPUT + id: playlist-update + - name: Check internal playlists + run: | + npm run playlist:lint + npm run playlist:validate + - name: Generate public playlists + run: npm run playlist:generate + - name: Generate .api/streams.json + run: npm run api:generate + - name: Update readme + run: npm run readme:update + - name: Setup git + run: | + git config user.name "iptv-bot[bot]" + git config user.email "84861620+iptv-bot[bot]@users.noreply.github.com" + - name: Commit changes to /streams + run: | + git add streams + git status + git commit --allow-empty -m "[Bot] Update /streams" -m "Committed by [iptv-bot](https://github.com/apps/iptv-bot) via [update](https://github.com/iptv-org/iptv/actions/runs/${{ github.run_id }}) workflow." -m "${{ steps.playlist-update.outputs.OUTPUT }}" --no-verify + - name: Commit changes to PLAYLIST.md + run: | + git add PLAYLISTS.md + git status + git commit --allow-empty -m "[Bot] Update PLAYLISTS.md" -m "Committed by [iptv-bot](https://github.com/apps/iptv-bot) via [update](https://github.com/iptv-org/iptv/actions/runs/${{ github.run_id }}) workflow." --no-verify + - name: Push all changes to the repository + if: ${{ !env.ACT && github.ref == 'refs/heads/master' }} + run: git push + - name: Deploy public playlists to GitHub Pages + uses: JamesIves/github-pages-deploy-action@4.1.1 + if: ${{ !env.ACT && github.ref == 'refs/heads/master' }} + with: + repository-name: iptv-org/iptv + branch: gh-pages + folder: .gh-pages + token: ${{ steps.create-app-token.outputs.token }} + git-config-name: iptv-bot[bot] + git-config-email: 84861620+iptv-bot[bot]@users.noreply.github.com + commit-message: '[Bot] Deploy to GitHub Pages' + clean: true + - name: Move .api/streams.json to iptv-org/api + uses: JamesIves/github-pages-deploy-action@4.1.1 + if: ${{ !env.ACT && github.ref == 'refs/heads/master' }} + with: + repository-name: iptv-org/api + branch: gh-pages + folder: .api + token: ${{ steps.create-app-token.outputs.token }} + git-config-name: iptv-bot[bot] + git-config-email: 84861620+iptv-bot[bot]@users.noreply.github.com + commit-message: '[Bot] Deploy to iptv-org/api' + clean: false diff --git a/.gitignore b/.gitignore index ad225b41d1..199606266c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,9 @@ -node_modules -.artifacts -.secrets -.actrc -.DS_Store -/.gh-pages/ -/.api/ -.env +node_modules +.artifacts +.secrets +.actrc +.DS_Store +/.gh-pages/ +/.api/ +.env /temp/ \ No newline at end of file diff --git a/.readme/.gitignore b/.readme/.gitignore index a2ac441348..3d74e4ba3f 100644 --- a/.readme/.gitignore +++ b/.readme/.gitignore @@ -1,4 +1,4 @@ -_categories.md -_countries.md -_languages.md +_categories.md +_countries.md +_languages.md _regions.md \ No newline at end of file diff --git a/.readme/template.md b/.readme/template.md index 74e1549f92..4b7a9594e2 100644 --- a/.readme/template.md +++ b/.readme/template.md @@ -1,88 +1,88 @@ -## Playlists - -There are several versions of playlists that differ in the way they are grouped. As of January 30th, 2024, we have stopped distributing NSFW channels. For more information, please look at [this issue](https://github.com/iptv-org/iptv/issues/15723). - -### Grouped by category - -Playlists in which channels are grouped by category. - -
-Expand -
- -``` -https://iptv-org.github.io/iptv/index.category.m3u -``` - -Same thing, but split up into separate files: - - -#include "./.readme/_categories.md" - -
- -### Grouped by language - -Playlists in which channels are grouped by the language in which they are broadcast. - -
-Expand -
- -``` -https://iptv-org.github.io/iptv/index.language.m3u -``` - -Same thing, but split up into separate files: - - -#include "./.readme/_languages.md" - -
- -### Grouped by broadcast area - -Playlists in which channels are grouped by broadcast area. - -
-Expand - -#### Countries - -``` -https://iptv-org.github.io/iptv/index.country.m3u -``` - -Same thing, but split up into separate files: - - -#include "./.readme/_countries.md" - -#### Regions - - -#include "./.readme/_regions.md" - -
- -### Grouped by sources - -Playlists in which channels are grouped by broadcast source. - -
-Expand -
- -To use the playlist, simply replace `` in the link below with the name of one of the files in the [streams](streams) folder. - -``` -https://iptv-org.github.io/iptv/sources/.m3u -``` - -
- -Also, any of our internal playlists are available in raw form (without any filtering or sorting) at this link: - -``` -https://iptv-org.github.io/iptv/raw/.m3u -``` +## Playlists + +There are several versions of playlists that differ in the way they are grouped. As of January 30th, 2024, we have stopped distributing NSFW channels. For more information, please look at [this issue](https://github.com/iptv-org/iptv/issues/15723). + +### Grouped by category + +Playlists in which channels are grouped by category. + +
+Expand +
+ +``` +https://iptv-org.github.io/iptv/index.category.m3u +``` + +Same thing, but split up into separate files: + + +#include "./.readme/_categories.md" + +
+ +### Grouped by language + +Playlists in which channels are grouped by the language in which they are broadcast. + +
+Expand +
+ +``` +https://iptv-org.github.io/iptv/index.language.m3u +``` + +Same thing, but split up into separate files: + + +#include "./.readme/_languages.md" + +
+ +### Grouped by broadcast area + +Playlists in which channels are grouped by broadcast area. + +
+Expand + +#### Countries + +``` +https://iptv-org.github.io/iptv/index.country.m3u +``` + +Same thing, but split up into separate files: + + +#include "./.readme/_countries.md" + +#### Regions + + +#include "./.readme/_regions.md" + +
+ +### Grouped by sources + +Playlists in which channels are grouped by broadcast source. + +
+Expand +
+ +To use the playlist, simply replace `` in the link below with the name of one of the files in the [streams](streams) folder. + +``` +https://iptv-org.github.io/iptv/sources/.m3u +``` + +
+ +Also, any of our internal playlists are available in raw form (without any filtering or sorting) at this link: + +``` +https://iptv-org.github.io/iptv/raw/.m3u +``` diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fefa6edd3d..925c5b8584 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,215 +1,215 @@ -# Contributing Guide - -- [How to?](#how-to) -- [Stream Description Scheme](#stream-description-scheme) -- [Project Structure](#project-structure) -- [Scripts](#scripts) -- [Workflows](#workflows) - -## How to? - -### How to add a new stream link to a playlists? - -You have several options: - -1. Create a new request using this [form](https://github.com/iptv-org/iptv/issues/new?assignees=&labels=streams:add&projects=&template=1_streams_add.yml&title=Add%3A+) and if approved, the link will automatically be added to the playlist on the next update. - -2. Add the link to the playlist directly using a [pull request](https://github.com/iptv-org/iptv/pulls). - -Regardless of which option you choose, before posting your request please do the following: - -- Make sure the link you want to add works stably. To check this, open it in one of the players (for example, [VLC player](https://www.videolan.org/vlc/index.html)) and watch the broadcast for at least a minute (some test streams are interrupted after 15-30 seconds). -- Make sure the link is not already in the playlist. This can be done by [searching](https://github.com/search?q=repo%3Aiptv-org%2Fiptv+http%3A%2F%2Fexample.com&type=code) the repository. -- Find the ID of the channel you want on [iptv-org.github.io](https://iptv-org.github.io/). If your desired channel is not on the list you can leave a request to add it [here](https://github.com/iptv-org/database/issues/new/choose). -- Make sure the channel is not blocklisted. It can also be done through [iptv-org.github.io](https://iptv-org.github.io/). -- The link does not lead to the Xtream Codes server. [Why don't you accept links to Xtream Codes server?](FAQ.md#why-dont-you-accept-links-to-xtream-codes-server) -- If you know that the broadcast only works in certain countries or it is periodically interrupted, do not forget to indicate this in the request. - -A requests without a valid stream ID or working link to the stream will be closed immediately. - -Note all links in playlists are sorted automatically by scripts so there is no need to sort them manually. For more info, see [Scripts](#scripts). - -### How to fix the stream description? - -Most of the stream description (channel name, feed name, categories, languages, broadcast area, logo) we load from the [iptv-org/database](https://github.com/iptv-org/database) using the stream ID. - -So first of all, make sure that the desired stream has the correct ID. A full list of all supported channels and their corresponding IDs can be found on [iptv-org.github.io](https://iptv-org.github.io/). To change the stream ID of any link in the playlist, just fill out this [form](https://github.com/iptv-org/iptv/issues/new?assignees=&labels=streams%3Aedit&projects=&template=2_streams_edit.yml&title=Edit%3A+). - -If, however, you have found an error in the database itself, this is the place to go: [How to edit channel description?](https://github.com/iptv-org/database/blob/master/CONTRIBUTING.md#how-to-edit-channel-description) - -### How to distinguish a link to an Xtream Codes server from a regular one? - -Most of them have this form: - -`http(s)://{hostname}:{port}/{username}/{password}/{channelID}` (port is often `25461`) - -To make sure that the link leads to the Xtream Codes server, copy the `hostname`, `port`, `username` and `password` into the link below and try to open it in a browser: - -`http(s)://{hostname}:{port}/panel_api.php?username={username}&password={password}` - -If the link answers, you're with an Xtream Codes server. - -### How to report a broken stream? - -Fill out this [form](https://github.com/iptv-org/iptv/issues/new?assignees=&labels=streams:remove&projects=&template=3_streams_report.yml&title=Broken%3A+) and as soon as a working replacement appears, we will add it to the playlist or at least remove the non-working one. - -The only thing before publishing your report is to make sure that: - -- The link is still in our playlists. You can verify this by [searching](https://github.com/search?q=repo%3Aiptv-org%2Fiptv+http%3A%2F%2Fexample.com&type=code) the repository. -- The link really doesn't work and is not just [geo-blocked](https://en.wikipedia.org/wiki/Geo-blocking). To check this, you can either use a [VPN](https://en.wikipedia.org/wiki/Virtual_private_network) or services such as [streamtest.in](https://streamtest.in/). - -An issue without a valid link will be closed immediately. - -### How to find a broken stream? - -For starters, you can just try to open the playlist in [VLC player](https://www.videolan.org/vlc/). The player outputs all errors to the log (Tools -> Messages) so you'll be able to determine pretty accurately why a link isn't working. - -Another way to test links is to use the NPM script. To do this, first make sure you have [Node.js](https://nodejs.org/en) installed on your system. Then go to the `iptv` folder using [Console](https://en.wikipedia.org/wiki/Windows_Console) (or [Terminal]() if you have macOS) and run the command: - -```sh -npm run playlist:test path/to/playlist.m3u -``` - -This command will run an automatic check of all links in the playlist and display their status: - -```sh -npm run playlist:test streams/fr.m3u - -streams/fr.m3u -┌─────┬───────────────────────────┬──────────────────────────────────────────────────────────────────────────────────────────────────────┬───────────────────────────┐ -│ │ tvg-id │ url │ status │ -├─────┼───────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────┼───────────────────────────┤ -│ 0 │ 6ter.fr │ https://origin-caf900c010ea8046.live.6cloud.fr/out/v1/29c7a579af3348b48230f76cd75699a5/dash_short... │ LOADING... │ -│ 1 │ 20MinutesTV.fr │ https://lives.digiteka.com/stream/86d3e867-a272-496b-8412-f59aa0104771/index.m3u8 │ FFMPEG_STREAMS_NOT_FOUND │ -│ 2 │ │ https://video1.getstreamhosting.com:1936/8420/8420/playlist.m3u8 │ OK │ -│ 3 │ ADNTVPlus.fr │ https://samsunguk-adn-samsung-fre-qfrlc.amagi.tv/playlist/samsunguk-adn-samsung-fre/playlist.m3u8 │ HTTP_FORBIDDEN │ -│ 4 │ Africa24.fr │ https://edge12.vedge.infomaniak.com/livecast/ik:africa24/manifest.m3u8 │ OK │ -│ 5 │ Africa24English.fr │ https://edge17.vedge.infomaniak.com/livecast/ik:africa24sport/manifest.m3u8 │ OK │ -│ 6 │ AfricanewsEnglish.fr │ https://37c774660687468c821a51190046facf.mediatailor.us-east-1.amazonaws.com/v1/master/04fd913bb2... │ HTTP_GATEWAY_TIMEOUT │ -│ 7 │ AlpedHuezTV.fr │ https://edge.vedge.infomaniak.com/livecast/ik:adhtv/chunklist.m3u8 │ HTTP_NOT_FOUND │ -``` - -After that, all you have to do is report any broken streams you find. - -### How to replace a broken stream? - -This can be done either by filling out this [form](https://github.com/iptv-org/iptv/issues/new?assignees=&labels=streams%3Aedit&projects=&template=2_streams_edit.yml&title=Edit%3A+). - -Either by directly updating the files in the [/streams](/streams) folder and then creating 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 remove my channel from playlist? - -To request removal of a link to a channel from the repository, you need to fill out this [form](https://github.com/iptv-org/iptv/issues/new?assignees=&labels=removal+request&projects=&template=6_copyright-claim.yml&title=Remove%3A+) and wait for the request to be reviewed (this usually takes no more than 1 business day). And if the request is approved, links to the channel will be immediately removed from the repository. - -The channel will also be added to our [blocklist](https://github.com/iptv-org/database/blob/master/data/blocklist.csv) to avoid its appearance in our playlists in the future. - -Please note that we only accept removal requests from channel owners and their official representatives, all other requests will be closed immediately. - -## Stream Description Scheme - -For a stream to be approved, its description must follow this template: - -``` -#EXTINF:-1 tvg-id="STREAM_ID",STREAM_TITLE (QUALITY) [LABEL] -STREAM_URL -``` - -| Attribute | Description | Required | Valid values | -| -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | -------------------------------------------- | -| `STREAM_ID` | Stream ID consisting of channel ID and feed ID. Full list of supported channels with corresponding ID could be found on [iptv-org.github.io](https://iptv-org.github.io/). | Optional | `` or `@` | -| `STREAM_TITLE` | Stream title consisting of channel name and feed name. May contain any characters except: `,`, `[`, `]`. | Required | - | -| `QUALITY` | Maximum stream quality. | Optional | `2160p`, `1080p`, `720p`, `480p`, `360p` etc | -| `LABEL` | Specified in cases where the broadcast for some reason may not be available to some users. | Optional | `Geo-blocked` or `Not 24/7` | -| `STREAM_URL` | Stream URL. | Required | - | - -Example: - -```xml -#EXTINF:-1 tvg-id="ExampleTV.us@East",Example TV East (720p) [Not 24/7] -https://example.com/playlist.m3u8 -``` - -Also, if necessary, you can specify custom [HTTP User-Agent](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent) and [HTTP Referrer](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referer) through additional attributes: - -```xml -#EXTINF:-1 tvg-id="ExampleTV.us" http-referrer="http://example.com/" http-user-agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64)",Example TV -http://example.com/stream.m3u8 -``` - -or use player-specific directives: - -_VLC_ - -```xml -#EXTINF:-1 tvg-id="ExampleTV.us@VLC",Example TV -#EXTVLCOPT:http-referrer=http://example.com/ -#EXTVLCOPT:http-user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) -http://example.com/stream.m3u8 -``` - -_Kodi_ - -```xml -#EXTINF:-1 tvg-id="ExampleTV.us@Kodi",Example TV -#KODIPROP:inputstream=inputstream.adaptive -#KODIPROP:inputstream.adaptive.stream_headers=Referer=http://example.com/&User-Agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) -http://example.com/stream.m3u8 -``` - -## Project Structure - -- `.github/` - - `ISSUE_TEMPLATE/`: issue templates for the repository. - - `workflows`: contains [GitHub actions](https://docs.github.com/en/actions/quickstart) workflows. - - `CODE_OF_CONDUCT.md`: rules you shouldn't break if you don't want to get banned. -- `.readme/` - - `config.json`: config for the `markdown-include` package, which is used to compile everything into one `PLAYLISTS.md` file. - - `preview.png`: image displayed in the `README.md`. - - `template.md`: template for `PLAYLISTS.md`. -- `scripts/`: contains all scripts used in the repository. -- `streams/`: contains all streams broken down by the country from which they are broadcast. -- `tests/`: contains tests to check the scripts. -- `CONTRIBUTING.md`: file you are currently reading. -- `PLAYLISTS.md`: auto-updated list of available playlists. -- `README.md`: project description. - -## Scripts - -These scripts are created to automate routine processes in the repository and make it a bit easier to maintain. - -For scripts to work, you must have [Node.js](https://nodejs.org/en) installed on your computer. - -To run scripts use the `npm run ` command. - -- `act:check`: allows to run the [check](https://github.com/iptv-org/iptv/blob/master/.github/workflows/check.yml) workflow locally. Depends on [nektos/act](https://github.com/nektos/act). -- `act:format`: allows to test the [format](https://github.com/iptv-org/iptv/blob/master/.github/workflows/update.yml) workflow locally. Depends on [nektos/act](https://github.com/nektos/act). -- `act:update`: allows to test the [update](https://github.com/iptv-org/iptv/blob/master/.github/workflows/update.yml) workflow locally. Depends on [nektos/act](https://github.com/nektos/act). -- `api:load`: downloads the latest channel and stream data from the [iptv-org/api](https://github.com/iptv-org/api). -- `api:generate`: generates a JSON file with all streams for the [iptv-org/api](https://github.com/iptv-org/api) repository. -- `api:deploy`: allows to manually upload a JSON file created via `api:generate` to the [iptv-org/api](https://github.com/iptv-org/api) repository. To run the script you must provide your [personal access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens) with write access to the repository. -- `playlist:format`: formats internal playlists. The process includes [URL normalization](https://en.wikipedia.org/wiki/URI_normalization), duplicate removal, removing invalid id's and sorting links by channel name, quality, and label. -- `playlist:update`: triggers an update of internal playlists. The process involves processing approved requests from issues. -- `playlist:generate`: generates all public playlists. -- `playlist:validate`: сhecks ids and links in internal playlists for errors. -- `playlist:lint`: сhecks internal playlists for syntax errors. -- `playlist:test`: tests links in internal playlists. -- `playlist:edit`: utility for quick streams mapping. -- `playlist:deploy`: allows to manually publish all generated via `playlist:generate` playlists. To run the script you must provide your [personal access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens) with write access to the repository. -- `readme:update`: updates the list of playlists in [README.md](README.md). -- `report:create`: creates a report on current issues. -- `check`: (shorthand) sequentially runs the `playlist:lint` and `playlist:validate` scripts. -- `format`: (shorthand) runs the `playlist:format` script. -- `update`: (shorthand) sequentially runs the `playlist:generate`, `api:generate` and `readme:update` scripts. -- `deploy`: (shorthand) sequentially runs the `playlist:deploy` and `api:deploy` scripts. -- `lint`: сhecks the scripts for syntax errors. -- `test`: runs a test of all the scripts described above. - -## Workflows - -To automate the run of the scripts described above, we use the [GitHub Actions workflows](https://docs.github.com/en/actions/using-workflows). - -Each workflow includes its own set of scripts that can be run either manually or in response to an event. - -- `check`: sequentially runs the `api:load`, `playlist:check` and `playlist:validate` scripts when a new pull request appears, and blocks the merge if it detects an error in it. -- `format`: sequentially runs `api:load`, `playlist:format`, `playlist:lint` and `playlist:validate` scripts. -- `update`: every day at 0:00 UTC sequentially runs `api:load`, `playlist:update`, `playlist:lint`, `playlist:validate`, `playlist:generate`, `api:generate` and `readme:update` scripts and deploys the output files if successful. +# Contributing Guide + +- [How to?](#how-to) +- [Stream Description Scheme](#stream-description-scheme) +- [Project Structure](#project-structure) +- [Scripts](#scripts) +- [Workflows](#workflows) + +## How to? + +### How to add a new stream link to a playlists? + +You have several options: + +1. Create a new request using this [form](https://github.com/iptv-org/iptv/issues/new?assignees=&labels=streams:add&projects=&template=1_streams_add.yml&title=Add%3A+) and if approved, the link will automatically be added to the playlist on the next update. + +2. Add the link to the playlist directly using a [pull request](https://github.com/iptv-org/iptv/pulls). + +Regardless of which option you choose, before posting your request please do the following: + +- Make sure the link you want to add works stably. To check this, open it in one of the players (for example, [VLC player](https://www.videolan.org/vlc/index.html)) and watch the broadcast for at least a minute (some test streams are interrupted after 15-30 seconds). +- Make sure the link is not already in the playlist. This can be done by [searching](https://github.com/search?q=repo%3Aiptv-org%2Fiptv+http%3A%2F%2Fexample.com&type=code) the repository. +- Find the ID of the channel you want on [iptv-org.github.io](https://iptv-org.github.io/). If your desired channel is not on the list you can leave a request to add it [here](https://github.com/iptv-org/database/issues/new/choose). +- Make sure the channel is not blocklisted. It can also be done through [iptv-org.github.io](https://iptv-org.github.io/). +- The link does not lead to the Xtream Codes server. [Why don't you accept links to Xtream Codes server?](FAQ.md#why-dont-you-accept-links-to-xtream-codes-server) +- If you know that the broadcast only works in certain countries or it is periodically interrupted, do not forget to indicate this in the request. + +A requests without a valid stream ID or working link to the stream will be closed immediately. + +Note all links in playlists are sorted automatically by scripts so there is no need to sort them manually. For more info, see [Scripts](#scripts). + +### How to fix the stream description? + +Most of the stream description (channel name, feed name, categories, languages, broadcast area, logo) we load from the [iptv-org/database](https://github.com/iptv-org/database) using the stream ID. + +So first of all, make sure that the desired stream has the correct ID. A full list of all supported channels and their corresponding IDs can be found on [iptv-org.github.io](https://iptv-org.github.io/). To change the stream ID of any link in the playlist, just fill out this [form](https://github.com/iptv-org/iptv/issues/new?assignees=&labels=streams%3Aedit&projects=&template=2_streams_edit.yml&title=Edit%3A+). + +If, however, you have found an error in the database itself, this is the place to go: [How to edit channel description?](https://github.com/iptv-org/database/blob/master/CONTRIBUTING.md#how-to-edit-channel-description) + +### How to distinguish a link to an Xtream Codes server from a regular one? + +Most of them have this form: + +`http(s)://{hostname}:{port}/{username}/{password}/{channelID}` (port is often `25461`) + +To make sure that the link leads to the Xtream Codes server, copy the `hostname`, `port`, `username` and `password` into the link below and try to open it in a browser: + +`http(s)://{hostname}:{port}/panel_api.php?username={username}&password={password}` + +If the link answers, you're with an Xtream Codes server. + +### How to report a broken stream? + +Fill out this [form](https://github.com/iptv-org/iptv/issues/new?assignees=&labels=streams:remove&projects=&template=3_streams_report.yml&title=Broken%3A+) and as soon as a working replacement appears, we will add it to the playlist or at least remove the non-working one. + +The only thing before publishing your report is to make sure that: + +- The link is still in our playlists. You can verify this by [searching](https://github.com/search?q=repo%3Aiptv-org%2Fiptv+http%3A%2F%2Fexample.com&type=code) the repository. +- The link really doesn't work and is not just [geo-blocked](https://en.wikipedia.org/wiki/Geo-blocking). To check this, you can either use a [VPN](https://en.wikipedia.org/wiki/Virtual_private_network) or services such as [streamtest.in](https://streamtest.in/). + +An issue without a valid link will be closed immediately. + +### How to find a broken stream? + +For starters, you can just try to open the playlist in [VLC player](https://www.videolan.org/vlc/). The player outputs all errors to the log (Tools -> Messages) so you'll be able to determine pretty accurately why a link isn't working. + +Another way to test links is to use the NPM script. To do this, first make sure you have [Node.js](https://nodejs.org/en) installed on your system. Then go to the `iptv` folder using [Console](https://en.wikipedia.org/wiki/Windows_Console) (or [Terminal]() if you have macOS) and run the command: + +```sh +npm run playlist:test path/to/playlist.m3u +``` + +This command will run an automatic check of all links in the playlist and display their status: + +```sh +npm run playlist:test streams/fr.m3u + +streams/fr.m3u +┌─────┬───────────────────────────┬──────────────────────────────────────────────────────────────────────────────────────────────────────┬───────────────────────────┐ +│ │ tvg-id │ url │ status │ +├─────┼───────────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────┼───────────────────────────┤ +│ 0 │ 6ter.fr │ https://origin-caf900c010ea8046.live.6cloud.fr/out/v1/29c7a579af3348b48230f76cd75699a5/dash_short... │ LOADING... │ +│ 1 │ 20MinutesTV.fr │ https://lives.digiteka.com/stream/86d3e867-a272-496b-8412-f59aa0104771/index.m3u8 │ FFMPEG_STREAMS_NOT_FOUND │ +│ 2 │ │ https://video1.getstreamhosting.com:1936/8420/8420/playlist.m3u8 │ OK │ +│ 3 │ ADNTVPlus.fr │ https://samsunguk-adn-samsung-fre-qfrlc.amagi.tv/playlist/samsunguk-adn-samsung-fre/playlist.m3u8 │ HTTP_FORBIDDEN │ +│ 4 │ Africa24.fr │ https://edge12.vedge.infomaniak.com/livecast/ik:africa24/manifest.m3u8 │ OK │ +│ 5 │ Africa24English.fr │ https://edge17.vedge.infomaniak.com/livecast/ik:africa24sport/manifest.m3u8 │ OK │ +│ 6 │ AfricanewsEnglish.fr │ https://37c774660687468c821a51190046facf.mediatailor.us-east-1.amazonaws.com/v1/master/04fd913bb2... │ HTTP_GATEWAY_TIMEOUT │ +│ 7 │ AlpedHuezTV.fr │ https://edge.vedge.infomaniak.com/livecast/ik:adhtv/chunklist.m3u8 │ HTTP_NOT_FOUND │ +``` + +After that, all you have to do is report any broken streams you find. + +### How to replace a broken stream? + +This can be done either by filling out this [form](https://github.com/iptv-org/iptv/issues/new?assignees=&labels=streams%3Aedit&projects=&template=2_streams_edit.yml&title=Edit%3A+). + +Either by directly updating the files in the [/streams](/streams) folder and then creating 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 remove my channel from playlist? + +To request removal of a link to a channel from the repository, you need to fill out this [form](https://github.com/iptv-org/iptv/issues/new?assignees=&labels=removal+request&projects=&template=6_copyright-claim.yml&title=Remove%3A+) and wait for the request to be reviewed (this usually takes no more than 1 business day). And if the request is approved, links to the channel will be immediately removed from the repository. + +The channel will also be added to our [blocklist](https://github.com/iptv-org/database/blob/master/data/blocklist.csv) to avoid its appearance in our playlists in the future. + +Please note that we only accept removal requests from channel owners and their official representatives, all other requests will be closed immediately. + +## Stream Description Scheme + +For a stream to be approved, its description must follow this template: + +``` +#EXTINF:-1 tvg-id="STREAM_ID",STREAM_TITLE (QUALITY) [LABEL] +STREAM_URL +``` + +| Attribute | Description | Required | Valid values | +| -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | -------------------------------------------- | +| `STREAM_ID` | Stream ID consisting of channel ID and feed ID. Full list of supported channels with corresponding ID could be found on [iptv-org.github.io](https://iptv-org.github.io/). | Optional | `` or `@` | +| `STREAM_TITLE` | Stream title consisting of channel name and feed name. May contain any characters except: `,`, `[`, `]`. | Required | - | +| `QUALITY` | Maximum stream quality. | Optional | `2160p`, `1080p`, `720p`, `480p`, `360p` etc | +| `LABEL` | Specified in cases where the broadcast for some reason may not be available to some users. | Optional | `Geo-blocked` or `Not 24/7` | +| `STREAM_URL` | Stream URL. | Required | - | + +Example: + +```xml +#EXTINF:-1 tvg-id="ExampleTV.us@East",Example TV East (720p) [Not 24/7] +https://example.com/playlist.m3u8 +``` + +Also, if necessary, you can specify custom [HTTP User-Agent](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent) and [HTTP Referrer](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referer) through additional attributes: + +```xml +#EXTINF:-1 tvg-id="ExampleTV.us" http-referrer="http://example.com/" http-user-agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64)",Example TV +http://example.com/stream.m3u8 +``` + +or use player-specific directives: + +_VLC_ + +```xml +#EXTINF:-1 tvg-id="ExampleTV.us@VLC",Example TV +#EXTVLCOPT:http-referrer=http://example.com/ +#EXTVLCOPT:http-user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) +http://example.com/stream.m3u8 +``` + +_Kodi_ + +```xml +#EXTINF:-1 tvg-id="ExampleTV.us@Kodi",Example TV +#KODIPROP:inputstream=inputstream.adaptive +#KODIPROP:inputstream.adaptive.stream_headers=Referer=http://example.com/&User-Agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) +http://example.com/stream.m3u8 +``` + +## Project Structure + +- `.github/` + - `ISSUE_TEMPLATE/`: issue templates for the repository. + - `workflows`: contains [GitHub actions](https://docs.github.com/en/actions/quickstart) workflows. + - `CODE_OF_CONDUCT.md`: rules you shouldn't break if you don't want to get banned. +- `.readme/` + - `config.json`: config for the `markdown-include` package, which is used to compile everything into one `PLAYLISTS.md` file. + - `preview.png`: image displayed in the `README.md`. + - `template.md`: template for `PLAYLISTS.md`. +- `scripts/`: contains all scripts used in the repository. +- `streams/`: contains all streams broken down by the country from which they are broadcast. +- `tests/`: contains tests to check the scripts. +- `CONTRIBUTING.md`: file you are currently reading. +- `PLAYLISTS.md`: auto-updated list of available playlists. +- `README.md`: project description. + +## Scripts + +These scripts are created to automate routine processes in the repository and make it a bit easier to maintain. + +For scripts to work, you must have [Node.js](https://nodejs.org/en) installed on your computer. + +To run scripts use the `npm run ` command. + +- `act:check`: allows to run the [check](https://github.com/iptv-org/iptv/blob/master/.github/workflows/check.yml) workflow locally. Depends on [nektos/act](https://github.com/nektos/act). +- `act:format`: allows to test the [format](https://github.com/iptv-org/iptv/blob/master/.github/workflows/update.yml) workflow locally. Depends on [nektos/act](https://github.com/nektos/act). +- `act:update`: allows to test the [update](https://github.com/iptv-org/iptv/blob/master/.github/workflows/update.yml) workflow locally. Depends on [nektos/act](https://github.com/nektos/act). +- `api:load`: downloads the latest channel and stream data from the [iptv-org/api](https://github.com/iptv-org/api). +- `api:generate`: generates a JSON file with all streams for the [iptv-org/api](https://github.com/iptv-org/api) repository. +- `api:deploy`: allows to manually upload a JSON file created via `api:generate` to the [iptv-org/api](https://github.com/iptv-org/api) repository. To run the script you must provide your [personal access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens) with write access to the repository. +- `playlist:format`: formats internal playlists. The process includes [URL normalization](https://en.wikipedia.org/wiki/URI_normalization), duplicate removal, removing invalid id's and sorting links by channel name, quality, and label. +- `playlist:update`: triggers an update of internal playlists. The process involves processing approved requests from issues. +- `playlist:generate`: generates all public playlists. +- `playlist:validate`: сhecks ids and links in internal playlists for errors. +- `playlist:lint`: сhecks internal playlists for syntax errors. +- `playlist:test`: tests links in internal playlists. +- `playlist:edit`: utility for quick streams mapping. +- `playlist:deploy`: allows to manually publish all generated via `playlist:generate` playlists. To run the script you must provide your [personal access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens) with write access to the repository. +- `readme:update`: updates the list of playlists in [README.md](README.md). +- `report:create`: creates a report on current issues. +- `check`: (shorthand) sequentially runs the `playlist:lint` and `playlist:validate` scripts. +- `format`: (shorthand) runs the `playlist:format` script. +- `update`: (shorthand) sequentially runs the `playlist:generate`, `api:generate` and `readme:update` scripts. +- `deploy`: (shorthand) sequentially runs the `playlist:deploy` and `api:deploy` scripts. +- `lint`: сhecks the scripts for syntax errors. +- `test`: runs a test of all the scripts described above. + +## Workflows + +To automate the run of the scripts described above, we use the [GitHub Actions workflows](https://docs.github.com/en/actions/using-workflows). + +Each workflow includes its own set of scripts that can be run either manually or in response to an event. + +- `check`: sequentially runs the `api:load`, `playlist:check` and `playlist:validate` scripts when a new pull request appears, and blocks the merge if it detects an error in it. +- `format`: sequentially runs `api:load`, `playlist:format`, `playlist:lint` and `playlist:validate` scripts. +- `update`: every day at 0:00 UTC sequentially runs `api:load`, `playlist:update`, `playlist:lint`, `playlist:validate`, `playlist:generate`, `api:generate` and `readme:update` scripts and deploys the output files if successful. diff --git a/FAQ.md b/FAQ.md index 4de9c73547..988fc265dc 100644 --- a/FAQ.md +++ b/FAQ.md @@ -1,23 +1,23 @@ -# Frequently Asked Questions - -### My favorite channel is not on the playlist. - -Start by asking our community for help via [Discussions](https://github.com/orgs/iptv-org/discussions). It is quite possible that someone already has a link to the channel you need and they just haven't added it to our playlist yet. - -But keep in mind that not all TV channels are available for viewing online, and in this case there is little we can do about it. - -### Are you planning to include a Video On Demand (VOD) to the playlist? - -No. - -### Why is the channel on the iptv-org.github.io but not in the playlist? - -The site contains a list of all TV channels in the world and only those of them for which we have working stream links are included in the playlists. - -### Can I add a radio broadcast? - -Yes, if it is a [visual radio](https://en.wikipedia.org/wiki/Visual_radio) in which a video and audio are shown at the same time. - -### Why don't you accept links to Xtream Codes server? - -Xtream Codes streams tend to be very unstable, and often links to them fail very quickly, so it's easier for us to initially exclude them from the playlist than to search for expired ones every day. +# Frequently Asked Questions + +### My favorite channel is not on the playlist. + +Start by asking our community for help via [Discussions](https://github.com/orgs/iptv-org/discussions). It is quite possible that someone already has a link to the channel you need and they just haven't added it to our playlist yet. + +But keep in mind that not all TV channels are available for viewing online, and in this case there is little we can do about it. + +### Are you planning to include a Video On Demand (VOD) to the playlist? + +No. + +### Why is the channel on the iptv-org.github.io but not in the playlist? + +The site contains a list of all TV channels in the world and only those of them for which we have working stream links are included in the playlists. + +### Can I add a radio broadcast? + +Yes, if it is a [visual radio](https://en.wikipedia.org/wiki/Visual_radio) in which a video and audio are shown at the same time. + +### Why don't you accept links to Xtream Codes server? + +Xtream Codes streams tend to be very unstable, and often links to them fail very quickly, so it's easier for us to initially exclude them from the playlist than to search for expired ones every day. diff --git a/LICENSE b/LICENSE index 68a49daad8..edeed79019 100644 --- a/LICENSE +++ b/LICENSE @@ -1,24 +1,24 @@ -This is free and unencumbered software released into the public domain. - -Anyone is free to copy, modify, publish, use, compile, sell, or -distribute this software, either in source code form or as a compiled -binary, for any purpose, commercial or non-commercial, and by any -means. - -In jurisdictions that recognize copyright laws, the author or authors -of this software dedicate any and all copyright interest in the -software to the public domain. We make this dedication for the benefit -of the public at large and to the detriment of our heirs and -successors. We intend this dedication to be an overt act of -relinquishment in perpetuity of all present and future rights to this -software under copyright law. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR -OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. - -For more information, please refer to +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to diff --git a/PLAYLISTS.md b/PLAYLISTS.md index 65906ac578..79d3e56e07 100644 --- a/PLAYLISTS.md +++ b/PLAYLISTS.md @@ -1,22 +1,22 @@ -## Playlists - -There are several versions of playlists that differ in the way they are grouped. As of January 30th, 2024, we have stopped distributing NSFW channels. For more information, please look at [this issue](https://github.com/iptv-org/iptv/issues/15723). - -### Grouped by category - -Playlists in which channels are grouped by category. - -
-Expand -
- -``` -https://iptv-org.github.io/iptv/index.category.m3u -``` - -Same thing, but split up into separate files: - - +## Playlists + +There are several versions of playlists that differ in the way they are grouped. As of January 30th, 2024, we have stopped distributing NSFW channels. For more information, please look at [this issue](https://github.com/iptv-org/iptv/issues/15723). + +### Grouped by category + +Playlists in which channels are grouped by category. + +
+Expand +
+ +``` +https://iptv-org.github.io/iptv/index.category.m3u +``` + +Same thing, but split up into separate files: + + @@ -54,25 +54,25 @@ Same thing, but split up into separate files: -
CategoryChannelsPlaylist
XXX0https://iptv-org.github.io/iptv/categories/xxx.m3u
Undefined3693https://iptv-org.github.io/iptv/categories/undefined.m3u
- -
- -### Grouped by language - -Playlists in which channels are grouped by the language in which they are broadcast. - -
-Expand -
- -``` -https://iptv-org.github.io/iptv/index.language.m3u -``` - -Same thing, but split up into separate files: - - + + +
+ +### Grouped by language + +Playlists in which channels are grouped by the language in which they are broadcast. + +
+Expand +
+ +``` +https://iptv-org.github.io/iptv/index.language.m3u +``` + +Same thing, but split up into separate files: + + @@ -288,26 +288,26 @@ Same thing, but split up into separate files: -
LanguageChannelsPlaylist
Zulu1https://iptv-org.github.io/iptv/languages/zul.m3u
Undefined2176https://iptv-org.github.io/iptv/languages/undefined.m3u
- -
- -### Grouped by broadcast area - -Playlists in which channels are grouped by broadcast area. - -
-Expand - -#### Countries - -``` -https://iptv-org.github.io/iptv/index.country.m3u -``` - -Same thing, but split up into separate files: - - + + +
+ +### Grouped by broadcast area + +Playlists in which channels are grouped by broadcast area. + +
+Expand + +#### Countries + +``` +https://iptv-org.github.io/iptv/index.country.m3u +``` + +Same thing, but split up into separate files: + + - 🇦🇫 Afghanistan https://iptv-org.github.io/iptv/countries/af.m3u - 🇦🇱 Albania https://iptv-org.github.io/iptv/countries/al.m3u - 🇩🇿 Algeria https://iptv-org.github.io/iptv/countries/dz.m3u @@ -1283,11 +1283,11 @@ Same thing, but split up into separate files: - 🇿🇲 Zambia https://iptv-org.github.io/iptv/countries/zm.m3u - 🇿🇼 Zimbabwe https://iptv-org.github.io/iptv/countries/zw.m3u - 🌐 International https://iptv-org.github.io/iptv/countries/int.m3u -- Undefined https://iptv-org.github.io/iptv/countries/undefined.m3u - -#### Regions - - +- Undefined https://iptv-org.github.io/iptv/countries/undefined.m3u + +#### Regions + + - Africa https://iptv-org.github.io/iptv/regions/afr.m3u - Americas https://iptv-org.github.io/iptv/regions/amer.m3u - Arab world https://iptv-org.github.io/iptv/regions/arab.m3u @@ -1329,28 +1329,28 @@ Same thing, but split up into separate files: - West Africa https://iptv-org.github.io/iptv/regions/waf.m3u - West Asia https://iptv-org.github.io/iptv/regions/was.m3u - Western Europe https://iptv-org.github.io/iptv/regions/wer.m3u -- Worldwide https://iptv-org.github.io/iptv/regions/ww.m3u - -
- -### Grouped by sources - -Playlists in which channels are grouped by broadcast source. - -
-Expand -
- -To use the playlist, simply replace `` in the link below with the name of one of the files in the [streams](streams) folder. - -``` -https://iptv-org.github.io/iptv/sources/.m3u -``` - -
- -Also, any of our internal playlists are available in raw form (without any filtering or sorting) at this link: - -``` -https://iptv-org.github.io/iptv/raw/.m3u -``` +- Worldwide https://iptv-org.github.io/iptv/regions/ww.m3u + +
+ +### Grouped by sources + +Playlists in which channels are grouped by broadcast source. + +
+Expand +
+ +To use the playlist, simply replace `` in the link below with the name of one of the files in the [streams](streams) folder. + +``` +https://iptv-org.github.io/iptv/sources/.m3u +``` + +
+ +Also, any of our internal playlists are available in raw form (without any filtering or sorting) at this link: + +``` +https://iptv-org.github.io/iptv/raw/.m3u +``` diff --git a/README.md b/README.md index 371afea056..24bb67ca03 100644 --- a/README.md +++ b/README.md @@ -1,79 +1,79 @@ -# IPTV [![update](https://github.com/iptv-org/iptv/actions/workflows/update.yml/badge.svg)](https://github.com/iptv-org/iptv/actions/workflows/update.yml) - -Collection of publicly available IPTV (Internet Protocol television) channels from all over the world. - -## Table of contents - -- 🚀 [How to use?](#how-to-use) -- 📺 [Playlists](#playlists) -- 🗓 [EPG](#epg) -- 🗄 [Database](#database) -- 👨‍💻 [API](#api) -- 📚 [Resources](#resources) -- 💬 [Discussions](#discussions) -- ❓ [FAQ](#faq) -- 🛠 [Contribution](#contribution) -- ⚖ [Legal](#legal) -- © [License](#license) - -## How to use? - -Simply paste the link to one of the playlists into [any video player](https://github.com/iptv-org/awesome-iptv#apps) that supports live streaming and press _Open_. - -![VLC Network Panel](https://github.com/iptv-org/iptv/raw/master/.readme/preview.png) - -## Playlists - -The main playlist containing all channels available in the repository can be found at: - -``` -https://iptv-org.github.io/iptv/index.m3u -``` - -Links to other playlists can be found in the [PLAYLISTS.md](PLAYLISTS.md) file. - -## EPG - -[Electronic Program Guide](https://en.wikipedia.org/wiki/Electronic_program_guide) for most of the channels can be downloaded using utilities published in the [iptv-org/epg](https://github.com/iptv-org/epg) repository. - -## 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. - -## API - -The API documentation can be found in the [iptv-org/api](https://github.com/iptv-org/api) repository. - -## Resources - -Links to other useful IPTV-related resources can be found in the [iptv-org/awesome-iptv](https://github.com/iptv-org/awesome-iptv) repository. - -## Discussions - -If you need help finding a channel, have a question or idea, welcome to the [Discussions](https://github.com/orgs/iptv-org/discussions). - -## FAQ - -The answers to the most popular questions can be found in the [FAQ.md](FAQ.md) file. - -## Contribution - -Please make sure to read the [Contributing Guide](CONTRIBUTING.md) before sending an issue or making a pull request. - -And thank you to everyone who has already contributed! - -### Backers - - - -### Contributors - - - -## Legal - -No video files are stored in this repository. The repository simply contains user-submitted links to publicly available video stream URLs, which to the best of our knowledge have been intentionally made publicly by the copyright holders. If any links in these playlists infringe on your rights as a copyright holder, they may be removed by sending a [pull request](https://github.com/iptv-org/iptv/pulls) or opening an [issue](https://github.com/iptv-org/iptv/issues/new?assignees=freearhey&labels=removal+request&template=--removal-request.yml&title=Remove%3A+). However, note that we have **no control** over the destination of the link, and just removing the link from the playlist will not remove its contents from the web. Note that linking does not directly infringe copyright because no copy is made on the site providing the link, and thus this is **not** a valid reason to send a DMCA notice to GitHub. To remove this content from the web, you should contact the web host that's actually hosting the content (**not** GitHub, nor the maintainers of this repository). - -## License - -[![CC0](http://mirrors.creativecommons.org/presskit/buttons/88x31/svg/cc-zero.svg)](LICENSE) +# IPTV [![update](https://github.com/iptv-org/iptv/actions/workflows/update.yml/badge.svg)](https://github.com/iptv-org/iptv/actions/workflows/update.yml) + +Collection of publicly available IPTV (Internet Protocol television) channels from all over the world. + +## Table of contents + +- 🚀 [How to use?](#how-to-use) +- 📺 [Playlists](#playlists) +- 🗓 [EPG](#epg) +- 🗄 [Database](#database) +- 👨‍💻 [API](#api) +- 📚 [Resources](#resources) +- 💬 [Discussions](#discussions) +- ❓ [FAQ](#faq) +- 🛠 [Contribution](#contribution) +- ⚖ [Legal](#legal) +- © [License](#license) + +## How to use? + +Simply paste the link to one of the playlists into [any video player](https://github.com/iptv-org/awesome-iptv#apps) that supports live streaming and press _Open_. + +![VLC Network Panel](https://github.com/iptv-org/iptv/raw/master/.readme/preview.png) + +## Playlists + +The main playlist containing all channels available in the repository can be found at: + +``` +https://iptv-org.github.io/iptv/index.m3u +``` + +Links to other playlists can be found in the [PLAYLISTS.md](PLAYLISTS.md) file. + +## EPG + +[Electronic Program Guide](https://en.wikipedia.org/wiki/Electronic_program_guide) for most of the channels can be downloaded using utilities published in the [iptv-org/epg](https://github.com/iptv-org/epg) repository. + +## 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. + +## API + +The API documentation can be found in the [iptv-org/api](https://github.com/iptv-org/api) repository. + +## Resources + +Links to other useful IPTV-related resources can be found in the [iptv-org/awesome-iptv](https://github.com/iptv-org/awesome-iptv) repository. + +## Discussions + +If you need help finding a channel, have a question or idea, welcome to the [Discussions](https://github.com/orgs/iptv-org/discussions). + +## FAQ + +The answers to the most popular questions can be found in the [FAQ.md](FAQ.md) file. + +## Contribution + +Please make sure to read the [Contributing Guide](CONTRIBUTING.md) before sending an issue or making a pull request. + +And thank you to everyone who has already contributed! + +### Backers + + + +### Contributors + + + +## Legal + +No video files are stored in this repository. The repository simply contains user-submitted links to publicly available video stream URLs, which to the best of our knowledge have been intentionally made publicly by the copyright holders. If any links in these playlists infringe on your rights as a copyright holder, they may be removed by sending a [pull request](https://github.com/iptv-org/iptv/pulls) or opening an [issue](https://github.com/iptv-org/iptv/issues/new?assignees=freearhey&labels=removal+request&template=--removal-request.yml&title=Remove%3A+). However, note that we have **no control** over the destination of the link, and just removing the link from the playlist will not remove its contents from the web. Note that linking does not directly infringe copyright because no copy is made on the site providing the link, and thus this is **not** a valid reason to send a DMCA notice to GitHub. To remove this content from the web, you should contact the web host that's actually hosting the content (**not** GitHub, nor the maintainers of this repository). + +## License + +[![CC0](http://mirrors.creativecommons.org/presskit/buttons/88x31/svg/cc-zero.svg)](LICENSE) diff --git a/eslint.config.mjs b/eslint.config.mjs index b6d59ca58d..8f9eab0e77 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,56 +1,56 @@ -import typescriptEslint from '@typescript-eslint/eslint-plugin' -import globals from 'globals' -import tsParser from '@typescript-eslint/parser' -import path from 'node:path' -import { fileURLToPath } from 'node:url' -import js from '@eslint/js' -import stylistic from '@stylistic/eslint-plugin' -import { FlatCompat } from '@eslint/eslintrc' - -const __filename = fileURLToPath(import.meta.url) -const __dirname = path.dirname(__filename) -const compat = new FlatCompat({ - baseDirectory: __dirname, - recommendedConfig: js.configs.recommended, - allConfig: js.configs.all -}) - -export default [ - ...compat.extends('eslint:recommended', 'plugin:@typescript-eslint/recommended'), - { - plugins: { - '@typescript-eslint': typescriptEslint, - '@stylistic': stylistic - }, - - languageOptions: { - globals: { - ...globals.browser - }, - - parser: tsParser, - ecmaVersion: 'latest', - sourceType: 'module' - }, - - rules: { - 'no-case-declarations': 'off', - - indent: [ - 'error', - 2, - { - SwitchCase: 1 - } - ], - - '@stylistic/linebreak-style': ['error', 'windows'], - quotes: ['error', 'single'], - semi: ['error', 'never'] - } - }, - - { - ignores: ['tests/__data__/**'] - } -] +import typescriptEslint from '@typescript-eslint/eslint-plugin' +import stylistic from '@stylistic/eslint-plugin' +import tsParser from '@typescript-eslint/parser' +import { FlatCompat } from '@eslint/eslintrc' +import { fileURLToPath } from 'node:url' +import globals from 'globals' +import path from 'node:path' +import js from '@eslint/js' + +const __filename = fileURLToPath(import.meta.url) +const __dirname = path.dirname(__filename) +const compat = new FlatCompat({ + baseDirectory: __dirname, + recommendedConfig: js.configs.recommended, + allConfig: js.configs.all +}) + +export default [ + ...compat.extends('eslint:recommended', 'plugin:@typescript-eslint/recommended'), + { + plugins: { + '@typescript-eslint': typescriptEslint, + '@stylistic': stylistic + }, + + languageOptions: { + globals: { + ...globals.browser + }, + + parser: tsParser, + ecmaVersion: 'latest', + sourceType: 'module' + }, + + rules: { + 'no-case-declarations': 'off', + + indent: [ + 'error', + 2, + { + SwitchCase: 1 + } + ], + + '@stylistic/linebreak-style': ['error', 'windows'], + quotes: ['error', 'single'], + semi: ['error', 'never'] + } + }, + + { + ignores: ['tests/__data__/**'] + } +] diff --git a/m3u-linter.json b/m3u-linter.json index 2f835c48dd..fc1f39a3d9 100644 --- a/m3u-linter.json +++ b/m3u-linter.json @@ -1,17 +1,17 @@ -{ - "files": ["streams/*.m3u"], - "rules": { - "no-empty-lines": true, - "require-header": true, - "attribute-quotes": true, - "require-info": true, - "require-title": true, - "no-trailing-spaces": false, - "no-whitespace-before-title": true, - "no-multi-spaces": true, - "no-extra-comma": true, - "space-before-paren": true, - "no-dash": true, - "require-link": true - } -} +{ + "files": ["streams/*.m3u"], + "rules": { + "no-empty-lines": true, + "require-header": true, + "attribute-quotes": true, + "require-info": true, + "require-title": true, + "no-trailing-spaces": false, + "no-whitespace-before-title": true, + "no-multi-spaces": true, + "no-extra-comma": true, + "space-before-paren": true, + "no-dash": true, + "require-link": true + } +} diff --git a/package-lock.json b/package-lock.json index 3503626d19..a5f14a99b4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,7849 +1,7903 @@ -{ - "name": "iptv", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "iptv", - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "@alex_neo/jest-expect-message": "^1.0.5", - "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "^9.32.0", - "@freearhey/core": "^0.10.2", - "@freearhey/search-js": "^0.1.2", - "@inquirer/prompts": "^7.8.0", - "@octokit/core": "^7.0.3", - "@octokit/plugin-paginate-rest": "^13.1.1", - "@octokit/plugin-rest-endpoint-methods": "^16.0.0", - "@octokit/types": "^14.1.0", - "@stylistic/eslint-plugin": "^5.2.2", - "@swc/jest": "^0.2.39", - "@types/async": "^3.2.25", - "@types/cli-progress": "^3.11.6", - "@types/fs-extra": "^11.0.4", - "@types/jest": "^30.0.0", - "@types/lodash.uniqueid": "^4.0.9", - "@typescript-eslint/eslint-plugin": "^8.38.0", - "@typescript-eslint/parser": "^8.38.0", - "async-es": "^3.2.6", - "axios": "^1.11.0", - "chalk": "^5.4.1", - "cli-progress": "^3.12.0", - "commander": "^14.0.0", - "console-table-printer": "^2.14.6", - "cross-env": "^10.0.0", - "eslint": "^9.32.0", - "glob": "^11.0.3", - "globals": "^16.3.0", - "iptv-playlist-parser": "^0.15.0", - "jest": "^30.0.5", - "jest-expect-message": "^1.1.3", - "lodash.uniqueid": "^4.0.1", - "m3u-linter": "^0.4.2", - "mediainfo.js": "^0.3.6", - "node-cleanup": "^2.1.2", - "socks-proxy-agent": "^8.0.5", - "tsx": "^4.20.3" - } - }, - "node_modules/@alex_neo/jest-expect-message": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@alex_neo/jest-expect-message/-/jest-expect-message-1.0.5.tgz", - "integrity": "sha512-1eBykZCd0pPGl5qKtV6Z5ARA6yuhXzHsVN2h5GH5/H6svYa37Jr7vMio5OFpiw1LBHtscrZs7amSkZkcwm0cvQ==" - }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "license": "Apache-2.0", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", - "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.27.1", - "js-tokens": "^4.0.0", - "picocolors": "^1.1.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.0.tgz", - "integrity": "sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==", - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.0.tgz", - "integrity": "sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ==", - "license": "MIT", - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.0", - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-module-transforms": "^7.27.3", - "@babel/helpers": "^7.27.6", - "@babel/parser": "^7.28.0", - "@babel/template": "^7.27.2", - "@babel/traverse": "^7.28.0", - "@babel/types": "^7.28.0", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/generator": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.0.tgz", - "integrity": "sha512-lJjzvrbEeWrhB4P3QBsH7tey117PjLZnDbLiQEKjQ/fNJTjuq4HSqgFA+UNSwZT8D7dxxbnuSBMsa1lrWzKlQg==", - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.28.0", - "@babel/types": "^7.28.0", - "@jridgewell/gen-mapping": "^0.3.12", - "@jridgewell/trace-mapping": "^0.3.28", - "jsesc": "^3.0.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", - "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", - "license": "MIT", - "dependencies": { - "@babel/compat-data": "^7.27.2", - "@babel/helper-validator-option": "^7.27.1", - "browserslist": "^4.24.0", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-globals": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", - "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", - "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", - "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.3.tgz", - "integrity": "sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==", - "license": "MIT", - "dependencies": { - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1", - "@babel/traverse": "^7.27.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", - "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", - "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", - "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.28.2", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.2.tgz", - "integrity": "sha512-/V9771t+EgXz62aCcyofnQhGM8DQACbRhvzKFsXKC9QM+5MadF8ZmIm0crDMaz3+o0h0zXfJnd4EhbYbxsrcFw==", - "license": "MIT", - "dependencies": { - "@babel/template": "^7.27.2", - "@babel/types": "^7.28.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.0.tgz", - "integrity": "sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==", - "license": "MIT", - "dependencies": { - "@babel/types": "^7.28.0" - }, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-bigint": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", - "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-class-properties": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", - "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-class-static-block": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", - "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz", - "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==", - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", - "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-private-property-in-object": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", - "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-top-level-await": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", - "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz", - "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==", - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/template": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", - "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/parser": "^7.27.2", - "@babel/types": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.0.tgz", - "integrity": "sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg==", - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.0", - "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.28.0", - "@babel/template": "^7.27.2", - "@babel/types": "^7.28.0", - "debug": "^4.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/types": { - "version": "7.28.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.2.tgz", - "integrity": "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==", - "license": "MIT", - "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "license": "MIT" - }, - "node_modules/@emnapi/core": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.4.5.tgz", - "integrity": "sha512-XsLw1dEOpkSX/WucdqUhPWP7hDxSvZiY+fsUC14h+FtQ2Ifni4znbBt8punRX+Uj2JG/uDb8nEHVKvrVlvdZ5Q==", - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/wasi-threads": "1.0.4", - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/runtime": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.5.tgz", - "integrity": "sha512-++LApOtY0pEEz1zrd9vy1/zXVaVJJ/EbAF3u0fXIzPJEDtnITsBGbbK0EkM72amhl/R5b+5xx0Y/QhcVOpuulg==", - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/wasi-threads": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.4.tgz", - "integrity": "sha512-PJR+bOmMOPH8AtcTGAyYNiuJ3/Fcoj2XN/gBEWzDIKh254XO+mM9XoXHk5GNEhodxeMznbg7BlRojVbKN+gC6g==", - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@epic-web/invariant": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@epic-web/invariant/-/invariant-1.0.0.tgz", - "integrity": "sha512-lrTPqgvfFQtR/eY/qkIzp98OGdNJu0m5ji3q/nJI8v3SXkRKEnWiOxMmbvcSoAIzv/cGiuvRy57k4suKQSAdwA==", - "license": "MIT" - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.3.tgz", - "integrity": "sha512-W8bFfPA8DowP8l//sxjJLSLkD8iEjMc7cBVyP+u4cEv9sM7mdUCkgsj+t0n/BWPFtv7WWCN5Yzj0N6FJNUUqBQ==", - "cpu": [ - "ppc64" - ], - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.3.tgz", - "integrity": "sha512-PuwVXbnP87Tcff5I9ngV0lmiSu40xw1At6i3GsU77U7cjDDB4s0X2cyFuBiDa1SBk9DnvWwnGvVaGBqoFWPb7A==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.3.tgz", - "integrity": "sha512-XelR6MzjlZuBM4f5z2IQHK6LkK34Cvv6Rj2EntER3lwCBFdg6h2lKbtRjpTTsdEjD/WSe1q8UyPBXP1x3i/wYQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.3.tgz", - "integrity": "sha512-ogtTpYHT/g1GWS/zKM0cc/tIebFjm1F9Aw1boQ2Y0eUQ+J89d0jFY//s9ei9jVIlkYi8AfOjiixcLJSGNSOAdQ==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.3.tgz", - "integrity": "sha512-eESK5yfPNTqpAmDfFWNsOhmIOaQA59tAcF/EfYvo5/QWQCzXn5iUSOnqt3ra3UdzBv073ykTtmeLJZGt3HhA+w==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.3.tgz", - "integrity": "sha512-Kd8glo7sIZtwOLcPbW0yLpKmBNWMANZhrC1r6K++uDR2zyzb6AeOYtI6udbtabmQpFaxJ8uduXMAo1gs5ozz8A==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.3.tgz", - "integrity": "sha512-EJiyS70BYybOBpJth3M0KLOus0n+RRMKTYzhYhFeMwp7e/RaajXvP+BWlmEXNk6uk+KAu46j/kaQzr6au+JcIw==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.3.tgz", - "integrity": "sha512-Q+wSjaLpGxYf7zC0kL0nDlhsfuFkoN+EXrx2KSB33RhinWzejOd6AvgmP5JbkgXKmjhmpfgKZq24pneodYqE8Q==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.3.tgz", - "integrity": "sha512-dUOVmAUzuHy2ZOKIHIKHCm58HKzFqd+puLaS424h6I85GlSDRZIA5ycBixb3mFgM0Jdh+ZOSB6KptX30DD8YOQ==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.3.tgz", - "integrity": "sha512-xCUgnNYhRD5bb1C1nqrDV1PfkwgbswTTBRbAd8aH5PhYzikdf/ddtsYyMXFfGSsb/6t6QaPSzxtbfAZr9uox4A==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.3.tgz", - "integrity": "sha512-yplPOpczHOO4jTYKmuYuANI3WhvIPSVANGcNUeMlxH4twz/TeXuzEP41tGKNGWJjuMhotpGabeFYGAOU2ummBw==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.3.tgz", - "integrity": "sha512-P4BLP5/fjyihmXCELRGrLd793q/lBtKMQl8ARGpDxgzgIKJDRJ/u4r1A/HgpBpKpKZelGct2PGI4T+axcedf6g==", - "cpu": [ - "loong64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.3.tgz", - "integrity": "sha512-eRAOV2ODpu6P5divMEMa26RRqb2yUoYsuQQOuFUexUoQndm4MdpXXDBbUoKIc0iPa4aCO7gIhtnYomkn2x+bag==", - "cpu": [ - "mips64el" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.3.tgz", - "integrity": "sha512-ZC4jV2p7VbzTlnl8nZKLcBkfzIf4Yad1SJM4ZMKYnJqZFD4rTI+pBG65u8ev4jk3/MPwY9DvGn50wi3uhdaghg==", - "cpu": [ - "ppc64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.3.tgz", - "integrity": "sha512-LDDODcFzNtECTrUUbVCs6j9/bDVqy7DDRsuIXJg6so+mFksgwG7ZVnTruYi5V+z3eE5y+BJZw7VvUadkbfg7QA==", - "cpu": [ - "riscv64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.3.tgz", - "integrity": "sha512-s+w/NOY2k0yC2p9SLen+ymflgcpRkvwwa02fqmAwhBRI3SC12uiS10edHHXlVWwfAagYSY5UpmT/zISXPMW3tQ==", - "cpu": [ - "s390x" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.3.tgz", - "integrity": "sha512-nQHDz4pXjSDC6UfOE1Fw9Q8d6GCAd9KdvMZpfVGWSJztYCarRgSDfOVBY5xwhQXseiyxapkiSJi/5/ja8mRFFA==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.3.tgz", - "integrity": "sha512-1QaLtOWq0mzK6tzzp0jRN3eccmN3hezey7mhLnzC6oNlJoUJz4nym5ZD7mDnS/LZQgkrhEbEiTn515lPeLpgWA==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.3.tgz", - "integrity": "sha512-i5Hm68HXHdgv8wkrt+10Bc50zM0/eonPb/a/OFVfB6Qvpiirco5gBA5bz7S2SHuU+Y4LWn/zehzNX14Sp4r27g==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.3.tgz", - "integrity": "sha512-zGAVApJEYTbOC6H/3QBr2mq3upG/LBEXr85/pTtKiv2IXcgKV0RT0QA/hSXZqSvLEpXeIxah7LczB4lkiYhTAQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.3.tgz", - "integrity": "sha512-fpqctI45NnCIDKBH5AXQBsD0NDPbEFczK98hk/aa6HJxbl+UtLkJV2+Bvy5hLSLk3LHmqt0NTkKNso1A9y1a4w==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.3.tgz", - "integrity": "sha512-ROJhm7d8bk9dMCUZjkS8fgzsPAZEjtRJqCAmVgB0gMrvG7hfmPmz9k1rwO4jSiblFjYmNvbECL9uhaPzONMfgA==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.3.tgz", - "integrity": "sha512-YWcow8peiHpNBiIXHwaswPnAXLsLVygFwCB3A7Bh5jRkIBFWHGmNQ48AlX4xDvQNoMZlPYzjVOQDYEzWCqufMQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.3.tgz", - "integrity": "sha512-qspTZOIGoXVS4DpNqUYUs9UxVb04khS1Degaw/MnfMe7goQ3lTfQ13Vw4qY/Nj0979BGvMRpAYbs/BAxEvU8ew==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.3.tgz", - "integrity": "sha512-ICgUR+kPimx0vvRzf+N/7L7tVSQeE3BYY+NhHRHXS1kBuPO7z2+7ea2HbhDyZdTephgvNvKrlDDKUexuCVBVvg==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", - "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", - "license": "MIT", - "dependencies": { - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", - "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/config-array": { - "version": "0.21.0", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz", - "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==", - "dependencies": { - "@eslint/object-schema": "^2.1.6", - "debug": "^4.3.1", - "minimatch": "^3.1.2" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/config-helpers": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.0.tgz", - "integrity": "sha512-ViuymvFmcJi04qdZeDc2whTHryouGcDlaxPqarTD0ZE10ISpxGUVZGZDx4w01upyIynL3iu6IXH2bS1NhclQMw==", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/core": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.1.tgz", - "integrity": "sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA==", - "dependencies": { - "@types/json-schema": "^7.0.15" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", - "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^10.0.1", - "globals": "^14.0.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/js": { - "version": "9.32.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.32.0.tgz", - "integrity": "sha512-BBpRFZK3eX6uMLKz8WxFOBIFFcGFJ/g8XuwjTHCqHROSIsopI+ddn/d5Cfh36+7+e5edVS8dbSHnBNhrLEX0zg==", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://eslint.org/donate" - } - }, - "node_modules/@eslint/object-schema": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", - "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/plugin-kit": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.4.tgz", - "integrity": "sha512-Ul5l+lHEcw3L5+k8POx6r74mxEYKG5kOb6Xpy2gCRW6zweT6TEhAf8vhxGgjhqrd/VO/Dirhsb+1hNpD1ue9hw==", - "dependencies": { - "@eslint/core": "^0.15.1", - "levn": "^0.4.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@freearhey/core": { - "version": "0.10.2", - "resolved": "https://registry.npmjs.org/@freearhey/core/-/core-0.10.2.tgz", - "integrity": "sha512-crIE1oVYnhmCvISuNvJ4eP70tmoPzCTg6emlPxDIimu8LAtC8FVyckC04nBQCMYaXjLuju7tI80vHmKRBXniVg==", - "license": "MIT", - "dependencies": { - "consola": "^3.4.2", - "dayjs": "^1.11.13", - "fs-extra": "^11.3.0", - "glob": "^11.0.1", - "lodash": "^4.17.21", - "natural-orderby": "^5.0.0", - "normalize-url": "^6.1.0", - "object-treeify": "^2.1.1", - "pako": "^2.1.0", - "timer-node": "^5.0.9" - } - }, - "node_modules/@freearhey/search-js": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@freearhey/search-js/-/search-js-0.1.2.tgz", - "integrity": "sha512-F2o+xpGCXOK4OsZfKEHfXNNkAZmny2eBnPOp+P0iyV20ja7gJGfTFaEc6okcuEo6OB6P7LnSxTvISkoArFtlfg==", - "dependencies": { - "lodash": "^4.17.21" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@humanfs/core": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", - "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/@humanfs/node": { - "version": "0.16.6", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", - "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", - "dependencies": { - "@humanfs/core": "^0.19.1", - "@humanwhocodes/retry": "^0.3.0" - }, - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", - "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", - "engines": { - "node": ">=18.18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/retry": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.2.tgz", - "integrity": "sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==", - "engines": { - "node": ">=18.18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@inquirer/checkbox": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-4.2.0.tgz", - "integrity": "sha512-fdSw07FLJEU5vbpOPzXo5c6xmMGDzbZE2+niuDHX5N6mc6V0Ebso/q3xiHra4D73+PMsC8MJmcaZKuAAoaQsSA==", - "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.1.15", - "@inquirer/figures": "^1.0.13", - "@inquirer/type": "^3.0.8", - "ansi-escapes": "^4.3.2", - "yoctocolors-cjs": "^2.1.2" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/confirm": { - "version": "5.1.14", - "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.14.tgz", - "integrity": "sha512-5yR4IBfe0kXe59r1YCTG8WXkUbl7Z35HK87Sw+WUyGD8wNUx7JvY7laahzeytyE1oLn74bQnL7hstctQxisQ8Q==", - "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.1.15", - "@inquirer/type": "^3.0.8" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/core": { - "version": "10.1.15", - "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.1.15.tgz", - "integrity": "sha512-8xrp836RZvKkpNbVvgWUlxjT4CraKk2q+I3Ksy+seI2zkcE+y6wNs1BVhgcv8VyImFecUhdQrYLdW32pAjwBdA==", - "license": "MIT", - "dependencies": { - "@inquirer/figures": "^1.0.13", - "@inquirer/type": "^3.0.8", - "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" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/editor": { - "version": "4.2.17", - "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-4.2.17.tgz", - "integrity": "sha512-r6bQLsyPSzbWrZZ9ufoWL+CztkSatnJ6uSxqd6N+o41EZC51sQeWOzI6s5jLb+xxTWxl7PlUppqm8/sow241gg==", - "dependencies": { - "@inquirer/core": "^10.1.15", - "@inquirer/external-editor": "^1.0.1", - "@inquirer/type": "^3.0.8" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/expand": { - "version": "4.0.17", - "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-4.0.17.tgz", - "integrity": "sha512-PSqy9VmJx/VbE3CT453yOfNa+PykpKg/0SYP7odez1/NWBGuDXgPhp4AeGYYKjhLn5lUUavVS/JbeYMPdH50Mw==", - "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.1.15", - "@inquirer/type": "^3.0.8", - "yoctocolors-cjs": "^2.1.2" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/external-editor": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-1.0.1.tgz", - "integrity": "sha512-Oau4yL24d2B5IL4ma4UpbQigkVhzPDXLoqy1ggK4gnHg/stmkffJE4oOXHXF3uz0UEpywG68KcyXsyYpA1Re/Q==", - "dependencies": { - "chardet": "^2.1.0", - "iconv-lite": "^0.6.3" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/figures": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.13.tgz", - "integrity": "sha512-lGPVU3yO9ZNqA7vTYz26jny41lE7yoQansmqdMLBEfqaGsmdg7V3W9mK9Pvb5IL4EVZ9GnSDGMO/cJXud5dMaw==", - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/@inquirer/input": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-4.2.1.tgz", - "integrity": "sha512-tVC+O1rBl0lJpoUZv4xY+WGWY8V5b0zxU1XDsMsIHYregdh7bN5X5QnIONNBAl0K765FYlAfNHS2Bhn7SSOVow==", - "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.1.15", - "@inquirer/type": "^3.0.8" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/number": { - "version": "3.0.17", - "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-3.0.17.tgz", - "integrity": "sha512-GcvGHkyIgfZgVnnimURdOueMk0CztycfC8NZTiIY9arIAkeOgt6zG57G+7vC59Jns3UX27LMkPKnKWAOF5xEYg==", - "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.1.15", - "@inquirer/type": "^3.0.8" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/password": { - "version": "4.0.17", - "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-4.0.17.tgz", - "integrity": "sha512-DJolTnNeZ00E1+1TW+8614F7rOJJCM4y4BAGQ3Gq6kQIG+OJ4zr3GLjIjVVJCbKsk2jmkmv6v2kQuN/vriHdZA==", - "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.1.15", - "@inquirer/type": "^3.0.8", - "ansi-escapes": "^4.3.2" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/prompts": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-7.8.0.tgz", - "integrity": "sha512-JHwGbQ6wjf1dxxnalDYpZwZxUEosT+6CPGD9Zh4sm9WXdtUp9XODCQD3NjSTmu+0OAyxWXNOqf0spjIymJa2Tw==", - "license": "MIT", - "dependencies": { - "@inquirer/checkbox": "^4.2.0", - "@inquirer/confirm": "^5.1.14", - "@inquirer/editor": "^4.2.15", - "@inquirer/expand": "^4.0.17", - "@inquirer/input": "^4.2.1", - "@inquirer/number": "^3.0.17", - "@inquirer/password": "^4.0.17", - "@inquirer/rawlist": "^4.1.5", - "@inquirer/search": "^3.1.0", - "@inquirer/select": "^4.3.1" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/rawlist": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-4.1.5.tgz", - "integrity": "sha512-R5qMyGJqtDdi4Ht521iAkNqyB6p2UPuZUbMifakg1sWtu24gc2Z8CJuw8rP081OckNDMgtDCuLe42Q2Kr3BolA==", - "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.1.15", - "@inquirer/type": "^3.0.8", - "yoctocolors-cjs": "^2.1.2" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/search": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-3.1.0.tgz", - "integrity": "sha512-PMk1+O/WBcYJDq2H7foV0aAZSmDdkzZB9Mw2v/DmONRJopwA/128cS9M/TXWLKKdEQKZnKwBzqu2G4x/2Nqx8Q==", - "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.1.15", - "@inquirer/figures": "^1.0.13", - "@inquirer/type": "^3.0.8", - "yoctocolors-cjs": "^2.1.2" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/select": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-4.3.1.tgz", - "integrity": "sha512-Gfl/5sqOF5vS/LIrSndFgOh7jgoe0UXEizDqahFRkq5aJBLegZ6WjuMh/hVEJwlFQjyLq1z9fRtvUMkb7jM1LA==", - "license": "MIT", - "dependencies": { - "@inquirer/core": "^10.1.15", - "@inquirer/figures": "^1.0.13", - "@inquirer/type": "^3.0.8", - "ansi-escapes": "^4.3.2", - "yoctocolors-cjs": "^2.1.2" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@inquirer/type": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.8.tgz", - "integrity": "sha512-lg9Whz8onIHRthWaN1Q9EGLa/0LFJjyM8mEUbL1eTi6yMGvBf8gvyDLtxSXztQsxMvhxxNpJYrwa1YHdq+w4Jw==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@types/node": ">=18" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - } - } - }, - "node_modules/@isaacs/balanced-match": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz", - "integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==", - "license": "MIT", - "engines": { - "node": "20 || >=22" - } - }, - "node_modules/@isaacs/brace-expansion": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz", - "integrity": "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==", - "license": "MIT", - "dependencies": { - "@isaacs/balanced-match": "^4.0.1" - }, - "engines": { - "node": "20 || >=22" - } - }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "license": "ISC", - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "license": "MIT" - }, - "node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", - "license": "ISC", - "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "license": "MIT", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "license": "MIT", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "license": "MIT", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "license": "MIT", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "license": "BSD-3-Clause" - }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/console": { - "version": "30.0.5", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-30.0.5.tgz", - "integrity": "sha512-xY6b0XiL0Nav3ReresUarwl2oIz1gTnxGbGpho9/rbUWsLH0f1OD/VT84xs8c7VmH7MChnLb0pag6PhZhAdDiA==", - "license": "MIT", - "dependencies": { - "@jest/types": "30.0.5", - "@types/node": "*", - "chalk": "^4.1.2", - "jest-message-util": "30.0.5", - "jest-util": "30.0.5", - "slash": "^3.0.0" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/@jest/console/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@jest/core": { - "version": "30.0.5", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-30.0.5.tgz", - "integrity": "sha512-fKD0OulvRsXF1hmaFgHhVJzczWzA1RXMMo9LTPuFXo9q/alDbME3JIyWYqovWsUBWSoBcsHaGPSLF9rz4l9Qeg==", - "license": "MIT", - "dependencies": { - "@jest/console": "30.0.5", - "@jest/pattern": "30.0.1", - "@jest/reporters": "30.0.5", - "@jest/test-result": "30.0.5", - "@jest/transform": "30.0.5", - "@jest/types": "30.0.5", - "@types/node": "*", - "ansi-escapes": "^4.3.2", - "chalk": "^4.1.2", - "ci-info": "^4.2.0", - "exit-x": "^0.2.2", - "graceful-fs": "^4.2.11", - "jest-changed-files": "30.0.5", - "jest-config": "30.0.5", - "jest-haste-map": "30.0.5", - "jest-message-util": "30.0.5", - "jest-regex-util": "30.0.1", - "jest-resolve": "30.0.5", - "jest-resolve-dependencies": "30.0.5", - "jest-runner": "30.0.5", - "jest-runtime": "30.0.5", - "jest-snapshot": "30.0.5", - "jest-util": "30.0.5", - "jest-validate": "30.0.5", - "jest-watcher": "30.0.5", - "micromatch": "^4.0.8", - "pretty-format": "30.0.5", - "slash": "^3.0.0" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/@jest/core/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@jest/create-cache-key-function": { - "version": "30.0.5", - "resolved": "https://registry.npmjs.org/@jest/create-cache-key-function/-/create-cache-key-function-30.0.5.tgz", - "integrity": "sha512-W1kmkwPq/WTMQWgvbzWSCbXSqvjI6rkqBQCxuvYmd+g6o4b5gHP98ikfh/Ei0SKzHvWdI84TOXp0hRcbpr8Q0w==", - "license": "MIT", - "dependencies": { - "@jest/types": "30.0.5" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/@jest/diff-sequences": { - "version": "30.0.1", - "resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.0.1.tgz", - "integrity": "sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw==", - "license": "MIT", - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/@jest/environment": { - "version": "30.0.5", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-30.0.5.tgz", - "integrity": "sha512-aRX7WoaWx1oaOkDQvCWImVQ8XNtdv5sEWgk4gxR6NXb7WBUnL5sRak4WRzIQRZ1VTWPvV4VI4mgGjNL9TeKMYA==", - "license": "MIT", - "dependencies": { - "@jest/fake-timers": "30.0.5", - "@jest/types": "30.0.5", - "@types/node": "*", - "jest-mock": "30.0.5" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/@jest/expect": { - "version": "30.0.5", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-30.0.5.tgz", - "integrity": "sha512-6udac8KKrtTtC+AXZ2iUN/R7dp7Ydry+Fo6FPFnDG54wjVMnb6vW/XNlf7Xj8UDjAE3aAVAsR4KFyKk3TCXmTA==", - "license": "MIT", - "dependencies": { - "expect": "30.0.5", - "jest-snapshot": "30.0.5" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/@jest/expect-utils": { - "version": "30.0.5", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.0.5.tgz", - "integrity": "sha512-F3lmTT7CXWYywoVUGTCmom0vXq3HTTkaZyTAzIy+bXSBizB7o5qzlC9VCtq0arOa8GqmNsbg/cE9C6HLn7Szew==", - "license": "MIT", - "dependencies": { - "@jest/get-type": "30.0.1" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/@jest/fake-timers": { - "version": "30.0.5", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-30.0.5.tgz", - "integrity": "sha512-ZO5DHfNV+kgEAeP3gK3XlpJLL4U3Sz6ebl/n68Uwt64qFFs5bv4bfEEjyRGK5uM0C90ewooNgFuKMdkbEoMEXw==", - "license": "MIT", - "dependencies": { - "@jest/types": "30.0.5", - "@sinonjs/fake-timers": "^13.0.0", - "@types/node": "*", - "jest-message-util": "30.0.5", - "jest-mock": "30.0.5", - "jest-util": "30.0.5" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/@jest/get-type": { - "version": "30.0.1", - "resolved": "https://registry.npmjs.org/@jest/get-type/-/get-type-30.0.1.tgz", - "integrity": "sha512-AyYdemXCptSRFirI5EPazNxyPwAL0jXt3zceFjaj8NFiKP9pOi0bfXonf6qkf82z2t3QWPeLCWWw4stPBzctLw==", - "license": "MIT", - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/@jest/globals": { - "version": "30.0.5", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-30.0.5.tgz", - "integrity": "sha512-7oEJT19WW4oe6HR7oLRvHxwlJk2gev0U9px3ufs8sX9PoD1Eza68KF0/tlN7X0dq/WVsBScXQGgCldA1V9Y/jA==", - "license": "MIT", - "dependencies": { - "@jest/environment": "30.0.5", - "@jest/expect": "30.0.5", - "@jest/types": "30.0.5", - "jest-mock": "30.0.5" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/@jest/pattern": { - "version": "30.0.1", - "resolved": "https://registry.npmjs.org/@jest/pattern/-/pattern-30.0.1.tgz", - "integrity": "sha512-gWp7NfQW27LaBQz3TITS8L7ZCQ0TLvtmI//4OwlQRx4rnWxcPNIYjxZpDcN4+UlGxgm3jS5QPz8IPTCkb59wZA==", - "license": "MIT", - "dependencies": { - "@types/node": "*", - "jest-regex-util": "30.0.1" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/@jest/reporters": { - "version": "30.0.5", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-30.0.5.tgz", - "integrity": "sha512-mafft7VBX4jzED1FwGC1o/9QUM2xebzavImZMeqnsklgcyxBto8mV4HzNSzUrryJ+8R9MFOM3HgYuDradWR+4g==", - "license": "MIT", - "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "30.0.5", - "@jest/test-result": "30.0.5", - "@jest/transform": "30.0.5", - "@jest/types": "30.0.5", - "@jridgewell/trace-mapping": "^0.3.25", - "@types/node": "*", - "chalk": "^4.1.2", - "collect-v8-coverage": "^1.0.2", - "exit-x": "^0.2.2", - "glob": "^10.3.10", - "graceful-fs": "^4.2.11", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^6.0.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^5.0.0", - "istanbul-reports": "^3.1.3", - "jest-message-util": "30.0.5", - "jest-util": "30.0.5", - "jest-worker": "30.0.5", - "slash": "^3.0.0", - "string-length": "^4.0.2", - "v8-to-istanbul": "^9.0.1" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/@jest/reporters/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@jest/reporters/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@jest/reporters/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@jest/reporters/node_modules/jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, - "node_modules/@jest/reporters/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "license": "ISC" - }, - "node_modules/@jest/reporters/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@jest/reporters/node_modules/path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "license": "BlueOak-1.0.0", - "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@jest/schemas": { - "version": "30.0.5", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.5.tgz", - "integrity": "sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==", - "license": "MIT", - "dependencies": { - "@sinclair/typebox": "^0.34.0" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/@jest/snapshot-utils": { - "version": "30.0.5", - "resolved": "https://registry.npmjs.org/@jest/snapshot-utils/-/snapshot-utils-30.0.5.tgz", - "integrity": "sha512-XcCQ5qWHLvi29UUrowgDFvV4t7ETxX91CbDczMnoqXPOIcZOxyNdSjm6kV5XMc8+HkxfRegU/MUmnTbJRzGrUQ==", - "license": "MIT", - "dependencies": { - "@jest/types": "30.0.5", - "chalk": "^4.1.2", - "graceful-fs": "^4.2.11", - "natural-compare": "^1.4.0" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/@jest/snapshot-utils/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@jest/source-map": { - "version": "30.0.1", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-30.0.1.tgz", - "integrity": "sha512-MIRWMUUR3sdbP36oyNyhbThLHyJ2eEDClPCiHVbrYAe5g3CHRArIVpBw7cdSB5fr+ofSfIb2Tnsw8iEHL0PYQg==", - "license": "MIT", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.25", - "callsites": "^3.1.0", - "graceful-fs": "^4.2.11" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/@jest/test-result": { - "version": "30.0.5", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-30.0.5.tgz", - "integrity": "sha512-wPyztnK0gbDMQAJZ43tdMro+qblDHH1Ru/ylzUo21TBKqt88ZqnKKK2m30LKmLLoKtR2lxdpCC/P3g1vfKcawQ==", - "license": "MIT", - "dependencies": { - "@jest/console": "30.0.5", - "@jest/types": "30.0.5", - "@types/istanbul-lib-coverage": "^2.0.6", - "collect-v8-coverage": "^1.0.2" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/@jest/test-sequencer": { - "version": "30.0.5", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-30.0.5.tgz", - "integrity": "sha512-Aea/G1egWoIIozmDD7PBXUOxkekXl7ueGzrsGGi1SbeKgQqCYCIf+wfbflEbf2LiPxL8j2JZGLyrzZagjvW4YQ==", - "license": "MIT", - "dependencies": { - "@jest/test-result": "30.0.5", - "graceful-fs": "^4.2.11", - "jest-haste-map": "30.0.5", - "slash": "^3.0.0" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/@jest/transform": { - "version": "30.0.5", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-30.0.5.tgz", - "integrity": "sha512-Vk8amLQCmuZyy6GbBht1Jfo9RSdBtg7Lks+B0PecnjI8J+PCLQPGh7uI8Q/2wwpW2gLdiAfiHNsmekKlywULqg==", - "license": "MIT", - "dependencies": { - "@babel/core": "^7.27.4", - "@jest/types": "30.0.5", - "@jridgewell/trace-mapping": "^0.3.25", - "babel-plugin-istanbul": "^7.0.0", - "chalk": "^4.1.2", - "convert-source-map": "^2.0.0", - "fast-json-stable-stringify": "^2.1.0", - "graceful-fs": "^4.2.11", - "jest-haste-map": "30.0.5", - "jest-regex-util": "30.0.1", - "jest-util": "30.0.5", - "micromatch": "^4.0.8", - "pirates": "^4.0.7", - "slash": "^3.0.0", - "write-file-atomic": "^5.0.1" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/@jest/transform/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@jest/types": { - "version": "30.0.5", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.0.5.tgz", - "integrity": "sha512-aREYa3aku9SSnea4aX6bhKn4bgv3AXkgijoQgbYV3yvbiGt6z+MQ85+6mIhx9DsKW2BuB/cLR/A+tcMThx+KLQ==", - "license": "MIT", - "dependencies": { - "@jest/pattern": "30.0.1", - "@jest/schemas": "30.0.5", - "@types/istanbul-lib-coverage": "^2.0.6", - "@types/istanbul-reports": "^3.0.4", - "@types/node": "*", - "@types/yargs": "^17.0.33", - "chalk": "^4.1.2" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/@jest/types/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.12", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz", - "integrity": "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==", - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz", - "integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==", - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.29", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz", - "integrity": "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==", - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@napi-rs/wasm-runtime": { - "version": "0.2.12", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", - "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==", - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/core": "^1.4.3", - "@emnapi/runtime": "^1.4.3", - "@tybys/wasm-util": "^0.10.0" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@octokit/auth-token": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-6.0.0.tgz", - "integrity": "sha512-P4YJBPdPSpWTQ1NU4XYdvHvXJJDxM6YwpS0FZHRgP7YFkdVxsWcpWGy/NVqlAA7PcPCnMacXlRm1y2PFZRWL/w==", - "license": "MIT", - "engines": { - "node": ">= 20" - } - }, - "node_modules/@octokit/core": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-7.0.3.tgz", - "integrity": "sha512-oNXsh2ywth5aowwIa7RKtawnkdH6LgU1ztfP9AIUCQCvzysB+WeU8o2kyyosDPwBZutPpjZDKPQGIzzrfTWweQ==", - "license": "MIT", - "dependencies": { - "@octokit/auth-token": "^6.0.0", - "@octokit/graphql": "^9.0.1", - "@octokit/request": "^10.0.2", - "@octokit/request-error": "^7.0.0", - "@octokit/types": "^14.0.0", - "before-after-hook": "^4.0.0", - "universal-user-agent": "^7.0.0" - }, - "engines": { - "node": ">= 20" - } - }, - "node_modules/@octokit/endpoint": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-11.0.0.tgz", - "integrity": "sha512-hoYicJZaqISMAI3JfaDr1qMNi48OctWuOih1m80bkYow/ayPw6Jj52tqWJ6GEoFTk1gBqfanSoI1iY99Z5+ekQ==", - "license": "MIT", - "dependencies": { - "@octokit/types": "^14.0.0", - "universal-user-agent": "^7.0.2" - }, - "engines": { - "node": ">= 20" - } - }, - "node_modules/@octokit/graphql": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-9.0.1.tgz", - "integrity": "sha512-j1nQNU1ZxNFx2ZtKmL4sMrs4egy5h65OMDmSbVyuCzjOcwsHq6EaYjOTGXPQxgfiN8dJ4CriYHk6zF050WEULg==", - "license": "MIT", - "dependencies": { - "@octokit/request": "^10.0.2", - "@octokit/types": "^14.0.0", - "universal-user-agent": "^7.0.0" - }, - "engines": { - "node": ">= 20" - } - }, - "node_modules/@octokit/openapi-types": { - "version": "25.1.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-25.1.0.tgz", - "integrity": "sha512-idsIggNXUKkk0+BExUn1dQ92sfysJrje03Q0bv0e+KPLrvyqZF8MnBpFz8UNfYDwB3Ie7Z0TByjWfzxt7vseaA==", - "license": "MIT" - }, - "node_modules/@octokit/plugin-paginate-rest": { - "version": "13.1.1", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-13.1.1.tgz", - "integrity": "sha512-q9iQGlZlxAVNRN2jDNskJW/Cafy7/XE52wjZ5TTvyhyOD904Cvx//DNyoO3J/MXJ0ve3rPoNWKEg5iZrisQSuw==", - "license": "MIT", - "dependencies": { - "@octokit/types": "^14.1.0" - }, - "engines": { - "node": ">= 20" - }, - "peerDependencies": { - "@octokit/core": ">=6" - } - }, - "node_modules/@octokit/plugin-rest-endpoint-methods": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-16.0.0.tgz", - "integrity": "sha512-kJVUQk6/dx/gRNLWUnAWKFs1kVPn5O5CYZyssyEoNYaFedqZxsfYs7DwI3d67hGz4qOwaJ1dpm07hOAD1BXx6g==", - "license": "MIT", - "dependencies": { - "@octokit/types": "^14.1.0" - }, - "engines": { - "node": ">= 20" - }, - "peerDependencies": { - "@octokit/core": ">=6" - } - }, - "node_modules/@octokit/request": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-10.0.3.tgz", - "integrity": "sha512-V6jhKokg35vk098iBqp2FBKunk3kMTXlmq+PtbV9Gl3TfskWlebSofU9uunVKhUN7xl+0+i5vt0TGTG8/p/7HA==", - "license": "MIT", - "dependencies": { - "@octokit/endpoint": "^11.0.0", - "@octokit/request-error": "^7.0.0", - "@octokit/types": "^14.0.0", - "fast-content-type-parse": "^3.0.0", - "universal-user-agent": "^7.0.2" - }, - "engines": { - "node": ">= 20" - } - }, - "node_modules/@octokit/request-error": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-7.0.0.tgz", - "integrity": "sha512-KRA7VTGdVyJlh0cP5Tf94hTiYVVqmt2f3I6mnimmaVz4UG3gQV/k4mDJlJv3X67iX6rmN7gSHCF8ssqeMnmhZg==", - "license": "MIT", - "dependencies": { - "@octokit/types": "^14.0.0" - }, - "engines": { - "node": ">= 20" - } - }, - "node_modules/@octokit/types": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-14.1.0.tgz", - "integrity": "sha512-1y6DgTy8Jomcpu33N+p5w58l6xyt55Ar2I91RPiIA0xCJBXyUAhXCcmZaDWSANiha7R9a6qJJ2CRomGPZ6f46g==", - "license": "MIT", - "dependencies": { - "@octokit/openapi-types": "^25.1.0" - } - }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/@pkgr/core": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz", - "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==", - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/pkgr" - } - }, - "node_modules/@sinclair/typebox": { - "version": "0.34.38", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.38.tgz", - "integrity": "sha512-HpkxMmc2XmZKhvaKIZZThlHmx1L0I/V1hWK1NubtlFnr6ZqdiOpV72TKudZUNQjZNsyDBay72qFEhEvb+bcwcA==", - "license": "MIT" - }, - "node_modules/@sinonjs/commons": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", - "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", - "license": "BSD-3-Clause", - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/@sinonjs/fake-timers": { - "version": "13.0.5", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz", - "integrity": "sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==", - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^3.0.1" - } - }, - "node_modules/@stylistic/eslint-plugin": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-5.2.2.tgz", - "integrity": "sha512-bE2DUjruqXlHYP3Q2Gpqiuj2bHq7/88FnuaS0FjeGGLCy+X6a07bGVuwtiOYnPSLHR6jmx5Bwdv+j7l8H+G97A==", - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/types": "^8.37.0", - "eslint-visitor-keys": "^4.2.1", - "espree": "^10.4.0", - "estraverse": "^5.3.0", - "picomatch": "^4.0.3" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "peerDependencies": { - "eslint": ">=9.0.0" - } - }, - "node_modules/@stylistic/eslint-plugin/node_modules/eslint-visitor-keys": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", - "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@stylistic/eslint-plugin/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/@swc/core": { - "version": "1.11.24", - "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.11.24.tgz", - "integrity": "sha512-MaQEIpfcEMzx3VWWopbofKJvaraqmL6HbLlw2bFZ7qYqYw3rkhM0cQVEgyzbHtTWwCwPMFZSC2DUbhlZgrMfLg==", - "hasInstallScript": true, - "peer": true, - "dependencies": { - "@swc/counter": "^0.1.3", - "@swc/types": "^0.1.21" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/swc" - }, - "optionalDependencies": { - "@swc/core-darwin-arm64": "1.11.24", - "@swc/core-darwin-x64": "1.11.24", - "@swc/core-linux-arm-gnueabihf": "1.11.24", - "@swc/core-linux-arm64-gnu": "1.11.24", - "@swc/core-linux-arm64-musl": "1.11.24", - "@swc/core-linux-x64-gnu": "1.11.24", - "@swc/core-linux-x64-musl": "1.11.24", - "@swc/core-win32-arm64-msvc": "1.11.24", - "@swc/core-win32-ia32-msvc": "1.11.24", - "@swc/core-win32-x64-msvc": "1.11.24" - }, - "peerDependencies": { - "@swc/helpers": ">=0.5.17" - }, - "peerDependenciesMeta": { - "@swc/helpers": { - "optional": true - } - } - }, - "node_modules/@swc/core-darwin-arm64": { - "version": "1.11.24", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.11.24.tgz", - "integrity": "sha512-dhtVj0PC1APOF4fl5qT2neGjRLgHAAYfiVP8poJelhzhB/318bO+QCFWAiimcDoyMgpCXOhTp757gnoJJrheWA==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "darwin" - ], - "peer": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-darwin-x64": { - "version": "1.11.24", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.11.24.tgz", - "integrity": "sha512-H/3cPs8uxcj2Fe3SoLlofN5JG6Ny5bl8DuZ6Yc2wr7gQFBmyBkbZEz+sPVgsID7IXuz7vTP95kMm1VL74SO5AQ==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "darwin" - ], - "peer": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm-gnueabihf": { - "version": "1.11.24", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.11.24.tgz", - "integrity": "sha512-PHJgWEpCsLo/NGj+A2lXZ2mgGjsr96ULNW3+T3Bj2KTc8XtMUkE8tmY2Da20ItZOvPNC/69KroU7edyo1Flfbw==", - "cpu": [ - "arm" - ], - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm64-gnu": { - "version": "1.11.24", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.11.24.tgz", - "integrity": "sha512-C2FJb08+n5SD4CYWCTZx1uR88BN41ZieoHvI8A55hfVf2woT8+6ZiBzt74qW2g+ntZ535Jts5VwXAKdu41HpBg==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm64-musl": { - "version": "1.11.24", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.11.24.tgz", - "integrity": "sha512-ypXLIdszRo0re7PNNaXN0+2lD454G8l9LPK/rbfRXnhLWDBPURxzKlLlU/YGd2zP98wPcVooMmegRSNOKfvErw==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-x64-gnu": { - "version": "1.11.24", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.11.24.tgz", - "integrity": "sha512-IM7d+STVZD48zxcgo69L0yYptfhaaE9cMZ+9OoMxirNafhKKXwoZuufol1+alEFKc+Wbwp+aUPe/DeWC/Lh3dg==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-x64-musl": { - "version": "1.11.24", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.11.24.tgz", - "integrity": "sha512-DZByJaMVzSfjQKKQn3cqSeqwy6lpMaQDQQ4HPlch9FWtDx/dLcpdIhxssqZXcR2rhaQVIaRQsCqwV6orSDGAGw==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "peer": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-win32-arm64-msvc": { - "version": "1.11.24", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.11.24.tgz", - "integrity": "sha512-Q64Ytn23y9aVDKN5iryFi8mRgyHw3/kyjTjT4qFCa8AEb5sGUuSj//AUZ6c0J7hQKMHlg9do5Etvoe61V98/JQ==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "win32" - ], - "peer": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-win32-ia32-msvc": { - "version": "1.11.24", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.11.24.tgz", - "integrity": "sha512-9pKLIisE/Hh2vJhGIPvSoTK4uBSPxNVyXHmOrtdDot4E1FUUI74Vi8tFdlwNbaj8/vusVnb8xPXsxF1uB0VgiQ==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "win32" - ], - "peer": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-win32-x64-msvc": { - "version": "1.11.24", - "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.11.24.tgz", - "integrity": "sha512-sybnXtOsdB+XvzVFlBVGgRHLqp3yRpHK7CrmpuDKszhj/QhmsaZzY/GHSeALlMtLup13M0gqbcQvsTNlAHTg3w==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "win32" - ], - "peer": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/counter": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", - "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==" - }, - "node_modules/@swc/jest": { - "version": "0.2.39", - "resolved": "https://registry.npmjs.org/@swc/jest/-/jest-0.2.39.tgz", - "integrity": "sha512-eyokjOwYd0Q8RnMHri+8/FS1HIrIUKK/sRrFp8c1dThUOfNeCWbLmBP1P5VsKdvmkd25JaH+OKYwEYiAYg9YAA==", - "license": "MIT", - "dependencies": { - "@jest/create-cache-key-function": "^30.0.0", - "@swc/counter": "^0.1.3", - "jsonc-parser": "^3.2.0" - }, - "engines": { - "npm": ">= 7.0.0" - }, - "peerDependencies": { - "@swc/core": "*" - } - }, - "node_modules/@swc/types": { - "version": "0.1.21", - "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.21.tgz", - "integrity": "sha512-2YEtj5HJVbKivud9N4bpPBAyZhj4S2Ipe5LkUG94alTpr7in/GU/EARgPAd3BwU+YOmFVJC2+kjqhGRi3r0ZpQ==", - "peer": true, - "dependencies": { - "@swc/counter": "^0.1.3" - } - }, - "node_modules/@tybys/wasm-util": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.0.tgz", - "integrity": "sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ==", - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@types/async": { - "version": "3.2.25", - "resolved": "https://registry.npmjs.org/@types/async/-/async-3.2.25.tgz", - "integrity": "sha512-O6Th/DI18XjrL9TX8LO9F/g26qAz5vynmQqlXt/qLGrskvzCKXKc5/tATz3G2N6lM8eOf3M8/StB14FncAmocg==" - }, - "node_modules/@types/babel__core": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", - "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "node_modules/@types/babel__generator": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", - "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", - "license": "MIT", - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", - "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__traverse": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.7.tgz", - "integrity": "sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==", - "license": "MIT", - "dependencies": { - "@babel/types": "^7.20.7" - } - }, - "node_modules/@types/cli-progress": { - "version": "3.11.6", - "resolved": "https://registry.npmjs.org/@types/cli-progress/-/cli-progress-3.11.6.tgz", - "integrity": "sha512-cE3+jb9WRlu+uOSAugewNpITJDt1VF8dHOopPO4IABFc3SXYL5WE/+PTz/FCdZRRfIujiWW3n3aMbv1eIGVRWA==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/estree": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz", - "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==" - }, - "node_modules/@types/fs-extra": { - "version": "11.0.4", - "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-11.0.4.tgz", - "integrity": "sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==", - "dependencies": { - "@types/jsonfile": "*", - "@types/node": "*" - } - }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", - "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", - "license": "MIT" - }, - "node_modules/@types/istanbul-lib-report": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", - "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", - "license": "MIT", - "dependencies": { - "@types/istanbul-lib-coverage": "*" - } - }, - "node_modules/@types/istanbul-reports": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", - "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", - "license": "MIT", - "dependencies": { - "@types/istanbul-lib-report": "*" - } - }, - "node_modules/@types/jest": { - "version": "30.0.0", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-30.0.0.tgz", - "integrity": "sha512-XTYugzhuwqWjws0CVz8QpM36+T+Dz5mTEBKhNs/esGLnCIlGdRy+Dq78NRjd7ls7r8BC8ZRMOrKlkO1hU0JOwA==", - "license": "MIT", - "dependencies": { - "expect": "^30.0.0", - "pretty-format": "^30.0.0" - } - }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==" - }, - "node_modules/@types/jsonfile": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/@types/jsonfile/-/jsonfile-6.1.4.tgz", - "integrity": "sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-H3MHACvFUEiujabxhaI/ImO6gUrd8oOurg7LQtS7mbwIXA/cUqWrvBsaeJ23aZEPk1TAYkurjfMbSELfoCXlGA==", - "license": "MIT" - }, - "node_modules/@types/lodash.uniqueid": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/@types/lodash.uniqueid/-/lodash.uniqueid-4.0.9.tgz", - "integrity": "sha512-SEzkJBS8t+tqAUnSmyqbuWqxKU+Z/Xu2cgPtD+Ik0l+M7L2q7So9VoN2rQ8H0mmL87lJ00ykxal8oB54QRet6g==", - "license": "MIT", - "dependencies": { - "@types/lodash": "*" - } - }, - "node_modules/@types/node": { - "version": "22.15.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.3.tgz", - "integrity": "sha512-lX7HFZeHf4QG/J7tBZqrCAXwz9J5RD56Y6MpP0eJkka8p+K0RY/yBTW7CYFJ4VGCclxqOLKmiGP5juQc6MKgcw==", - "dependencies": { - "undici-types": "~6.21.0" - } - }, - "node_modules/@types/stack-utils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", - "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", - "license": "MIT" - }, - "node_modules/@types/yargs": { - "version": "17.0.33", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", - "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", - "license": "MIT", - "dependencies": { - "@types/yargs-parser": "*" - } - }, - "node_modules/@types/yargs-parser": { - "version": "21.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", - "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", - "license": "MIT" - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.38.0.tgz", - "integrity": "sha512-CPoznzpuAnIOl4nhj4tRr4gIPj5AfKgkiJmGQDaq+fQnRJTYlcBjbX3wbciGmpoPf8DREufuPRe1tNMZnGdanA==", - "license": "MIT", - "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.38.0", - "@typescript-eslint/type-utils": "8.38.0", - "@typescript-eslint/utils": "8.38.0", - "@typescript-eslint/visitor-keys": "8.38.0", - "graphemer": "^1.4.0", - "ignore": "^7.0.0", - "natural-compare": "^1.4.0", - "ts-api-utils": "^2.1.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^8.38.0", - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.9.0" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", - "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "8.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.38.0.tgz", - "integrity": "sha512-Zhy8HCvBUEfBECzIl1PKqF4p11+d0aUJS1GeUiuqK9WmOug8YCmC4h4bjyBvMyAMI9sbRczmrYL5lKg/YMbrcQ==", - "license": "MIT", - "dependencies": { - "@typescript-eslint/scope-manager": "8.38.0", - "@typescript-eslint/types": "8.38.0", - "@typescript-eslint/typescript-estree": "8.38.0", - "@typescript-eslint/visitor-keys": "8.38.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.9.0" - } - }, - "node_modules/@typescript-eslint/project-service": { - "version": "8.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.38.0.tgz", - "integrity": "sha512-dbK7Jvqcb8c9QfH01YB6pORpqX1mn5gDZc9n63Ak/+jD67oWXn3Gs0M6vddAN+eDXBCS5EmNWzbSxsn9SzFWWg==", - "license": "MIT", - "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.38.0", - "@typescript-eslint/types": "^8.38.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <5.9.0" - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "8.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.38.0.tgz", - "integrity": "sha512-WJw3AVlFFcdT9Ri1xs/lg8LwDqgekWXWhH3iAF+1ZM+QPd7oxQ6jvtW/JPwzAScxitILUIFs0/AnQ/UWHzbATQ==", - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.38.0", - "@typescript-eslint/visitor-keys": "8.38.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.38.0.tgz", - "integrity": "sha512-Lum9RtSE3EroKk/bYns+sPOodqb2Fv50XOl/gMviMKNvanETUuUcC9ObRbzrJ4VSd2JalPqgSAavwrPiPvnAiQ==", - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <5.9.0" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "8.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.38.0.tgz", - "integrity": "sha512-c7jAvGEZVf0ao2z+nnz8BUaHZD09Agbh+DY7qvBQqLiz8uJzRgVPj5YvOh8I8uEiH8oIUGIfHzMwUcGVco/SJg==", - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.38.0", - "@typescript-eslint/typescript-estree": "8.38.0", - "@typescript-eslint/utils": "8.38.0", - "debug": "^4.3.4", - "ts-api-utils": "^2.1.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.9.0" - } - }, - "node_modules/@typescript-eslint/types": { - "version": "8.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.38.0.tgz", - "integrity": "sha512-wzkUfX3plUqij4YwWaJyqhiPE5UCRVlFpKn1oCRn2O1bJ592XxWJj8ROQ3JD5MYXLORW84063z3tZTb/cs4Tyw==", - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.38.0.tgz", - "integrity": "sha512-fooELKcAKzxux6fA6pxOflpNS0jc+nOQEEOipXFNjSlBS6fqrJOVY/whSn70SScHrcJ2LDsxWrneFoWYSVfqhQ==", - "license": "MIT", - "dependencies": { - "@typescript-eslint/project-service": "8.38.0", - "@typescript-eslint/tsconfig-utils": "8.38.0", - "@typescript-eslint/types": "8.38.0", - "@typescript-eslint/visitor-keys": "8.38.0", - "debug": "^4.3.4", - "fast-glob": "^3.3.2", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^2.1.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <5.9.0" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@typescript-eslint/utils": { - "version": "8.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.38.0.tgz", - "integrity": "sha512-hHcMA86Hgt+ijJlrD8fX0j1j8w4C92zue/8LOPAFioIno+W0+L7KqE8QZKCcPGc/92Vs9x36w/4MPTJhqXdyvg==", - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.38.0", - "@typescript-eslint/types": "8.38.0", - "@typescript-eslint/typescript-estree": "8.38.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.9.0" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.38.0.tgz", - "integrity": "sha512-pWrTcoFNWuwHlA9CvlfSsGWs14JxfN1TH25zM5L7o0pRLhsoZkDnTsXfQRJBEWJoV5DL0jf+Z+sxiud+K0mq1g==", - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.38.0", - "eslint-visitor-keys": "^4.2.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", - "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@ungap/structured-clone": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", - "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", - "license": "ISC" - }, - "node_modules/@unrs/resolver-binding-android-arm-eabi": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz", - "integrity": "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@unrs/resolver-binding-android-arm64": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz", - "integrity": "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@unrs/resolver-binding-darwin-arm64": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz", - "integrity": "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@unrs/resolver-binding-darwin-x64": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz", - "integrity": "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@unrs/resolver-binding-freebsd-x64": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz", - "integrity": "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz", - "integrity": "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz", - "integrity": "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz", - "integrity": "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-arm64-musl": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz", - "integrity": "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz", - "integrity": "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==", - "cpu": [ - "ppc64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz", - "integrity": "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==", - "cpu": [ - "riscv64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz", - "integrity": "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==", - "cpu": [ - "riscv64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz", - "integrity": "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==", - "cpu": [ - "s390x" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-x64-gnu": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz", - "integrity": "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-linux-x64-musl": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz", - "integrity": "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@unrs/resolver-binding-wasm32-wasi": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz", - "integrity": "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==", - "cpu": [ - "wasm32" - ], - "license": "MIT", - "optional": true, - "dependencies": { - "@napi-rs/wasm-runtime": "^0.2.11" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz", - "integrity": "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz", - "integrity": "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==", - "cpu": [ - "ia32" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@unrs/resolver-binding-win32-x64-msvc": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz", - "integrity": "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/agent-base": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", - "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", - "engines": { - "node": ">= 14" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dependencies": { - "type-fest": "^0.21.3" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "license": "ISC", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" - }, - "node_modules/async-es": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/async-es/-/async-es-3.2.6.tgz", - "integrity": "sha512-9C2+oOPd7/EzIeneF4k24o75oY7OcHU/Isl7xIot12EBRwXonyuqKsmxwLuAbFWL6B/FucTQip09xTbiu1CA8A==" - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" - }, - "node_modules/axios": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.11.0.tgz", - "integrity": "sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==", - "license": "MIT", - "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.4", - "proxy-from-env": "^1.1.0" - } - }, - "node_modules/babel-jest": { - "version": "30.0.5", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-30.0.5.tgz", - "integrity": "sha512-mRijnKimhGDMsizTvBTWotwNpzrkHr+VvZUQBof2AufXKB8NXrL1W69TG20EvOz7aevx6FTJIaBuBkYxS8zolg==", - "license": "MIT", - "dependencies": { - "@jest/transform": "30.0.5", - "@types/babel__core": "^7.20.5", - "babel-plugin-istanbul": "^7.0.0", - "babel-preset-jest": "30.0.1", - "chalk": "^4.1.2", - "graceful-fs": "^4.2.11", - "slash": "^3.0.0" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.11.0" - } - }, - "node_modules/babel-jest/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/babel-plugin-istanbul": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-7.0.0.tgz", - "integrity": "sha512-C5OzENSx/A+gt7t4VH1I2XsflxyPUmXRFPKBxt33xncdOmq7oROVM3bZv9Ysjjkv8OJYDMa+tKuKMvqU/H3xdw==", - "license": "BSD-3-Clause", - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.3", - "istanbul-lib-instrument": "^6.0.2", - "test-exclude": "^6.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/babel-plugin-jest-hoist": { - "version": "30.0.1", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-30.0.1.tgz", - "integrity": "sha512-zTPME3pI50NsFW8ZBaVIOeAxzEY7XHlmWeXXu9srI+9kNfzCUTy8MFan46xOGZY8NZThMqq+e3qZUKsvXbasnQ==", - "license": "MIT", - "dependencies": { - "@babel/template": "^7.27.2", - "@babel/types": "^7.27.3", - "@types/babel__core": "^7.20.5" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/babel-preset-current-node-syntax": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz", - "integrity": "sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==", - "license": "MIT", - "dependencies": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-import-attributes": "^7.24.7", - "@babel/plugin-syntax-import-meta": "^7.10.4", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5" - }, - "peerDependencies": { - "@babel/core": "^7.0.0 || ^8.0.0-0" - } - }, - "node_modules/babel-preset-jest": { - "version": "30.0.1", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-30.0.1.tgz", - "integrity": "sha512-+YHejD5iTWI46cZmcc/YtX4gaKBtdqCHCVfuVinizVpbmyjO3zYmeuyFdfA8duRqQZfgCAMlsfmkVbJ+e2MAJw==", - "license": "MIT", - "dependencies": { - "babel-plugin-jest-hoist": "30.0.1", - "babel-preset-current-node-syntax": "^1.1.0" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.11.0" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "node_modules/before-after-hook": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-4.0.0.tgz", - "integrity": "sha512-q6tR3RPqIB1pMiTRMFcZwuG5T8vwp+vUvEG0vuI6B+Rikh5BfPp2fQ82c925FOs+b0lcFQ8CFrL+KbilfZFhOQ==", - "license": "Apache-2.0" - }, - "node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browserslist": { - "version": "4.25.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.1.tgz", - "integrity": "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "caniuse-lite": "^1.0.30001726", - "electron-to-chromium": "^1.5.173", - "node-releases": "^2.0.19", - "update-browserslist-db": "^1.1.3" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/bser": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", - "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", - "license": "Apache-2.0", - "dependencies": { - "node-int64": "^0.4.0" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "license": "MIT" - }, - "node_modules/call-bind-apply-helpers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", - "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001731", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001731.tgz", - "integrity": "sha512-lDdp2/wrOmTRWuoB5DpfNkC0rJDU8DqRa6nYL6HK6sytw70QMopt/NIc/9SM7ylItlBWfACXk0tEn37UWM/+mg==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "CC-BY-4.0" - }, - "node_modules/chalk": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", - "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/char-regex": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", - "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/chardet": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-2.1.0.tgz", - "integrity": "sha512-bNFETTG/pM5ryzQ9Ad0lJOTa6HWD/YsScAR3EnCPZRPlQh77JocYktSHOUHelyhm8IARL+o4c4F1bP5KVOjiRA==" - }, - "node_modules/ci-info": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.0.tgz", - "integrity": "sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cjs-module-lexer": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-2.1.0.tgz", - "integrity": "sha512-UX0OwmYRYQQetfrLEZeewIFFI+wSTofC+pMBLNuH3RUuu/xzG1oz84UCEDOSoQlN3fZ4+AzmV50ZYvGqkMh9yA==", - "license": "MIT" - }, - "node_modules/cli-progress": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/cli-progress/-/cli-progress-3.12.0.tgz", - "integrity": "sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A==", - "dependencies": { - "string-width": "^4.2.3" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cli-width": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", - "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", - "license": "ISC", - "engines": { - "node": ">= 12" - } - }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/cliui/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", - "license": "MIT", - "engines": { - "iojs": ">= 1.0.0", - "node": ">= 0.12.0" - } - }, - "node_modules/collect-v8-coverage": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", - "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", - "license": "MIT" - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/commander": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.0.tgz", - "integrity": "sha512-2uM9rYjPvyq39NwLRqaiLtWHyDC1FvryJDa2ATTVims5YAS4PupsEQsDvP14FqhFr0P49CYDugi59xaxJlTXRA==", - "license": "MIT", - "engines": { - "node": ">=20" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, - "node_modules/consola": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", - "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", - "engines": { - "node": "^14.18.0 || >=16.10.0" - } - }, - "node_modules/console-table-printer": { - "version": "2.14.6", - "resolved": "https://registry.npmjs.org/console-table-printer/-/console-table-printer-2.14.6.tgz", - "integrity": "sha512-MCBl5HNVaFuuHW6FGbL/4fB7N/ormCy+tQ+sxTrF6QtSbSNETvPuOVbkJBhzDgYhvjWGrTma4eYJa37ZuoQsPw==", - "license": "MIT", - "dependencies": { - "simple-wcswidth": "^1.0.1" - } - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "license": "MIT" - }, - "node_modules/cross-env": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-10.0.0.tgz", - "integrity": "sha512-aU8qlEK/nHYtVuN4p7UQgAwVljzMg8hB4YK5ThRqD2l/ziSnryncPNn7bMLt5cFYsKVKBh8HqLqyCoTupEUu7Q==", - "license": "MIT", - "dependencies": { - "@epic-web/invariant": "^1.0.0", - "cross-spawn": "^7.0.6" - }, - "bin": { - "cross-env": "dist/bin/cross-env.js", - "cross-env-shell": "dist/bin/cross-env-shell.js" - }, - "engines": { - "node": ">=20" - } - }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/dayjs": { - "version": "1.11.13", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", - "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==" - }, - "node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/dedent": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.6.0.tgz", - "integrity": "sha512-F1Z+5UCFpmQUzJa11agbyPVMbpgT/qA3/SKyJ1jyBgm7dUcUEa8v9JwDkerSQXfakBwFljIxhOJqGkjUwZ9FSA==", - "license": "MIT", - "peerDependencies": { - "babel-plugin-macros": "^3.1.0" - }, - "peerDependenciesMeta": { - "babel-plugin-macros": { - "optional": true - } - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" - }, - "node_modules/deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/detect-newline": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", - "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/dunder-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", - "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "license": "MIT" - }, - "node_modules/electron-to-chromium": { - "version": "1.5.192", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.192.tgz", - "integrity": "sha512-rP8Ez0w7UNw/9j5eSXCe10o1g/8B1P5SM90PCCMVkIRQn2R0LEHWz4Eh9RnxkniuDe1W0cTSOB3MLlkTGDcuCg==", - "license": "ISC" - }, - "node_modules/emittery": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", - "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sindresorhus/emittery?sponsor=1" - } - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "license": "MIT", - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/es-define-property": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-object-atoms": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", - "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-set-tostringtag": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", - "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", - "dependencies": { - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/esbuild": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.3.tgz", - "integrity": "sha512-qKA6Pvai73+M2FtftpNKRxJ78GIjmFXFxd/1DVBqGo/qNhLSfv+G12n9pNoWdytJC8U00TrViOwpjT0zgqQS8Q==", - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.3", - "@esbuild/android-arm": "0.25.3", - "@esbuild/android-arm64": "0.25.3", - "@esbuild/android-x64": "0.25.3", - "@esbuild/darwin-arm64": "0.25.3", - "@esbuild/darwin-x64": "0.25.3", - "@esbuild/freebsd-arm64": "0.25.3", - "@esbuild/freebsd-x64": "0.25.3", - "@esbuild/linux-arm": "0.25.3", - "@esbuild/linux-arm64": "0.25.3", - "@esbuild/linux-ia32": "0.25.3", - "@esbuild/linux-loong64": "0.25.3", - "@esbuild/linux-mips64el": "0.25.3", - "@esbuild/linux-ppc64": "0.25.3", - "@esbuild/linux-riscv64": "0.25.3", - "@esbuild/linux-s390x": "0.25.3", - "@esbuild/linux-x64": "0.25.3", - "@esbuild/netbsd-arm64": "0.25.3", - "@esbuild/netbsd-x64": "0.25.3", - "@esbuild/openbsd-arm64": "0.25.3", - "@esbuild/openbsd-x64": "0.25.3", - "@esbuild/sunos-x64": "0.25.3", - "@esbuild/win32-arm64": "0.25.3", - "@esbuild/win32-ia32": "0.25.3", - "@esbuild/win32-x64": "0.25.3" - } - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint": { - "version": "9.32.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.32.0.tgz", - "integrity": "sha512-LSehfdpgMeWcTZkWZVIJl+tkZ2nuSkyyB9C27MZqFWXuph7DvaowgcTvKqxvpLW1JZIk8PN7hFY3Rj9LQ7m7lg==", - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.21.0", - "@eslint/config-helpers": "^0.3.0", - "@eslint/core": "^0.15.0", - "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.32.0", - "@eslint/plugin-kit": "^0.3.4", - "@humanfs/node": "^0.16.6", - "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.4.2", - "@types/estree": "^1.0.6", - "@types/json-schema": "^7.0.15", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.6", - "debug": "^4.3.2", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.4.0", - "eslint-visitor-keys": "^4.2.1", - "espree": "^10.4.0", - "esquery": "^1.5.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^8.0.0", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://eslint.org/donate" - }, - "peerDependencies": { - "jiti": "*" - }, - "peerDependenciesMeta": { - "jiti": { - "optional": true - } - } - }, - "node_modules/eslint-scope": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", - "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", - "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/espree": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", - "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", - "dependencies": { - "acorn": "^8.15.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.2.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", - "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "license": "BSD-2-Clause", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/esquery": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", - "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "license": "MIT", - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/execa/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "license": "ISC" - }, - "node_modules/exit-x": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/exit-x/-/exit-x-0.2.2.tgz", - "integrity": "sha512-+I6B/IkJc1o/2tiURyz/ivu/O0nKNEArIUB5O7zBrlDVJr22SCLH3xTeEry428LvFhRzIA1g8izguxJ/gbNcVQ==", - "license": "MIT", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/expect": { - "version": "30.0.5", - "resolved": "https://registry.npmjs.org/expect/-/expect-30.0.5.tgz", - "integrity": "sha512-P0te2pt+hHI5qLJkIR+iMvS+lYUZml8rKKsohVHAGY+uClp9XVbdyYNJOIjSRpHVp8s8YqxJCiHUkSYZGr8rtQ==", - "license": "MIT", - "dependencies": { - "@jest/expect-utils": "30.0.5", - "@jest/get-type": "30.0.1", - "jest-matcher-utils": "30.0.5", - "jest-message-util": "30.0.5", - "jest-mock": "30.0.5", - "jest-util": "30.0.5" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/fast-content-type-parse": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-3.0.0.tgz", - "integrity": "sha512-ZvLdcY8P+N8mGQJahJV5G4U88CSvT1rP8ApL6uETe88MBXrBHAkZlSEySdUlyztF7ccb+Znos3TFqaepHxdhBg==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "MIT" - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "node_modules/fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.8" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" - }, - "node_modules/fastq": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", - "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fb-watchman": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", - "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", - "license": "Apache-2.0", - "dependencies": { - "bser": "2.1.1" - } - }, - "node_modules/file-entry-cache": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", - "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", - "dependencies": { - "flat-cache": "^4.0.0" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat-cache": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", - "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.4" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/flatted": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", - "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==" - }, - "node_modules/follow-redirects": { - "version": "1.15.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", - "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/foreground-child": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", - "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", - "dependencies": { - "cross-spawn": "^7.0.6", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/form-data": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", - "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.2", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fs-extra": { - "version": "11.3.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz", - "integrity": "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "license": "ISC" - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-east-asian-width": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.3.1.tgz", - "integrity": "sha512-R1QfovbPsKmosqTnPoRFiJ7CF9MLRgb53ChvMZm+r4p76/+8yKDy17qLL2PKInORy2RkZZekuK0efYgmzTkXyQ==", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-intrinsic": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", - "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "function-bind": "^1.1.2", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "math-intrinsics": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "license": "MIT", - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/get-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/get-tsconfig": { - "version": "4.10.0", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.0.tgz", - "integrity": "sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==", - "dependencies": { - "resolve-pkg-maps": "^1.0.0" - }, - "funding": { - "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" - } - }, - "node_modules/glob": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.3.tgz", - "integrity": "sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA==", - "license": "ISC", - "dependencies": { - "foreground-child": "^3.3.1", - "jackspeak": "^4.1.1", - "minimatch": "^10.0.3", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^2.0.0" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/glob/node_modules/minimatch": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.3.tgz", - "integrity": "sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw==", - "license": "ISC", - "dependencies": { - "@isaacs/brace-expansion": "^5.0.0" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/globals": { - "version": "16.3.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-16.3.0.tgz", - "integrity": "sha512-bqWEnJ1Nt3neqx2q5SFfGS8r/ahumIakg3HcwtNlrVlwXIeNumWn/c7Pn/wKzGhf6SaW6H6uWXLqC30STCMchQ==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" - }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==" - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/has-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "dependencies": { - "has-symbols": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "license": "MIT" - }, - "node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "license": "Apache-2.0", - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", - "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/import-local": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", - "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", - "license": "MIT", - "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "license": "ISC", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "license": "ISC" - }, - "node_modules/ip-address": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.0.1.tgz", - "integrity": "sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA==", - "engines": { - "node": ">= 12" - } - }, - "node_modules/iptv-playlist-parser": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/iptv-playlist-parser/-/iptv-playlist-parser-0.15.0.tgz", - "integrity": "sha512-9EGiQ5y95UZsV24HBSHuSyOuqzFR4YCAm7X8MqJNHlcm9jP38DHH7inYU0YJuXVq9fAttij3Yh8MJZkV1Bu/SA==", - "dependencies": { - "is-valid-path": "^0.1.1", - "validator": "^13.7.0" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "license": "MIT" - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-generator-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", - "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-invalid-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-invalid-path/-/is-invalid-path-0.1.0.tgz", - "integrity": "sha512-aZMG0T3F34mTg4eTdszcGXx54oiZ4NtHSft3hWNJMGJXUUqdIj3cOZuHcU0nCWWcY3jd7yRe/3AEm3vSNTpBGQ==", - "dependencies": { - "is-glob": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-invalid-path/node_modules/is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha512-7Q+VbVafe6x2T+Tu6NcOf6sRklazEPmBoB3IWk3WdGZM2iGUwU/Oe3Wtq5lSEkDTTlpp8yx+5t4pzO/i9Ty1ww==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-invalid-path/node_modules/is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha512-a1dBeB19NXsf/E0+FHqkagizel/LQw2DjSQpvQrj3zT+jYPpaUCryPnrQajXKFLCMuf4I6FhRpaGtw4lPrG6Eg==", - "dependencies": { - "is-extglob": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-valid-path": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-valid-path/-/is-valid-path-0.1.1.tgz", - "integrity": "sha512-+kwPrVDu9Ms03L90Qaml+79+6DZHqHyRoANI6IsZJ/g8frhnfchDOBCa0RbQ6/kdHt5CS5OeIEyrYznNuVN+8A==", - "dependencies": { - "is-invalid-path": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" - }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", - "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-instrument": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", - "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", - "license": "BSD-3-Clause", - "dependencies": { - "@babel/core": "^7.23.9", - "@babel/parser": "^7.23.9", - "@istanbuljs/schema": "^0.1.3", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^7.5.4" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-report": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", - "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", - "license": "BSD-3-Clause", - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^4.0.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-source-maps": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz", - "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==", - "license": "BSD-3-Clause", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.23", - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-reports": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", - "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", - "license": "BSD-3-Clause", - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jackspeak": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.1.tgz", - "integrity": "sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==", - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/jest": { - "version": "30.0.5", - "resolved": "https://registry.npmjs.org/jest/-/jest-30.0.5.tgz", - "integrity": "sha512-y2mfcJywuTUkvLm2Lp1/pFX8kTgMO5yyQGq/Sk/n2mN7XWYp4JsCZ/QXW34M8YScgk8bPZlREH04f6blPnoHnQ==", - "license": "MIT", - "dependencies": { - "@jest/core": "30.0.5", - "@jest/types": "30.0.5", - "import-local": "^3.2.0", - "jest-cli": "30.0.5" - }, - "bin": { - "jest": "bin/jest.js" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/jest-changed-files": { - "version": "30.0.5", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-30.0.5.tgz", - "integrity": "sha512-bGl2Ntdx0eAwXuGpdLdVYVr5YQHnSZlQ0y9HVDu565lCUAe9sj6JOtBbMmBBikGIegne9piDDIOeiLVoqTkz4A==", - "license": "MIT", - "dependencies": { - "execa": "^5.1.1", - "jest-util": "30.0.5", - "p-limit": "^3.1.0" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/jest-circus": { - "version": "30.0.5", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-30.0.5.tgz", - "integrity": "sha512-h/sjXEs4GS+NFFfqBDYT7y5Msfxh04EwWLhQi0F8kuWpe+J/7tICSlswU8qvBqumR3kFgHbfu7vU6qruWWBPug==", - "license": "MIT", - "dependencies": { - "@jest/environment": "30.0.5", - "@jest/expect": "30.0.5", - "@jest/test-result": "30.0.5", - "@jest/types": "30.0.5", - "@types/node": "*", - "chalk": "^4.1.2", - "co": "^4.6.0", - "dedent": "^1.6.0", - "is-generator-fn": "^2.1.0", - "jest-each": "30.0.5", - "jest-matcher-utils": "30.0.5", - "jest-message-util": "30.0.5", - "jest-runtime": "30.0.5", - "jest-snapshot": "30.0.5", - "jest-util": "30.0.5", - "p-limit": "^3.1.0", - "pretty-format": "30.0.5", - "pure-rand": "^7.0.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.6" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/jest-circus/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-cli": { - "version": "30.0.5", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-30.0.5.tgz", - "integrity": "sha512-Sa45PGMkBZzF94HMrlX4kUyPOwUpdZasaliKN3mifvDmkhLYqLLg8HQTzn6gq7vJGahFYMQjXgyJWfYImKZzOw==", - "license": "MIT", - "dependencies": { - "@jest/core": "30.0.5", - "@jest/test-result": "30.0.5", - "@jest/types": "30.0.5", - "chalk": "^4.1.2", - "exit-x": "^0.2.2", - "import-local": "^3.2.0", - "jest-config": "30.0.5", - "jest-util": "30.0.5", - "jest-validate": "30.0.5", - "yargs": "^17.7.2" - }, - "bin": { - "jest": "bin/jest.js" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/jest-cli/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-config": { - "version": "30.0.5", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-30.0.5.tgz", - "integrity": "sha512-aIVh+JNOOpzUgzUnPn5FLtyVnqc3TQHVMupYtyeURSb//iLColiMIR8TxCIDKyx9ZgjKnXGucuW68hCxgbrwmA==", - "license": "MIT", - "dependencies": { - "@babel/core": "^7.27.4", - "@jest/get-type": "30.0.1", - "@jest/pattern": "30.0.1", - "@jest/test-sequencer": "30.0.5", - "@jest/types": "30.0.5", - "babel-jest": "30.0.5", - "chalk": "^4.1.2", - "ci-info": "^4.2.0", - "deepmerge": "^4.3.1", - "glob": "^10.3.10", - "graceful-fs": "^4.2.11", - "jest-circus": "30.0.5", - "jest-docblock": "30.0.1", - "jest-environment-node": "30.0.5", - "jest-regex-util": "30.0.1", - "jest-resolve": "30.0.5", - "jest-runner": "30.0.5", - "jest-util": "30.0.5", - "jest-validate": "30.0.5", - "micromatch": "^4.0.8", - "parse-json": "^5.2.0", - "pretty-format": "30.0.5", - "slash": "^3.0.0", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - }, - "peerDependencies": { - "@types/node": "*", - "esbuild-register": ">=3.4.0", - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "esbuild-register": { - "optional": true - }, - "ts-node": { - "optional": true - } - } - }, - "node_modules/jest-config/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/jest-config/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-config/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/jest-config/node_modules/jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, - "node_modules/jest-config/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "license": "ISC" - }, - "node_modules/jest-config/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/jest-config/node_modules/path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "license": "BlueOak-1.0.0", - "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/jest-diff": { - "version": "30.0.5", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.0.5.tgz", - "integrity": "sha512-1UIqE9PoEKaHcIKvq2vbibrCog4Y8G0zmOxgQUVEiTqwR5hJVMCoDsN1vFvI5JvwD37hjueZ1C4l2FyGnfpE0A==", - "license": "MIT", - "dependencies": { - "@jest/diff-sequences": "30.0.1", - "@jest/get-type": "30.0.1", - "chalk": "^4.1.2", - "pretty-format": "30.0.5" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/jest-diff/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-docblock": { - "version": "30.0.1", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-30.0.1.tgz", - "integrity": "sha512-/vF78qn3DYphAaIc3jy4gA7XSAz167n9Bm/wn/1XhTLW7tTBIzXtCJpb/vcmc73NIIeeohCbdL94JasyXUZsGA==", - "license": "MIT", - "dependencies": { - "detect-newline": "^3.1.0" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/jest-each": { - "version": "30.0.5", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-30.0.5.tgz", - "integrity": "sha512-dKjRsx1uZ96TVyejD3/aAWcNKy6ajMaN531CwWIsrazIqIoXI9TnnpPlkrEYku/8rkS3dh2rbH+kMOyiEIv0xQ==", - "license": "MIT", - "dependencies": { - "@jest/get-type": "30.0.1", - "@jest/types": "30.0.5", - "chalk": "^4.1.2", - "jest-util": "30.0.5", - "pretty-format": "30.0.5" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/jest-each/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-environment-node": { - "version": "30.0.5", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-30.0.5.tgz", - "integrity": "sha512-ppYizXdLMSvciGsRsMEnv/5EFpvOdXBaXRBzFUDPWrsfmog4kYrOGWXarLllz6AXan6ZAA/kYokgDWuos1IKDA==", - "license": "MIT", - "dependencies": { - "@jest/environment": "30.0.5", - "@jest/fake-timers": "30.0.5", - "@jest/types": "30.0.5", - "@types/node": "*", - "jest-mock": "30.0.5", - "jest-util": "30.0.5", - "jest-validate": "30.0.5" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/jest-expect-message": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/jest-expect-message/-/jest-expect-message-1.1.3.tgz", - "integrity": "sha512-bTK77T4P+zto+XepAX3low8XVQxDgaEqh3jSTQOG8qvPpD69LsIdyJTa+RmnJh3HNSzJng62/44RPPc7OIlFxg==" - }, - "node_modules/jest-haste-map": { - "version": "30.0.5", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-30.0.5.tgz", - "integrity": "sha512-dkmlWNlsTSR0nH3nRfW5BKbqHefLZv0/6LCccG0xFCTWcJu8TuEwG+5Cm75iBfjVoockmO6J35o5gxtFSn5xeg==", - "license": "MIT", - "dependencies": { - "@jest/types": "30.0.5", - "@types/node": "*", - "anymatch": "^3.1.3", - "fb-watchman": "^2.0.2", - "graceful-fs": "^4.2.11", - "jest-regex-util": "30.0.1", - "jest-util": "30.0.5", - "jest-worker": "30.0.5", - "micromatch": "^4.0.8", - "walker": "^1.0.8" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - }, - "optionalDependencies": { - "fsevents": "^2.3.3" - } - }, - "node_modules/jest-leak-detector": { - "version": "30.0.5", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-30.0.5.tgz", - "integrity": "sha512-3Uxr5uP8jmHMcsOtYMRB/zf1gXN3yUIc+iPorhNETG54gErFIiUhLvyY/OggYpSMOEYqsmRxmuU4ZOoX5jpRFg==", - "license": "MIT", - "dependencies": { - "@jest/get-type": "30.0.1", - "pretty-format": "30.0.5" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/jest-matcher-utils": { - "version": "30.0.5", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.0.5.tgz", - "integrity": "sha512-uQgGWt7GOrRLP1P7IwNWwK1WAQbq+m//ZY0yXygyfWp0rJlksMSLQAA4wYQC3b6wl3zfnchyTx+k3HZ5aPtCbQ==", - "license": "MIT", - "dependencies": { - "@jest/get-type": "30.0.1", - "chalk": "^4.1.2", - "jest-diff": "30.0.5", - "pretty-format": "30.0.5" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/jest-matcher-utils/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-message-util": { - "version": "30.0.5", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.0.5.tgz", - "integrity": "sha512-NAiDOhsK3V7RU0Aa/HnrQo+E4JlbarbmI3q6Pi4KcxicdtjV82gcIUrejOtczChtVQR4kddu1E1EJlW6EN9IyA==", - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@jest/types": "30.0.5", - "@types/stack-utils": "^2.0.3", - "chalk": "^4.1.2", - "graceful-fs": "^4.2.11", - "micromatch": "^4.0.8", - "pretty-format": "30.0.5", - "slash": "^3.0.0", - "stack-utils": "^2.0.6" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/jest-message-util/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-mock": { - "version": "30.0.5", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.0.5.tgz", - "integrity": "sha512-Od7TyasAAQX/6S+QCbN6vZoWOMwlTtzzGuxJku1GhGanAjz9y+QsQkpScDmETvdc9aSXyJ/Op4rhpMYBWW91wQ==", - "license": "MIT", - "dependencies": { - "@jest/types": "30.0.5", - "@types/node": "*", - "jest-util": "30.0.5" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/jest-pnp-resolver": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", - "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", - "license": "MIT", - "engines": { - "node": ">=6" - }, - "peerDependencies": { - "jest-resolve": "*" - }, - "peerDependenciesMeta": { - "jest-resolve": { - "optional": true - } - } - }, - "node_modules/jest-regex-util": { - "version": "30.0.1", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-30.0.1.tgz", - "integrity": "sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==", - "license": "MIT", - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/jest-resolve": { - "version": "30.0.5", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-30.0.5.tgz", - "integrity": "sha512-d+DjBQ1tIhdz91B79mywH5yYu76bZuE96sSbxj8MkjWVx5WNdt1deEFRONVL4UkKLSrAbMkdhb24XN691yDRHg==", - "license": "MIT", - "dependencies": { - "chalk": "^4.1.2", - "graceful-fs": "^4.2.11", - "jest-haste-map": "30.0.5", - "jest-pnp-resolver": "^1.2.3", - "jest-util": "30.0.5", - "jest-validate": "30.0.5", - "slash": "^3.0.0", - "unrs-resolver": "^1.7.11" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/jest-resolve-dependencies": { - "version": "30.0.5", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-30.0.5.tgz", - "integrity": "sha512-/xMvBR4MpwkrHW4ikZIWRttBBRZgWK4d6xt3xW1iRDSKt4tXzYkMkyPfBnSCgv96cpkrctfXs6gexeqMYqdEpw==", - "license": "MIT", - "dependencies": { - "jest-regex-util": "30.0.1", - "jest-snapshot": "30.0.5" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/jest-resolve/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-runner": { - "version": "30.0.5", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-30.0.5.tgz", - "integrity": "sha512-JcCOucZmgp+YuGgLAXHNy7ualBx4wYSgJVWrYMRBnb79j9PD0Jxh0EHvR5Cx/r0Ce+ZBC4hCdz2AzFFLl9hCiw==", - "license": "MIT", - "dependencies": { - "@jest/console": "30.0.5", - "@jest/environment": "30.0.5", - "@jest/test-result": "30.0.5", - "@jest/transform": "30.0.5", - "@jest/types": "30.0.5", - "@types/node": "*", - "chalk": "^4.1.2", - "emittery": "^0.13.1", - "exit-x": "^0.2.2", - "graceful-fs": "^4.2.11", - "jest-docblock": "30.0.1", - "jest-environment-node": "30.0.5", - "jest-haste-map": "30.0.5", - "jest-leak-detector": "30.0.5", - "jest-message-util": "30.0.5", - "jest-resolve": "30.0.5", - "jest-runtime": "30.0.5", - "jest-util": "30.0.5", - "jest-watcher": "30.0.5", - "jest-worker": "30.0.5", - "p-limit": "^3.1.0", - "source-map-support": "0.5.13" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/jest-runner/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-runtime": { - "version": "30.0.5", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-30.0.5.tgz", - "integrity": "sha512-7oySNDkqpe4xpX5PPiJTe5vEa+Ak/NnNz2bGYZrA1ftG3RL3EFlHaUkA1Cjx+R8IhK0Vg43RML5mJedGTPNz3A==", - "license": "MIT", - "dependencies": { - "@jest/environment": "30.0.5", - "@jest/fake-timers": "30.0.5", - "@jest/globals": "30.0.5", - "@jest/source-map": "30.0.1", - "@jest/test-result": "30.0.5", - "@jest/transform": "30.0.5", - "@jest/types": "30.0.5", - "@types/node": "*", - "chalk": "^4.1.2", - "cjs-module-lexer": "^2.1.0", - "collect-v8-coverage": "^1.0.2", - "glob": "^10.3.10", - "graceful-fs": "^4.2.11", - "jest-haste-map": "30.0.5", - "jest-message-util": "30.0.5", - "jest-mock": "30.0.5", - "jest-regex-util": "30.0.1", - "jest-resolve": "30.0.5", - "jest-snapshot": "30.0.5", - "jest-util": "30.0.5", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/jest-runtime/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/jest-runtime/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-runtime/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/jest-runtime/node_modules/jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, - "node_modules/jest-runtime/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "license": "ISC" - }, - "node_modules/jest-runtime/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/jest-runtime/node_modules/path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "license": "BlueOak-1.0.0", - "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/jest-snapshot": { - "version": "30.0.5", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-30.0.5.tgz", - "integrity": "sha512-T00dWU/Ek3LqTp4+DcW6PraVxjk28WY5Ua/s+3zUKSERZSNyxTqhDXCWKG5p2HAJ+crVQ3WJ2P9YVHpj1tkW+g==", - "license": "MIT", - "dependencies": { - "@babel/core": "^7.27.4", - "@babel/generator": "^7.27.5", - "@babel/plugin-syntax-jsx": "^7.27.1", - "@babel/plugin-syntax-typescript": "^7.27.1", - "@babel/types": "^7.27.3", - "@jest/expect-utils": "30.0.5", - "@jest/get-type": "30.0.1", - "@jest/snapshot-utils": "30.0.5", - "@jest/transform": "30.0.5", - "@jest/types": "30.0.5", - "babel-preset-current-node-syntax": "^1.1.0", - "chalk": "^4.1.2", - "expect": "30.0.5", - "graceful-fs": "^4.2.11", - "jest-diff": "30.0.5", - "jest-matcher-utils": "30.0.5", - "jest-message-util": "30.0.5", - "jest-util": "30.0.5", - "pretty-format": "30.0.5", - "semver": "^7.7.2", - "synckit": "^0.11.8" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/jest-snapshot/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-util": { - "version": "30.0.5", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.0.5.tgz", - "integrity": "sha512-pvyPWssDZR0FlfMxCBoc0tvM8iUEskaRFALUtGQYzVEAqisAztmy+R8LnU14KT4XA0H/a5HMVTXat1jLne010g==", - "license": "MIT", - "dependencies": { - "@jest/types": "30.0.5", - "@types/node": "*", - "chalk": "^4.1.2", - "ci-info": "^4.2.0", - "graceful-fs": "^4.2.11", - "picomatch": "^4.0.2" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/jest-util/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-util/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/jest-validate": { - "version": "30.0.5", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-30.0.5.tgz", - "integrity": "sha512-ouTm6VFHaS2boyl+k4u+Qip4TSH7Uld5tyD8psQ8abGgt2uYYB8VwVfAHWHjHc0NWmGGbwO5h0sCPOGHHevefw==", - "license": "MIT", - "dependencies": { - "@jest/get-type": "30.0.1", - "@jest/types": "30.0.5", - "camelcase": "^6.3.0", - "chalk": "^4.1.2", - "leven": "^3.1.0", - "pretty-format": "30.0.5" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/jest-validate/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/jest-validate/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-watcher": { - "version": "30.0.5", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-30.0.5.tgz", - "integrity": "sha512-z9slj/0vOwBDBjN3L4z4ZYaA+pG56d6p3kTUhFRYGvXbXMWhXmb/FIxREZCD06DYUwDKKnj2T80+Pb71CQ0KEg==", - "license": "MIT", - "dependencies": { - "@jest/test-result": "30.0.5", - "@jest/types": "30.0.5", - "@types/node": "*", - "ansi-escapes": "^4.3.2", - "chalk": "^4.1.2", - "emittery": "^0.13.1", - "jest-util": "30.0.5", - "string-length": "^4.0.2" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/jest-watcher/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/jest-worker": { - "version": "30.0.5", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-30.0.5.tgz", - "integrity": "sha512-ojRXsWzEP16NdUuBw/4H/zkZdHOa7MMYCk4E430l+8fELeLg/mqmMlRhjL7UNZvQrDmnovWZV4DxX03fZF48fQ==", - "license": "MIT", - "dependencies": { - "@types/node": "*", - "@ungap/structured-clone": "^1.3.0", - "jest-util": "30.0.5", - "merge-stream": "^2.0.0", - "supports-color": "^8.1.1" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "license": "MIT" - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsesc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "license": "MIT" - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "license": "MIT", - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jsonc-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", - "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==" - }, - "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "license": "MIT" - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" - }, - "node_modules/lodash.uniqueid": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.uniqueid/-/lodash.uniqueid-4.0.1.tgz", - "integrity": "sha512-GQQWaIeGlL6DIIr06kj1j6sSmBxyNMwI8kaX9aKpHR/XsMTiaXDVPNPAkiboOTK9OJpTJF/dXT3xYoFQnj386Q==", - "license": "MIT" - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "license": "ISC", - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/m3u-linter": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/m3u-linter/-/m3u-linter-0.4.2.tgz", - "integrity": "sha512-KeUirh5JnGRuFDb+7tsc8Dkb+q/slco3hszKE7lwbmGKKo+QnSr7198e1ATYZ9HkY8sbvEQBuTj2hPsv9o3gGw==", - "dependencies": { - "chalk": "^4.1.1", - "commander": "^7.2.0", - "glob": "^11.0.0", - "is-valid-path": "^0.1.1" - }, - "bin": { - "m3u-linter": "bin/m3u-linter.js" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/m3u-linter/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/m3u-linter/node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "engines": { - "node": ">= 10" - } - }, - "node_modules/make-dir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", - "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", - "license": "MIT", - "dependencies": { - "semver": "^7.5.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/makeerror": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", - "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", - "license": "BSD-3-Clause", - "dependencies": { - "tmpl": "1.0.5" - } - }, - "node_modules/math-intrinsics": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/mediainfo.js": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/mediainfo.js/-/mediainfo.js-0.3.6.tgz", - "integrity": "sha512-3xVRlxwlVWIZV3z1q7pb8LzFOO7iKi/DXoRiFRZdOlrUEhPyJDaaRt0uK32yQJabArQicRBeq7cRxmdZlIBTyA==", - "dependencies": { - "yargs": "^18.0.0" - }, - "bin": { - "mediainfo.js": "dist/esm/cli.js" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/mediainfo.js/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/mediainfo.js/node_modules/cliui": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-9.0.1.tgz", - "integrity": "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==", - "dependencies": { - "string-width": "^7.2.0", - "strip-ansi": "^7.1.0", - "wrap-ansi": "^9.0.0" - }, - "engines": { - "node": ">=20" - } - }, - "node_modules/mediainfo.js/node_modules/emoji-regex": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.5.0.tgz", - "integrity": "sha512-lb49vf1Xzfx080OKA0o6l8DQQpV+6Vg95zyCJX9VB/BqKYlhG7N4wgROUUHRA+ZPUefLnteQOad7z1kT2bV7bg==" - }, - "node_modules/mediainfo.js/node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mediainfo.js/node_modules/wrap-ansi": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", - "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", - "dependencies": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/mediainfo.js/node_modules/yargs": { - "version": "18.0.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-18.0.0.tgz", - "integrity": "sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==", - "dependencies": { - "cliui": "^9.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "string-width": "^7.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^22.0.0" - }, - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=23" - } - }, - "node_modules/mediainfo.js/node_modules/yargs-parser": { - "version": "22.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-22.0.0.tgz", - "integrity": "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==", - "engines": { - "node": "^20.19.0 || ^22.12.0 || >=23" - } - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "license": "MIT" - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "license": "MIT", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, - "node_modules/mute-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", - "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==", - "license": "ISC", - "engines": { - "node": "^18.17.0 || >=20.5.0" - } - }, - "node_modules/napi-postinstall": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.2.tgz", - "integrity": "sha512-tWVJxJHmBWLy69PvO96TZMZDrzmw5KeiZBz3RHmiM2XZ9grBJ2WgMAFVVg25nqp3ZjTFUs2Ftw1JhscL3Teliw==", - "license": "MIT", - "bin": { - "napi-postinstall": "lib/cli.js" - }, - "engines": { - "node": "^12.20.0 || ^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/napi-postinstall" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" - }, - "node_modules/natural-orderby": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/natural-orderby/-/natural-orderby-5.0.0.tgz", - "integrity": "sha512-kKHJhxwpR/Okycz4HhQKKlhWe4ASEfPgkSWNmKFHd7+ezuQlxkA5cM3+XkBPvm1gmHen3w53qsYAv+8GwRrBlg==", - "engines": { - "node": ">=18" - } - }, - "node_modules/node-cleanup": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/node-cleanup/-/node-cleanup-2.1.2.tgz", - "integrity": "sha512-qN8v/s2PAJwGUtr1/hYTpNKlD6Y9rc4p8KSmJXyGdYGZsDGKXrGThikLFP9OCHFeLeEpQzPwiAtdIvBLqm//Hw==" - }, - "node_modules/node-int64": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", - "license": "MIT" - }, - "node_modules/node-releases": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", - "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", - "license": "MIT" - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/normalize-url": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "license": "MIT", - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/object-treeify": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/object-treeify/-/object-treeify-2.1.1.tgz", - "integrity": "sha512-ofXhazOvXTYWbbibExMiS+asaTbYG/ZWopVroXFFOdjmc8ehXMq9R2VUaTx/C3CnZkQbT52wAZT4DrBLK/nQfw==", - "engines": { - "node": ">= 12" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "license": "MIT", - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/package-json-from-dist": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", - "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==" - }, - "node_modules/pako": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz", - "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==" - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-scurry": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", - "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", - "dependencies": { - "lru-cache": "^11.0.0", - "minipass": "^7.1.2" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/path-scurry/node_modules/lru-cache": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.1.0.tgz", - "integrity": "sha512-QIXZUBJUx+2zHUdQujWejBkcD9+cs94tLn0+YL8UrCh+D5sCXZ4c7LaEH48pNwRY3MLDgqUFyhlCyjJPf1WP0A==", - "engines": { - "node": "20 || >=22" - } - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pirates": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", - "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "license": "MIT", - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "license": "MIT", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "license": "MIT", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pkg-dir/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pkg-dir/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/pretty-format": { - "version": "30.0.5", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.0.5.tgz", - "integrity": "sha512-D1tKtYvByrBkFLe2wHJl2bwMJIiT8rW+XA+TiataH79/FszLQMrpGEvzUVkzPau7OCO0Qnrhpe87PqtOAIB8Yw==", - "license": "MIT", - "dependencies": { - "@jest/schemas": "30.0.5", - "ansi-styles": "^5.2.0", - "react-is": "^18.3.1" - }, - "engines": { - "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" - } - }, - "node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/pure-rand": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-7.0.1.tgz", - "integrity": "sha512-oTUZM/NAZS8p7ANR3SHh30kXB+zK2r2BPcEn/awJIbOvq82WoMN4p62AWWp3Hhw50G0xMsw1mhIBLqHw64EcNQ==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/dubzzz" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fast-check" - } - ], - "license": "MIT" - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "license": "MIT" - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "license": "MIT", - "dependencies": { - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-cwd/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "engines": { - "node": ">=4" - } - }, - "node_modules/resolve-pkg-maps": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", - "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", - "funding": { - "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" - } - }, - "node_modules/reusify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", - "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", - "license": "MIT", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "node_modules/semver": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", - "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "engines": { - "node": ">=8" - } - }, - "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/simple-wcswidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/simple-wcswidth/-/simple-wcswidth-1.0.1.tgz", - "integrity": "sha512-xMO/8eNREtaROt7tJvWJqHBDTMFN4eiQ5I4JRMuilwfnFcV5W9u7RUkueNkdw0jPqGMX36iCywelS5yilTuOxg==" - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socks": { - "version": "2.8.7", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz", - "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==", - "dependencies": { - "ip-address": "^10.0.1", - "smart-buffer": "^4.2.0" - }, - "engines": { - "node": ">= 10.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socks-proxy-agent": { - "version": "8.0.5", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", - "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", - "dependencies": { - "agent-base": "^7.1.2", - "debug": "^4.3.4", - "socks": "^2.8.3" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.13", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", - "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", - "license": "MIT", - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/stack-utils": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", - "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", - "license": "MIT", - "dependencies": { - "escape-string-regexp": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/stack-utils/node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/string-length": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", - "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", - "license": "MIT", - "dependencies": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/string-length/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/string-length/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/synckit": { - "version": "0.11.11", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.11.tgz", - "integrity": "sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==", - "license": "MIT", - "dependencies": { - "@pkgr/core": "^0.2.9" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/synckit" - } - }, - "node_modules/test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "license": "ISC", - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/test-exclude/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/timer-node": { - "version": "5.0.9", - "resolved": "https://registry.npmjs.org/timer-node/-/timer-node-5.0.9.tgz", - "integrity": "sha512-zXxCE/5/YDi0hY9pygqgRqjRbrFRzigYxOudG0I3syaqAAmX9/w9sxex1bNFCN6c1S66RwPtEIJv65dN+1psew==" - }, - "node_modules/tmpl": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", - "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", - "license": "BSD-3-Clause" - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/ts-api-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", - "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", - "license": "MIT", - "engines": { - "node": ">=18.12" - }, - "peerDependencies": { - "typescript": ">=4.8.4" - } - }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD", - "optional": true - }, - "node_modules/tsx": { - "version": "4.20.3", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.20.3.tgz", - "integrity": "sha512-qjbnuR9Tr+FJOMBqJCW5ehvIo/buZq7vH7qD7JziU98h6l3qGy0a/yPFjwO+y0/T7GFpNgNAvEcPPVfyT8rrPQ==", - "license": "MIT", - "dependencies": { - "esbuild": "~0.25.0", - "get-tsconfig": "^4.7.5" - }, - "bin": { - "tsx": "dist/cli.mjs" - }, - "engines": { - "node": ">=18.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - } - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typescript": { - "version": "5.8.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", - "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", - "peer": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/undici-types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==" - }, - "node_modules/universal-user-agent": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.3.tgz", - "integrity": "sha512-TmnEAEAsBJVZM/AADELsK76llnwcf9vMKuPz8JflO1frO8Lchitr0fNaN9d+Ap0BjKtqWqd/J17qeDnXh8CL2A==", - "license": "ISC" - }, - "node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/unrs-resolver": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz", - "integrity": "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==", - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "napi-postinstall": "^0.3.0" - }, - "funding": { - "url": "https://opencollective.com/unrs-resolver" - }, - "optionalDependencies": { - "@unrs/resolver-binding-android-arm-eabi": "1.11.1", - "@unrs/resolver-binding-android-arm64": "1.11.1", - "@unrs/resolver-binding-darwin-arm64": "1.11.1", - "@unrs/resolver-binding-darwin-x64": "1.11.1", - "@unrs/resolver-binding-freebsd-x64": "1.11.1", - "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", - "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", - "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", - "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", - "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", - "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", - "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", - "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", - "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", - "@unrs/resolver-binding-linux-x64-musl": "1.11.1", - "@unrs/resolver-binding-wasm32-wasi": "1.11.1", - "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", - "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1", - "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", - "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/v8-to-istanbul": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", - "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", - "license": "ISC", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^2.0.0" - }, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/validator": { - "version": "13.15.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.15.0.tgz", - "integrity": "sha512-36B2ryl4+oL5QxZ3AzD0t5SsMNGvTtQHpjgFO5tbNxfXbMFkY822ktCDe1MnlqV3301QQI9SLHDNJokDI+Z9pA==", - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/walker": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", - "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", - "license": "Apache-2.0", - "dependencies": { - "makeerror": "1.0.12" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "license": "ISC" - }, - "node_modules/write-file-atomic": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", - "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", - "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "license": "ISC" - }, - "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "engines": { - "node": ">=12" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yoctocolors-cjs": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.2.tgz", - "integrity": "sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - } -} +{ + "name": "iptv", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "iptv", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "@alex_neo/jest-expect-message": "^1.0.5", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "^9.32.0", + "@freearhey/core": "^0.14.3", + "@freearhey/search-js": "^0.1.2", + "@freearhey/storage-js": "^0.1.0", + "@inquirer/prompts": "^7.8.0", + "@iptv-org/sdk": "^1.0.2", + "@octokit/core": "^7.0.3", + "@octokit/plugin-paginate-rest": "^13.1.1", + "@octokit/plugin-rest-endpoint-methods": "^16.0.0", + "@octokit/types": "^14.1.0", + "@stylistic/eslint-plugin": "^5.2.2", + "@swc/jest": "^0.2.39", + "@types/async": "^3.2.25", + "@types/cli-progress": "^3.11.6", + "@types/fs-extra": "^11.0.4", + "@types/jest": "^30.0.0", + "@types/lodash.uniqueid": "^4.0.9", + "@types/node-cleanup": "^2.1.5", + "@typescript-eslint/eslint-plugin": "^8.38.0", + "@typescript-eslint/parser": "^8.38.0", + "async": "^3.2.6", + "axios": "^1.11.0", + "chalk": "^5.4.1", + "cli-progress": "^3.12.0", + "commander": "^14.0.0", + "console-table-printer": "^2.14.6", + "cross-env": "^10.0.0", + "eslint": "^9.32.0", + "glob": "^11.0.3", + "globals": "^16.3.0", + "iptv-playlist-parser": "^0.15.1", + "jest": "^30.0.5", + "jest-expect-message": "^1.1.3", + "lodash.uniqueid": "^4.0.1", + "m3u-linter": "^0.4.2", + "mediainfo.js": "^0.3.6", + "node-cleanup": "^2.1.2", + "normalize-url": "^8.1.0", + "socks-proxy-agent": "^8.0.5", + "tsx": "^4.20.3" + } + }, + "node_modules/@alex_neo/jest-expect-message": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@alex_neo/jest-expect-message/-/jest-expect-message-1.0.5.tgz", + "integrity": "sha512-1eBykZCd0pPGl5qKtV6Z5ARA6yuhXzHsVN2h5GH5/H6svYa37Jr7vMio5OFpiw1LBHtscrZs7amSkZkcwm0cvQ==" + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "license": "Apache-2.0", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.0.tgz", + "integrity": "sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.0.tgz", + "integrity": "sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ==", + "license": "MIT", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.0", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-module-transforms": "^7.27.3", + "@babel/helpers": "^7.27.6", + "@babel/parser": "^7.28.0", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.0", + "@babel/types": "^7.28.0", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.0.tgz", + "integrity": "sha512-lJjzvrbEeWrhB4P3QBsH7tey117PjLZnDbLiQEKjQ/fNJTjuq4HSqgFA+UNSwZT8D7dxxbnuSBMsa1lrWzKlQg==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.0", + "@babel/types": "^7.28.0", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.27.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.3.tgz", + "integrity": "sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.27.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", + "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.28.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.2.tgz", + "integrity": "sha512-/V9771t+EgXz62aCcyofnQhGM8DQACbRhvzKFsXKC9QM+5MadF8ZmIm0crDMaz3+o0h0zXfJnd4EhbYbxsrcFw==", + "license": "MIT", + "dependencies": { + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.0.tgz", + "integrity": "sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz", + "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", + "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz", + "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.0.tgz", + "integrity": "sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.0", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.0", + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.0", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.28.2", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.2.tgz", + "integrity": "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "license": "MIT" + }, + "node_modules/@emnapi/core": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.4.5.tgz", + "integrity": "sha512-XsLw1dEOpkSX/WucdqUhPWP7hDxSvZiY+fsUC14h+FtQ2Ifni4znbBt8punRX+Uj2JG/uDb8nEHVKvrVlvdZ5Q==", + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.0.4", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.5.tgz", + "integrity": "sha512-++LApOtY0pEEz1zrd9vy1/zXVaVJJ/EbAF3u0fXIzPJEDtnITsBGbbK0EkM72amhl/R5b+5xx0Y/QhcVOpuulg==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.4.tgz", + "integrity": "sha512-PJR+bOmMOPH8AtcTGAyYNiuJ3/Fcoj2XN/gBEWzDIKh254XO+mM9XoXHk5GNEhodxeMznbg7BlRojVbKN+gC6g==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@epic-web/invariant": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@epic-web/invariant/-/invariant-1.0.0.tgz", + "integrity": "sha512-lrTPqgvfFQtR/eY/qkIzp98OGdNJu0m5ji3q/nJI8v3SXkRKEnWiOxMmbvcSoAIzv/cGiuvRy57k4suKQSAdwA==", + "license": "MIT" + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.3.tgz", + "integrity": "sha512-W8bFfPA8DowP8l//sxjJLSLkD8iEjMc7cBVyP+u4cEv9sM7mdUCkgsj+t0n/BWPFtv7WWCN5Yzj0N6FJNUUqBQ==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.3.tgz", + "integrity": "sha512-PuwVXbnP87Tcff5I9ngV0lmiSu40xw1At6i3GsU77U7cjDDB4s0X2cyFuBiDa1SBk9DnvWwnGvVaGBqoFWPb7A==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.3.tgz", + "integrity": "sha512-XelR6MzjlZuBM4f5z2IQHK6LkK34Cvv6Rj2EntER3lwCBFdg6h2lKbtRjpTTsdEjD/WSe1q8UyPBXP1x3i/wYQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.3.tgz", + "integrity": "sha512-ogtTpYHT/g1GWS/zKM0cc/tIebFjm1F9Aw1boQ2Y0eUQ+J89d0jFY//s9ei9jVIlkYi8AfOjiixcLJSGNSOAdQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.3.tgz", + "integrity": "sha512-eESK5yfPNTqpAmDfFWNsOhmIOaQA59tAcF/EfYvo5/QWQCzXn5iUSOnqt3ra3UdzBv073ykTtmeLJZGt3HhA+w==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.3.tgz", + "integrity": "sha512-Kd8glo7sIZtwOLcPbW0yLpKmBNWMANZhrC1r6K++uDR2zyzb6AeOYtI6udbtabmQpFaxJ8uduXMAo1gs5ozz8A==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.3.tgz", + "integrity": "sha512-EJiyS70BYybOBpJth3M0KLOus0n+RRMKTYzhYhFeMwp7e/RaajXvP+BWlmEXNk6uk+KAu46j/kaQzr6au+JcIw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.3.tgz", + "integrity": "sha512-Q+wSjaLpGxYf7zC0kL0nDlhsfuFkoN+EXrx2KSB33RhinWzejOd6AvgmP5JbkgXKmjhmpfgKZq24pneodYqE8Q==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.3.tgz", + "integrity": "sha512-dUOVmAUzuHy2ZOKIHIKHCm58HKzFqd+puLaS424h6I85GlSDRZIA5ycBixb3mFgM0Jdh+ZOSB6KptX30DD8YOQ==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.3.tgz", + "integrity": "sha512-xCUgnNYhRD5bb1C1nqrDV1PfkwgbswTTBRbAd8aH5PhYzikdf/ddtsYyMXFfGSsb/6t6QaPSzxtbfAZr9uox4A==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.3.tgz", + "integrity": "sha512-yplPOpczHOO4jTYKmuYuANI3WhvIPSVANGcNUeMlxH4twz/TeXuzEP41tGKNGWJjuMhotpGabeFYGAOU2ummBw==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.3.tgz", + "integrity": "sha512-P4BLP5/fjyihmXCELRGrLd793q/lBtKMQl8ARGpDxgzgIKJDRJ/u4r1A/HgpBpKpKZelGct2PGI4T+axcedf6g==", + "cpu": [ + "loong64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.3.tgz", + "integrity": "sha512-eRAOV2ODpu6P5divMEMa26RRqb2yUoYsuQQOuFUexUoQndm4MdpXXDBbUoKIc0iPa4aCO7gIhtnYomkn2x+bag==", + "cpu": [ + "mips64el" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.3.tgz", + "integrity": "sha512-ZC4jV2p7VbzTlnl8nZKLcBkfzIf4Yad1SJM4ZMKYnJqZFD4rTI+pBG65u8ev4jk3/MPwY9DvGn50wi3uhdaghg==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.3.tgz", + "integrity": "sha512-LDDODcFzNtECTrUUbVCs6j9/bDVqy7DDRsuIXJg6so+mFksgwG7ZVnTruYi5V+z3eE5y+BJZw7VvUadkbfg7QA==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.3.tgz", + "integrity": "sha512-s+w/NOY2k0yC2p9SLen+ymflgcpRkvwwa02fqmAwhBRI3SC12uiS10edHHXlVWwfAagYSY5UpmT/zISXPMW3tQ==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.3.tgz", + "integrity": "sha512-nQHDz4pXjSDC6UfOE1Fw9Q8d6GCAd9KdvMZpfVGWSJztYCarRgSDfOVBY5xwhQXseiyxapkiSJi/5/ja8mRFFA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.3.tgz", + "integrity": "sha512-1QaLtOWq0mzK6tzzp0jRN3eccmN3hezey7mhLnzC6oNlJoUJz4nym5ZD7mDnS/LZQgkrhEbEiTn515lPeLpgWA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.3.tgz", + "integrity": "sha512-i5Hm68HXHdgv8wkrt+10Bc50zM0/eonPb/a/OFVfB6Qvpiirco5gBA5bz7S2SHuU+Y4LWn/zehzNX14Sp4r27g==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.3.tgz", + "integrity": "sha512-zGAVApJEYTbOC6H/3QBr2mq3upG/LBEXr85/pTtKiv2IXcgKV0RT0QA/hSXZqSvLEpXeIxah7LczB4lkiYhTAQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.3.tgz", + "integrity": "sha512-fpqctI45NnCIDKBH5AXQBsD0NDPbEFczK98hk/aa6HJxbl+UtLkJV2+Bvy5hLSLk3LHmqt0NTkKNso1A9y1a4w==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.3.tgz", + "integrity": "sha512-ROJhm7d8bk9dMCUZjkS8fgzsPAZEjtRJqCAmVgB0gMrvG7hfmPmz9k1rwO4jSiblFjYmNvbECL9uhaPzONMfgA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.3.tgz", + "integrity": "sha512-YWcow8peiHpNBiIXHwaswPnAXLsLVygFwCB3A7Bh5jRkIBFWHGmNQ48AlX4xDvQNoMZlPYzjVOQDYEzWCqufMQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.3.tgz", + "integrity": "sha512-qspTZOIGoXVS4DpNqUYUs9UxVb04khS1Degaw/MnfMe7goQ3lTfQ13Vw4qY/Nj0979BGvMRpAYbs/BAxEvU8ew==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.3.tgz", + "integrity": "sha512-ICgUR+kPimx0vvRzf+N/7L7tVSQeE3BYY+NhHRHXS1kBuPO7z2+7ea2HbhDyZdTephgvNvKrlDDKUexuCVBVvg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", + "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz", + "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==", + "dependencies": { + "@eslint/object-schema": "^2.1.6", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.0.tgz", + "integrity": "sha512-ViuymvFmcJi04qdZeDc2whTHryouGcDlaxPqarTD0ZE10ISpxGUVZGZDx4w01upyIynL3iu6IXH2bS1NhclQMw==", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.1.tgz", + "integrity": "sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA==", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", + "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "9.32.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.32.0.tgz", + "integrity": "sha512-BBpRFZK3eX6uMLKz8WxFOBIFFcGFJ/g8XuwjTHCqHROSIsopI+ddn/d5Cfh36+7+e5edVS8dbSHnBNhrLEX0zg==", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", + "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.4.tgz", + "integrity": "sha512-Ul5l+lHEcw3L5+k8POx6r74mxEYKG5kOb6Xpy2gCRW6zweT6TEhAf8vhxGgjhqrd/VO/Dirhsb+1hNpD1ue9hw==", + "dependencies": { + "@eslint/core": "^0.15.1", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@freearhey/core": { + "version": "0.14.3", + "resolved": "https://registry.npmjs.org/@freearhey/core/-/core-0.14.3.tgz", + "integrity": "sha512-w/kaoUdZlbqvOSOmid0nrBI9iGZkUZ+KLZUfkWpfZRPXOEu/FxlEP5gPANGgovwijrgogAbVf/qnf9VV+429ag==", + "dependencies": { + "@types/lodash": "^4.14.198", + "@types/pako": "^2.0.3", + "consola": "^3.4.2", + "dayjs": "^1.11.13", + "glob": "^11.0.1", + "lodash": "^4.17.21", + "natural-orderby": "^5.0.0", + "normalize-url": "^8.1.0", + "object-treeify": "^2.1.1", + "pako": "^2.1.0", + "timer-node": "^5.0.9" + } + }, + "node_modules/@freearhey/search-js": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@freearhey/search-js/-/search-js-0.1.2.tgz", + "integrity": "sha512-F2o+xpGCXOK4OsZfKEHfXNNkAZmny2eBnPOp+P0iyV20ja7gJGfTFaEc6okcuEo6OB6P7LnSxTvISkoArFtlfg==", + "dependencies": { + "lodash": "^4.17.21" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@freearhey/storage-js": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@freearhey/storage-js/-/storage-js-0.1.0.tgz", + "integrity": "sha512-1TR5vPPkVewwNVelM4atDMxgjUaBE1kz/sD9z82zOVSMoyWahachhXW2/pxSHSElENg7SBY75Wki99kS+Kouxw==", + "dependencies": { + "fs-extra": "^11.3.1", + "glob": "^11.0.3" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.3.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.2.tgz", + "integrity": "sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@inquirer/checkbox": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@inquirer/checkbox/-/checkbox-4.2.0.tgz", + "integrity": "sha512-fdSw07FLJEU5vbpOPzXo5c6xmMGDzbZE2+niuDHX5N6mc6V0Ebso/q3xiHra4D73+PMsC8MJmcaZKuAAoaQsSA==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.1.15", + "@inquirer/figures": "^1.0.13", + "@inquirer/type": "^3.0.8", + "ansi-escapes": "^4.3.2", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/confirm": { + "version": "5.1.14", + "resolved": "https://registry.npmjs.org/@inquirer/confirm/-/confirm-5.1.14.tgz", + "integrity": "sha512-5yR4IBfe0kXe59r1YCTG8WXkUbl7Z35HK87Sw+WUyGD8wNUx7JvY7laahzeytyE1oLn74bQnL7hstctQxisQ8Q==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.1.15", + "@inquirer/type": "^3.0.8" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/core": { + "version": "10.1.15", + "resolved": "https://registry.npmjs.org/@inquirer/core/-/core-10.1.15.tgz", + "integrity": "sha512-8xrp836RZvKkpNbVvgWUlxjT4CraKk2q+I3Ksy+seI2zkcE+y6wNs1BVhgcv8VyImFecUhdQrYLdW32pAjwBdA==", + "license": "MIT", + "dependencies": { + "@inquirer/figures": "^1.0.13", + "@inquirer/type": "^3.0.8", + "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" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/editor": { + "version": "4.2.17", + "resolved": "https://registry.npmjs.org/@inquirer/editor/-/editor-4.2.17.tgz", + "integrity": "sha512-r6bQLsyPSzbWrZZ9ufoWL+CztkSatnJ6uSxqd6N+o41EZC51sQeWOzI6s5jLb+xxTWxl7PlUppqm8/sow241gg==", + "dependencies": { + "@inquirer/core": "^10.1.15", + "@inquirer/external-editor": "^1.0.1", + "@inquirer/type": "^3.0.8" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/expand": { + "version": "4.0.17", + "resolved": "https://registry.npmjs.org/@inquirer/expand/-/expand-4.0.17.tgz", + "integrity": "sha512-PSqy9VmJx/VbE3CT453yOfNa+PykpKg/0SYP7odez1/NWBGuDXgPhp4AeGYYKjhLn5lUUavVS/JbeYMPdH50Mw==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.1.15", + "@inquirer/type": "^3.0.8", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/external-editor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-1.0.1.tgz", + "integrity": "sha512-Oau4yL24d2B5IL4ma4UpbQigkVhzPDXLoqy1ggK4gnHg/stmkffJE4oOXHXF3uz0UEpywG68KcyXsyYpA1Re/Q==", + "dependencies": { + "chardet": "^2.1.0", + "iconv-lite": "^0.6.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/figures": { + "version": "1.0.13", + "resolved": "https://registry.npmjs.org/@inquirer/figures/-/figures-1.0.13.tgz", + "integrity": "sha512-lGPVU3yO9ZNqA7vTYz26jny41lE7yoQansmqdMLBEfqaGsmdg7V3W9mK9Pvb5IL4EVZ9GnSDGMO/cJXud5dMaw==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@inquirer/input": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@inquirer/input/-/input-4.2.1.tgz", + "integrity": "sha512-tVC+O1rBl0lJpoUZv4xY+WGWY8V5b0zxU1XDsMsIHYregdh7bN5X5QnIONNBAl0K765FYlAfNHS2Bhn7SSOVow==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.1.15", + "@inquirer/type": "^3.0.8" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/number": { + "version": "3.0.17", + "resolved": "https://registry.npmjs.org/@inquirer/number/-/number-3.0.17.tgz", + "integrity": "sha512-GcvGHkyIgfZgVnnimURdOueMk0CztycfC8NZTiIY9arIAkeOgt6zG57G+7vC59Jns3UX27LMkPKnKWAOF5xEYg==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.1.15", + "@inquirer/type": "^3.0.8" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/password": { + "version": "4.0.17", + "resolved": "https://registry.npmjs.org/@inquirer/password/-/password-4.0.17.tgz", + "integrity": "sha512-DJolTnNeZ00E1+1TW+8614F7rOJJCM4y4BAGQ3Gq6kQIG+OJ4zr3GLjIjVVJCbKsk2jmkmv6v2kQuN/vriHdZA==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.1.15", + "@inquirer/type": "^3.0.8", + "ansi-escapes": "^4.3.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/prompts": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@inquirer/prompts/-/prompts-7.8.0.tgz", + "integrity": "sha512-JHwGbQ6wjf1dxxnalDYpZwZxUEosT+6CPGD9Zh4sm9WXdtUp9XODCQD3NjSTmu+0OAyxWXNOqf0spjIymJa2Tw==", + "license": "MIT", + "dependencies": { + "@inquirer/checkbox": "^4.2.0", + "@inquirer/confirm": "^5.1.14", + "@inquirer/editor": "^4.2.15", + "@inquirer/expand": "^4.0.17", + "@inquirer/input": "^4.2.1", + "@inquirer/number": "^3.0.17", + "@inquirer/password": "^4.0.17", + "@inquirer/rawlist": "^4.1.5", + "@inquirer/search": "^3.1.0", + "@inquirer/select": "^4.3.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/rawlist": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@inquirer/rawlist/-/rawlist-4.1.5.tgz", + "integrity": "sha512-R5qMyGJqtDdi4Ht521iAkNqyB6p2UPuZUbMifakg1sWtu24gc2Z8CJuw8rP081OckNDMgtDCuLe42Q2Kr3BolA==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.1.15", + "@inquirer/type": "^3.0.8", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/search": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@inquirer/search/-/search-3.1.0.tgz", + "integrity": "sha512-PMk1+O/WBcYJDq2H7foV0aAZSmDdkzZB9Mw2v/DmONRJopwA/128cS9M/TXWLKKdEQKZnKwBzqu2G4x/2Nqx8Q==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.1.15", + "@inquirer/figures": "^1.0.13", + "@inquirer/type": "^3.0.8", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/select": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@inquirer/select/-/select-4.3.1.tgz", + "integrity": "sha512-Gfl/5sqOF5vS/LIrSndFgOh7jgoe0UXEizDqahFRkq5aJBLegZ6WjuMh/hVEJwlFQjyLq1z9fRtvUMkb7jM1LA==", + "license": "MIT", + "dependencies": { + "@inquirer/core": "^10.1.15", + "@inquirer/figures": "^1.0.13", + "@inquirer/type": "^3.0.8", + "ansi-escapes": "^4.3.2", + "yoctocolors-cjs": "^2.1.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@inquirer/type": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@inquirer/type/-/type-3.0.8.tgz", + "integrity": "sha512-lg9Whz8onIHRthWaN1Q9EGLa/0LFJjyM8mEUbL1eTi6yMGvBf8gvyDLtxSXztQsxMvhxxNpJYrwa1YHdq+w4Jw==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@types/node": ">=18" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/@iptv-org/sdk": { + "version": "1.0.2", + "resolved": "https://npm.pkg.github.com/download/@iptv-org/sdk/1.0.2/131e5145ff68ffb5e213eb02d26d43db91a8a5a3", + "integrity": "sha512-Lpq+5vko9HkqOMDaXpeLBzKVgJikuKax7dJgBjr+XIgxRgMB1gucCjbvTNCR5AHhnORWvX+LFaodzy06jKukOA==", + "license": "UNLICENSED", + "dependencies": { + "@freearhey/core": "^0.14.3", + "@freearhey/search-js": "^0.2.0", + "@ntlab/sfetch": "^1.2.0", + "axios": "^1.11.0", + "dayjs": "^1.11.18" + } + }, + "node_modules/@iptv-org/sdk/node_modules/@freearhey/search-js": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@freearhey/search-js/-/search-js-0.2.0.tgz", + "integrity": "sha512-1sxfCRbxM12Js3nM/S51cVKLYEjoksERidz539bleMAXes44eTC2m0TEQTJzJyE7l1pw2qUwsIhjd2l2l88fSw==", + "dependencies": { + "lodash": "^4.17.21" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@isaacs/balanced-match": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz", + "integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==", + "license": "MIT", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@isaacs/brace-expansion": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz", + "integrity": "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==", + "license": "MIT", + "dependencies": { + "@isaacs/balanced-match": "^4.0.1" + }, + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "license": "MIT" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "license": "ISC", + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "license": "BSD-3-Clause" + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-30.0.5.tgz", + "integrity": "sha512-xY6b0XiL0Nav3ReresUarwl2oIz1gTnxGbGpho9/rbUWsLH0f1OD/VT84xs8c7VmH7MChnLb0pag6PhZhAdDiA==", + "license": "MIT", + "dependencies": { + "@jest/types": "30.0.5", + "@types/node": "*", + "chalk": "^4.1.2", + "jest-message-util": "30.0.5", + "jest-util": "30.0.5", + "slash": "^3.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/console/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/core": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-30.0.5.tgz", + "integrity": "sha512-fKD0OulvRsXF1hmaFgHhVJzczWzA1RXMMo9LTPuFXo9q/alDbME3JIyWYqovWsUBWSoBcsHaGPSLF9rz4l9Qeg==", + "license": "MIT", + "dependencies": { + "@jest/console": "30.0.5", + "@jest/pattern": "30.0.1", + "@jest/reporters": "30.0.5", + "@jest/test-result": "30.0.5", + "@jest/transform": "30.0.5", + "@jest/types": "30.0.5", + "@types/node": "*", + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "exit-x": "^0.2.2", + "graceful-fs": "^4.2.11", + "jest-changed-files": "30.0.5", + "jest-config": "30.0.5", + "jest-haste-map": "30.0.5", + "jest-message-util": "30.0.5", + "jest-regex-util": "30.0.1", + "jest-resolve": "30.0.5", + "jest-resolve-dependencies": "30.0.5", + "jest-runner": "30.0.5", + "jest-runtime": "30.0.5", + "jest-snapshot": "30.0.5", + "jest-util": "30.0.5", + "jest-validate": "30.0.5", + "jest-watcher": "30.0.5", + "micromatch": "^4.0.8", + "pretty-format": "30.0.5", + "slash": "^3.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/core/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/create-cache-key-function": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/create-cache-key-function/-/create-cache-key-function-30.0.5.tgz", + "integrity": "sha512-W1kmkwPq/WTMQWgvbzWSCbXSqvjI6rkqBQCxuvYmd+g6o4b5gHP98ikfh/Ei0SKzHvWdI84TOXp0hRcbpr8Q0w==", + "license": "MIT", + "dependencies": { + "@jest/types": "30.0.5" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/diff-sequences": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/diff-sequences/-/diff-sequences-30.0.1.tgz", + "integrity": "sha512-n5H8QLDJ47QqbCNn5SuFjCRDrOLEZ0h8vAHCK5RL9Ls7Xa8AQLa/YxAc9UjFqoEDM48muwtBGjtMY5cr0PLDCw==", + "license": "MIT", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/environment": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-30.0.5.tgz", + "integrity": "sha512-aRX7WoaWx1oaOkDQvCWImVQ8XNtdv5sEWgk4gxR6NXb7WBUnL5sRak4WRzIQRZ1VTWPvV4VI4mgGjNL9TeKMYA==", + "license": "MIT", + "dependencies": { + "@jest/fake-timers": "30.0.5", + "@jest/types": "30.0.5", + "@types/node": "*", + "jest-mock": "30.0.5" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-30.0.5.tgz", + "integrity": "sha512-6udac8KKrtTtC+AXZ2iUN/R7dp7Ydry+Fo6FPFnDG54wjVMnb6vW/XNlf7Xj8UDjAE3aAVAsR4KFyKk3TCXmTA==", + "license": "MIT", + "dependencies": { + "expect": "30.0.5", + "jest-snapshot": "30.0.5" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-30.0.5.tgz", + "integrity": "sha512-F3lmTT7CXWYywoVUGTCmom0vXq3HTTkaZyTAzIy+bXSBizB7o5qzlC9VCtq0arOa8GqmNsbg/cE9C6HLn7Szew==", + "license": "MIT", + "dependencies": { + "@jest/get-type": "30.0.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-30.0.5.tgz", + "integrity": "sha512-ZO5DHfNV+kgEAeP3gK3XlpJLL4U3Sz6ebl/n68Uwt64qFFs5bv4bfEEjyRGK5uM0C90ewooNgFuKMdkbEoMEXw==", + "license": "MIT", + "dependencies": { + "@jest/types": "30.0.5", + "@sinonjs/fake-timers": "^13.0.0", + "@types/node": "*", + "jest-message-util": "30.0.5", + "jest-mock": "30.0.5", + "jest-util": "30.0.5" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/get-type": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/get-type/-/get-type-30.0.1.tgz", + "integrity": "sha512-AyYdemXCptSRFirI5EPazNxyPwAL0jXt3zceFjaj8NFiKP9pOi0bfXonf6qkf82z2t3QWPeLCWWw4stPBzctLw==", + "license": "MIT", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-30.0.5.tgz", + "integrity": "sha512-7oEJT19WW4oe6HR7oLRvHxwlJk2gev0U9px3ufs8sX9PoD1Eza68KF0/tlN7X0dq/WVsBScXQGgCldA1V9Y/jA==", + "license": "MIT", + "dependencies": { + "@jest/environment": "30.0.5", + "@jest/expect": "30.0.5", + "@jest/types": "30.0.5", + "jest-mock": "30.0.5" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/pattern": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/pattern/-/pattern-30.0.1.tgz", + "integrity": "sha512-gWp7NfQW27LaBQz3TITS8L7ZCQ0TLvtmI//4OwlQRx4rnWxcPNIYjxZpDcN4+UlGxgm3jS5QPz8IPTCkb59wZA==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "jest-regex-util": "30.0.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-30.0.5.tgz", + "integrity": "sha512-mafft7VBX4jzED1FwGC1o/9QUM2xebzavImZMeqnsklgcyxBto8mV4HzNSzUrryJ+8R9MFOM3HgYuDradWR+4g==", + "license": "MIT", + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "30.0.5", + "@jest/test-result": "30.0.5", + "@jest/transform": "30.0.5", + "@jest/types": "30.0.5", + "@jridgewell/trace-mapping": "^0.3.25", + "@types/node": "*", + "chalk": "^4.1.2", + "collect-v8-coverage": "^1.0.2", + "exit-x": "^0.2.2", + "glob": "^10.3.10", + "graceful-fs": "^4.2.11", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^5.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "30.0.5", + "jest-util": "30.0.5", + "jest-worker": "30.0.5", + "slash": "^3.0.0", + "string-length": "^4.0.2", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/reporters/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@jest/reporters/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/reporters/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@jest/reporters/node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/@jest/reporters/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "license": "ISC" + }, + "node_modules/@jest/reporters/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@jest/reporters/node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@jest/schemas": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-30.0.5.tgz", + "integrity": "sha512-DmdYgtezMkh3cpU8/1uyXakv3tJRcmcXxBOcO0tbaozPwpmh4YMsnWrQm9ZmZMfa5ocbxzbFk6O4bDPEc/iAnA==", + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.34.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/snapshot-utils": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/snapshot-utils/-/snapshot-utils-30.0.5.tgz", + "integrity": "sha512-XcCQ5qWHLvi29UUrowgDFvV4t7ETxX91CbDczMnoqXPOIcZOxyNdSjm6kV5XMc8+HkxfRegU/MUmnTbJRzGrUQ==", + "license": "MIT", + "dependencies": { + "@jest/types": "30.0.5", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "natural-compare": "^1.4.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/snapshot-utils/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/source-map": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-30.0.1.tgz", + "integrity": "sha512-MIRWMUUR3sdbP36oyNyhbThLHyJ2eEDClPCiHVbrYAe5g3CHRArIVpBw7cdSB5fr+ofSfIb2Tnsw8iEHL0PYQg==", + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.25", + "callsites": "^3.1.0", + "graceful-fs": "^4.2.11" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/test-result": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-30.0.5.tgz", + "integrity": "sha512-wPyztnK0gbDMQAJZ43tdMro+qblDHH1Ru/ylzUo21TBKqt88ZqnKKK2m30LKmLLoKtR2lxdpCC/P3g1vfKcawQ==", + "license": "MIT", + "dependencies": { + "@jest/console": "30.0.5", + "@jest/types": "30.0.5", + "@types/istanbul-lib-coverage": "^2.0.6", + "collect-v8-coverage": "^1.0.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-30.0.5.tgz", + "integrity": "sha512-Aea/G1egWoIIozmDD7PBXUOxkekXl7ueGzrsGGi1SbeKgQqCYCIf+wfbflEbf2LiPxL8j2JZGLyrzZagjvW4YQ==", + "license": "MIT", + "dependencies": { + "@jest/test-result": "30.0.5", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.0.5", + "slash": "^3.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-30.0.5.tgz", + "integrity": "sha512-Vk8amLQCmuZyy6GbBht1Jfo9RSdBtg7Lks+B0PecnjI8J+PCLQPGh7uI8Q/2wwpW2gLdiAfiHNsmekKlywULqg==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.27.4", + "@jest/types": "30.0.5", + "@jridgewell/trace-mapping": "^0.3.25", + "babel-plugin-istanbul": "^7.0.0", + "chalk": "^4.1.2", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.0.5", + "jest-regex-util": "30.0.1", + "jest-util": "30.0.5", + "micromatch": "^4.0.8", + "pirates": "^4.0.7", + "slash": "^3.0.0", + "write-file-atomic": "^5.0.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/transform/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/types": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-30.0.5.tgz", + "integrity": "sha512-aREYa3aku9SSnea4aX6bhKn4bgv3AXkgijoQgbYV3yvbiGt6z+MQ85+6mIhx9DsKW2BuB/cLR/A+tcMThx+KLQ==", + "license": "MIT", + "dependencies": { + "@jest/pattern": "30.0.1", + "@jest/schemas": "30.0.5", + "@types/istanbul-lib-coverage": "^2.0.6", + "@types/istanbul-reports": "^3.0.4", + "@types/node": "*", + "@types/yargs": "^17.0.33", + "chalk": "^4.1.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/@jest/types/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.12", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz", + "integrity": "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz", + "integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.29", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz", + "integrity": "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", + "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.4.3", + "@emnapi/runtime": "^1.4.3", + "@tybys/wasm-util": "^0.10.0" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@ntlab/sfetch": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ntlab/sfetch/-/sfetch-1.2.0.tgz", + "integrity": "sha512-9SE4NnqWo8l6mG0rnAkgng6ozSamIpF3EC+GOTQGGa6eAC0tNJvzrylMz6YRjjEGH6mOfn7ZBAuKj5WIZUul6A==", + "dependencies": { + "axios": "^1.7.9" + } + }, + "node_modules/@octokit/auth-token": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-6.0.0.tgz", + "integrity": "sha512-P4YJBPdPSpWTQ1NU4XYdvHvXJJDxM6YwpS0FZHRgP7YFkdVxsWcpWGy/NVqlAA7PcPCnMacXlRm1y2PFZRWL/w==", + "license": "MIT", + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/core": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-7.0.3.tgz", + "integrity": "sha512-oNXsh2ywth5aowwIa7RKtawnkdH6LgU1ztfP9AIUCQCvzysB+WeU8o2kyyosDPwBZutPpjZDKPQGIzzrfTWweQ==", + "license": "MIT", + "dependencies": { + "@octokit/auth-token": "^6.0.0", + "@octokit/graphql": "^9.0.1", + "@octokit/request": "^10.0.2", + "@octokit/request-error": "^7.0.0", + "@octokit/types": "^14.0.0", + "before-after-hook": "^4.0.0", + "universal-user-agent": "^7.0.0" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/endpoint": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-11.0.0.tgz", + "integrity": "sha512-hoYicJZaqISMAI3JfaDr1qMNi48OctWuOih1m80bkYow/ayPw6Jj52tqWJ6GEoFTk1gBqfanSoI1iY99Z5+ekQ==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^14.0.0", + "universal-user-agent": "^7.0.2" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/graphql": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-9.0.1.tgz", + "integrity": "sha512-j1nQNU1ZxNFx2ZtKmL4sMrs4egy5h65OMDmSbVyuCzjOcwsHq6EaYjOTGXPQxgfiN8dJ4CriYHk6zF050WEULg==", + "license": "MIT", + "dependencies": { + "@octokit/request": "^10.0.2", + "@octokit/types": "^14.0.0", + "universal-user-agent": "^7.0.0" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/openapi-types": { + "version": "25.1.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-25.1.0.tgz", + "integrity": "sha512-idsIggNXUKkk0+BExUn1dQ92sfysJrje03Q0bv0e+KPLrvyqZF8MnBpFz8UNfYDwB3Ie7Z0TByjWfzxt7vseaA==", + "license": "MIT" + }, + "node_modules/@octokit/plugin-paginate-rest": { + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-13.1.1.tgz", + "integrity": "sha512-q9iQGlZlxAVNRN2jDNskJW/Cafy7/XE52wjZ5TTvyhyOD904Cvx//DNyoO3J/MXJ0ve3rPoNWKEg5iZrisQSuw==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^14.1.0" + }, + "engines": { + "node": ">= 20" + }, + "peerDependencies": { + "@octokit/core": ">=6" + } + }, + "node_modules/@octokit/plugin-rest-endpoint-methods": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-16.0.0.tgz", + "integrity": "sha512-kJVUQk6/dx/gRNLWUnAWKFs1kVPn5O5CYZyssyEoNYaFedqZxsfYs7DwI3d67hGz4qOwaJ1dpm07hOAD1BXx6g==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^14.1.0" + }, + "engines": { + "node": ">= 20" + }, + "peerDependencies": { + "@octokit/core": ">=6" + } + }, + "node_modules/@octokit/request": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-10.0.3.tgz", + "integrity": "sha512-V6jhKokg35vk098iBqp2FBKunk3kMTXlmq+PtbV9Gl3TfskWlebSofU9uunVKhUN7xl+0+i5vt0TGTG8/p/7HA==", + "license": "MIT", + "dependencies": { + "@octokit/endpoint": "^11.0.0", + "@octokit/request-error": "^7.0.0", + "@octokit/types": "^14.0.0", + "fast-content-type-parse": "^3.0.0", + "universal-user-agent": "^7.0.2" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/request-error": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-7.0.0.tgz", + "integrity": "sha512-KRA7VTGdVyJlh0cP5Tf94hTiYVVqmt2f3I6mnimmaVz4UG3gQV/k4mDJlJv3X67iX6rmN7gSHCF8ssqeMnmhZg==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^14.0.0" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/@octokit/types": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-14.1.0.tgz", + "integrity": "sha512-1y6DgTy8Jomcpu33N+p5w58l6xyt55Ar2I91RPiIA0xCJBXyUAhXCcmZaDWSANiha7R9a6qJJ2CRomGPZ6f46g==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^25.1.0" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@pkgr/core": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz", + "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/pkgr" + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.34.38", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.38.tgz", + "integrity": "sha512-HpkxMmc2XmZKhvaKIZZThlHmx1L0I/V1hWK1NubtlFnr6ZqdiOpV72TKudZUNQjZNsyDBay72qFEhEvb+bcwcA==", + "license": "MIT" + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "license": "BSD-3-Clause", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "13.0.5", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz", + "integrity": "sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==", + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.1" + } + }, + "node_modules/@stylistic/eslint-plugin": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-5.2.2.tgz", + "integrity": "sha512-bE2DUjruqXlHYP3Q2Gpqiuj2bHq7/88FnuaS0FjeGGLCy+X6a07bGVuwtiOYnPSLHR6jmx5Bwdv+j7l8H+G97A==", + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/types": "^8.37.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "estraverse": "^5.3.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "peerDependencies": { + "eslint": ">=9.0.0" + } + }, + "node_modules/@stylistic/eslint-plugin/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@stylistic/eslint-plugin/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/@swc/core": { + "version": "1.11.24", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.11.24.tgz", + "integrity": "sha512-MaQEIpfcEMzx3VWWopbofKJvaraqmL6HbLlw2bFZ7qYqYw3rkhM0cQVEgyzbHtTWwCwPMFZSC2DUbhlZgrMfLg==", + "hasInstallScript": true, + "peer": true, + "dependencies": { + "@swc/counter": "^0.1.3", + "@swc/types": "^0.1.21" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/swc" + }, + "optionalDependencies": { + "@swc/core-darwin-arm64": "1.11.24", + "@swc/core-darwin-x64": "1.11.24", + "@swc/core-linux-arm-gnueabihf": "1.11.24", + "@swc/core-linux-arm64-gnu": "1.11.24", + "@swc/core-linux-arm64-musl": "1.11.24", + "@swc/core-linux-x64-gnu": "1.11.24", + "@swc/core-linux-x64-musl": "1.11.24", + "@swc/core-win32-arm64-msvc": "1.11.24", + "@swc/core-win32-ia32-msvc": "1.11.24", + "@swc/core-win32-x64-msvc": "1.11.24" + }, + "peerDependencies": { + "@swc/helpers": ">=0.5.17" + }, + "peerDependenciesMeta": { + "@swc/helpers": { + "optional": true + } + } + }, + "node_modules/@swc/core-darwin-arm64": { + "version": "1.11.24", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.11.24.tgz", + "integrity": "sha512-dhtVj0PC1APOF4fl5qT2neGjRLgHAAYfiVP8poJelhzhB/318bO+QCFWAiimcDoyMgpCXOhTp757gnoJJrheWA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "peer": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-darwin-x64": { + "version": "1.11.24", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.11.24.tgz", + "integrity": "sha512-H/3cPs8uxcj2Fe3SoLlofN5JG6Ny5bl8DuZ6Yc2wr7gQFBmyBkbZEz+sPVgsID7IXuz7vTP95kMm1VL74SO5AQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "peer": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm-gnueabihf": { + "version": "1.11.24", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.11.24.tgz", + "integrity": "sha512-PHJgWEpCsLo/NGj+A2lXZ2mgGjsr96ULNW3+T3Bj2KTc8XtMUkE8tmY2Da20ItZOvPNC/69KroU7edyo1Flfbw==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-gnu": { + "version": "1.11.24", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.11.24.tgz", + "integrity": "sha512-C2FJb08+n5SD4CYWCTZx1uR88BN41ZieoHvI8A55hfVf2woT8+6ZiBzt74qW2g+ntZ535Jts5VwXAKdu41HpBg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-musl": { + "version": "1.11.24", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.11.24.tgz", + "integrity": "sha512-ypXLIdszRo0re7PNNaXN0+2lD454G8l9LPK/rbfRXnhLWDBPURxzKlLlU/YGd2zP98wPcVooMmegRSNOKfvErw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-gnu": { + "version": "1.11.24", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.11.24.tgz", + "integrity": "sha512-IM7d+STVZD48zxcgo69L0yYptfhaaE9cMZ+9OoMxirNafhKKXwoZuufol1+alEFKc+Wbwp+aUPe/DeWC/Lh3dg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-musl": { + "version": "1.11.24", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.11.24.tgz", + "integrity": "sha512-DZByJaMVzSfjQKKQn3cqSeqwy6lpMaQDQQ4HPlch9FWtDx/dLcpdIhxssqZXcR2rhaQVIaRQsCqwV6orSDGAGw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "peer": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-arm64-msvc": { + "version": "1.11.24", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.11.24.tgz", + "integrity": "sha512-Q64Ytn23y9aVDKN5iryFi8mRgyHw3/kyjTjT4qFCa8AEb5sGUuSj//AUZ6c0J7hQKMHlg9do5Etvoe61V98/JQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-ia32-msvc": { + "version": "1.11.24", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.11.24.tgz", + "integrity": "sha512-9pKLIisE/Hh2vJhGIPvSoTK4uBSPxNVyXHmOrtdDot4E1FUUI74Vi8tFdlwNbaj8/vusVnb8xPXsxF1uB0VgiQ==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-x64-msvc": { + "version": "1.11.24", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.11.24.tgz", + "integrity": "sha512-sybnXtOsdB+XvzVFlBVGgRHLqp3yRpHK7CrmpuDKszhj/QhmsaZzY/GHSeALlMtLup13M0gqbcQvsTNlAHTg3w==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "peer": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/counter": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==" + }, + "node_modules/@swc/jest": { + "version": "0.2.39", + "resolved": "https://registry.npmjs.org/@swc/jest/-/jest-0.2.39.tgz", + "integrity": "sha512-eyokjOwYd0Q8RnMHri+8/FS1HIrIUKK/sRrFp8c1dThUOfNeCWbLmBP1P5VsKdvmkd25JaH+OKYwEYiAYg9YAA==", + "license": "MIT", + "dependencies": { + "@jest/create-cache-key-function": "^30.0.0", + "@swc/counter": "^0.1.3", + "jsonc-parser": "^3.2.0" + }, + "engines": { + "npm": ">= 7.0.0" + }, + "peerDependencies": { + "@swc/core": "*" + } + }, + "node_modules/@swc/types": { + "version": "0.1.21", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.21.tgz", + "integrity": "sha512-2YEtj5HJVbKivud9N4bpPBAyZhj4S2Ipe5LkUG94alTpr7in/GU/EARgPAd3BwU+YOmFVJC2+kjqhGRi3r0ZpQ==", + "peer": true, + "dependencies": { + "@swc/counter": "^0.1.3" + } + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.0.tgz", + "integrity": "sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/async": { + "version": "3.2.25", + "resolved": "https://registry.npmjs.org/@types/async/-/async-3.2.25.tgz", + "integrity": "sha512-O6Th/DI18XjrL9TX8LO9F/g26qAz5vynmQqlXt/qLGrskvzCKXKc5/tATz3G2N6lM8eOf3M8/StB14FncAmocg==" + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.7.tgz", + "integrity": "sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/cli-progress": { + "version": "3.11.6", + "resolved": "https://registry.npmjs.org/@types/cli-progress/-/cli-progress-3.11.6.tgz", + "integrity": "sha512-cE3+jb9WRlu+uOSAugewNpITJDt1VF8dHOopPO4IABFc3SXYL5WE/+PTz/FCdZRRfIujiWW3n3aMbv1eIGVRWA==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz", + "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==" + }, + "node_modules/@types/fs-extra": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-11.0.4.tgz", + "integrity": "sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==", + "dependencies": { + "@types/jsonfile": "*", + "@types/node": "*" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jest": { + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-30.0.0.tgz", + "integrity": "sha512-XTYugzhuwqWjws0CVz8QpM36+T+Dz5mTEBKhNs/esGLnCIlGdRy+Dq78NRjd7ls7r8BC8ZRMOrKlkO1hU0JOwA==", + "license": "MIT", + "dependencies": { + "expect": "^30.0.0", + "pretty-format": "^30.0.0" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==" + }, + "node_modules/@types/jsonfile": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/@types/jsonfile/-/jsonfile-6.1.4.tgz", + "integrity": "sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-H3MHACvFUEiujabxhaI/ImO6gUrd8oOurg7LQtS7mbwIXA/cUqWrvBsaeJ23aZEPk1TAYkurjfMbSELfoCXlGA==", + "license": "MIT" + }, + "node_modules/@types/lodash.uniqueid": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/lodash.uniqueid/-/lodash.uniqueid-4.0.9.tgz", + "integrity": "sha512-SEzkJBS8t+tqAUnSmyqbuWqxKU+Z/Xu2cgPtD+Ik0l+M7L2q7So9VoN2rQ8H0mmL87lJ00ykxal8oB54QRet6g==", + "license": "MIT", + "dependencies": { + "@types/lodash": "*" + } + }, + "node_modules/@types/node": { + "version": "22.15.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.3.tgz", + "integrity": "sha512-lX7HFZeHf4QG/J7tBZqrCAXwz9J5RD56Y6MpP0eJkka8p+K0RY/yBTW7CYFJ4VGCclxqOLKmiGP5juQc6MKgcw==", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/node-cleanup": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@types/node-cleanup/-/node-cleanup-2.1.5.tgz", + "integrity": "sha512-+82RAk5uYiqiMoEv2fPeh03AL4pB5d3TL+Pf+hz31Mme6ECFI1kRlgmxYjdSlHzDbJ9yLorTnKi4Op5FA54kQQ==" + }, + "node_modules/@types/pako": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/pako/-/pako-2.0.4.tgz", + "integrity": "sha512-VWDCbrLeVXJM9fihYodcLiIv0ku+AlOa/TQ1SvYOaBuyrSKgEcro95LJyIsJ4vSo6BXIxOKxiJAat04CmST9Fw==" + }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "license": "MIT" + }, + "node_modules/@types/yargs": { + "version": "17.0.33", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", + "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "license": "MIT" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.38.0.tgz", + "integrity": "sha512-CPoznzpuAnIOl4nhj4tRr4gIPj5AfKgkiJmGQDaq+fQnRJTYlcBjbX3wbciGmpoPf8DREufuPRe1tNMZnGdanA==", + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.38.0", + "@typescript-eslint/type-utils": "8.38.0", + "@typescript-eslint/utils": "8.38.0", + "@typescript-eslint/visitor-keys": "8.38.0", + "graphemer": "^1.4.0", + "ignore": "^7.0.0", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.38.0", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.38.0.tgz", + "integrity": "sha512-Zhy8HCvBUEfBECzIl1PKqF4p11+d0aUJS1GeUiuqK9WmOug8YCmC4h4bjyBvMyAMI9sbRczmrYL5lKg/YMbrcQ==", + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.38.0", + "@typescript-eslint/types": "8.38.0", + "@typescript-eslint/typescript-estree": "8.38.0", + "@typescript-eslint/visitor-keys": "8.38.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.38.0.tgz", + "integrity": "sha512-dbK7Jvqcb8c9QfH01YB6pORpqX1mn5gDZc9n63Ak/+jD67oWXn3Gs0M6vddAN+eDXBCS5EmNWzbSxsn9SzFWWg==", + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.38.0", + "@typescript-eslint/types": "^8.38.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.38.0.tgz", + "integrity": "sha512-WJw3AVlFFcdT9Ri1xs/lg8LwDqgekWXWhH3iAF+1ZM+QPd7oxQ6jvtW/JPwzAScxitILUIFs0/AnQ/UWHzbATQ==", + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.38.0", + "@typescript-eslint/visitor-keys": "8.38.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.38.0.tgz", + "integrity": "sha512-Lum9RtSE3EroKk/bYns+sPOodqb2Fv50XOl/gMviMKNvanETUuUcC9ObRbzrJ4VSd2JalPqgSAavwrPiPvnAiQ==", + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.38.0.tgz", + "integrity": "sha512-c7jAvGEZVf0ao2z+nnz8BUaHZD09Agbh+DY7qvBQqLiz8uJzRgVPj5YvOh8I8uEiH8oIUGIfHzMwUcGVco/SJg==", + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.38.0", + "@typescript-eslint/typescript-estree": "8.38.0", + "@typescript-eslint/utils": "8.38.0", + "debug": "^4.3.4", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.38.0.tgz", + "integrity": "sha512-wzkUfX3plUqij4YwWaJyqhiPE5UCRVlFpKn1oCRn2O1bJ592XxWJj8ROQ3JD5MYXLORW84063z3tZTb/cs4Tyw==", + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.38.0.tgz", + "integrity": "sha512-fooELKcAKzxux6fA6pxOflpNS0jc+nOQEEOipXFNjSlBS6fqrJOVY/whSn70SScHrcJ2LDsxWrneFoWYSVfqhQ==", + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.38.0", + "@typescript-eslint/tsconfig-utils": "8.38.0", + "@typescript-eslint/types": "8.38.0", + "@typescript-eslint/visitor-keys": "8.38.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.38.0.tgz", + "integrity": "sha512-hHcMA86Hgt+ijJlrD8fX0j1j8w4C92zue/8LOPAFioIno+W0+L7KqE8QZKCcPGc/92Vs9x36w/4MPTJhqXdyvg==", + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.38.0", + "@typescript-eslint/types": "8.38.0", + "@typescript-eslint/typescript-estree": "8.38.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.38.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.38.0.tgz", + "integrity": "sha512-pWrTcoFNWuwHlA9CvlfSsGWs14JxfN1TH25zM5L7o0pRLhsoZkDnTsXfQRJBEWJoV5DL0jf+Z+sxiud+K0mq1g==", + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.38.0", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "license": "ISC" + }, + "node_modules/@unrs/resolver-binding-android-arm-eabi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz", + "integrity": "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-android-arm64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz", + "integrity": "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-arm64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz", + "integrity": "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz", + "integrity": "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-freebsd-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz", + "integrity": "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz", + "integrity": "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz", + "integrity": "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz", + "integrity": "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz", + "integrity": "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz", + "integrity": "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz", + "integrity": "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz", + "integrity": "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz", + "integrity": "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz", + "integrity": "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz", + "integrity": "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz", + "integrity": "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==", + "cpu": [ + "wasm32" + ], + "license": "MIT", + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^0.2.11" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz", + "integrity": "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz", + "integrity": "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-x64-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz", + "integrity": "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "engines": { + "node": ">= 14" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/axios": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.12.1.tgz", + "integrity": "sha512-Kn4kbSXpkFHCGE6rBFNwIv0GQs4AvDT80jlveJDKFxjbTYMUeB4QtsdPCv6H8Cm19Je7IU6VFtRl2zWZI0rudQ==", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.4", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/babel-jest": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-30.0.5.tgz", + "integrity": "sha512-mRijnKimhGDMsizTvBTWotwNpzrkHr+VvZUQBof2AufXKB8NXrL1W69TG20EvOz7aevx6FTJIaBuBkYxS8zolg==", + "license": "MIT", + "dependencies": { + "@jest/transform": "30.0.5", + "@types/babel__core": "^7.20.5", + "babel-plugin-istanbul": "^7.0.0", + "babel-preset-jest": "30.0.1", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "slash": "^3.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.11.0" + } + }, + "node_modules/babel-jest/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-7.0.0.tgz", + "integrity": "sha512-C5OzENSx/A+gt7t4VH1I2XsflxyPUmXRFPKBxt33xncdOmq7oROVM3bZv9Ysjjkv8OJYDMa+tKuKMvqU/H3xdw==", + "license": "BSD-3-Clause", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-instrument": "^6.0.2", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-30.0.1.tgz", + "integrity": "sha512-zTPME3pI50NsFW8ZBaVIOeAxzEY7XHlmWeXXu9srI+9kNfzCUTy8MFan46xOGZY8NZThMqq+e3qZUKsvXbasnQ==", + "license": "MIT", + "dependencies": { + "@babel/template": "^7.27.2", + "@babel/types": "^7.27.3", + "@types/babel__core": "^7.20.5" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz", + "integrity": "sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==", + "license": "MIT", + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" + }, + "peerDependencies": { + "@babel/core": "^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/babel-preset-jest": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-30.0.1.tgz", + "integrity": "sha512-+YHejD5iTWI46cZmcc/YtX4gaKBtdqCHCVfuVinizVpbmyjO3zYmeuyFdfA8duRqQZfgCAMlsfmkVbJ+e2MAJw==", + "license": "MIT", + "dependencies": { + "babel-plugin-jest-hoist": "30.0.1", + "babel-preset-current-node-syntax": "^1.1.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.11.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/before-after-hook": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-4.0.0.tgz", + "integrity": "sha512-q6tR3RPqIB1pMiTRMFcZwuG5T8vwp+vUvEG0vuI6B+Rikh5BfPp2fQ82c925FOs+b0lcFQ8CFrL+KbilfZFhOQ==", + "license": "Apache-2.0" + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.25.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.1.tgz", + "integrity": "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "caniuse-lite": "^1.0.30001726", + "electron-to-chromium": "^1.5.173", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "license": "Apache-2.0", + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "license": "MIT" + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001731", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001731.tgz", + "integrity": "sha512-lDdp2/wrOmTRWuoB5DpfNkC0rJDU8DqRa6nYL6HK6sytw70QMopt/NIc/9SM7ylItlBWfACXk0tEn37UWM/+mg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", + "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/chardet": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-2.1.0.tgz", + "integrity": "sha512-bNFETTG/pM5ryzQ9Ad0lJOTa6HWD/YsScAR3EnCPZRPlQh77JocYktSHOUHelyhm8IARL+o4c4F1bP5KVOjiRA==" + }, + "node_modules/ci-info": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.0.tgz", + "integrity": "sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cjs-module-lexer": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-2.1.0.tgz", + "integrity": "sha512-UX0OwmYRYQQetfrLEZeewIFFI+wSTofC+pMBLNuH3RUuu/xzG1oz84UCEDOSoQlN3fZ4+AzmV50ZYvGqkMh9yA==", + "license": "MIT" + }, + "node_modules/cli-progress": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/cli-progress/-/cli-progress-3.12.0.tgz", + "integrity": "sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A==", + "dependencies": { + "string-width": "^4.2.3" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cli-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", + "license": "ISC", + "engines": { + "node": ">= 12" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "license": "MIT", + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", + "license": "MIT" + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.0.tgz", + "integrity": "sha512-2uM9rYjPvyq39NwLRqaiLtWHyDC1FvryJDa2ATTVims5YAS4PupsEQsDvP14FqhFr0P49CYDugi59xaxJlTXRA==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/consola": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", + "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", + "engines": { + "node": "^14.18.0 || >=16.10.0" + } + }, + "node_modules/console-table-printer": { + "version": "2.14.6", + "resolved": "https://registry.npmjs.org/console-table-printer/-/console-table-printer-2.14.6.tgz", + "integrity": "sha512-MCBl5HNVaFuuHW6FGbL/4fB7N/ormCy+tQ+sxTrF6QtSbSNETvPuOVbkJBhzDgYhvjWGrTma4eYJa37ZuoQsPw==", + "license": "MIT", + "dependencies": { + "simple-wcswidth": "^1.0.1" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "license": "MIT" + }, + "node_modules/cross-env": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-10.0.0.tgz", + "integrity": "sha512-aU8qlEK/nHYtVuN4p7UQgAwVljzMg8hB4YK5ThRqD2l/ziSnryncPNn7bMLt5cFYsKVKBh8HqLqyCoTupEUu7Q==", + "license": "MIT", + "dependencies": { + "@epic-web/invariant": "^1.0.0", + "cross-spawn": "^7.0.6" + }, + "bin": { + "cross-env": "dist/bin/cross-env.js", + "cross-env-shell": "dist/bin/cross-env-shell.js" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/dayjs": { + "version": "1.11.18", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.18.tgz", + "integrity": "sha512-zFBQ7WFRvVRhKcWoUh+ZA1g2HVgUbsZm9sbddh8EC5iv93sui8DVVz1Npvz+r6meo9VKfa8NyLWBsQK1VvIKPA==" + }, + "node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/dedent": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.6.0.tgz", + "integrity": "sha512-F1Z+5UCFpmQUzJa11agbyPVMbpgT/qA3/SKyJ1jyBgm7dUcUEa8v9JwDkerSQXfakBwFljIxhOJqGkjUwZ9FSA==", + "license": "MIT", + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.192", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.192.tgz", + "integrity": "sha512-rP8Ez0w7UNw/9j5eSXCe10o1g/8B1P5SM90PCCMVkIRQn2R0LEHWz4Eh9RnxkniuDe1W0cTSOB3MLlkTGDcuCg==", + "license": "ISC" + }, + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.3.tgz", + "integrity": "sha512-qKA6Pvai73+M2FtftpNKRxJ78GIjmFXFxd/1DVBqGo/qNhLSfv+G12n9pNoWdytJC8U00TrViOwpjT0zgqQS8Q==", + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.3", + "@esbuild/android-arm": "0.25.3", + "@esbuild/android-arm64": "0.25.3", + "@esbuild/android-x64": "0.25.3", + "@esbuild/darwin-arm64": "0.25.3", + "@esbuild/darwin-x64": "0.25.3", + "@esbuild/freebsd-arm64": "0.25.3", + "@esbuild/freebsd-x64": "0.25.3", + "@esbuild/linux-arm": "0.25.3", + "@esbuild/linux-arm64": "0.25.3", + "@esbuild/linux-ia32": "0.25.3", + "@esbuild/linux-loong64": "0.25.3", + "@esbuild/linux-mips64el": "0.25.3", + "@esbuild/linux-ppc64": "0.25.3", + "@esbuild/linux-riscv64": "0.25.3", + "@esbuild/linux-s390x": "0.25.3", + "@esbuild/linux-x64": "0.25.3", + "@esbuild/netbsd-arm64": "0.25.3", + "@esbuild/netbsd-x64": "0.25.3", + "@esbuild/openbsd-arm64": "0.25.3", + "@esbuild/openbsd-x64": "0.25.3", + "@esbuild/sunos-x64": "0.25.3", + "@esbuild/win32-arm64": "0.25.3", + "@esbuild/win32-ia32": "0.25.3", + "@esbuild/win32-x64": "0.25.3" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.32.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.32.0.tgz", + "integrity": "sha512-LSehfdpgMeWcTZkWZVIJl+tkZ2nuSkyyB9C27MZqFWXuph7DvaowgcTvKqxvpLW1JZIk8PN7hFY3Rj9LQ7m7lg==", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.0", + "@eslint/config-helpers": "^0.3.0", + "@eslint/core": "^0.15.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.32.0", + "@eslint/plugin-kit": "^0.3.4", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/execa/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC" + }, + "node_modules/exit-x": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/exit-x/-/exit-x-0.2.2.tgz", + "integrity": "sha512-+I6B/IkJc1o/2tiURyz/ivu/O0nKNEArIUB5O7zBrlDVJr22SCLH3xTeEry428LvFhRzIA1g8izguxJ/gbNcVQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expect": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/expect/-/expect-30.0.5.tgz", + "integrity": "sha512-P0te2pt+hHI5qLJkIR+iMvS+lYUZml8rKKsohVHAGY+uClp9XVbdyYNJOIjSRpHVp8s8YqxJCiHUkSYZGr8rtQ==", + "license": "MIT", + "dependencies": { + "@jest/expect-utils": "30.0.5", + "@jest/get-type": "30.0.1", + "jest-matcher-utils": "30.0.5", + "jest-message-util": "30.0.5", + "jest-mock": "30.0.5", + "jest-util": "30.0.5" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/fast-content-type-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-3.0.0.tgz", + "integrity": "sha512-ZvLdcY8P+N8mGQJahJV5G4U88CSvT1rP8ApL6uETe88MBXrBHAkZlSEySdUlyztF7ccb+Znos3TFqaepHxdhBg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "MIT" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==" + }, + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "license": "Apache-2.0", + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==" + }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/form-data": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fs-extra": { + "version": "11.3.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.1.tgz", + "integrity": "sha512-eXvGGwZ5CL17ZSwHWd3bbgk7UUpF6IFHtP57NYYakPvHOs8GDgDe5KJI36jIJzDkJ6eJjuzRA8eBQb6SkKue0g==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-east-asian-width": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.3.1.tgz", + "integrity": "sha512-R1QfovbPsKmosqTnPoRFiJ7CF9MLRgb53ChvMZm+r4p76/+8yKDy17qLL2PKInORy2RkZZekuK0efYgmzTkXyQ==", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-tsconfig": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.0.tgz", + "integrity": "sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/glob": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.0.3.tgz", + "integrity": "sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA==", + "license": "ISC", + "dependencies": { + "foreground-child": "^3.3.1", + "jackspeak": "^4.1.1", + "minimatch": "^10.0.3", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^2.0.0" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.3.tgz", + "integrity": "sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw==", + "license": "ISC", + "dependencies": { + "@isaacs/brace-expansion": "^5.0.0" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/globals": { + "version": "16.3.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.3.0.tgz", + "integrity": "sha512-bqWEnJ1Nt3neqx2q5SFfGS8r/ahumIakg3HcwtNlrVlwXIeNumWn/c7Pn/wKzGhf6SaW6H6uWXLqC30STCMchQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "license": "MIT" + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "license": "Apache-2.0", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "license": "MIT", + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ip-address": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.0.1.tgz", + "integrity": "sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA==", + "engines": { + "node": ">= 12" + } + }, + "node_modules/iptv-playlist-parser": { + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/iptv-playlist-parser/-/iptv-playlist-parser-0.15.1.tgz", + "integrity": "sha512-Fsm0uGiKsxZxOFvrpO0YY8eZtZLA9yqre7ne+T5AN2xvMsxFF2yY84CbFF6CTMYm7S+/AUQ+hPVst+uo9dGEuA==", + "dependencies": { + "is-valid-path": "^0.1.1", + "validator": "^13.7.0" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "license": "MIT" + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-invalid-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-invalid-path/-/is-invalid-path-0.1.0.tgz", + "integrity": "sha512-aZMG0T3F34mTg4eTdszcGXx54oiZ4NtHSft3hWNJMGJXUUqdIj3cOZuHcU0nCWWcY3jd7yRe/3AEm3vSNTpBGQ==", + "dependencies": { + "is-glob": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-invalid-path/node_modules/is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha512-7Q+VbVafe6x2T+Tu6NcOf6sRklazEPmBoB3IWk3WdGZM2iGUwU/Oe3Wtq5lSEkDTTlpp8yx+5t4pzO/i9Ty1ww==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-invalid-path/node_modules/is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha512-a1dBeB19NXsf/E0+FHqkagizel/LQw2DjSQpvQrj3zT+jYPpaUCryPnrQajXKFLCMuf4I6FhRpaGtw4lPrG6Eg==", + "dependencies": { + "is-extglob": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-valid-path": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-valid-path/-/is-valid-path-0.1.1.tgz", + "integrity": "sha512-+kwPrVDu9Ms03L90Qaml+79+6DZHqHyRoANI6IsZJ/g8frhnfchDOBCa0RbQ6/kdHt5CS5OeIEyrYznNuVN+8A==", + "dependencies": { + "is-invalid-path": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "license": "BSD-3-Clause", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz", + "integrity": "sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==", + "license": "BSD-3-Clause", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.23", + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jackspeak": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.1.tgz", + "integrity": "sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest/-/jest-30.0.5.tgz", + "integrity": "sha512-y2mfcJywuTUkvLm2Lp1/pFX8kTgMO5yyQGq/Sk/n2mN7XWYp4JsCZ/QXW34M8YScgk8bPZlREH04f6blPnoHnQ==", + "license": "MIT", + "dependencies": { + "@jest/core": "30.0.5", + "@jest/types": "30.0.5", + "import-local": "^3.2.0", + "jest-cli": "30.0.5" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-changed-files": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-30.0.5.tgz", + "integrity": "sha512-bGl2Ntdx0eAwXuGpdLdVYVr5YQHnSZlQ0y9HVDu565lCUAe9sj6JOtBbMmBBikGIegne9piDDIOeiLVoqTkz4A==", + "license": "MIT", + "dependencies": { + "execa": "^5.1.1", + "jest-util": "30.0.5", + "p-limit": "^3.1.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-circus": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-30.0.5.tgz", + "integrity": "sha512-h/sjXEs4GS+NFFfqBDYT7y5Msfxh04EwWLhQi0F8kuWpe+J/7tICSlswU8qvBqumR3kFgHbfu7vU6qruWWBPug==", + "license": "MIT", + "dependencies": { + "@jest/environment": "30.0.5", + "@jest/expect": "30.0.5", + "@jest/test-result": "30.0.5", + "@jest/types": "30.0.5", + "@types/node": "*", + "chalk": "^4.1.2", + "co": "^4.6.0", + "dedent": "^1.6.0", + "is-generator-fn": "^2.1.0", + "jest-each": "30.0.5", + "jest-matcher-utils": "30.0.5", + "jest-message-util": "30.0.5", + "jest-runtime": "30.0.5", + "jest-snapshot": "30.0.5", + "jest-util": "30.0.5", + "p-limit": "^3.1.0", + "pretty-format": "30.0.5", + "pure-rand": "^7.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.6" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-circus/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-cli": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-30.0.5.tgz", + "integrity": "sha512-Sa45PGMkBZzF94HMrlX4kUyPOwUpdZasaliKN3mifvDmkhLYqLLg8HQTzn6gq7vJGahFYMQjXgyJWfYImKZzOw==", + "license": "MIT", + "dependencies": { + "@jest/core": "30.0.5", + "@jest/test-result": "30.0.5", + "@jest/types": "30.0.5", + "chalk": "^4.1.2", + "exit-x": "^0.2.2", + "import-local": "^3.2.0", + "jest-config": "30.0.5", + "jest-util": "30.0.5", + "jest-validate": "30.0.5", + "yargs": "^17.7.2" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-cli/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-config": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-30.0.5.tgz", + "integrity": "sha512-aIVh+JNOOpzUgzUnPn5FLtyVnqc3TQHVMupYtyeURSb//iLColiMIR8TxCIDKyx9ZgjKnXGucuW68hCxgbrwmA==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.27.4", + "@jest/get-type": "30.0.1", + "@jest/pattern": "30.0.1", + "@jest/test-sequencer": "30.0.5", + "@jest/types": "30.0.5", + "babel-jest": "30.0.5", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "deepmerge": "^4.3.1", + "glob": "^10.3.10", + "graceful-fs": "^4.2.11", + "jest-circus": "30.0.5", + "jest-docblock": "30.0.1", + "jest-environment-node": "30.0.5", + "jest-regex-util": "30.0.1", + "jest-resolve": "30.0.5", + "jest-runner": "30.0.5", + "jest-util": "30.0.5", + "jest-validate": "30.0.5", + "micromatch": "^4.0.8", + "parse-json": "^5.2.0", + "pretty-format": "30.0.5", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "esbuild-register": ">=3.4.0", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "esbuild-register": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-config/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/jest-config/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-config/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-config/node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jest-config/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "license": "ISC" + }, + "node_modules/jest-config/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-config/node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-diff": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-30.0.5.tgz", + "integrity": "sha512-1UIqE9PoEKaHcIKvq2vbibrCog4Y8G0zmOxgQUVEiTqwR5hJVMCoDsN1vFvI5JvwD37hjueZ1C4l2FyGnfpE0A==", + "license": "MIT", + "dependencies": { + "@jest/diff-sequences": "30.0.1", + "@jest/get-type": "30.0.1", + "chalk": "^4.1.2", + "pretty-format": "30.0.5" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-diff/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-docblock": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-30.0.1.tgz", + "integrity": "sha512-/vF78qn3DYphAaIc3jy4gA7XSAz167n9Bm/wn/1XhTLW7tTBIzXtCJpb/vcmc73NIIeeohCbdL94JasyXUZsGA==", + "license": "MIT", + "dependencies": { + "detect-newline": "^3.1.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-each": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-30.0.5.tgz", + "integrity": "sha512-dKjRsx1uZ96TVyejD3/aAWcNKy6ajMaN531CwWIsrazIqIoXI9TnnpPlkrEYku/8rkS3dh2rbH+kMOyiEIv0xQ==", + "license": "MIT", + "dependencies": { + "@jest/get-type": "30.0.1", + "@jest/types": "30.0.5", + "chalk": "^4.1.2", + "jest-util": "30.0.5", + "pretty-format": "30.0.5" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-each/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-environment-node": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-30.0.5.tgz", + "integrity": "sha512-ppYizXdLMSvciGsRsMEnv/5EFpvOdXBaXRBzFUDPWrsfmog4kYrOGWXarLllz6AXan6ZAA/kYokgDWuos1IKDA==", + "license": "MIT", + "dependencies": { + "@jest/environment": "30.0.5", + "@jest/fake-timers": "30.0.5", + "@jest/types": "30.0.5", + "@types/node": "*", + "jest-mock": "30.0.5", + "jest-util": "30.0.5", + "jest-validate": "30.0.5" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-expect-message": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/jest-expect-message/-/jest-expect-message-1.1.3.tgz", + "integrity": "sha512-bTK77T4P+zto+XepAX3low8XVQxDgaEqh3jSTQOG8qvPpD69LsIdyJTa+RmnJh3HNSzJng62/44RPPc7OIlFxg==" + }, + "node_modules/jest-haste-map": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-30.0.5.tgz", + "integrity": "sha512-dkmlWNlsTSR0nH3nRfW5BKbqHefLZv0/6LCccG0xFCTWcJu8TuEwG+5Cm75iBfjVoockmO6J35o5gxtFSn5xeg==", + "license": "MIT", + "dependencies": { + "@jest/types": "30.0.5", + "@types/node": "*", + "anymatch": "^3.1.3", + "fb-watchman": "^2.0.2", + "graceful-fs": "^4.2.11", + "jest-regex-util": "30.0.1", + "jest-util": "30.0.5", + "jest-worker": "30.0.5", + "micromatch": "^4.0.8", + "walker": "^1.0.8" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.3" + } + }, + "node_modules/jest-leak-detector": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-30.0.5.tgz", + "integrity": "sha512-3Uxr5uP8jmHMcsOtYMRB/zf1gXN3yUIc+iPorhNETG54gErFIiUhLvyY/OggYpSMOEYqsmRxmuU4ZOoX5jpRFg==", + "license": "MIT", + "dependencies": { + "@jest/get-type": "30.0.1", + "pretty-format": "30.0.5" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-30.0.5.tgz", + "integrity": "sha512-uQgGWt7GOrRLP1P7IwNWwK1WAQbq+m//ZY0yXygyfWp0rJlksMSLQAA4wYQC3b6wl3zfnchyTx+k3HZ5aPtCbQ==", + "license": "MIT", + "dependencies": { + "@jest/get-type": "30.0.1", + "chalk": "^4.1.2", + "jest-diff": "30.0.5", + "pretty-format": "30.0.5" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-matcher-utils/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-message-util": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-30.0.5.tgz", + "integrity": "sha512-NAiDOhsK3V7RU0Aa/HnrQo+E4JlbarbmI3q6Pi4KcxicdtjV82gcIUrejOtczChtVQR4kddu1E1EJlW6EN9IyA==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@jest/types": "30.0.5", + "@types/stack-utils": "^2.0.3", + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "micromatch": "^4.0.8", + "pretty-format": "30.0.5", + "slash": "^3.0.0", + "stack-utils": "^2.0.6" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-message-util/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-mock": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-30.0.5.tgz", + "integrity": "sha512-Od7TyasAAQX/6S+QCbN6vZoWOMwlTtzzGuxJku1GhGanAjz9y+QsQkpScDmETvdc9aSXyJ/Op4rhpMYBWW91wQ==", + "license": "MIT", + "dependencies": { + "@jest/types": "30.0.5", + "@types/node": "*", + "jest-util": "30.0.5" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "license": "MIT", + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-30.0.1.tgz", + "integrity": "sha512-jHEQgBXAgc+Gh4g0p3bCevgRCVRkB4VB70zhoAE48gxeSr1hfUOsM/C2WoJgVL7Eyg//hudYENbm3Ne+/dRVVA==", + "license": "MIT", + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-resolve": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-30.0.5.tgz", + "integrity": "sha512-d+DjBQ1tIhdz91B79mywH5yYu76bZuE96sSbxj8MkjWVx5WNdt1deEFRONVL4UkKLSrAbMkdhb24XN691yDRHg==", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.0.5", + "jest-pnp-resolver": "^1.2.3", + "jest-util": "30.0.5", + "jest-validate": "30.0.5", + "slash": "^3.0.0", + "unrs-resolver": "^1.7.11" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-30.0.5.tgz", + "integrity": "sha512-/xMvBR4MpwkrHW4ikZIWRttBBRZgWK4d6xt3xW1iRDSKt4tXzYkMkyPfBnSCgv96cpkrctfXs6gexeqMYqdEpw==", + "license": "MIT", + "dependencies": { + "jest-regex-util": "30.0.1", + "jest-snapshot": "30.0.5" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-resolve/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-runner": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-30.0.5.tgz", + "integrity": "sha512-JcCOucZmgp+YuGgLAXHNy7ualBx4wYSgJVWrYMRBnb79j9PD0Jxh0EHvR5Cx/r0Ce+ZBC4hCdz2AzFFLl9hCiw==", + "license": "MIT", + "dependencies": { + "@jest/console": "30.0.5", + "@jest/environment": "30.0.5", + "@jest/test-result": "30.0.5", + "@jest/transform": "30.0.5", + "@jest/types": "30.0.5", + "@types/node": "*", + "chalk": "^4.1.2", + "emittery": "^0.13.1", + "exit-x": "^0.2.2", + "graceful-fs": "^4.2.11", + "jest-docblock": "30.0.1", + "jest-environment-node": "30.0.5", + "jest-haste-map": "30.0.5", + "jest-leak-detector": "30.0.5", + "jest-message-util": "30.0.5", + "jest-resolve": "30.0.5", + "jest-runtime": "30.0.5", + "jest-util": "30.0.5", + "jest-watcher": "30.0.5", + "jest-worker": "30.0.5", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-runner/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-runtime": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-30.0.5.tgz", + "integrity": "sha512-7oySNDkqpe4xpX5PPiJTe5vEa+Ak/NnNz2bGYZrA1ftG3RL3EFlHaUkA1Cjx+R8IhK0Vg43RML5mJedGTPNz3A==", + "license": "MIT", + "dependencies": { + "@jest/environment": "30.0.5", + "@jest/fake-timers": "30.0.5", + "@jest/globals": "30.0.5", + "@jest/source-map": "30.0.1", + "@jest/test-result": "30.0.5", + "@jest/transform": "30.0.5", + "@jest/types": "30.0.5", + "@types/node": "*", + "chalk": "^4.1.2", + "cjs-module-lexer": "^2.1.0", + "collect-v8-coverage": "^1.0.2", + "glob": "^10.3.10", + "graceful-fs": "^4.2.11", + "jest-haste-map": "30.0.5", + "jest-message-util": "30.0.5", + "jest-mock": "30.0.5", + "jest-regex-util": "30.0.1", + "jest-resolve": "30.0.5", + "jest-snapshot": "30.0.5", + "jest-util": "30.0.5", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-runtime/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/jest-runtime/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-runtime/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-runtime/node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jest-runtime/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "license": "ISC" + }, + "node_modules/jest-runtime/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-runtime/node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jest-snapshot": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-30.0.5.tgz", + "integrity": "sha512-T00dWU/Ek3LqTp4+DcW6PraVxjk28WY5Ua/s+3zUKSERZSNyxTqhDXCWKG5p2HAJ+crVQ3WJ2P9YVHpj1tkW+g==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.27.4", + "@babel/generator": "^7.27.5", + "@babel/plugin-syntax-jsx": "^7.27.1", + "@babel/plugin-syntax-typescript": "^7.27.1", + "@babel/types": "^7.27.3", + "@jest/expect-utils": "30.0.5", + "@jest/get-type": "30.0.1", + "@jest/snapshot-utils": "30.0.5", + "@jest/transform": "30.0.5", + "@jest/types": "30.0.5", + "babel-preset-current-node-syntax": "^1.1.0", + "chalk": "^4.1.2", + "expect": "30.0.5", + "graceful-fs": "^4.2.11", + "jest-diff": "30.0.5", + "jest-matcher-utils": "30.0.5", + "jest-message-util": "30.0.5", + "jest-util": "30.0.5", + "pretty-format": "30.0.5", + "semver": "^7.7.2", + "synckit": "^0.11.8" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-util": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-30.0.5.tgz", + "integrity": "sha512-pvyPWssDZR0FlfMxCBoc0tvM8iUEskaRFALUtGQYzVEAqisAztmy+R8LnU14KT4XA0H/a5HMVTXat1jLne010g==", + "license": "MIT", + "dependencies": { + "@jest/types": "30.0.5", + "@types/node": "*", + "chalk": "^4.1.2", + "ci-info": "^4.2.0", + "graceful-fs": "^4.2.11", + "picomatch": "^4.0.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-util/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-util/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/jest-validate": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-30.0.5.tgz", + "integrity": "sha512-ouTm6VFHaS2boyl+k4u+Qip4TSH7Uld5tyD8psQ8abGgt2uYYB8VwVfAHWHjHc0NWmGGbwO5h0sCPOGHHevefw==", + "license": "MIT", + "dependencies": { + "@jest/get-type": "30.0.1", + "@jest/types": "30.0.5", + "camelcase": "^6.3.0", + "chalk": "^4.1.2", + "leven": "^3.1.0", + "pretty-format": "30.0.5" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-validate/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-watcher": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-30.0.5.tgz", + "integrity": "sha512-z9slj/0vOwBDBjN3L4z4ZYaA+pG56d6p3kTUhFRYGvXbXMWhXmb/FIxREZCD06DYUwDKKnj2T80+Pb71CQ0KEg==", + "license": "MIT", + "dependencies": { + "@jest/test-result": "30.0.5", + "@jest/types": "30.0.5", + "@types/node": "*", + "ansi-escapes": "^4.3.2", + "chalk": "^4.1.2", + "emittery": "^0.13.1", + "jest-util": "30.0.5", + "string-length": "^4.0.2" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-watcher/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-worker": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-30.0.5.tgz", + "integrity": "sha512-ojRXsWzEP16NdUuBw/4H/zkZdHOa7MMYCk4E430l+8fELeLg/mqmMlRhjL7UNZvQrDmnovWZV4DxX03fZF48fQ==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@ungap/structured-clone": "^1.3.0", + "jest-util": "30.0.5", + "merge-stream": "^2.0.0", + "supports-color": "^8.1.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonc-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", + "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==" + }, + "node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "license": "MIT" + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" + }, + "node_modules/lodash.uniqueid": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.uniqueid/-/lodash.uniqueid-4.0.1.tgz", + "integrity": "sha512-GQQWaIeGlL6DIIr06kj1j6sSmBxyNMwI8kaX9aKpHR/XsMTiaXDVPNPAkiboOTK9OJpTJF/dXT3xYoFQnj386Q==", + "license": "MIT" + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/m3u-linter": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/m3u-linter/-/m3u-linter-0.4.2.tgz", + "integrity": "sha512-KeUirh5JnGRuFDb+7tsc8Dkb+q/slco3hszKE7lwbmGKKo+QnSr7198e1ATYZ9HkY8sbvEQBuTj2hPsv9o3gGw==", + "dependencies": { + "chalk": "^4.1.1", + "commander": "^7.2.0", + "glob": "^11.0.0", + "is-valid-path": "^0.1.1" + }, + "bin": { + "m3u-linter": "bin/m3u-linter.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/m3u-linter/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/m3u-linter/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "license": "BSD-3-Clause", + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mediainfo.js": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/mediainfo.js/-/mediainfo.js-0.3.6.tgz", + "integrity": "sha512-3xVRlxwlVWIZV3z1q7pb8LzFOO7iKi/DXoRiFRZdOlrUEhPyJDaaRt0uK32yQJabArQicRBeq7cRxmdZlIBTyA==", + "dependencies": { + "yargs": "^18.0.0" + }, + "bin": { + "mediainfo.js": "dist/esm/cli.js" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/mediainfo.js/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/mediainfo.js/node_modules/cliui": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-9.0.1.tgz", + "integrity": "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==", + "dependencies": { + "string-width": "^7.2.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/mediainfo.js/node_modules/emoji-regex": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.5.0.tgz", + "integrity": "sha512-lb49vf1Xzfx080OKA0o6l8DQQpV+6Vg95zyCJX9VB/BqKYlhG7N4wgROUUHRA+ZPUefLnteQOad7z1kT2bV7bg==" + }, + "node_modules/mediainfo.js/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mediainfo.js/node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/mediainfo.js/node_modules/yargs": { + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-18.0.0.tgz", + "integrity": "sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==", + "dependencies": { + "cliui": "^9.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "string-width": "^7.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^22.0.0" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=23" + } + }, + "node_modules/mediainfo.js/node_modules/yargs-parser": { + "version": "22.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-22.0.0.tgz", + "integrity": "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==", + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=23" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "license": "MIT" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/mute-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-2.0.0.tgz", + "integrity": "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==", + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/napi-postinstall": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.2.tgz", + "integrity": "sha512-tWVJxJHmBWLy69PvO96TZMZDrzmw5KeiZBz3RHmiM2XZ9grBJ2WgMAFVVg25nqp3ZjTFUs2Ftw1JhscL3Teliw==", + "license": "MIT", + "bin": { + "napi-postinstall": "lib/cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/napi-postinstall" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" + }, + "node_modules/natural-orderby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/natural-orderby/-/natural-orderby-5.0.0.tgz", + "integrity": "sha512-kKHJhxwpR/Okycz4HhQKKlhWe4ASEfPgkSWNmKFHd7+ezuQlxkA5cM3+XkBPvm1gmHen3w53qsYAv+8GwRrBlg==", + "engines": { + "node": ">=18" + } + }, + "node_modules/node-cleanup": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/node-cleanup/-/node-cleanup-2.1.2.tgz", + "integrity": "sha512-qN8v/s2PAJwGUtr1/hYTpNKlD6Y9rc4p8KSmJXyGdYGZsDGKXrGThikLFP9OCHFeLeEpQzPwiAtdIvBLqm//Hw==" + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "license": "MIT" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-url": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.1.0.tgz", + "integrity": "sha512-X06Mfd/5aKsRHc0O0J5CUedwnPmnDtLF2+nq+KN9KSDlJHkPuh0JUviWjEWMe0SW/9TDdSLVPuk7L5gGTIA1/w==", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/object-treeify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/object-treeify/-/object-treeify-2.1.1.tgz", + "integrity": "sha512-ofXhazOvXTYWbbibExMiS+asaTbYG/ZWopVroXFFOdjmc8ehXMq9R2VUaTx/C3CnZkQbT52wAZT4DrBLK/nQfw==", + "engines": { + "node": ">= 12" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==" + }, + "node_modules/pako": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz", + "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==" + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz", + "integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.1.0.tgz", + "integrity": "sha512-QIXZUBJUx+2zHUdQujWejBkcD9+cs94tLn0+YL8UrCh+D5sCXZ4c7LaEH48pNwRY3MLDgqUFyhlCyjJPf1WP0A==", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "license": "MIT", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-dir/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/pretty-format": { + "version": "30.0.5", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.0.5.tgz", + "integrity": "sha512-D1tKtYvByrBkFLe2wHJl2bwMJIiT8rW+XA+TiataH79/FszLQMrpGEvzUVkzPau7OCO0Qnrhpe87PqtOAIB8Yw==", + "license": "MIT", + "dependencies": { + "@jest/schemas": "30.0.5", + "ansi-styles": "^5.2.0", + "react-is": "^18.3.1" + }, + "engines": { + "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/pure-rand": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-7.0.1.tgz", + "integrity": "sha512-oTUZM/NAZS8p7ANR3SHh30kXB+zK2r2BPcEn/awJIbOvq82WoMN4p62AWWp3Hhw50G0xMsw1mhIBLqHw64EcNQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT" + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "license": "MIT" + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "license": "MIT", + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-cwd/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/simple-wcswidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-wcswidth/-/simple-wcswidth-1.0.1.tgz", + "integrity": "sha512-xMO/8eNREtaROt7tJvWJqHBDTMFN4eiQ5I4JRMuilwfnFcV5W9u7RUkueNkdw0jPqGMX36iCywelS5yilTuOxg==" + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.8.7", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz", + "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==", + "dependencies": { + "ip-address": "^10.0.1", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", + "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "socks": "^2.8.3" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "license": "MIT", + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-length/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-length/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/synckit": { + "version": "0.11.11", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.11.tgz", + "integrity": "sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==", + "license": "MIT", + "dependencies": { + "@pkgr/core": "^0.2.9" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/synckit" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "license": "ISC", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/test-exclude/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/timer-node": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/timer-node/-/timer-node-5.0.9.tgz", + "integrity": "sha512-zXxCE/5/YDi0hY9pygqgRqjRbrFRzigYxOudG0I3syaqAAmX9/w9sxex1bNFCN6c1S66RwPtEIJv65dN+1psew==" + }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "license": "BSD-3-Clause" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-api-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", + "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/tsx": { + "version": "4.20.3", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.20.3.tgz", + "integrity": "sha512-qjbnuR9Tr+FJOMBqJCW5ehvIo/buZq7vH7qD7JziU98h6l3qGy0a/yPFjwO+y0/T7GFpNgNAvEcPPVfyT8rrPQ==", + "license": "MIT", + "dependencies": { + "esbuild": "~0.25.0", + "get-tsconfig": "^4.7.5" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "5.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", + "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==" + }, + "node_modules/universal-user-agent": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.3.tgz", + "integrity": "sha512-TmnEAEAsBJVZM/AADELsK76llnwcf9vMKuPz8JflO1frO8Lchitr0fNaN9d+Ap0BjKtqWqd/J17qeDnXh8CL2A==", + "license": "ISC" + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unrs-resolver": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz", + "integrity": "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "napi-postinstall": "^0.3.0" + }, + "funding": { + "url": "https://opencollective.com/unrs-resolver" + }, + "optionalDependencies": { + "@unrs/resolver-binding-android-arm-eabi": "1.11.1", + "@unrs/resolver-binding-android-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-x64": "1.11.1", + "@unrs/resolver-binding-freebsd-x64": "1.11.1", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", + "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-musl": "1.11.1", + "@unrs/resolver-binding-wasm32-wasi": "1.11.1", + "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", + "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1", + "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/v8-to-istanbul": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", + "license": "ISC", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/validator": { + "version": "13.15.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.15.0.tgz", + "integrity": "sha512-36B2ryl4+oL5QxZ3AzD0t5SsMNGvTtQHpjgFO5tbNxfXbMFkY822ktCDe1MnlqV3301QQI9SLHDNJokDI+Z9pA==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "license": "Apache-2.0", + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/write-file-atomic": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "license": "ISC" + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yoctocolors-cjs": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.2.tgz", + "integrity": "sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/package.json b/package.json index 276eb517f9..3fe38c50db 100644 --- a/package.json +++ b/package.json @@ -1,80 +1,84 @@ -{ - "name": "iptv", - "scripts": { - "act:check": "act pull_request -W .github/workflows/check.yml", - "act:format": "act workflow_dispatch -W .github/workflows/format.yml", - "act:update": "act workflow_dispatch -W .github/workflows/update.yml", - "api:load": "tsx scripts/commands/api/load.ts", - "api:generate": "tsx scripts/commands/api/generate.ts", - "api:deploy": "npx gh-pages-clean && npx gh-pages -a -m \"Deploy to iptv-org/api\" -d .api -r https://$GITHUB_TOKEN@github.com/iptv-org/api.git", - "playlist:format": "tsx scripts/commands/playlist/format.ts", - "playlist:update": "tsx scripts/commands/playlist/update.ts", - "playlist:generate": "tsx scripts/commands/playlist/generate.ts", - "playlist:validate": "tsx scripts/commands/playlist/validate.ts", - "playlist:lint": "npx m3u-linter -c m3u-linter.json", - "playlist:test": "tsx scripts/commands/playlist/test.ts", - "playlist:edit": "tsx scripts/commands/playlist/edit.ts", - "playlist:deploy": "npx gh-pages-clean && npx gh-pages -m \"Deploy to GitHub Pages\" -d .gh-pages -r https://$GITHUB_TOKEN@github.com/iptv-org/iptv.git", - "readme:update": "tsx scripts/commands/readme/update.ts", - "report:create": "tsx scripts/commands/report/create.ts", - "check": "npm run playlist:lint && npm run playlist:validate", - "format": "npm run playlist:format", - "update": "npm run playlist:generate && npm run api:generate && npm run readme:update", - "deploy": "npm run playlist:deploy && npm run api:deploy", - "lint": "npx eslint \"scripts/**/*.{ts,js}\" \"tests/**/*.{ts,js}\"", - "test": "jest --runInBand", - "postinstall": "npm run api:load" - }, - "jest": { - "transform": { - "^.+\\.ts$": "@swc/jest" - }, - "testRegex": "tests/(.*?/)?.*test.ts$", - "setupFilesAfterEnv": [ - "jest-expect-message" - ] - }, - "author": "Arhey", - "private": true, - "license": "MIT", - "dependencies": { - "@alex_neo/jest-expect-message": "^1.0.5", - "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "^9.32.0", - "@freearhey/core": "^0.10.2", - "@freearhey/search-js": "^0.1.2", - "@inquirer/prompts": "^7.8.0", - "@octokit/core": "^7.0.3", - "@octokit/plugin-paginate-rest": "^13.1.1", - "@octokit/plugin-rest-endpoint-methods": "^16.0.0", - "@octokit/types": "^14.1.0", - "@stylistic/eslint-plugin": "^5.2.2", - "@swc/jest": "^0.2.39", - "@types/async": "^3.2.25", - "@types/cli-progress": "^3.11.6", - "@types/fs-extra": "^11.0.4", - "@types/jest": "^30.0.0", - "@types/lodash.uniqueid": "^4.0.9", - "@typescript-eslint/eslint-plugin": "^8.38.0", - "@typescript-eslint/parser": "^8.38.0", - "async-es": "^3.2.6", - "axios": "^1.11.0", - "chalk": "^5.4.1", - "cli-progress": "^3.12.0", - "commander": "^14.0.0", - "console-table-printer": "^2.14.6", - "cross-env": "^10.0.0", - "eslint": "^9.32.0", - "glob": "^11.0.3", - "globals": "^16.3.0", - "iptv-playlist-parser": "^0.15.0", - "jest": "^30.0.5", - "jest-expect-message": "^1.1.3", - "lodash.uniqueid": "^4.0.1", - "m3u-linter": "^0.4.2", - "mediainfo.js": "^0.3.6", - "node-cleanup": "^2.1.2", - "socks-proxy-agent": "^8.0.5", - "tsx": "^4.20.3" - } -} +{ + "name": "iptv", + "scripts": { + "act:check": "act pull_request -W .github/workflows/check.yml -s GITHUB_TOKEN=\"$(gh auth token)\"", + "act:format": "act workflow_dispatch -W .github/workflows/format.yml -s GITHUB_TOKEN=\"$(gh auth token)\"", + "act:update": "act workflow_dispatch -W .github/workflows/update.yml -s GITHUB_TOKEN=\"$(gh auth token)\"", + "api:load": "tsx scripts/commands/api/load.ts", + "api:generate": "tsx scripts/commands/api/generate.ts", + "api:deploy": "npx gh-pages-clean && npx gh-pages -a -m \"Deploy to iptv-org/api\" -d .api -r https://$GITHUB_TOKEN@github.com/iptv-org/api.git", + "playlist:format": "tsx scripts/commands/playlist/format.ts", + "playlist:update": "tsx scripts/commands/playlist/update.ts", + "playlist:generate": "tsx scripts/commands/playlist/generate.ts", + "playlist:validate": "tsx scripts/commands/playlist/validate.ts", + "playlist:lint": "npx m3u-linter -c m3u-linter.json", + "playlist:test": "tsx scripts/commands/playlist/test.ts", + "playlist:edit": "tsx scripts/commands/playlist/edit.ts", + "playlist:deploy": "npx gh-pages-clean && npx gh-pages -m \"Deploy to GitHub Pages\" -d .gh-pages -r https://$GITHUB_TOKEN@github.com/iptv-org/iptv.git", + "readme:update": "tsx scripts/commands/readme/update.ts", + "report:create": "tsx scripts/commands/report/create.ts", + "check": "npm run playlist:lint && npm run playlist:validate", + "format": "npm run playlist:format", + "update": "npm run playlist:generate && npm run api:generate && npm run readme:update", + "deploy": "npm run playlist:deploy && npm run api:deploy", + "lint": "npx eslint \"scripts/**/*.{ts,js}\" \"tests/**/*.{ts,js}\"", + "test": "jest --runInBand", + "postinstall": "npm run api:load" + }, + "jest": { + "transform": { + "^.+\\.ts$": "@swc/jest" + }, + "testRegex": "tests/(.*?/)?.*test.ts$", + "setupFilesAfterEnv": [ + "jest-expect-message" + ] + }, + "author": "Arhey", + "private": true, + "license": "MIT", + "dependencies": { + "@alex_neo/jest-expect-message": "^1.0.5", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "^9.32.0", + "@freearhey/core": "^0.14.3", + "@freearhey/search-js": "^0.1.2", + "@freearhey/storage-js": "^0.1.0", + "@inquirer/prompts": "^7.8.0", + "@iptv-org/sdk": "^1.0.2", + "@octokit/core": "^7.0.3", + "@octokit/plugin-paginate-rest": "^13.1.1", + "@octokit/plugin-rest-endpoint-methods": "^16.0.0", + "@octokit/types": "^14.1.0", + "@stylistic/eslint-plugin": "^5.2.2", + "@swc/jest": "^0.2.39", + "@types/async": "^3.2.25", + "@types/cli-progress": "^3.11.6", + "@types/fs-extra": "^11.0.4", + "@types/jest": "^30.0.0", + "@types/lodash.uniqueid": "^4.0.9", + "@types/node-cleanup": "^2.1.5", + "@typescript-eslint/eslint-plugin": "^8.38.0", + "@typescript-eslint/parser": "^8.38.0", + "async": "^3.2.6", + "axios": "^1.11.0", + "chalk": "^5.4.1", + "cli-progress": "^3.12.0", + "commander": "^14.0.0", + "console-table-printer": "^2.14.6", + "cross-env": "^10.0.0", + "eslint": "^9.32.0", + "glob": "^11.0.3", + "globals": "^16.3.0", + "iptv-playlist-parser": "^0.15.1", + "jest": "^30.0.5", + "jest-expect-message": "^1.1.3", + "lodash.uniqueid": "^4.0.1", + "m3u-linter": "^0.4.2", + "mediainfo.js": "^0.3.6", + "node-cleanup": "^2.1.2", + "normalize-url": "^8.1.0", + "socks-proxy-agent": "^8.0.5", + "tsx": "^4.20.3" + } +} diff --git a/scripts/api.ts b/scripts/api.ts new file mode 100644 index 0000000000..a4649d427f --- /dev/null +++ b/scripts/api.ts @@ -0,0 +1,151 @@ +import { Collection, Dictionary } from '@freearhey/core' +import { DATA_DIR } from './constants' +import cliProgress from 'cli-progress' +import * as sdk from '@iptv-org/sdk' + +const data = { + categoriesKeyById: new Dictionary(), + countriesKeyByCode: new Dictionary(), + subdivisionsKeyByCode: new Dictionary(), + citiesKeyByCode: new Dictionary(), + regionsKeyByCode: new Dictionary(), + languagesKeyByCode: new Dictionary(), + channelsKeyById: new Dictionary(), + feedsKeyByStreamId: new Dictionary(), + feedsGroupedByChannel: new Dictionary(), + blocklistRecordsGroupedByChannel: new Dictionary(), + categories: new Collection(), + countries: new Collection(), + subdivisions: new Collection(), + cities: new Collection(), + regions: new Collection() +} + +let searchIndex + +async function loadData() { + const dataManager = new sdk.DataManager({ dataDir: DATA_DIR }) + await dataManager.loadFromDisk() + dataManager.processData() + + const { + channels, + feeds, + categories, + languages, + countries, + subdivisions, + cities, + regions, + blocklist + } = dataManager.getProcessedData() + + searchIndex = sdk.SearchEngine.createIndex(channels) + + data.categoriesKeyById = categories.keyBy((category: sdk.Models.Category) => category.id) + data.countriesKeyByCode = countries.keyBy((country: sdk.Models.Country) => country.code) + data.subdivisionsKeyByCode = subdivisions.keyBy( + (subdivision: sdk.Models.Subdivision) => subdivision.code + ) + data.citiesKeyByCode = cities.keyBy((city: sdk.Models.City) => city.code) + data.regionsKeyByCode = regions.keyBy((region: sdk.Models.Region) => region.code) + data.languagesKeyByCode = languages.keyBy((language: sdk.Models.Language) => language.code) + data.channelsKeyById = channels.keyBy((channel: sdk.Models.Channel) => channel.id) + data.feedsKeyByStreamId = feeds.keyBy((feed: sdk.Models.Feed) => feed.getStreamId()) + data.feedsGroupedByChannel = feeds.groupBy((feed: sdk.Models.Feed) => feed.channel) + data.blocklistRecordsGroupedByChannel = blocklist.groupBy( + (blocklistRecord: sdk.Models.BlocklistRecord) => blocklistRecord.channel + ) + data.categories = categories + data.countries = countries + data.subdivisions = subdivisions + data.cities = cities + data.regions = regions +} + +async function downloadData() { + function formatBytes(bytes: number) { + if (bytes === 0) return '0 B' + const k = 1024 + const sizes = ['B', 'KB', 'MB', 'GB'] + const i = Math.floor(Math.log(bytes) / Math.log(k)) + return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i] + } + + const files = [ + 'blocklist', + 'categories', + 'channels', + 'cities', + 'countries', + 'feeds', + 'guides', + 'languages', + 'logos', + 'regions', + 'streams', + 'subdivisions', + 'timezones' + ] + + const multiBar = new cliProgress.MultiBar({ + stopOnComplete: true, + hideCursor: true, + forceRedraw: true, + barsize: 36, + format(options, params, payload) { + const filename = payload.filename.padEnd(18, ' ') + const barsize = options.barsize || 40 + const percent = (params.progress * 100).toFixed(2) + const speed = payload.speed ? formatBytes(payload.speed) + '/s' : 'N/A' + const total = formatBytes(params.total) + const completeSize = Math.round(params.progress * barsize) + const incompleteSize = barsize - completeSize + const bar = + options.barCompleteString && options.barIncompleteString + ? options.barCompleteString.substr(0, completeSize) + + options.barGlue + + options.barIncompleteString.substr(0, incompleteSize) + : '-'.repeat(barsize) + + return `${filename} [${bar}] ${percent}% | ETA: ${params.eta}s | ${total} | ${speed}` + } + }) + + const dataManager = new sdk.DataManager({ dataDir: DATA_DIR }) + + const requests: Promise[] = [] + for (const basename of files) { + const filename = `${basename}.json` + const progressBar = multiBar.create(0, 0, { filename }) + const request = dataManager.downloadFileToDisk(basename, { + onDownloadProgress({ total, loaded, rate }) { + if (total) progressBar.setTotal(total) + progressBar.update(loaded, { speed: rate }) + } + }) + + requests.push(request) + } + + await Promise.allSettled(requests).catch(console.error) +} + +function searchChannels(query: string): Collection { + if (!searchIndex) return new Collection() + + const results = searchIndex.search(query) + + const channels = new Collection() + + new Collection(results).forEach( + (item: sdk.Types.ChannelSearchableData) => { + const channel = data.channelsKeyById.get(item.id) + if (channel) channels.add(channel) + } + ) + + return channels +} + +export { data, loadData, downloadData, searchChannels } diff --git a/scripts/commands/api/generate.ts b/scripts/commands/api/generate.ts index 14967e87f5..71c00a6f2e 100644 --- a/scripts/commands/api/generate.ts +++ b/scripts/commands/api/generate.ts @@ -1,39 +1,31 @@ -import { DataLoader, DataProcessor, PlaylistParser } from '../../core' -import type { DataProcessorData } from '../../types/dataProcessor' -import { API_DIR, STREAMS_DIR, DATA_DIR } from '../../constants' -import type { DataLoaderData } from '../../types/dataLoader' -import { Logger, Storage } from '@freearhey/core' -import { Stream } from '../../models' - -async function main() { - const logger = new Logger() - - logger.info('loading data from api...') - const processor = new DataProcessor() - const dataStorage = new Storage(DATA_DIR) - const dataLoader = new DataLoader({ storage: dataStorage }) - const data: DataLoaderData = await dataLoader.load() - const { channelsKeyById, feedsGroupedByChannelId, logosGroupedByStreamId }: DataProcessorData = - processor.process(data) - - logger.info('loading streams...') - const streamsStorage = new Storage(STREAMS_DIR) - const parser = new PlaylistParser({ - storage: streamsStorage, - channelsKeyById, - logosGroupedByStreamId, - feedsGroupedByChannelId - }) - const files = await streamsStorage.list('**/*.m3u') - let streams = await parser.parse(files) - streams = streams - .orderBy((stream: Stream) => stream.getId()) - .map((stream: Stream) => stream.toJSON()) - logger.info(`found ${streams.count()} streams`) - - logger.info('saving to .api/streams.json...') - const apiStorage = new Storage(API_DIR) - await apiStorage.save('streams.json', streams.toJSON()) -} - -main() +import { API_DIR, STREAMS_DIR } from '../../constants' +import { Storage } from '@freearhey/storage-js' +import { PlaylistParser } from '../../core' +import { Logger } from '@freearhey/core' +import { Stream } from '../../models' +import { loadData } from '../../api' + +async function main() { + const logger = new Logger() + + logger.info('loading data from api...') + await loadData() + + logger.info('loading streams...') + const streamsStorage = new Storage(STREAMS_DIR) + const parser = new PlaylistParser({ + storage: streamsStorage + }) + const files = await streamsStorage.list('**/*.m3u') + const parsed = await parser.parse(files) + const _streams = parsed + .sortBy((stream: Stream) => stream.getId()) + .map((stream: Stream) => stream.toObject()) + logger.info(`found ${_streams.count()} streams`) + + logger.info('saving to .api/streams.json...') + const apiStorage = new Storage(API_DIR) + await apiStorage.save('streams.json', _streams.toJSON()) +} + +main() diff --git a/scripts/commands/api/load.ts b/scripts/commands/api/load.ts index 39cf0a2e8b..42919ffd8d 100644 --- a/scripts/commands/api/load.ts +++ b/scripts/commands/api/load.ts @@ -1,26 +1,7 @@ -import { DATA_DIR } from '../../constants' -import { Storage } from '@freearhey/core' -import { DataLoader } from '../../core' - -async function main() { - const storage = new Storage(DATA_DIR) - const loader = new DataLoader({ storage }) - - await Promise.all([ - loader.download('blocklist.json'), - loader.download('categories.json'), - loader.download('channels.json'), - loader.download('countries.json'), - loader.download('languages.json'), - loader.download('regions.json'), - loader.download('subdivisions.json'), - loader.download('feeds.json'), - loader.download('logos.json'), - loader.download('timezones.json'), - loader.download('guides.json'), - loader.download('streams.json'), - loader.download('cities.json') - ]) -} - -main() +import { downloadData } from '../../api' + +async function main() { + await downloadData() +} + +main() diff --git a/scripts/commands/playlist/edit.ts b/scripts/commands/playlist/edit.ts index c58be822a3..d8719cab32 100644 --- a/scripts/commands/playlist/edit.ts +++ b/scripts/commands/playlist/edit.ts @@ -1,217 +1,190 @@ -import { Storage, Collection, Logger, Dictionary } from '@freearhey/core' -import { DataLoader, DataProcessor, PlaylistParser } from '../../core' -import type { ChannelSearchableData } from '../../types/channel' -import { Channel, Feed, Playlist, Stream } from '../../models' -import { DataProcessorData } from '../../types/dataProcessor' -import { DataLoaderData } from '../../types/dataLoader' -import { select, input } from '@inquirer/prompts' -import { DATA_DIR } from '../../constants' -import nodeCleanup from 'node-cleanup' -import sjs from '@freearhey/search-js' -import { Command } from 'commander' -import readline from 'readline' - -type ChoiceValue = { type: string; value?: Feed | Channel } -type Choice = { name: string; short?: string; value: ChoiceValue; default?: boolean } - -if (process.platform === 'win32') { - readline - .createInterface({ - input: process.stdin, - output: process.stdout - }) - .on('SIGINT', function () { - process.emit('SIGINT') - }) -} - -const program = new Command() - -program.argument('', 'Path to *.channels.xml file to edit').parse(process.argv) - -const filepath = program.args[0] -const logger = new Logger() -const storage = new Storage() -let parsedStreams = new Collection() - -main(filepath) -nodeCleanup(() => { - save(filepath) -}) - -export default async function main(filepath: string) { - if (!(await storage.exists(filepath))) { - throw new Error(`File "${filepath}" does not exists`) - } - - logger.info('loading data from api...') - const processor = new DataProcessor() - const dataStorage = new Storage(DATA_DIR) - const loader = new DataLoader({ storage: dataStorage }) - const data: DataLoaderData = await loader.load() - const { - channels, - channelsKeyById, - feedsGroupedByChannelId, - logosGroupedByStreamId - }: DataProcessorData = processor.process(data) - - logger.info('loading streams...') - const parser = new PlaylistParser({ - storage, - feedsGroupedByChannelId, - logosGroupedByStreamId, - channelsKeyById - }) - parsedStreams = await parser.parseFile(filepath) - const streamsWithoutId = parsedStreams.filter((stream: Stream) => !stream.id) - - logger.info( - `found ${parsedStreams.count()} streams (including ${streamsWithoutId.count()} without ID)` - ) - - logger.info('creating search index...') - const items = channels.map((channel: Channel) => channel.getSearchable()).all() - const searchIndex = sjs.createIndex(items, { - searchable: ['name', 'altNames', 'guideNames', 'streamTitles', 'feedFullNames'] - }) - - logger.info('starting...\n') - - for (const stream of streamsWithoutId.all()) { - try { - stream.id = await selectChannel(stream, searchIndex, feedsGroupedByChannelId, channelsKeyById) - } catch (err) { - logger.info(err.message) - break - } - } - - streamsWithoutId.forEach((stream: Stream) => { - if (stream.id === '-') { - stream.id = '' - } - }) -} - -async function selectChannel( - stream: Stream, - searchIndex, - feedsGroupedByChannelId: Dictionary, - channelsKeyById: Dictionary -): Promise { - const query = escapeRegex(stream.getTitle()) - const similarChannels = searchIndex - .search(query) - .map((item: ChannelSearchableData) => channelsKeyById.get(item.id)) - - const url = stream.url.length > 50 ? stream.url.slice(0, 50) + '...' : stream.url - - const selected: ChoiceValue = await select({ - message: `Select channel ID for "${stream.title}" (${url}):`, - choices: getChannelChoises(new Collection(similarChannels)), - pageSize: 10 - }) - - switch (selected.type) { - case 'skip': - return '-' - case 'type': { - const typedChannelId = await input({ message: ' Channel ID:' }) - if (!typedChannelId) return '' - const selectedFeedId = await selectFeed(typedChannelId, feedsGroupedByChannelId) - if (selectedFeedId === '-') return typedChannelId - return [typedChannelId, selectedFeedId].join('@') - } - case 'channel': { - const selectedChannel = selected.value - if (!selectedChannel) return '' - const selectedFeedId = await selectFeed(selectedChannel.id, feedsGroupedByChannelId) - if (selectedFeedId === '-') return selectedChannel.id - return [selectedChannel.id, selectedFeedId].join('@') - } - } - - return '' -} - -async function selectFeed(channelId: string, feedsGroupedByChannelId: Dictionary): Promise { - const channelFeeds = new Collection(feedsGroupedByChannelId.get(channelId)) - const choices = getFeedChoises(channelFeeds) - - const selected: ChoiceValue = await select({ - message: `Select feed ID for "${channelId}":`, - choices, - pageSize: 10 - }) - - switch (selected.type) { - case 'skip': - return '-' - case 'type': - return await input({ message: ' Feed ID:', default: 'SD' }) - 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 = new Collection([channel.name, ...channel.altNames.all()]).uniq().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 - }, - default: feed.isMain, - name, - short: feed.id - }) - }) - - choises.push({ name: 'Type...', value: { type: 'type' } }) - choises.push({ name: 'Skip', value: { type: 'skip' } }) - - return choises -} - -function save(filepath: string) { - if (!storage.existsSync(filepath)) return - const playlist = new Playlist(parsedStreams) - storage.saveSync(filepath, playlist.toString()) - logger.info(`\nFile '${filepath}' successfully saved`) -} - -function escapeRegex(string: string) { - return string.replace(/[/\-\\^$*+?.()|[\]{}]/g, '\\$&') -} +import { loadData, data, searchChannels } from '../../api' +import { Collection, Logger } from '@freearhey/core' +import { select, input } from '@inquirer/prompts' +import { Playlist, Stream } from '../../models' +import { Storage } from '@freearhey/storage-js' +import { PlaylistParser } from '../../core' +import nodeCleanup from 'node-cleanup' +import * as sdk from '@iptv-org/sdk' +import { truncate } from '../../utils' +import { Command } from 'commander' +import readline from 'readline' + +type ChoiceValue = { type: string; value?: sdk.Models.Feed | sdk.Models.Channel } +type Choice = { name: string; short?: string; value: ChoiceValue; default?: boolean } + +if (process.platform === 'win32') { + readline + .createInterface({ + input: process.stdin, + output: process.stdout + }) + .on('SIGINT', function () { + process.emit('SIGINT') + }) +} + +const program = new Command() + +program.argument('', 'Path to *.channels.xml file to edit').parse(process.argv) + +const filepath = program.args[0] +const logger = new Logger() +const storage = new Storage() +let parsedStreams = new Collection() + +main(filepath) +nodeCleanup(() => { + save(filepath) +}) + +export default async function main(filepath: string) { + if (!(await storage.exists(filepath))) { + throw new Error(`File "${filepath}" does not exists`) + } + + logger.info('loading data from api...') + await loadData() + + logger.info('loading streams...') + const parser = new PlaylistParser({ + storage + }) + parsedStreams = await parser.parseFile(filepath) + const streamsWithoutId = parsedStreams.filter((stream: Stream) => !stream.tvgId) + + logger.info( + `found ${parsedStreams.count()} streams (including ${streamsWithoutId.count()} without ID)` + ) + + logger.info('starting...\n') + + for (const stream of streamsWithoutId.all()) { + try { + stream.tvgId = await selectChannel(stream) + } catch (err) { + logger.info(err.message) + break + } + } + + streamsWithoutId.forEach((stream: Stream) => { + if (stream.channel === '-') { + stream.channel = '' + } + }) +} + +async function selectChannel(stream: Stream): Promise { + const query = escapeRegex(stream.title) + const similarChannels = searchChannels(query) + const url = truncate(stream.url, 50) + + const selected: ChoiceValue = await select({ + message: `Select channel ID for "${stream.title}" (${url}):`, + choices: getChannelChoises(similarChannels), + pageSize: 10 + }) + + switch (selected.type) { + case 'skip': + return '-' + case 'type': { + const typedChannelId = await input({ message: ' Channel ID:' }) + if (!typedChannelId) return '' + const selectedFeedId = await selectFeed(typedChannelId) + if (selectedFeedId === '-') return typedChannelId + return [typedChannelId, selectedFeedId].join('@') + } + case 'channel': { + const selectedChannel = selected.value + if (!selectedChannel) return '' + const selectedFeedId = await selectFeed(selectedChannel.id) + if (selectedFeedId === '-') return selectedChannel.id + return [selectedChannel.id, selectedFeedId].join('@') + } + } + + return '' +} + +async function selectFeed(channelId: string): Promise { + const channelFeeds = new Collection(data.feedsGroupedByChannel.get(channelId)) + const choices = getFeedChoises(channelFeeds) + + const selected: ChoiceValue = await select({ + message: `Select feed ID for "${channelId}":`, + choices, + pageSize: 10 + }) + + switch (selected.type) { + case 'skip': + return '-' + case 'type': + return await input({ message: ' Feed ID:', default: 'SD' }) + case 'feed': + const selectedFeed = selected.value + if (!selectedFeed) return '' + return selectedFeed.id + } + + return '' +} + +function getChannelChoises(channels: Collection): Choice[] { + const choises: Choice[] = [] + + channels.forEach((channel: sdk.Models.Channel) => { + const names = new Collection([channel.name, ...channel.alt_names]).uniq().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: sdk.Models.Feed) => { + let name = `${feed.id} (${feed.name})` + if (feed.is_main) name += ' [main]' + + choises.push({ + value: { + type: 'feed', + value: feed + }, + default: feed.is_main, + name, + short: feed.id + }) + }) + + choises.push({ name: 'Type...', value: { type: 'type' } }) + choises.push({ name: 'Skip', value: { type: 'skip' } }) + + return choises +} + +function save(filepath: string) { + if (!storage.existsSync(filepath)) return + const playlist = new Playlist(parsedStreams) + storage.saveSync(filepath, playlist.toString()) + logger.info(`\nFile '${filepath}' successfully saved`) +} + +function escapeRegex(string: string) { + return string.replace(/[/\-\\^$*+?.()|[\]{}]/g, '\\$&') +} diff --git a/scripts/commands/playlist/format.ts b/scripts/commands/playlist/format.ts index 345789bc28..15b4bc017e 100644 --- a/scripts/commands/playlist/format.ts +++ b/scripts/commands/playlist/format.ts @@ -1,78 +1,84 @@ -import { Logger, Storage } from '@freearhey/core' -import { STREAMS_DIR, DATA_DIR } from '../../constants' -import { DataLoader, DataProcessor, PlaylistParser } from '../../core' -import { Stream, Playlist } from '../../models' -import { program } from 'commander' -import { DataLoaderData } from '../../types/dataLoader' -import { DataProcessorData } from '../../types/dataProcessor' -import path from 'node:path' - -program.argument('[filepath...]', 'Path to file to format').parse(process.argv) - -async function main() { - const logger = new Logger() - - logger.info('loading data from api...') - const processor = new DataProcessor() - const dataStorage = new Storage(DATA_DIR) - const loader = new DataLoader({ storage: dataStorage }) - const data: DataLoaderData = await loader.load() - const { channelsKeyById, feedsGroupedByChannelId, logosGroupedByStreamId }: DataProcessorData = - processor.process(data) - - logger.info('loading streams...') - const streamsStorage = new Storage(STREAMS_DIR) - const parser = new PlaylistParser({ - storage: streamsStorage, - channelsKeyById, - feedsGroupedByChannelId, - logosGroupedByStreamId - }) - let files = program.args.length ? program.args : await streamsStorage.list('**/*.m3u') - files = files.map((filepath: string) => path.basename(filepath)) - let streams = await parser.parse(files) - - logger.info(`found ${streams.count()} streams`) - - logger.info('normalizing links...') - streams = streams.map(stream => { - stream.normalizeURL() - return stream - }) - - logger.info('removing duplicates...') - streams = streams.uniqBy(stream => stream.url) - - logger.info('removing wrong id...') - streams = streams.map((stream: Stream) => { - if (!stream.channel || channelsKeyById.missing(stream.channel.id)) { - stream.id = '' - } - - return stream - }) - - logger.info('sorting links...') - streams = streams.orderBy( - [ - (stream: Stream) => stream.title, - (stream: Stream) => stream.getVerticalResolution(), - (stream: Stream) => stream.getLabel(), - (stream: Stream) => stream.url - ], - ['asc', 'desc', 'asc', 'asc'] - ) - - logger.info('saving...') - const groupedStreams = streams.groupBy((stream: Stream) => stream.getFilepath()) - for (const filepath of groupedStreams.keys()) { - const streams = groupedStreams.get(filepath) || [] - - if (!streams.length) return - - const playlist = new Playlist(streams, { public: false }) - await streamsStorage.save(filepath, playlist.toString()) - } -} - -main() +import { Collection, Logger } from '@freearhey/core' +import { Stream, Playlist } from '../../models' +import { Storage } from '@freearhey/storage-js' +import { STREAMS_DIR } from '../../constants' +import { PlaylistParser } from '../../core' +import { loadData } from '../../api' +import { program } from 'commander' +import path from 'node:path' + +program.argument('[filepath...]', 'Path to file to format').parse(process.argv) + +async function main() { + const logger = new Logger() + + logger.info('loading data from api...') + await loadData() + + logger.info('loading streams...') + const streamsStorage = new Storage(STREAMS_DIR) + const parser = new PlaylistParser({ + storage: streamsStorage + }) + let files = program.args.length ? program.args : await streamsStorage.list('**/*.m3u') + files = files.map((filepath: string) => path.basename(filepath)) + let streams = await parser.parse(files) + + logger.info(`found ${streams.count()} streams`) + + logger.info('normalizing links...') + streams = streams.map(stream => { + stream.normalizeURL() + return stream + }) + + logger.info('removing duplicates...') + streams = streams.uniqBy(stream => stream.url) + + logger.info('removing wrong id...') + streams = streams.map((stream: Stream) => { + const channel = stream.getChannel() + if (channel) return stream + + stream.tvgId = '' + stream.channel = '' + stream.feed = '' + + return stream + }) + + logger.info('adding the missing feed id...') + streams = streams.map((stream: Stream) => { + const feed = stream.getFeed() + if (feed) { + stream.feed = feed.id + stream.tvgId = stream.getId() + } + + return stream + }) + + logger.info('sorting links...') + streams = streams.sortBy( + [ + (stream: Stream) => stream.title, + (stream: Stream) => stream.getVerticalResolution(), + (stream: Stream) => stream.label, + (stream: Stream) => stream.url + ], + ['asc', 'desc', 'asc', 'asc'] + ) + + logger.info('saving...') + const groupedStreams = streams.groupBy((stream: Stream) => stream.getFilepath()) + for (const filepath of groupedStreams.keys()) { + const streams = new Collection(groupedStreams.get(filepath)) + + if (streams.isEmpty()) return + + const playlist = new Playlist(streams, { public: false }) + await streamsStorage.save(filepath, playlist.toString()) + } +} + +main() diff --git a/scripts/commands/playlist/generate.ts b/scripts/commands/playlist/generate.ts index 6e960832a5..a84bd82651 100644 --- a/scripts/commands/playlist/generate.ts +++ b/scripts/commands/playlist/generate.ts @@ -1,131 +1,115 @@ -import { PlaylistParser, DataProcessor, DataLoader } from '../../core' -import type { DataProcessorData } from '../../types/dataProcessor' -import { DATA_DIR, LOGS_DIR, STREAMS_DIR } from '../../constants' -import type { DataLoaderData } from '../../types/dataLoader' -import { Logger, Storage, File } from '@freearhey/core' -import { Stream } from '../../models' -import uniqueId from 'lodash.uniqueid' -import { - IndexCategoryGenerator, - IndexLanguageGenerator, - IndexCountryGenerator, - SubdivisionsGenerator, - CategoriesGenerator, - CountriesGenerator, - LanguagesGenerator, - RegionsGenerator, - SourcesGenerator, - CitiesGenerator, - IndexGenerator, - RawGenerator -} from '../../generators' - -async function main() { - const logger = new Logger() - const logFile = new File('generators.log') - - logger.info('loading data from api...') - const processor = new DataProcessor() - const dataStorage = new Storage(DATA_DIR) - const loader = new DataLoader({ storage: dataStorage }) - const data: DataLoaderData = await loader.load() - const { - feedsGroupedByChannelId, - logosGroupedByStreamId, - channelsKeyById, - subdivisions, - categories, - countries, - regions, - cities - }: DataProcessorData = processor.process(data) - - logger.info('loading streams...') - const streamsStorage = new Storage(STREAMS_DIR) - const parser = new PlaylistParser({ - storage: streamsStorage, - feedsGroupedByChannelId, - logosGroupedByStreamId, - channelsKeyById - }) - const files = await streamsStorage.list('**/*.m3u') - let streams = await parser.parse(files) - const totalStreams = streams.count() - logger.info(`found ${totalStreams} streams`) - - logger.info('generating raw/...') - await new RawGenerator({ streams, logFile }).generate() - - logger.info('filtering streams...') - streams = streams.uniqBy((stream: Stream) => - stream.hasId() ? stream.getChannelId() + stream.getFeedId() : uniqueId() - ) - - logger.info('sorting streams...') - streams = streams.orderBy( - [ - (stream: Stream) => stream.getId(), - (stream: Stream) => stream.getVerticalResolution(), - (stream: Stream) => stream.getLabel() - ], - ['asc', 'asc', 'desc'] - ) - - logger.info('generating categories/...') - await new CategoriesGenerator({ categories, streams, logFile }).generate() - - logger.info('generating languages/...') - await new LanguagesGenerator({ streams, logFile }).generate() - - logger.info('generating countries/...') - await new CountriesGenerator({ - countries, - streams, - logFile - }).generate() - - logger.info('generating subdivisions/...') - await new SubdivisionsGenerator({ - subdivisions, - streams, - logFile - }).generate() - - logger.info('generating cities/...') - await new CitiesGenerator({ - cities, - streams, - logFile - }).generate() - - logger.info('generating regions/...') - await new RegionsGenerator({ - streams, - regions, - logFile - }).generate() - - logger.info('generating sources/...') - await new SourcesGenerator({ streams, logFile }).generate() - - logger.info('generating index.m3u...') - await new IndexGenerator({ streams, logFile }).generate() - - logger.info('generating index.category.m3u...') - await new IndexCategoryGenerator({ streams, logFile }).generate() - - logger.info('generating index.country.m3u...') - await new IndexCountryGenerator({ - streams, - logFile - }).generate() - - logger.info('generating index.language.m3u...') - await new IndexLanguageGenerator({ streams, logFile }).generate() - - logger.info('saving generators.log...') - const logStorage = new Storage(LOGS_DIR) - logStorage.saveFile(logFile) -} - -main() +import { LOGS_DIR, STREAMS_DIR } from '../../constants' +import { Storage, File } from '@freearhey/storage-js' +import { PlaylistParser } from '../../core' +import { loadData, data } from '../../api' +import { Logger } from '@freearhey/core' +import uniqueId from 'lodash.uniqueid' +import { Stream } from '../../models' +import { + IndexCategoryGenerator, + IndexLanguageGenerator, + IndexCountryGenerator, + SubdivisionsGenerator, + CategoriesGenerator, + CountriesGenerator, + LanguagesGenerator, + RegionsGenerator, + SourcesGenerator, + CitiesGenerator, + IndexGenerator, + RawGenerator +} from '../../generators' + +async function main() { + const logger = new Logger() + const logFile = new File('generators.log') + + logger.info('loading data from api...') + await loadData() + + logger.info('loading streams...') + const streamsStorage = new Storage(STREAMS_DIR) + const parser = new PlaylistParser({ + storage: streamsStorage + }) + const files = await streamsStorage.list('**/*.m3u') + let streams = await parser.parse(files) + const totalStreams = streams.count() + logger.info(`found ${totalStreams} streams`) + + logger.info('generating raw/...') + await new RawGenerator({ streams, logFile }).generate() + + logger.info('filtering streams...') + streams = streams.uniqBy((stream: Stream) => stream.getId() || uniqueId()) + + logger.info('sorting streams...') + streams = streams.sortBy( + [ + (stream: Stream) => stream.getId(), + (stream: Stream) => stream.getVerticalResolution(), + (stream: Stream) => stream.label + ], + ['asc', 'asc', 'desc'] + ) + + const { categories, countries, subdivisions, cities, regions } = data + + logger.info('generating categories/...') + await new CategoriesGenerator({ categories, streams, logFile }).generate() + + logger.info('generating languages/...') + await new LanguagesGenerator({ streams, logFile }).generate() + + logger.info('generating countries/...') + await new CountriesGenerator({ + countries, + streams, + logFile + }).generate() + + logger.info('generating subdivisions/...') + await new SubdivisionsGenerator({ + subdivisions, + streams, + logFile + }).generate() + + logger.info('generating cities/...') + await new CitiesGenerator({ + cities, + streams, + logFile + }).generate() + + logger.info('generating regions/...') + await new RegionsGenerator({ + streams, + regions, + logFile + }).generate() + + logger.info('generating sources/...') + await new SourcesGenerator({ streams, logFile }).generate() + + logger.info('generating index.m3u...') + await new IndexGenerator({ streams, logFile }).generate() + + logger.info('generating index.category.m3u...') + await new IndexCategoryGenerator({ streams, logFile }).generate() + + logger.info('generating index.country.m3u...') + await new IndexCountryGenerator({ + streams, + logFile + }).generate() + + logger.info('generating index.language.m3u...') + await new IndexLanguageGenerator({ streams, logFile }).generate() + + logger.info('saving generators.log...') + const logStorage = new Storage(LOGS_DIR) + logStorage.saveFile(logFile) +} + +main() diff --git a/scripts/commands/playlist/test.ts b/scripts/commands/playlist/test.ts index f4d59cac1a..737b2dbea7 100644 --- a/scripts/commands/playlist/test.ts +++ b/scripts/commands/playlist/test.ts @@ -1,182 +1,177 @@ -import { Logger, Storage, Collection } from '@freearhey/core' -import { ROOT_DIR, STREAMS_DIR, DATA_DIR } from '../../constants' -import { PlaylistParser, StreamTester, CliTable, DataProcessor, DataLoader } from '../../core' -import type { TestResult } from '../../core/streamTester' -import { Stream } from '../../models' -import { program, OptionValues } from 'commander' -import { eachLimit } from 'async-es' -import chalk from 'chalk' -import os from 'node:os' -import dns from 'node:dns' -import type { DataLoaderData } from '../../types/dataLoader' -import type { DataProcessorData } from '../../types/dataProcessor' - -const LIVE_UPDATE_INTERVAL = 5000 -const LIVE_UPDATE_MAX_STREAMS = 100 - -let errors = 0 -let warnings = 0 -const results: { [key: string]: string } = {} -let interval: string | number | NodeJS.Timeout | undefined -let streams = new Collection() -let isLiveUpdateEnabled = true - -program - .argument('[filepath...]', 'Path to file to test') - .option( - '-p, --parallel ', - 'Batch size of streams to test concurrently', - (value: string) => parseInt(value), - os.cpus().length - ) - .option('-x, --proxy ', 'Use the specified proxy') - .option( - '-t, --timeout ', - 'The number of milliseconds before the request will be aborted', - (value: string) => parseInt(value), - 30000 - ) - .parse(process.argv) - -const options: OptionValues = program.opts() - -const logger = new Logger() -const tester = new StreamTester({ options }) - -async function main() { - if (await isOffline()) { - logger.error(chalk.red('Internet connection is required for the script to work')) - return - } - - logger.info('loading data from api...') - const processor = new DataProcessor() - const dataStorage = new Storage(DATA_DIR) - const loader = new DataLoader({ storage: dataStorage }) - const data: DataLoaderData = await loader.load() - const { channelsKeyById, feedsGroupedByChannelId, logosGroupedByStreamId }: DataProcessorData = - processor.process(data) - - logger.info('loading streams...') - const rootStorage = new Storage(ROOT_DIR) - const parser = new PlaylistParser({ - storage: rootStorage, - channelsKeyById, - feedsGroupedByChannelId, - logosGroupedByStreamId - }) - const files = program.args.length ? program.args : await rootStorage.list(`${STREAMS_DIR}/*.m3u`) - streams = await parser.parse(files) - - logger.info(`found ${streams.count()} streams`) - if (streams.count() > LIVE_UPDATE_MAX_STREAMS) isLiveUpdateEnabled = false - - logger.info('starting...') - if (!isLiveUpdateEnabled) { - drawTable() - interval = setInterval(() => { - drawTable() - }, LIVE_UPDATE_INTERVAL) - } - - await eachLimit( - streams.all(), - options.parallel, - async (stream: Stream) => { - await runTest(stream) - - if (isLiveUpdateEnabled) { - drawTable() - } - }, - onFinish - ) -} - -main() - -async function runTest(stream: Stream) { - const key = stream.filepath + stream.getId() + stream.url - results[key] = chalk.white('LOADING...') - - const result: TestResult = await tester.test(stream) - - let status = '' - const errorStatusCodes = ['ENOTFOUND', 'HTTP_404_NOT_FOUND'] - if (result.status.ok) status = chalk.green('OK') - else if (errorStatusCodes.includes(result.status.code)) { - status = chalk.red(result.status.code) - errors++ - } else { - status = chalk.yellow(result.status.code) - warnings++ - } - - results[key] = status -} - -function drawTable() { - process.stdout.write('\u001b[3J\u001b[1J') - console.clear() - - const streamsGrouped = streams.groupBy((stream: Stream) => stream.filepath) - for (const filepath of streamsGrouped.keys()) { - const streams: Stream[] = streamsGrouped.get(filepath) - - const table = new CliTable({ - columns: [ - { name: '', alignment: 'center', minLen: 3, maxLen: 3 }, - { name: 'tvg-id', alignment: 'left', color: 'green', minLen: 25, maxLen: 25 }, - { name: 'url', alignment: 'left', color: 'green', minLen: 100, maxLen: 100 }, - { name: 'status', alignment: 'left', minLen: 25, maxLen: 25 } - ] - }) - streams.forEach((stream: Stream, index: number) => { - const status = results[stream.filepath + stream.getId() + stream.url] || chalk.gray('PENDING') - - const row = { - '': index, - 'tvg-id': stream.getId().length > 25 ? stream.getId().slice(0, 22) + '...' : stream.getId(), - url: stream.url.length > 100 ? stream.url.slice(0, 97) + '...' : stream.url, - status - } - table.append(row) - }) - - process.stdout.write(`\n${chalk.underline(filepath)}\n`) - - process.stdout.write(table.toString()) - } -} - -function onFinish(error: any) { - clearInterval(interval) - - if (error) { - console.error(error) - process.exit(1) - } - - drawTable() - - if (errors > 0 || warnings > 0) { - console.log( - chalk.red(`\n${errors + warnings} problems (${errors} errors, ${warnings} warnings)`) - ) - - if (errors > 0) { - process.exit(1) - } - } - - process.exit(0) -} - -async function isOffline() { - return new Promise((resolve, reject) => { - dns.lookup('info.cern.ch', err => { - if (err) resolve(true) - reject(false) - }) - }).catch(() => {}) -} +import { PlaylistParser, StreamTester, CliTable } from '../../core' +import type { TestResult } from '../../core/streamTester' +import { ROOT_DIR, STREAMS_DIR } from '../../constants' +import { Logger, Collection } from '@freearhey/core' +import { program, OptionValues } from 'commander' +import { Storage } from '@freearhey/storage-js' +import { Stream } from '../../models' +import { loadData } from '../../api' +import { eachLimit } from 'async' +import dns from 'node:dns' +import chalk from 'chalk' +import os from 'node:os' +import { truncate } from '../../utils' + +const LIVE_UPDATE_INTERVAL = 5000 +const LIVE_UPDATE_MAX_STREAMS = 100 + +let errors = 0 +let warnings = 0 +const results: { [key: string]: string } = {} +let interval: string | number | NodeJS.Timeout | undefined +let streams = new Collection() +let isLiveUpdateEnabled = true + +program + .argument('[filepath...]', 'Path to file to test') + .option( + '-p, --parallel ', + 'Batch size of streams to test concurrently', + (value: string) => parseInt(value), + os.cpus().length + ) + .option('-x, --proxy ', 'Use the specified proxy') + .option( + '-t, --timeout ', + 'The number of milliseconds before the request will be aborted', + (value: string) => parseInt(value), + 30000 + ) + .parse(process.argv) + +const options: OptionValues = program.opts() + +const logger = new Logger() +const tester = new StreamTester({ options }) + +async function main() { + if (await isOffline()) { + logger.error(chalk.red('Internet connection is required for the script to work')) + return + } + + logger.info('loading data from api...') + await loadData() + + logger.info('loading streams...') + const rootStorage = new Storage(ROOT_DIR) + const parser = new PlaylistParser({ + storage: rootStorage + }) + const files = program.args.length ? program.args : await rootStorage.list(`${STREAMS_DIR}/*.m3u`) + streams = await parser.parse(files) + + logger.info(`found ${streams.count()} streams`) + if (streams.count() > LIVE_UPDATE_MAX_STREAMS) isLiveUpdateEnabled = false + + logger.info('starting...') + if (!isLiveUpdateEnabled) { + drawTable() + interval = setInterval(() => { + drawTable() + }, LIVE_UPDATE_INTERVAL) + } + + eachLimit( + streams.all(), + options.parallel, + async (stream: Stream) => { + await runTest(stream) + + if (isLiveUpdateEnabled) { + drawTable() + } + }, + onFinish + ) +} + +main() + +async function runTest(stream: Stream) { + const key = stream.getUniqKey() + results[key] = chalk.white('LOADING...') + + const result: TestResult = await tester.test(stream) + + let status = '' + const errorStatusCodes = ['ENOTFOUND', 'HTTP_404_NOT_FOUND'] + if (result.status.ok) status = chalk.green('OK') + else if (errorStatusCodes.includes(result.status.code)) { + status = chalk.red(result.status.code) + errors++ + } else { + status = chalk.yellow(result.status.code) + warnings++ + } + + results[key] = status +} + +function drawTable() { + process.stdout.write('\u001b[3J\u001b[1J') + console.clear() + + const streamsGrouped = streams.groupBy((stream: Stream) => stream.filepath) + for (const filepath of streamsGrouped.keys()) { + const streams: Stream[] = streamsGrouped.get(filepath) || [] + + const table = new CliTable({ + columns: [ + { name: '', alignment: 'center', minLen: 3, maxLen: 3 }, + { name: 'tvg-id', alignment: 'left', color: 'green', minLen: 25, maxLen: 25 }, + { name: 'url', alignment: 'left', color: 'green', minLen: 100, maxLen: 100 }, + { name: 'status', alignment: 'left', minLen: 25, maxLen: 25 } + ] + }) + streams.forEach((stream: Stream, index: number) => { + const key = stream.getUniqKey() + const status = results[key] || chalk.gray('PENDING') + const tvgId = stream.getTvgId() + + const row = { + '': index, + 'tvg-id': truncate(tvgId, 25), + url: truncate(stream.url, 100), + status + } + table.append(row) + }) + + process.stdout.write(`\n${chalk.underline(filepath)}\n`) + + process.stdout.write(table.toString()) + } +} + +function onFinish(error: Error) { + clearInterval(interval) + + if (error) { + console.error(error) + process.exit(1) + } + + drawTable() + + if (errors > 0 || warnings > 0) { + console.log( + chalk.red(`\n${errors + warnings} problems (${errors} errors, ${warnings} warnings)`) + ) + + if (errors > 0) { + process.exit(1) + } + } + + process.exit(0) +} + +async function isOffline() { + return new Promise((resolve, reject) => { + dns.lookup('info.cern.ch', err => { + if (err) resolve(true) + reject(false) + }) + }).catch(() => {}) +} diff --git a/scripts/commands/playlist/update.ts b/scripts/commands/playlist/update.ts index 2ded669e75..600b23ac34 100644 --- a/scripts/commands/playlist/update.ts +++ b/scripts/commands/playlist/update.ts @@ -1,194 +1,174 @@ -import { DataLoader, DataProcessor, IssueLoader, PlaylistParser } from '../../core' -import { Logger, Storage, Collection, Dictionary } from '@freearhey/core' -import type { DataProcessorData } from '../../types/dataProcessor' -import { Stream, Playlist, Channel, Issue } from '../../models' -import type { DataLoaderData } from '../../types/dataLoader' -import { DATA_DIR, STREAMS_DIR } from '../../constants' -import { isURI } from '../../utils' - -const processedIssues = new Collection() - -async function main() { - const logger = new Logger({ level: -999 }) - const issueLoader = new IssueLoader() - - logger.info('loading issues...') - const issues = await issueLoader.load() - - logger.info('loading data from api...') - const processor = new DataProcessor() - const dataStorage = new Storage(DATA_DIR) - const dataLoader = new DataLoader({ storage: dataStorage }) - const data: DataLoaderData = await dataLoader.load() - const { channelsKeyById, feedsGroupedByChannelId, logosGroupedByStreamId }: DataProcessorData = - processor.process(data) - - logger.info('loading streams...') - const streamsStorage = new Storage(STREAMS_DIR) - const parser = new PlaylistParser({ - storage: streamsStorage, - feedsGroupedByChannelId, - logosGroupedByStreamId, - channelsKeyById - }) - const files = await streamsStorage.list('**/*.m3u') - const streams = await parser.parse(files) - - logger.info('removing streams...') - await removeStreams({ streams, issues }) - - logger.info('edit stream description...') - await editStreams({ - streams, - issues, - channelsKeyById, - feedsGroupedByChannelId - }) - - logger.info('add new streams...') - await addStreams({ - streams, - issues, - channelsKeyById, - feedsGroupedByChannelId - }) - - logger.info('saving...') - const groupedStreams = streams.groupBy((stream: Stream) => stream.getFilepath()) - for (const filepath of groupedStreams.keys()) { - let streams = groupedStreams.get(filepath) || [] - streams = streams.filter((stream: Stream) => stream.removed === false) - - const playlist = new Playlist(streams, { public: false }) - await streamsStorage.save(filepath, playlist.toString()) - } - - const output = processedIssues.map(issue_number => `closes #${issue_number}`).join(', ') - console.log(`OUTPUT=${output}`) -} - -main() - -async function removeStreams({ streams, issues }: { streams: Collection; issues: Collection }) { - const requests = issues.filter( - issue => issue.labels.includes('streams:remove') && issue.labels.includes('approved') - ) - requests.forEach((issue: Issue) => { - const data = issue.data - if (data.missing('streamUrl')) return - - const streamUrls = data.getString('streamUrl') || '' - - let changed = false - streamUrls - .split(/\r?\n/) - .filter(Boolean) - .forEach(link => { - const found: Stream = streams.first((_stream: Stream) => _stream.url === link.trim()) - if (found) { - found.removed = true - changed = true - } - }) - - if (changed) processedIssues.add(issue.number) - }) -} - -async function editStreams({ - streams, - issues, - channelsKeyById, - feedsGroupedByChannelId -}: { - streams: Collection - issues: Collection - channelsKeyById: Dictionary - feedsGroupedByChannelId: Dictionary -}) { - const requests = issues.filter( - issue => issue.labels.includes('streams:edit') && issue.labels.includes('approved') - ) - requests.forEach((issue: Issue) => { - const data = issue.data - - if (data.missing('streamUrl')) return - - const stream: Stream = streams.first( - (_stream: Stream) => _stream.url === data.getString('streamUrl') - ) - if (!stream) return - - const streamId = data.getString('streamId') || '' - const [channelId, feedId] = streamId.split('@') - - if (channelId) { - stream - .setChannelId(channelId) - .setFeedId(feedId) - .withChannel(channelsKeyById) - .withFeed(feedsGroupedByChannelId) - .updateId() - .updateTitle() - .updateFilepath() - } - - stream.update(data) - - processedIssues.add(issue.number) - }) -} - -async function addStreams({ - streams, - issues, - channelsKeyById, - feedsGroupedByChannelId -}: { - streams: Collection - issues: Collection - channelsKeyById: Dictionary - feedsGroupedByChannelId: Dictionary -}) { - const requests = issues.filter( - issue => issue.labels.includes('streams:add') && issue.labels.includes('approved') - ) - requests.forEach((issue: Issue) => { - const data = issue.data - if (data.missing('streamId') || data.missing('streamUrl')) return - if (streams.includes((_stream: Stream) => _stream.url === data.getString('streamUrl'))) return - const streamUrl = data.getString('streamUrl') || '' - if (!isURI(streamUrl)) return - - const streamId = data.getString('streamId') || '' - const [channelId, feedId] = streamId.split('@') - - const channel: Channel = channelsKeyById.get(channelId) - if (!channel) return - - const label = data.getString('label') || null - const quality = data.getString('quality') || null - const httpUserAgent = data.getString('httpUserAgent') || null - const httpReferrer = data.getString('httpReferrer') || null - const directives = data.getArray('directives') || [] - - const stream = new Stream({ - channelId, - feedId, - title: channel.name, - url: streamUrl, - userAgent: httpUserAgent, - referrer: httpReferrer, - directives, - quality, - label - }) - .withChannel(channelsKeyById) - .withFeed(feedsGroupedByChannelId) - .updateTitle() - .updateFilepath() - - streams.add(stream) - processedIssues.add(issue.number) - }) -} +import { IssueLoader, PlaylistParser } from '../../core' +import { Playlist, Issue, Stream } from '../../models' +import { loadData, data as apiData } from '../../api' +import { Logger, Collection } from '@freearhey/core' +import { Storage } from '@freearhey/storage-js' +import { STREAMS_DIR } from '../../constants' +import * as sdk from '@iptv-org/sdk' +import { isURI } from '../../utils' + +const processedIssues = new Collection() + +async function main() { + const logger = new Logger({ level: -999 }) + const issueLoader = new IssueLoader() + + logger.info('loading issues...') + const issues = await issueLoader.load() + + logger.info('loading data from api...') + await loadData() + + logger.info('loading streams...') + const streamsStorage = new Storage(STREAMS_DIR) + const parser = new PlaylistParser({ + storage: streamsStorage + }) + const files = await streamsStorage.list('**/*.m3u') + const streams = await parser.parse(files) + + logger.info('removing streams...') + await removeStreams({ streams, issues }) + + logger.info('edit stream description...') + await editStreams({ + streams, + issues + }) + + logger.info('add new streams...') + await addStreams({ + streams, + issues + }) + + logger.info('saving...') + const groupedStreams = streams.groupBy((stream: Stream) => stream.getFilepath()) + for (const filepath of groupedStreams.keys()) { + let streams = new Collection(groupedStreams.get(filepath)) + streams = streams.filter((stream: Stream) => stream.removed === false) + + const playlist = new Playlist(streams, { public: false }) + await streamsStorage.save(filepath, playlist.toString()) + } + + const output = processedIssues.map(issue_number => `closes #${issue_number}`).join(', ') + console.log(`OUTPUT=${output}`) +} + +main() + +async function removeStreams({ + streams, + issues +}: { + streams: Collection + issues: Collection +}) { + const requests = issues.filter( + issue => issue.labels.includes('streams:remove') && issue.labels.includes('approved') + ) + + requests.forEach((issue: Issue) => { + const data = issue.data + if (data.missing('streamUrl')) return + + const streamUrls = data.getString('streamUrl') || '' + + let changed = false + streamUrls + .split(/\r?\n/) + .filter(Boolean) + .forEach(link => { + const found: Stream = streams.first((_stream: Stream) => _stream.url === link.trim()) + if (found) { + found.removed = true + changed = true + } + }) + + if (changed) processedIssues.add(issue.number) + }) +} + +async function editStreams({ + streams, + issues +}: { + streams: Collection + issues: Collection +}) { + const requests = issues.filter( + issue => issue.labels.includes('streams:edit') && issue.labels.includes('approved') + ) + requests.forEach((issue: Issue) => { + const data = issue.data + + if (data.missing('streamUrl')) return + + const stream: Stream = streams.first( + (_stream: Stream) => _stream.url === data.getString('streamUrl') + ) + if (!stream) return + + const streamId = data.getString('streamId') || '' + const [channelId, feedId] = streamId.split('@') + + if (channelId) { + stream.channel = channelId + stream.feed = feedId + stream.updateTvgId().updateTitle().updateFilepath() + } + + stream.updateWithIssue(data) + + processedIssues.add(issue.number) + }) +} + +async function addStreams({ + streams, + issues +}: { + streams: Collection + issues: Collection +}) { + const requests = issues.filter( + issue => issue.labels.includes('streams:add') && issue.labels.includes('approved') + ) + requests.forEach((issue: Issue) => { + const data = issue.data + if (data.missing('streamId') || data.missing('streamUrl')) return + if (streams.includes((_stream: Stream) => _stream.url === data.getString('streamUrl'))) return + const streamUrl = data.getString('streamUrl') || '' + if (!isURI(streamUrl)) return + + const streamId = data.getString('streamId') || '' + const [channelId, feedId] = streamId.split('@') + + const channel: sdk.Models.Channel | undefined = apiData.channelsKeyById.get(channelId) + if (!channel) return + + const label = data.getString('label') || '' + const quality = data.getString('quality') || null + const httpUserAgent = data.getString('httpUserAgent') || null + const httpReferrer = data.getString('httpReferrer') || null + const directives = data.getArray('directives') || [] + + const stream = new Stream({ + channel: channelId, + feed: feedId, + title: channel.name, + url: streamUrl, + user_agent: httpUserAgent, + referrer: httpReferrer, + quality + }) + + stream.label = label + stream.setDirectives(directives).updateTitle().updateFilepath() + + streams.add(stream) + processedIssues.add(issue.number) + }) +} diff --git a/scripts/commands/playlist/validate.ts b/scripts/commands/playlist/validate.ts index 823acec73f..36ec037e23 100644 --- a/scripts/commands/playlist/validate.ts +++ b/scripts/commands/playlist/validate.ts @@ -1,129 +1,120 @@ -import { Logger, Storage, Collection, Dictionary } from '@freearhey/core' -import { DataLoader, DataProcessor, PlaylistParser } from '../../core' -import { DataProcessorData } from '../../types/dataProcessor' -import { DATA_DIR, ROOT_DIR } from '../../constants' -import { DataLoaderData } from '../../types/dataLoader' -import { BlocklistRecord, Stream } from '../../models' -import { program } from 'commander' -import chalk from 'chalk' - -program.argument('[filepath...]', 'Path to file to validate').parse(process.argv) - -type LogItem = { - type: string - line: number - message: string -} - -async function main() { - const logger = new Logger() - - logger.info('loading data from api...') - const processor = new DataProcessor() - const dataStorage = new Storage(DATA_DIR) - const loader = new DataLoader({ storage: dataStorage }) - const data: DataLoaderData = await loader.load() - const { - channelsKeyById, - feedsGroupedByChannelId, - logosGroupedByStreamId, - blocklistRecordsGroupedByChannelId - }: DataProcessorData = processor.process(data) - - logger.info('loading streams...') - const rootStorage = new Storage(ROOT_DIR) - const parser = new PlaylistParser({ - storage: rootStorage, - channelsKeyById, - feedsGroupedByChannelId, - logosGroupedByStreamId - }) - const files = program.args.length ? program.args : await rootStorage.list('streams/**/*.m3u') - const streams = await parser.parse(files) - logger.info(`found ${streams.count()} streams`) - - let errors = new Collection() - let warnings = new Collection() - const streamsGroupedByFilepath = streams.groupBy((stream: Stream) => stream.getFilepath()) - for (const filepath of streamsGroupedByFilepath.keys()) { - const streams = streamsGroupedByFilepath.get(filepath) - if (!streams) continue - - const log = new Collection() - const buffer = new Dictionary() - streams.forEach((stream: Stream) => { - if (stream.channelId) { - const channel = channelsKeyById.get(stream.channelId) - if (!channel) { - log.add({ - type: 'warning', - line: stream.getLine(), - message: `"${stream.id}" is not in the database` - }) - } - } - - const duplicate = stream.url && buffer.has(stream.url) - if (duplicate) { - log.add({ - type: 'warning', - line: stream.getLine(), - message: `"${stream.url}" is already on the playlist` - }) - } else { - buffer.set(stream.url, true) - } - - const blocklistRecords = stream.channel - ? new Collection(blocklistRecordsGroupedByChannelId.get(stream.channel.id)) - : new Collection() - - blocklistRecords.forEach((blocklistRecord: BlocklistRecord) => { - if (blocklistRecord.reason === 'dmca') { - log.add({ - type: 'error', - line: stream.getLine(), - message: `"${blocklistRecord.channelId}" is on the blocklist due to claims of copyright holders (${blocklistRecord.ref})` - }) - } else if (blocklistRecord.reason === 'nsfw') { - log.add({ - type: 'error', - line: stream.getLine(), - message: `"${blocklistRecord.channelId}" is on the blocklist due to NSFW content (${blocklistRecord.ref})` - }) - } - }) - }) - - if (log.notEmpty()) { - console.log(`\n${chalk.underline(filepath)}`) - - log.forEach((logItem: LogItem) => { - const position = logItem.line.toString().padEnd(6, ' ') - const type = logItem.type.padEnd(9, ' ') - const status = logItem.type === 'error' ? chalk.red(type) : chalk.yellow(type) - - console.log(` ${chalk.gray(position)}${status}${logItem.message}`) - }) - - errors = errors.concat(log.filter((logItem: LogItem) => logItem.type === 'error')) - warnings = warnings.concat(log.filter((logItem: LogItem) => logItem.type === 'warning')) - } - } - - if (errors.count() || warnings.count()) { - console.log( - chalk.red( - `\n${ - errors.count() + warnings.count() - } problems (${errors.count()} errors, ${warnings.count()} warnings)` - ) - ) - - if (errors.count()) { - process.exit(1) - } - } -} - -main() +import { Logger, Collection, Dictionary } from '@freearhey/core' +import { Storage } from '@freearhey/storage-js' +import { PlaylistParser } from '../../core' +import { data, loadData } from '../../api' +import { ROOT_DIR } from '../../constants' +import { Stream } from '../../models' +import * as sdk from '@iptv-org/sdk' +import { program } from 'commander' +import chalk from 'chalk' + +program.argument('[filepath...]', 'Path to file to validate').parse(process.argv) + +type LogItem = { + type: string + line: number + message: string +} + +async function main() { + const logger = new Logger() + + logger.info('loading data from api...') + await loadData() + + logger.info('loading streams...') + const rootStorage = new Storage(ROOT_DIR) + const parser = new PlaylistParser({ + storage: rootStorage + }) + const files = program.args.length ? program.args : await rootStorage.list('streams/**/*.m3u') + const streams = await parser.parse(files) + logger.info(`found ${streams.count()} streams`) + + let errors = new Collection() + let warnings = new Collection() + const streamsGroupedByFilepath = streams.groupBy((stream: Stream) => stream.getFilepath()) + for (const filepath of streamsGroupedByFilepath.keys()) { + const streams = streamsGroupedByFilepath.get(filepath) + if (!streams) continue + + const log = new Collection() + const buffer = new Dictionary() + streams.forEach((stream: Stream) => { + if (stream.channel) { + const channel = data.channelsKeyById.get(stream.channel) + if (!channel) { + log.add({ + type: 'warning', + line: stream.getLine(), + message: `"${stream.tvgId}" is not in the database` + }) + } + } + + const duplicate = stream.url && buffer.has(stream.url) + if (duplicate) { + log.add({ + type: 'warning', + line: stream.getLine(), + message: `"${stream.url}" is already on the playlist` + }) + } else { + buffer.set(stream.url, true) + } + + if (stream.channel) { + const blocklistRecords = new Collection( + data.blocklistRecordsGroupedByChannel.get(stream.channel) + ) + + blocklistRecords.forEach((blocklistRecord: sdk.Models.BlocklistRecord) => { + if (blocklistRecord.reason === 'dmca') { + log.add({ + type: 'error', + line: stream.getLine(), + message: `"${blocklistRecord.channel}" is on the blocklist due to claims of copyright holders (${blocklistRecord.ref})` + }) + } else if (blocklistRecord.reason === 'nsfw') { + log.add({ + type: 'error', + line: stream.getLine(), + message: `"${blocklistRecord.channel}" is on the blocklist due to NSFW content (${blocklistRecord.ref})` + }) + } + }) + } + }) + + if (log.isNotEmpty()) { + console.log(`\n${chalk.underline(filepath)}`) + + log.forEach((logItem: LogItem) => { + const position = logItem.line.toString().padEnd(6, ' ') + const type = logItem.type.padEnd(9, ' ') + const status = logItem.type === 'error' ? chalk.red(type) : chalk.yellow(type) + + console.log(` ${chalk.gray(position)}${status}${logItem.message}`) + }) + + errors = errors.concat(log.filter((logItem: LogItem) => logItem.type === 'error')) + warnings = warnings.concat(log.filter((logItem: LogItem) => logItem.type === 'warning')) + } + } + + if (errors.count() || warnings.count()) { + console.log( + chalk.red( + `\n${ + errors.count() + warnings.count() + } problems (${errors.count()} errors, ${warnings.count()} warnings)` + ) + ) + + if (errors.count()) { + process.exit(1) + } + } +} + +main() diff --git a/scripts/commands/readme/update.ts b/scripts/commands/readme/update.ts index d47f6ba48a..24ce044ab8 100644 --- a/scripts/commands/readme/update.ts +++ b/scripts/commands/readme/update.ts @@ -1,48 +1,30 @@ -import { CategoriesTable, CountriesTable, LanguagesTable, RegionsTable } from '../../tables' -import { DataLoader, DataProcessor, Markdown } from '../../core' -import { DataProcessorData } from '../../types/dataProcessor' -import { DataLoaderData } from '../../types/dataLoader' -import { README_DIR, DATA_DIR, ROOT_DIR } from '../../constants' -import { Logger, Storage } from '@freearhey/core' - -async function main() { - const logger = new Logger() - const dataStorage = new Storage(DATA_DIR) - const processor = new DataProcessor() - const loader = new DataLoader({ storage: dataStorage }) - const data: DataLoaderData = await loader.load() - const { - subdivisionsKeyByCode, - languagesKeyByCode, - countriesKeyByCode, - categoriesKeyById, - subdivisions, - countries, - regions, - cities - }: DataProcessorData = processor.process(data) - - logger.info('creating category table...') - await new CategoriesTable({ categoriesKeyById }).make() - logger.info('creating language table...') - await new LanguagesTable({ languagesKeyByCode }).make() - logger.info('creating countires table...') - await new CountriesTable({ - countriesKeyByCode, - subdivisionsKeyByCode, - subdivisions, - countries, - cities - }).make() - logger.info('creating region table...') - await new RegionsTable({ regions }).make() - - logger.info('updating playlists.md...') - const playlists = new Markdown({ - build: `${ROOT_DIR}/PLAYLISTS.md`, - template: `${README_DIR}/template.md` - }) - playlists.compile() -} - -main() +import { CategoriesTable, CountriesTable, LanguagesTable, RegionsTable } from '../../tables' +import { README_DIR, ROOT_DIR } from '../../constants' +import { Logger } from '@freearhey/core' +import { Markdown } from '../../core' +import { loadData } from '../../api' + +async function main() { + const logger = new Logger() + + logger.info('loading data from api...') + await loadData() + + logger.info('creating category table...') + await new CategoriesTable().create() + logger.info('creating language table...') + await new LanguagesTable().create() + logger.info('creating countires table...') + await new CountriesTable().create() + logger.info('creating region table...') + await new RegionsTable().create() + + logger.info('updating playlists.md...') + const playlists = new Markdown({ + build: `${ROOT_DIR}/PLAYLISTS.md`, + template: `${README_DIR}/template.md` + }) + playlists.compile() +} + +main() diff --git a/scripts/commands/report/create.ts b/scripts/commands/report/create.ts index 176681bd6e..52986637fd 100644 --- a/scripts/commands/report/create.ts +++ b/scripts/commands/report/create.ts @@ -1,178 +1,176 @@ -import { DataLoader, DataProcessor, IssueLoader, PlaylistParser } from '../../core' -import { Logger, Storage, Collection, Dictionary } from '@freearhey/core' -import { DataProcessorData } from '../../types/dataProcessor' -import { DATA_DIR, STREAMS_DIR } from '../../constants' -import { DataLoaderData } from '../../types/dataLoader' -import { Issue, Stream } from '../../models' -import { isURI } from '../../utils' - -async function main() { - const logger = new Logger() - const issueLoader = new IssueLoader() - let report = new Collection() - - logger.info('loading issues...') - const issues = await issueLoader.load() - - logger.info('loading data from api...') - const processor = new DataProcessor() - const dataStorage = new Storage(DATA_DIR) - const dataLoader = new DataLoader({ storage: dataStorage }) - const data: DataLoaderData = await dataLoader.load() - const { - channelsKeyById, - feedsGroupedByChannelId, - logosGroupedByStreamId, - blocklistRecordsGroupedByChannelId - }: DataProcessorData = processor.process(data) - - logger.info('loading streams...') - const streamsStorage = new Storage(STREAMS_DIR) - const parser = new PlaylistParser({ - storage: streamsStorage, - channelsKeyById, - feedsGroupedByChannelId, - logosGroupedByStreamId - }) - const files = await streamsStorage.list('**/*.m3u') - const streams = await parser.parse(files) - const streamsGroupedByUrl = streams.groupBy((stream: Stream) => stream.url) - const streamsGroupedByChannelId = streams.groupBy((stream: Stream) => stream.channelId) - const streamsGroupedById = streams.groupBy((stream: Stream) => stream.getId()) - - logger.info('checking streams:remove requests...') - const removeRequests = issues.filter(issue => - issue.labels.find((label: string) => label === 'streams:remove') - ) - removeRequests.forEach((issue: Issue) => { - const streamUrls = issue.data.getArray('streamUrl') || [] - - if (!streamUrls.length) { - const result = { - issueNumber: issue.number, - type: 'streams:remove', - streamId: undefined, - streamUrl: undefined, - status: 'missing_link' - } - - report.add(result) - } else { - for (const streamUrl of streamUrls) { - const result = { - issueNumber: issue.number, - type: 'streams:remove', - streamId: undefined, - streamUrl: truncate(streamUrl), - status: 'pending' - } - - if (streamsGroupedByUrl.missing(streamUrl)) { - result.status = 'wrong_link' - } - - report.add(result) - } - } - }) - - logger.info('checking streams:add requests...') - const addRequests = issues.filter(issue => issue.labels.includes('streams:add')) - const addRequestsBuffer = new Dictionary() - addRequests.forEach((issue: Issue) => { - const streamId = issue.data.getString('streamId') || '' - const streamUrl = issue.data.getString('streamUrl') || '' - const [channelId] = streamId.split('@') - - const result = { - issueNumber: issue.number, - type: 'streams:add', - streamId: streamId || undefined, - streamUrl: truncate(streamUrl), - status: 'pending' - } - - if (!channelId) result.status = 'missing_id' - else if (!streamUrl) result.status = 'missing_link' - else if (!isURI(streamUrl)) result.status = 'invalid_link' - else if (blocklistRecordsGroupedByChannelId.has(channelId)) result.status = 'blocked' - else if (channelsKeyById.missing(channelId)) result.status = 'wrong_id' - else if (streamsGroupedByUrl.has(streamUrl)) result.status = 'on_playlist' - else if (addRequestsBuffer.has(streamUrl)) result.status = 'duplicate' - else result.status = 'pending' - - addRequestsBuffer.set(streamUrl, true) - - report.add(result) - }) - - logger.info('checking streams:edit requests...') - const editRequests = issues.filter(issue => - issue.labels.find((label: string) => label === 'streams:edit') - ) - editRequests.forEach((issue: Issue) => { - const streamId = issue.data.getString('streamId') || '' - const streamUrl = issue.data.getString('streamUrl') || '' - const [channelId] = streamId.split('@') - - const result = { - issueNumber: issue.number, - type: 'streams:edit', - streamId: streamId || undefined, - streamUrl: truncate(streamUrl), - status: 'pending' - } - - if (!streamUrl) result.status = 'missing_link' - else if (streamsGroupedByUrl.missing(streamUrl)) result.status = 'invalid_link' - else if (channelId && channelsKeyById.missing(channelId)) result.status = 'invalid_id' - - report.add(result) - }) - - logger.info('checking channel search requests...') - const channelSearchRequests = issues.filter(issue => - issue.labels.find((label: string) => label === 'channel search') - ) - const channelSearchRequestsBuffer = new Dictionary() - channelSearchRequests.forEach((issue: Issue) => { - const streamId = issue.data.getString('channelId') || '' - const [channelId, feedId] = streamId.split('@') - - const result = { - issueNumber: issue.number, - type: 'channel search', - streamId: streamId || undefined, - streamUrl: undefined, - status: 'pending' - } - - if (!channelId) result.status = 'missing_id' - else if (channelsKeyById.missing(channelId)) result.status = 'invalid_id' - else if (channelSearchRequestsBuffer.has(streamId)) result.status = 'duplicate' - else if (blocklistRecordsGroupedByChannelId.has(channelId)) result.status = 'blocked' - else if (streamsGroupedById.has(streamId)) result.status = 'fulfilled' - else if (!feedId && streamsGroupedByChannelId.has(channelId)) result.status = 'fulfilled' - else { - const channelData = channelsKeyById.get(channelId) - if (channelData && channelData.isClosed) result.status = 'closed' - } - - channelSearchRequestsBuffer.set(streamId, true) - - report.add(result) - }) - - report = report.orderBy(item => item.issueNumber).filter(item => item.status !== 'pending') - - console.table(report.all()) -} - -main() - -function truncate(string: string, limit: number = 100) { - if (!string) return string - if (string.length < limit) return string - - return string.slice(0, limit) + '...' -} +import { Logger, Collection, Dictionary } from '@freearhey/core' +import { IssueLoader, PlaylistParser } from '../../core' +import { Storage } from '@freearhey/storage-js' +import { isURI, truncate } from '../../utils' +import { STREAMS_DIR } from '../../constants' +import { Issue, Stream } from '../../models' +import { data, loadData } from '../../api' + +const status = { + PENDING: 'pending', + FULFILLED: 'fulfilled', + MISSING_CHANNEL_ID: 'missing_channel_id', + INVALID_CHANNEL_ID: 'invalid_channel_id', + MISSING_STREAM_URL: 'missing_stream_url', + INVALID_STREAM_URL: 'invalid_stream_url', + NONEXISTENT_LINK: 'nonexistent_link', + CHANNEL_BLOCKED: 'channel_blocked', + CHANNEL_CLOSED: 'channel_closed', + DUPLICATE_LINK: 'duplicate_link', + DUPLICATE_REQUEST: 'duplicate_request' +} + +async function main() { + const logger = new Logger() + const issueLoader = new IssueLoader() + let report = new Collection() + + logger.info('loading issues...') + const issues = await issueLoader.load() + + logger.info('loading data from api...') + await loadData() + + logger.info('loading streams...') + const streamsStorage = new Storage(STREAMS_DIR) + const parser = new PlaylistParser({ + storage: streamsStorage + }) + const files = await streamsStorage.list('**/*.m3u') + const streams = await parser.parse(files) + const streamsGroupedByUrl = streams.groupBy((stream: Stream) => stream.url) + const streamsGroupedByChannel = streams.groupBy((stream: Stream) => stream.channel) + const streamsGroupedById = streams.groupBy((stream: Stream) => stream.getId()) + + logger.info('checking streams:remove requests...') + const removeRequests = issues.filter(issue => + issue.labels.find((label: string) => label === 'streams:remove') + ) + removeRequests.forEach((issue: Issue) => { + const streamUrls = issue.data.getArray('streamUrl') || [] + + if (!streamUrls.length) { + const result = { + issueNumber: issue.number, + type: 'streams:remove', + streamId: undefined, + streamUrl: undefined, + status: status.NONEXISTENT_LINK + } + + report.add(result) + } else { + for (const streamUrl of streamUrls) { + const result = { + issueNumber: issue.number, + type: 'streams:remove', + streamId: undefined, + streamUrl: truncate(streamUrl), + status: status.PENDING + } + + if (streamsGroupedByUrl.missing(streamUrl)) { + result.status = status.NONEXISTENT_LINK + } + + report.add(result) + } + } + }) + + logger.info('checking streams:add requests...') + const addRequests = issues.filter(issue => issue.labels.includes('streams:add')) + const addRequestsBuffer = new Dictionary() + addRequests.forEach((issue: Issue) => { + const streamId = issue.data.getString('streamId') || '' + const streamUrl = issue.data.getString('streamUrl') || '' + const [channelId] = streamId.split('@') + + const result = { + issueNumber: issue.number, + type: 'streams:add', + streamId: streamId || undefined, + streamUrl: truncate(streamUrl), + status: status.PENDING + } + + if (!channelId) result.status = status.MISSING_CHANNEL_ID + else if (!streamUrl) result.status = status.MISSING_STREAM_URL + else if (!isURI(streamUrl)) result.status = status.INVALID_STREAM_URL + else if (data.blocklistRecordsGroupedByChannel.has(channelId)) + result.status = status.CHANNEL_BLOCKED + else if (data.channelsKeyById.missing(channelId)) result.status = status.INVALID_CHANNEL_ID + else if (streamsGroupedByUrl.has(streamUrl)) result.status = status.DUPLICATE_LINK + else if (addRequestsBuffer.has(streamUrl)) result.status = status.DUPLICATE_REQUEST + else result.status = status.PENDING + + addRequestsBuffer.set(streamUrl, true) + + report.add(result) + }) + + logger.info('checking streams:edit requests...') + const editRequests = issues.filter(issue => + issue.labels.find((label: string) => label === 'streams:edit') + ) + editRequests.forEach((issue: Issue) => { + const streamId = issue.data.getString('streamId') || '' + const streamUrl = issue.data.getString('streamUrl') || '' + const [channelId] = streamId.split('@') + + const result = { + issueNumber: issue.number, + type: 'streams:edit', + streamId: streamId || undefined, + streamUrl: truncate(streamUrl), + status: status.PENDING + } + + if (!streamUrl) result.status = status.MISSING_STREAM_URL + else if (streamsGroupedByUrl.missing(streamUrl)) result.status = status.NONEXISTENT_LINK + else if (channelId && data.channelsKeyById.missing(channelId)) + result.status = status.INVALID_CHANNEL_ID + + report.add(result) + }) + + logger.info('checking channel search requests...') + const channelSearchRequests = issues.filter(issue => + issue.labels.find((label: string) => label === 'channel search') + ) + const channelSearchRequestsBuffer = new Dictionary() + channelSearchRequests.forEach((issue: Issue) => { + const streamId = issue.data.getString('streamId') || issue.data.getString('channelId') || '' + const [channelId, feedId] = streamId.split('@') + + const result = { + issueNumber: issue.number, + type: 'channel search', + streamId: streamId || undefined, + streamUrl: undefined, + status: status.PENDING + } + + if (!channelId) result.status = status.MISSING_CHANNEL_ID + else if (data.channelsKeyById.missing(channelId)) result.status = status.INVALID_CHANNEL_ID + else if (channelSearchRequestsBuffer.has(streamId)) result.status = status.DUPLICATE_REQUEST + else if (data.blocklistRecordsGroupedByChannel.has(channelId)) + result.status = status.CHANNEL_BLOCKED + else if (streamsGroupedById.has(streamId)) result.status = status.FULFILLED + else if (!feedId && streamsGroupedByChannel.has(channelId)) result.status = status.FULFILLED + else { + const channelData = data.channelsKeyById.get(channelId) + if (channelData && channelData.isClosed()) result.status = status.CHANNEL_CLOSED + } + + channelSearchRequestsBuffer.set(streamId, true) + + report.add(result) + }) + + report = report.sortBy(item => item.issueNumber).filter(item => item.status !== status.PENDING) + + console.table(report.all()) +} + +main() diff --git a/scripts/constants.ts b/scripts/constants.ts index f6b688714b..e607a87b5e 100644 --- a/scripts/constants.ts +++ b/scripts/constants.ts @@ -1,11 +1,11 @@ -export const ROOT_DIR = process.env.ROOT_DIR || './' -export const STREAMS_DIR = process.env.STREAMS_DIR || './streams' -export const PUBLIC_DIR = process.env.PUBLIC_DIR || './.gh-pages' -export const README_DIR = process.env.README_DIR || './.readme' -export const API_DIR = process.env.API_DIR || './.api' -export const DATA_DIR = process.env.DATA_DIR || './temp/data' -export const LOGS_DIR = process.env.LOGS_DIR || './temp/logs' -export const TESTING = process.env.NODE_ENV === 'test' ? true : false -export const OWNER = 'iptv-org' -export const REPO = 'iptv' -export const EOL = '\r\n' +export const ROOT_DIR = process.env.ROOT_DIR || './' +export const STREAMS_DIR = process.env.STREAMS_DIR || './streams' +export const PUBLIC_DIR = process.env.PUBLIC_DIR || './.gh-pages' +export const README_DIR = process.env.README_DIR || './.readme' +export const API_DIR = process.env.API_DIR || './.api' +export const DATA_DIR = process.env.DATA_DIR || './temp/data' +export const LOGS_DIR = process.env.LOGS_DIR || './temp/logs' +export const TESTING = process.env.NODE_ENV === 'test' ? true : false +export const OWNER = 'iptv-org' +export const REPO = 'iptv' +export const EOL = '\r\n' diff --git a/scripts/core/apiClient.ts b/scripts/core/apiClient.ts deleted file mode 100644 index e4815a81aa..0000000000 --- a/scripts/core/apiClient.ts +++ /dev/null @@ -1,16 +0,0 @@ -import axios, { AxiosInstance, AxiosResponse, AxiosRequestConfig } from 'axios' - -export class ApiClient { - instance: AxiosInstance - - constructor() { - this.instance = axios.create({ - baseURL: 'https://iptv-org.github.io/api', - responseType: 'stream' - }) - } - - get(url: string, options: AxiosRequestConfig): Promise { - return this.instance.get(url, options) - } -} diff --git a/scripts/core/cliTable.ts b/scripts/core/cliTable.ts index 61d9e608e6..bf8e20b81e 100644 --- a/scripts/core/cliTable.ts +++ b/scripts/core/cliTable.ts @@ -1,22 +1,22 @@ -import { Table } from 'console-table-printer' -import { ComplexOptions } from 'console-table-printer/dist/src/models/external-table' - -export class CliTable { - table: Table - - constructor(options?: ComplexOptions | string[]) { - this.table = new Table(options) - } - - append(row) { - this.table.addRow(row) - } - - render() { - this.table.printTable() - } - - toString() { - return this.table.render() - } -} +import { ComplexOptions } from 'console-table-printer/dist/src/models/external-table' +import { Table } from 'console-table-printer' + +export class CliTable { + table: Table + + constructor(options?: ComplexOptions | string[]) { + this.table = new Table(options) + } + + append(row) { + this.table.addRow(row) + } + + render() { + this.table.printTable() + } + + toString() { + return this.table.render() + } +} diff --git a/scripts/core/dataLoader.ts b/scripts/core/dataLoader.ts deleted file mode 100644 index 89b45c00c0..0000000000 --- a/scripts/core/dataLoader.ts +++ /dev/null @@ -1,113 +0,0 @@ -import { ApiClient } from './apiClient' -import { Storage } from '@freearhey/core' -import cliProgress, { MultiBar } from 'cli-progress' -import type { DataLoaderProps, DataLoaderData } from '../types/dataLoader' - -const formatBytes = (bytes: number) => { - if (bytes === 0) return '0 B' - const k = 1024 - const sizes = ['B', 'KB', 'MB', 'GB'] - const i = Math.floor(Math.log(bytes) / Math.log(k)) - return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i] -} - -export class DataLoader { - client: ApiClient - storage: Storage - progressBar: MultiBar - - constructor(props: DataLoaderProps) { - this.client = new ApiClient() - this.storage = props.storage - this.progressBar = new cliProgress.MultiBar({ - stopOnComplete: true, - hideCursor: true, - forceRedraw: true, - barsize: 36, - format(options, params, payload) { - const filename = payload.filename.padEnd(18, ' ') - const barsize = options.barsize || 40 - const percent = (params.progress * 100).toFixed(2) - const speed = payload.speed ? formatBytes(payload.speed) + '/s' : 'N/A' - const total = formatBytes(params.total) - const completeSize = Math.round(params.progress * barsize) - const incompleteSize = barsize - completeSize - const bar = - options.barCompleteString && options.barIncompleteString - ? options.barCompleteString.substr(0, completeSize) + - options.barGlue + - options.barIncompleteString.substr(0, incompleteSize) - : '-'.repeat(barsize) - - return `${filename} [${bar}] ${percent}% | ETA: ${params.eta}s | ${total} | ${speed}` - } - }) - } - - async load(): Promise { - const [ - countries, - regions, - subdivisions, - languages, - categories, - blocklist, - channels, - feeds, - logos, - timezones, - guides, - streams, - cities - ] = await Promise.all([ - this.storage.json('countries.json'), - this.storage.json('regions.json'), - this.storage.json('subdivisions.json'), - this.storage.json('languages.json'), - this.storage.json('categories.json'), - this.storage.json('blocklist.json'), - this.storage.json('channels.json'), - this.storage.json('feeds.json'), - this.storage.json('logos.json'), - this.storage.json('timezones.json'), - this.storage.json('guides.json'), - this.storage.json('streams.json'), - this.storage.json('cities.json') - ]) - - return { - countries, - regions, - subdivisions, - languages, - categories, - blocklist, - channels, - feeds, - logos, - timezones, - guides, - streams, - cities - } - } - - async download(filename: string) { - if (!this.storage || !this.progressBar) return - - const stream = await this.storage.createStream(filename) - const progressBar = this.progressBar.create(0, 0, { filename }) - - this.client - .get(filename, { - responseType: 'stream', - onDownloadProgress({ total, loaded, rate }) { - if (total) progressBar.setTotal(total) - progressBar.update(loaded, { speed: rate }) - } - }) - .then(response => { - response.data.pipe(stream) - }) - } -} diff --git a/scripts/core/dataProcessor.ts b/scripts/core/dataProcessor.ts deleted file mode 100644 index e7fd94dd5d..0000000000 --- a/scripts/core/dataProcessor.ts +++ /dev/null @@ -1,165 +0,0 @@ -import { DataProcessorData } from '../types/dataProcessor' -import { DataLoaderData } from '../types/dataLoader' -import { Collection } from '@freearhey/core' -import { - BlocklistRecord, - Subdivision, - Category, - Language, - Timezone, - Channel, - Country, - Region, - Stream, - Guide, - City, - Feed, - Logo -} from '../models' - -export class DataProcessor { - process(data: DataLoaderData): DataProcessorData { - let regions = new Collection(data.regions).map(data => new Region(data)) - let regionsKeyByCode = regions.keyBy((region: Region) => region.code) - - const categories = new Collection(data.categories).map(data => new Category(data)) - const categoriesKeyById = categories.keyBy((category: Category) => category.id) - - const languages = new Collection(data.languages).map(data => new Language(data)) - const languagesKeyByCode = languages.keyBy((language: Language) => language.code) - - let subdivisions = new Collection(data.subdivisions).map(data => new Subdivision(data)) - let subdivisionsKeyByCode = subdivisions.keyBy((subdivision: Subdivision) => subdivision.code) - let subdivisionsGroupedByCountryCode = subdivisions.groupBy( - (subdivision: Subdivision) => subdivision.countryCode - ) - - let countries = new Collection(data.countries).map(data => new Country(data)) - let countriesKeyByCode = countries.keyBy((country: Country) => country.code) - - const cities = new Collection(data.cities).map(data => - new City(data) - .withRegions(regions) - .withCountry(countriesKeyByCode) - .withSubdivision(subdivisionsKeyByCode) - ) - const citiesKeyByCode = cities.keyBy((city: City) => city.code) - const citiesGroupedByCountryCode = cities.groupBy((city: City) => city.countryCode) - const citiesGroupedBySubdivisionCode = cities.groupBy((city: City) => city.subdivisionCode) - - const timezones = new Collection(data.timezones).map(data => - new Timezone(data).withCountries(countriesKeyByCode) - ) - const timezonesKeyById = timezones.keyBy((timezone: Timezone) => timezone.id) - - const blocklistRecords = new Collection(data.blocklist).map(data => new BlocklistRecord(data)) - const blocklistRecordsGroupedByChannelId = blocklistRecords.groupBy( - (blocklistRecord: BlocklistRecord) => blocklistRecord.channelId - ) - - let channels = new Collection(data.channels).map(data => new Channel(data)) - let channelsKeyById = channels.keyBy((channel: Channel) => channel.id) - - let feeds = new Collection(data.feeds).map(data => new Feed(data)) - let feedsGroupedByChannelId = feeds.groupBy((feed: Feed) => feed.channelId) - let feedsGroupedById = feeds.groupBy((feed: Feed) => feed.id) - - const logos = new Collection(data.logos).map(data => new Logo(data).withFeed(feedsGroupedById)) - const logosGroupedByChannelId = logos.groupBy((logo: Logo) => logo.channelId) - const logosGroupedByStreamId = logos.groupBy((logo: Logo) => logo.getStreamId()) - - const streams = new Collection(data.streams).map(data => - new Stream(data).withLogos(logosGroupedByStreamId) - ) - const streamsGroupedById = streams.groupBy((stream: Stream) => stream.getId()) - - const guides = new Collection(data.guides).map(data => new Guide(data)) - const guidesGroupedByStreamId = guides.groupBy((guide: Guide) => guide.getStreamId()) - - regions = regions.map((region: Region) => - region - .withCountries(countriesKeyByCode) - .withRegions(regions) - .withSubdivisions(subdivisions) - .withCities(cities) - ) - regionsKeyByCode = regions.keyBy((region: Region) => region.code) - - countries = countries.map((country: Country) => - country - .withCities(citiesGroupedByCountryCode) - .withSubdivisions(subdivisionsGroupedByCountryCode) - .withRegions(regions) - .withLanguage(languagesKeyByCode) - ) - countriesKeyByCode = countries.keyBy((country: Country) => country.code) - - subdivisions = subdivisions.map((subdivision: Subdivision) => - subdivision - .withCities(citiesGroupedBySubdivisionCode) - .withCountry(countriesKeyByCode) - .withRegions(regions) - .withParent(subdivisionsKeyByCode) - ) - subdivisionsKeyByCode = subdivisions.keyBy((subdivision: Subdivision) => subdivision.code) - subdivisionsGroupedByCountryCode = subdivisions.groupBy( - (subdivision: Subdivision) => subdivision.countryCode - ) - - channels = channels.map((channel: Channel) => - channel - .withFeeds(feedsGroupedByChannelId) - .withLogos(logosGroupedByChannelId) - .withCategories(categoriesKeyById) - .withCountry(countriesKeyByCode) - .withSubdivision(subdivisionsKeyByCode) - .withCategories(categoriesKeyById) - ) - channelsKeyById = channels.keyBy((channel: Channel) => channel.id) - - feeds = feeds.map((feed: Feed) => - feed - .withChannel(channelsKeyById) - .withLanguages(languagesKeyByCode) - .withTimezones(timezonesKeyById) - .withBroadcastArea( - citiesKeyByCode, - subdivisionsKeyByCode, - countriesKeyByCode, - regionsKeyByCode - ) - ) - feedsGroupedByChannelId = feeds.groupBy((feed: Feed) => feed.channelId) - feedsGroupedById = feeds.groupBy((feed: Feed) => feed.id) - - return { - blocklistRecordsGroupedByChannelId, - subdivisionsGroupedByCountryCode, - feedsGroupedByChannelId, - guidesGroupedByStreamId, - logosGroupedByStreamId, - subdivisionsKeyByCode, - countriesKeyByCode, - languagesKeyByCode, - streamsGroupedById, - categoriesKeyById, - timezonesKeyById, - regionsKeyByCode, - blocklistRecords, - channelsKeyById, - citiesKeyByCode, - subdivisions, - categories, - countries, - languages, - timezones, - channels, - regions, - streams, - cities, - guides, - feeds, - logos - } - } -} diff --git a/scripts/core/htmlTable.ts b/scripts/core/htmlTable.ts index b4f7b42ac6..f90dd4b913 100644 --- a/scripts/core/htmlTable.ts +++ b/scripts/core/htmlTable.ts @@ -1,46 +1,50 @@ -type Column = { - name: string - nowrap?: boolean - align?: string -} - -type DataItem = string[] - -export class HTMLTable { - data: DataItem[] - columns: Column[] - - constructor(data: DataItem[], columns: Column[]) { - this.data = data - this.columns = columns - } - - toString() { - let output = '\r\n' - - output += ' \r\n ' - for (const column of this.columns) { - output += `` - } - output += '\r\n \r\n' - - output += ' \r\n' - for (const item of this.data) { - output += ' ' - let i = 0 - for (const prop in item) { - const column = this.columns[i] - const nowrap = column.nowrap ? ' nowrap' : '' - const align = column.align ? ` align="${column.align}"` : '' - output += `${item[prop]}` - i++ - } - output += '\r\n' - } - output += ' \r\n' - - output += '
${column.name}
' - - return output - } -} +import { Collection } from '@freearhey/core' + +export type HTMLTableColumn = { + name: string + nowrap?: boolean + align?: string +} + +export type HTMLTableItem = string[] + +export class HTMLTable { + data: Collection + columns: Collection + + constructor(data: Collection, columns: Collection) { + this.data = data + this.columns = columns + } + + toString() { + let output = '\r\n' + + output += ' \r\n ' + this.columns.forEach((column: HTMLTableColumn) => { + output += `` + }) + + output += '\r\n \r\n' + + output += ' \r\n' + this.data.forEach((item: HTMLTableItem) => { + output += ' ' + let i = 0 + for (const prop in item) { + const column = this.columns.all()[i] + const nowrap = column.nowrap ? ' nowrap' : '' + const align = column.align ? ` align="${column.align}"` : '' + output += `${item[prop]}` + i++ + } + output += '\r\n' + }) + + output += ' \r\n' + + output += '
${column.name}
' + + return output + } +} diff --git a/scripts/core/index.ts b/scripts/core/index.ts index 2e24771bf0..850b9d9cfb 100644 --- a/scripts/core/index.ts +++ b/scripts/core/index.ts @@ -1,14 +1,11 @@ -export * from './apiClient' -export * from './cliTable' -export * from './dataProcessor' -export * from './dataLoader' -export * from './htmlTable' -export * from './issueData' -export * from './issueLoader' -export * from './issueParser' -export * from './logParser' -export * from './markdown' -export * from './numberParser' -export * from './playlistParser' -export * from './proxyParser' -export * from './streamTester' +export * from './cliTable' +export * from './htmlTable' +export * from './issueData' +export * from './issueLoader' +export * from './issueParser' +export * from './logParser' +export * from './markdown' +export * from './numberParser' +export * from './playlistParser' +export * from './proxyParser' +export * from './streamTester' diff --git a/scripts/core/issueData.ts b/scripts/core/issueData.ts index e185e1b02f..a38209250a 100644 --- a/scripts/core/issueData.ts +++ b/scripts/core/issueData.ts @@ -1,34 +1,36 @@ -import { Dictionary } from '@freearhey/core' - -export class IssueData { - _data: Dictionary - constructor(data: Dictionary) { - this._data = data - } - - has(key: string): boolean { - return this._data.has(key) - } - - missing(key: string): boolean { - return this._data.missing(key) || this._data.get(key) === undefined - } - - getBoolean(key: string): boolean { - return Boolean(this._data.get(key)) - } - - getString(key: string): string | undefined { - const deleteSymbol = '~' - - return this._data.get(key) === deleteSymbol ? '' : this._data.get(key) - } - - getArray(key: string): string[] | undefined { - const deleteSymbol = '~' - - if (this._data.missing(key)) return undefined - - return this._data.get(key) === deleteSymbol ? [] : this._data.get(key).split('\r\n') - } -} +import { Dictionary } from '@freearhey/core' + +export class IssueData { + _data: Dictionary + constructor(data: Dictionary) { + this._data = data + } + + has(key: string): boolean { + return this._data.has(key) + } + + missing(key: string): boolean { + return this._data.missing(key) || this._data.get(key) === undefined + } + + getBoolean(key: string): boolean { + return Boolean(this._data.get(key)) + } + + getString(key: string): string | undefined { + const deleteSymbol = '~' + + return this._data.get(key) === deleteSymbol ? '' : this._data.get(key) + } + + getArray(key: string): string[] | undefined { + const deleteSymbol = '~' + + if (this._data.missing(key)) return undefined + + const value = this._data.get(key) + + return !value || value === deleteSymbol ? [] : value.split('\r\n') + } +} diff --git a/scripts/core/issueLoader.ts b/scripts/core/issueLoader.ts index e9102f25a1..43fb2185b6 100644 --- a/scripts/core/issueLoader.ts +++ b/scripts/core/issueLoader.ts @@ -1,37 +1,37 @@ -import { Collection } from '@freearhey/core' -import { restEndpointMethods } from '@octokit/plugin-rest-endpoint-methods' -import { paginateRest } from '@octokit/plugin-paginate-rest' -import { Octokit } from '@octokit/core' -import { IssueParser } from './' -import { TESTING, OWNER, REPO } from '../constants' - -const CustomOctokit = Octokit.plugin(paginateRest, restEndpointMethods) -const octokit = new CustomOctokit() - -export class IssueLoader { - async load(props?: { labels: string | string[] }) { - let labels = '' - if (props && props.labels) { - labels = Array.isArray(props.labels) ? props.labels.join(',') : props.labels - } - let issues: object[] = [] - if (TESTING) { - issues = (await import('../../tests/__data__/input/issues.js')).default - } else { - issues = await octokit.paginate(octokit.rest.issues.listForRepo, { - owner: OWNER, - repo: REPO, - per_page: 100, - labels, - status: 'open', - headers: { - 'X-GitHub-Api-Version': '2022-11-28' - } - }) - } - - const parser = new IssueParser() - - return new Collection(issues).map(parser.parse) - } -} +import { restEndpointMethods } from '@octokit/plugin-rest-endpoint-methods' +import { paginateRest } from '@octokit/plugin-paginate-rest' +import { TESTING, OWNER, REPO } from '../constants' +import { Collection } from '@freearhey/core' +import { Octokit } from '@octokit/core' +import { IssueParser } from './' + +const CustomOctokit = Octokit.plugin(paginateRest, restEndpointMethods) +const octokit = new CustomOctokit() + +export class IssueLoader { + async load(props?: { labels: string | string[] }) { + let labels = '' + if (props && props.labels) { + labels = Array.isArray(props.labels) ? props.labels.join(',') : props.labels + } + let issues: object[] = [] + if (TESTING) { + issues = (await import('../../tests/__data__/input/issues.js')).default + } else { + issues = await octokit.paginate(octokit.rest.issues.listForRepo, { + owner: OWNER, + repo: REPO, + per_page: 100, + labels, + status: 'open', + headers: { + 'X-GitHub-Api-Version': '2022-11-28' + } + }) + } + + const parser = new IssueParser() + + return new Collection(issues).map(parser.parse) + } +} diff --git a/scripts/core/issueParser.ts b/scripts/core/issueParser.ts index b5feeaec80..ad488e6c5d 100644 --- a/scripts/core/issueParser.ts +++ b/scripts/core/issueParser.ts @@ -1,48 +1,48 @@ -import { Dictionary } from '@freearhey/core' -import { Issue } from '../models' -import { IssueData } from './issueData' - -const FIELDS = new Dictionary({ - 'Stream ID': 'streamId', - 'Channel ID': 'channelId', - 'Feed ID': 'feedId', - 'Stream URL': 'streamUrl', - 'New Stream URL': 'newStreamUrl', - Label: 'label', - Quality: 'quality', - 'HTTP User-Agent': 'httpUserAgent', - 'HTTP User Agent': 'httpUserAgent', - 'HTTP Referrer': 'httpReferrer', - 'What happened to the stream?': 'reason', - Reason: 'reason', - Notes: 'notes', - Directives: 'directives' -}) - -export class IssueParser { - parse(issue: { number: number; body: string; labels: { name: string }[] }): Issue { - const fields = typeof issue.body === 'string' ? issue.body.split('###') : [] - - const data = new Dictionary() - fields.forEach((field: string) => { - const parsed = typeof field === 'string' ? field.split(/\r?\n/).filter(Boolean) : [] - let _label = parsed.shift() - _label = _label ? _label.replace(/ \(optional\)| \(required\)/, '').trim() : '' - let _value = parsed.join('\r\n') - _value = _value ? _value.trim() : '' - - if (!_label || !_value) return data - - const id: string = FIELDS.get(_label) - const value: string = _value === '_No response_' || _value === 'None' ? '' : _value - - if (!id) return - - data.set(id, value) - }) - - const labels = issue.labels.map(label => label.name) - - return new Issue({ number: issue.number, labels, data: new IssueData(data) }) - } -} +import { Dictionary } from '@freearhey/core' +import { IssueData } from './issueData' +import { Issue } from '../models' + +const FIELDS = new Dictionary({ + 'Stream ID': 'streamId', + 'Channel ID': 'channelId', + 'Feed ID': 'feedId', + 'Stream URL': 'streamUrl', + 'New Stream URL': 'newStreamUrl', + Label: 'label', + Quality: 'quality', + 'HTTP User-Agent': 'httpUserAgent', + 'HTTP User Agent': 'httpUserAgent', + 'HTTP Referrer': 'httpReferrer', + 'What happened to the stream?': 'reason', + Reason: 'reason', + Notes: 'notes', + Directives: 'directives' +}) + +export class IssueParser { + parse(issue: { number: number; body: string; labels: { name: string }[] }): Issue { + const fields = typeof issue.body === 'string' ? issue.body.split('###') : [] + + const data = new Dictionary() + fields.forEach((field: string) => { + const parsed = typeof field === 'string' ? field.split(/\r?\n/).filter(Boolean) : [] + let _label = parsed.shift() + _label = _label ? _label.replace(/ \(optional\)| \(required\)/, '').trim() : '' + let _value = parsed.join('\r\n') + _value = _value ? _value.trim() : '' + + if (!_label || !_value) return data + + const id = FIELDS.get(_label) + const value: string = _value === '_No response_' || _value === 'None' ? '' : _value + + if (!id) return + + data.set(id, value) + }) + + const labels = issue.labels.map(label => label.name) + + return new Issue({ number: issue.number, labels, data: new IssueData(data) }) + } +} diff --git a/scripts/core/logParser.ts b/scripts/core/logParser.ts index fb888f6b5a..7b80f32460 100644 --- a/scripts/core/logParser.ts +++ b/scripts/core/logParser.ts @@ -1,14 +1,14 @@ -export type LogItem = { - type: string - filepath: string - count: number -} - -export class LogParser { - parse(content: string): LogItem[] { - if (!content) return [] - const lines = content.split('\n') - - return lines.map(line => (line ? JSON.parse(line) : null)).filter(l => l) - } -} +export type LogItem = { + type: string + filepath: string + count: number +} + +export class LogParser { + parse(content: string): LogItem[] { + if (!content) return [] + const lines = content.split('\n') + + return lines.map(line => (line ? JSON.parse(line) : null)).filter(l => l) + } +} diff --git a/scripts/core/markdown.ts b/scripts/core/markdown.ts index e229999409..25e15095ec 100644 --- a/scripts/core/markdown.ts +++ b/scripts/core/markdown.ts @@ -1,45 +1,45 @@ -import fs from 'fs' -import path from 'path' - -type MarkdownConfig = { - build: string - template: string -} - -export class Markdown { - build: string - template: string - - constructor(config: MarkdownConfig) { - this.build = config.build - this.template = config.template - } - - compile() { - const workingDir = process.cwd() - - const templatePath = path.resolve(workingDir, this.template) - const template = fs.readFileSync(templatePath, 'utf8') - const processedContent = this.processIncludes(template, workingDir) - - if (this.build) { - const outputPath = path.resolve(workingDir, this.build) - fs.writeFileSync(outputPath, processedContent, 'utf8') - } - } - - private processIncludes(template: string, baseDir: string): string { - const includeRegex = /#include\s+"([^"]+)"/g - - return template.replace(includeRegex, (match, includePath) => { - try { - const fullPath = path.resolve(baseDir, includePath) - const includeContent = fs.readFileSync(fullPath, 'utf8') - return this.processIncludes(includeContent, baseDir) - } catch (error) { - console.warn(`Warning: Could not include file ${includePath}: ${error}`) - return match - } - }) - } -} +import path from 'path' +import fs from 'fs' + +type MarkdownConfig = { + build: string + template: string +} + +export class Markdown { + build: string + template: string + + constructor(config: MarkdownConfig) { + this.build = config.build + this.template = config.template + } + + compile() { + const workingDir = process.cwd() + + const templatePath = path.resolve(workingDir, this.template) + const template = fs.readFileSync(templatePath, 'utf8') + const processedContent = this.processIncludes(template, workingDir) + + if (this.build) { + const outputPath = path.resolve(workingDir, this.build) + fs.writeFileSync(outputPath, processedContent, 'utf8') + } + } + + private processIncludes(template: string, baseDir: string): string { + const includeRegex = /#include\s+"([^"]+)"/g + + return template.replace(includeRegex, (match, includePath) => { + try { + const fullPath = path.resolve(baseDir, includePath) + const includeContent = fs.readFileSync(fullPath, 'utf8') + return this.processIncludes(includeContent, baseDir) + } catch (error) { + console.warn(`Warning: Could not include file ${includePath}: ${error}`) + return match + } + }) + } +} diff --git a/scripts/core/numberParser.ts b/scripts/core/numberParser.ts index 187cc7469d..f9b5a4fbdf 100644 --- a/scripts/core/numberParser.ts +++ b/scripts/core/numberParser.ts @@ -1,10 +1,10 @@ -export default class NumberParser { - async parse(number: string) { - const parsed = parseInt(number) - if (isNaN(parsed)) { - throw new Error('numberParser:parse() Input value is not a number') - } - - return parsed - } -} +export default class NumberParser { + async parse(number: string) { + const parsed = parseInt(number) + if (isNaN(parsed)) { + throw new Error('numberParser:parse() Input value is not a number') + } + + return parsed + } +} diff --git a/scripts/core/playlistParser.ts b/scripts/core/playlistParser.ts index 2086bb568e..08b2542ff9 100644 --- a/scripts/core/playlistParser.ts +++ b/scripts/core/playlistParser.ts @@ -1,60 +1,43 @@ -import { Collection, Storage, Dictionary } from '@freearhey/core' -import parser from 'iptv-playlist-parser' -import { Stream } from '../models' - -type PlaylistPareserProps = { - storage: Storage - feedsGroupedByChannelId: Dictionary - logosGroupedByStreamId: Dictionary - channelsKeyById: Dictionary -} - -export class PlaylistParser { - storage: Storage - feedsGroupedByChannelId: Dictionary - logosGroupedByStreamId: Dictionary - channelsKeyById: Dictionary - - constructor({ - storage, - feedsGroupedByChannelId, - logosGroupedByStreamId, - channelsKeyById - }: PlaylistPareserProps) { - this.storage = storage - this.feedsGroupedByChannelId = feedsGroupedByChannelId - this.logosGroupedByStreamId = logosGroupedByStreamId - this.channelsKeyById = channelsKeyById - } - - async parse(files: string[]): Promise { - let streams = new Collection() - - for (const filepath of files) { - if (!this.storage.existsSync(filepath)) continue - - const _streams: Collection = await this.parseFile(filepath) - streams = streams.concat(_streams) - } - - return streams - } - - async parseFile(filepath: string): Promise { - const content = await this.storage.load(filepath) - const parsed: parser.Playlist = parser.parse(content) - - const streams = new Collection(parsed.items).map((data: parser.PlaylistItem) => { - const stream = new Stream() - .fromPlaylistItem(data) - .withFeed(this.feedsGroupedByChannelId) - .withChannel(this.channelsKeyById) - .withLogos(this.logosGroupedByStreamId) - .setFilepath(filepath) - - return stream - }) - - return streams - } -} +import { Storage } from '@freearhey/storage-js' +import { Collection } from '@freearhey/core' +import parser from 'iptv-playlist-parser' +import { Stream } from '../models' + +type PlaylistPareserProps = { + storage: Storage +} + +export class PlaylistParser { + storage: Storage + + constructor({ storage }: PlaylistPareserProps) { + this.storage = storage + } + + async parse(files: string[]): Promise> { + const parsed = new Collection() + + for (const filepath of files) { + if (!this.storage.existsSync(filepath)) continue + const _parsed: Collection = await this.parseFile(filepath) + parsed.concat(_parsed) + } + + return parsed + } + + async parseFile(filepath: string): Promise> { + const content = await this.storage.load(filepath) + const parsed: parser.Playlist = parser.parse(content) + + const streams = new Collection() + parsed.items.forEach((data: parser.PlaylistItem) => { + const stream = Stream.fromPlaylistItem(data) + stream.filepath = filepath + + streams.add(stream) + }) + + return streams + } +} diff --git a/scripts/core/proxyParser.ts b/scripts/core/proxyParser.ts index 9cede1afc5..545d190a90 100644 --- a/scripts/core/proxyParser.ts +++ b/scripts/core/proxyParser.ts @@ -1,31 +1,31 @@ -import { URL } from 'node:url' - -interface ProxyParserResult { - protocol: string | null - auth?: { - username?: string - password?: string - } - host: string - port: number | null -} - -export class ProxyParser { - parse(_url: string): ProxyParserResult { - const parsed = new URL(_url) - - const result: ProxyParserResult = { - protocol: parsed.protocol.replace(':', '') || null, - host: parsed.hostname, - port: parsed.port ? parseInt(parsed.port) : null - } - - if (parsed.username || parsed.password) { - result.auth = {} - if (parsed.username) result.auth.username = parsed.username - if (parsed.password) result.auth.password = parsed.password - } - - return result - } -} +import { URL } from 'node:url' + +interface ProxyParserResult { + protocol: string | null + auth?: { + username?: string + password?: string + } + host: string + port: number | null +} + +export class ProxyParser { + parse(_url: string): ProxyParserResult { + const parsed = new URL(_url) + + const result: ProxyParserResult = { + protocol: parsed.protocol.replace(':', '') || null, + host: parsed.hostname, + port: parsed.port ? parseInt(parsed.port) : null + } + + if (parsed.username || parsed.password) { + result.auth = {} + if (parsed.username) result.auth.username = parsed.username + if (parsed.password) result.auth.password = parsed.password + } + + return result + } +} diff --git a/scripts/core/streamTester.ts b/scripts/core/streamTester.ts index d5a4f5f591..acb38edc9c 100644 --- a/scripts/core/streamTester.ts +++ b/scripts/core/streamTester.ts @@ -1,117 +1,125 @@ -import { Stream } from '../models' -import { TESTING } from '../constants' -import mediaInfoFactory from 'mediainfo.js' -import axios, { AxiosInstance, AxiosProxyConfig, AxiosRequestConfig } from 'axios' -import { ProxyParser } from './proxyParser.js' -import { OptionValues } from 'commander' -import { SocksProxyAgent } from 'socks-proxy-agent' - -export type TestResult = { - status: { - ok: boolean - code: string - } -} - -export type StreamTesterProps = { - options: OptionValues -} - -export class StreamTester { - client: AxiosInstance - options: OptionValues - - constructor({ options }: StreamTesterProps) { - const proxyParser = new ProxyParser() - let request: AxiosRequestConfig = { - responseType: 'arraybuffer' - } - - if (options.proxy !== undefined) { - const proxy = proxyParser.parse(options.proxy) as AxiosProxyConfig - - if ( - proxy.protocol && - ['socks', 'socks5', 'socks5h', 'socks4', 'socks4a'].includes(String(proxy.protocol)) - ) { - const socksProxyAgent = new SocksProxyAgent(options.proxy) - - request = { ...request, ...{ httpAgent: socksProxyAgent, httpsAgent: socksProxyAgent } } - } else { - request = { ...request, ...{ proxy } } - } - } - - this.client = axios.create(request) - this.options = options - } - - async test(stream: Stream): Promise { - if (TESTING) { - const results = (await import('../../tests/__data__/input/playlist_test/results.js')).default - - return results[stream.url as keyof typeof results] - } else { - try { - const res = await this.client(stream.url, { - signal: AbortSignal.timeout(this.options.timeout), - headers: { - 'User-Agent': stream.getUserAgent() || 'Mozilla/5.0', - Referer: stream.getReferrer() - } - }) - - const mediainfo = await mediaInfoFactory({ format: 'object' }) - const buffer = await res.data - const result = await mediainfo.analyzeData( - () => buffer.byteLength, - (size: any, offset: number | undefined) => - Buffer.from(buffer).subarray(offset, offset + size) - ) - - if (result && result.media && result.media.track.length > 0) { - return { - status: { - ok: true, - code: 'OK' - } - } - } else { - return { - status: { - ok: false, - code: 'NO_VIDEO' - } - } - } - } catch (error: any) { - let code = 'UNKNOWN_ERROR' - if (error.name === 'CanceledError') { - code = 'TIMEOUT' - } else if (error.name === 'AxiosError') { - if (error.response) { - const status = error.response?.status - const statusText = error.response?.statusText.toUpperCase().replace(/\s+/, '_') - code = `HTTP_${status}_${statusText}` - } else { - code = `AXIOS_${error.code}` - } - } else if (error.cause) { - const cause = error.cause as Error & { code?: string } - if (cause.code) { - code = cause.code - } else { - code = cause.name - } - } - - return { - status: { - ok: false, - code - } - } - } - } - } -} +import axios, { AxiosInstance, AxiosProxyConfig, AxiosRequestConfig, AxiosResponse } from 'axios' +import { SocksProxyAgent } from 'socks-proxy-agent' +import { ProxyParser } from './proxyParser.js' +import mediaInfoFactory from 'mediainfo.js' +import { OptionValues } from 'commander' +import { TESTING } from '../constants' +import { Stream } from '../models' + +export type StreamTesterResult = { + status: { + ok: boolean + code: string + } +} + +export type StreamTesterError = { + name: string + code?: string + cause?: Error & { code?: string } + response?: AxiosResponse +} + +export type StreamTesterProps = { + options: OptionValues +} + +export class StreamTester { + client: AxiosInstance + options: OptionValues + + constructor({ options }: StreamTesterProps) { + const proxyParser = new ProxyParser() + let request: AxiosRequestConfig = { + responseType: 'arraybuffer' + } + + if (options.proxy !== undefined) { + const proxy = proxyParser.parse(options.proxy) as AxiosProxyConfig + + if ( + proxy.protocol && + ['socks', 'socks5', 'socks5h', 'socks4', 'socks4a'].includes(String(proxy.protocol)) + ) { + const socksProxyAgent = new SocksProxyAgent(options.proxy) + + request = { ...request, ...{ httpAgent: socksProxyAgent, httpsAgent: socksProxyAgent } } + } else { + request = { ...request, ...{ proxy } } + } + } + + this.client = axios.create(request) + this.options = options + } + + async test(stream: Stream): Promise { + if (TESTING) { + const results = (await import('../../tests/__data__/input/playlist_test/results.js')).default + + return results[stream.url as keyof typeof results] + } else { + try { + const res = await this.client(stream.url, { + signal: AbortSignal.timeout(this.options.timeout), + headers: { + 'User-Agent': stream.user_agent || 'Mozilla/5.0', + Referer: stream.referrer + } + }) + + const mediainfo = await mediaInfoFactory({ format: 'object' }) + const buffer = await res.data + const result = await mediainfo.analyzeData( + () => buffer.byteLength, + (size: number, offset: number) => Buffer.from(buffer).subarray(offset, offset + size) + ) + + if (result && result.media && result.media.track.length > 0) { + return { + status: { + ok: true, + code: 'OK' + } + } + } else { + return { + status: { + ok: false, + code: 'NO_VIDEO' + } + } + } + } catch (err: unknown) { + const error = err as StreamTesterError + + let code = 'UNKNOWN_ERROR' + if (error.name === 'CanceledError') { + code = 'TIMEOUT' + } else if (error.name === 'AxiosError') { + if (error.response) { + const status = error.response?.status + const statusText = error.response?.statusText.toUpperCase().replace(/\s+/, '_') + code = `HTTP_${status}_${statusText}` + } else { + code = `AXIOS_${error.code}` + } + } else if (error.cause) { + const cause = error.cause + if (cause.code) { + code = cause.code + } else { + code = cause.name + } + } + + return { + status: { + ok: false, + code + } + } + } + } + } +} diff --git a/scripts/generators/categoriesGenerator.ts b/scripts/generators/categoriesGenerator.ts index 83eb4b5255..d42719392e 100644 --- a/scripts/generators/categoriesGenerator.ts +++ b/scripts/generators/categoriesGenerator.ts @@ -1,54 +1,60 @@ -import { Collection, Storage, File } from '@freearhey/core' -import { Stream, Category, Playlist } from '../models' -import { PUBLIC_DIR, EOL } from '../constants' -import { Generator } from './generator' - -type CategoriesGeneratorProps = { - streams: Collection - categories: Collection - logFile: File -} - -export class CategoriesGenerator implements Generator { - streams: Collection - categories: Collection - storage: Storage - logFile: File - - constructor({ streams, categories, logFile }: CategoriesGeneratorProps) { - this.streams = streams.clone() - this.categories = categories - this.storage = new Storage(PUBLIC_DIR) - this.logFile = logFile - } - - async generate() { - const streams = this.streams.orderBy([(stream: Stream) => stream.getTitle()]) - - this.categories.forEach(async (category: Category) => { - const categoryStreams = streams - .filter((stream: Stream) => stream.hasCategory(category)) - .map((stream: Stream) => { - const groupTitle = stream.getCategoryNames().join(';') - if (groupTitle) stream.groupTitle = groupTitle - - return stream - }) - - const playlist = new Playlist(categoryStreams, { public: true }) - const filepath = `categories/${category.id}.m3u` - await this.storage.save(filepath, playlist.toString()) - this.logFile.append( - JSON.stringify({ type: 'category', filepath, count: playlist.streams.count() }) + EOL - ) - }) - - const undefinedStreams = streams.filter((stream: Stream) => !stream.hasCategories()) - const playlist = new Playlist(undefinedStreams, { public: true }) - const filepath = 'categories/undefined.m3u' - await this.storage.save(filepath, playlist.toString()) - this.logFile.append( - JSON.stringify({ type: 'category', filepath, count: playlist.streams.count() }) + EOL - ) - } -} +import { Storage, File } from '@freearhey/storage-js' +import { PUBLIC_DIR, EOL } from '../constants' +import { Collection } from '@freearhey/core' +import { Stream, Playlist } from '../models' +import { Generator } from './generator' +import * as sdk from '@iptv-org/sdk' + +type CategoriesGeneratorProps = { + streams: Collection + categories: Collection + logFile: File +} + +export class CategoriesGenerator implements Generator { + streams: Collection + categories: Collection + storage: Storage + logFile: File + + constructor({ streams, categories, logFile }: CategoriesGeneratorProps) { + this.streams = streams.clone() + this.categories = categories + this.storage = new Storage(PUBLIC_DIR) + this.logFile = logFile + } + + async generate() { + const streams = this.streams.sortBy([(stream: Stream) => stream.title]) + + this.categories.forEach(async (category: sdk.Models.Category) => { + const categoryStreams = streams + .filter((stream: Stream) => stream.hasCategory(category)) + .map((stream: Stream) => { + const groupTitle = stream + .getCategories() + .map(category => category.name) + .sort() + .join(';') + if (groupTitle) stream.groupTitle = groupTitle + + return stream + }) + + const playlist = new Playlist(categoryStreams, { public: true }) + const filepath = `categories/${category.id}.m3u` + await this.storage.save(filepath, playlist.toString()) + this.logFile.append( + JSON.stringify({ type: 'category', filepath, count: playlist.streams.count() }) + EOL + ) + }) + + const undefinedStreams = streams.filter((stream: Stream) => stream.getCategories().isEmpty()) + const playlist = new Playlist(undefinedStreams, { public: true }) + const filepath = 'categories/undefined.m3u' + await this.storage.save(filepath, playlist.toString()) + this.logFile.append( + JSON.stringify({ type: 'category', filepath, count: playlist.streams.count() }) + EOL + ) + } +} diff --git a/scripts/generators/citiesGenerator.ts b/scripts/generators/citiesGenerator.ts index 7d0891fbc8..237e8da3dc 100644 --- a/scripts/generators/citiesGenerator.ts +++ b/scripts/generators/citiesGenerator.ts @@ -1,43 +1,54 @@ -import { City, Stream, Playlist } from '../models' -import { Collection, Storage, File } from '@freearhey/core' -import { PUBLIC_DIR, EOL } from '../constants' -import { Generator } from './generator' - -type CitiesGeneratorProps = { - streams: Collection - cities: Collection - logFile: File -} - -export class CitiesGenerator implements Generator { - streams: Collection - cities: Collection - storage: Storage - logFile: File - - constructor({ streams, cities, logFile }: CitiesGeneratorProps) { - this.streams = streams.clone() - this.cities = cities - this.storage = new Storage(PUBLIC_DIR) - this.logFile = logFile - } - - async generate(): Promise { - const streams = this.streams - .orderBy((stream: Stream) => stream.getTitle()) - .filter((stream: Stream) => stream.isSFW()) - - this.cities.forEach(async (city: City) => { - const cityStreams = streams.filter((stream: Stream) => stream.isBroadcastInCity(city)) - - if (cityStreams.isEmpty()) return - - const playlist = new Playlist(cityStreams, { public: true }) - const filepath = `cities/${city.code.toLowerCase()}.m3u` - await this.storage.save(filepath, playlist.toString()) - this.logFile.append( - JSON.stringify({ type: 'city', filepath, count: playlist.streams.count() }) + EOL - ) - }) - } -} +import { Storage, File } from '@freearhey/storage-js' +import { PUBLIC_DIR, EOL } from '../constants' +import { Stream, Playlist } from '../models' +import { Collection } from '@freearhey/core' +import { Generator } from './generator' +import * as sdk from '@iptv-org/sdk' + +type CitiesGeneratorProps = { + streams: Collection + cities: Collection + logFile: File +} + +export class CitiesGenerator implements Generator { + streams: Collection + cities: Collection + storage: Storage + logFile: File + + constructor({ streams, cities, logFile }: CitiesGeneratorProps) { + this.streams = streams.clone() + this.cities = cities + this.storage = new Storage(PUBLIC_DIR) + this.logFile = logFile + } + + async generate(): Promise { + const streams = this.streams + .sortBy((stream: Stream) => stream.title) + .filter((stream: Stream) => stream.isSFW()) + + const streamsGroupedByCityCode = {} + streams.forEach((stream: Stream) => { + stream.getBroadcastCities().forEach((city: sdk.Models.City) => { + if (streamsGroupedByCityCode[city.code]) { + streamsGroupedByCityCode[city.code].add(stream) + } else { + streamsGroupedByCityCode[city.code] = new Collection([stream]) + } + }) + }) + + for (const cityCode in streamsGroupedByCityCode) { + const cityStreams = streamsGroupedByCityCode[cityCode] + + const playlist = new Playlist(cityStreams, { public: true }) + const filepath = `cities/${cityCode.toLowerCase()}.m3u` + await this.storage.save(filepath, playlist.toString()) + this.logFile.append( + JSON.stringify({ type: 'city', filepath, count: playlist.streams.count() }) + EOL + ) + } + } +} diff --git a/scripts/generators/countriesGenerator.ts b/scripts/generators/countriesGenerator.ts index 39d7612582..0ee466dc62 100644 --- a/scripts/generators/countriesGenerator.ts +++ b/scripts/generators/countriesGenerator.ts @@ -1,68 +1,80 @@ -import { Country, Stream, Playlist } from '../models' -import { Collection, Storage, File } from '@freearhey/core' -import { PUBLIC_DIR, EOL } from '../constants' -import { Generator } from './generator' - -type CountriesGeneratorProps = { - streams: Collection - countries: Collection - logFile: File -} - -export class CountriesGenerator implements Generator { - streams: Collection - countries: Collection - storage: Storage - logFile: File - - constructor({ streams, countries, logFile }: CountriesGeneratorProps) { - this.streams = streams.clone() - this.countries = countries - this.storage = new Storage(PUBLIC_DIR) - this.logFile = logFile - } - - async generate(): Promise { - const streams = this.streams - .orderBy((stream: Stream) => stream.getTitle()) - .filter((stream: Stream) => stream.isSFW()) - - this.countries.forEach(async (country: Country) => { - const countryStreams = streams.filter((stream: Stream) => - stream.isBroadcastInCountry(country) - ) - if (countryStreams.isEmpty()) return - - const playlist = new Playlist(countryStreams, { public: true }) - const filepath = `countries/${country.code.toLowerCase()}.m3u` - await this.storage.save(filepath, playlist.toString()) - this.logFile.append( - JSON.stringify({ type: 'country', filepath, count: playlist.streams.count() }) + EOL - ) - }) - - const internationalStreams = streams.filter((stream: Stream) => stream.isInternational()) - const internationalPlaylist = new Playlist(internationalStreams, { public: true }) - const internationalFilepath = 'countries/int.m3u' - await this.storage.save(internationalFilepath, internationalPlaylist.toString()) - this.logFile.append( - JSON.stringify({ - type: 'country', - filepath: internationalFilepath, - count: internationalPlaylist.streams.count() - }) + EOL - ) - - const undefinedStreams = streams.filter((stream: Stream) => !stream.hasBroadcastArea()) - const undefinedPlaylist = new Playlist(undefinedStreams, { public: true }) - const undefinedFilepath = 'countries/undefined.m3u' - await this.storage.save(undefinedFilepath, undefinedPlaylist.toString()) - this.logFile.append( - JSON.stringify({ - type: 'country', - filepath: undefinedFilepath, - count: undefinedPlaylist.streams.count() - }) + EOL - ) - } -} +import { Storage, File } from '@freearhey/storage-js' +import { PUBLIC_DIR, EOL } from '../constants' +import { Stream, Playlist } from '../models' +import { Collection } from '@freearhey/core' +import { Generator } from './generator' +import * as sdk from '@iptv-org/sdk' + +type CountriesGeneratorProps = { + streams: Collection + countries: Collection + logFile: File +} + +export class CountriesGenerator implements Generator { + streams: Collection + countries: Collection + storage: Storage + logFile: File + + constructor({ streams, countries, logFile }: CountriesGeneratorProps) { + this.streams = streams.clone() + this.countries = countries + this.storage = new Storage(PUBLIC_DIR) + this.logFile = logFile + } + + async generate(): Promise { + const streams = this.streams + .sortBy((stream: Stream) => stream.title) + .filter((stream: Stream) => stream.isSFW()) + + const streamsGroupedByCountryCode = {} + streams.forEach((stream: Stream) => { + stream.getBroadcastCountries().forEach((country: sdk.Models.Country) => { + if (streamsGroupedByCountryCode[country.code]) { + streamsGroupedByCountryCode[country.code].add(stream) + } else { + streamsGroupedByCountryCode[country.code] = new Collection([stream]) + } + }) + }) + + for (const countryCode in streamsGroupedByCountryCode) { + const countryStreams = streamsGroupedByCountryCode[countryCode] + + const playlist = new Playlist(countryStreams, { public: true }) + const filepath = `countries/${countryCode.toLowerCase()}.m3u` + await this.storage.save(filepath, playlist.toString()) + this.logFile.append( + JSON.stringify({ type: 'country', filepath, count: playlist.streams.count() }) + EOL + ) + } + + const internationalStreams = streams.filter((stream: Stream) => stream.isInternational()) + const internationalPlaylist = new Playlist(internationalStreams, { public: true }) + const internationalFilepath = 'countries/int.m3u' + await this.storage.save(internationalFilepath, internationalPlaylist.toString()) + this.logFile.append( + JSON.stringify({ + type: 'country', + filepath: internationalFilepath, + count: internationalPlaylist.streams.count() + }) + EOL + ) + + const undefinedStreams = streams.filter((stream: Stream) => + stream.getBroadcastAreaCodes().isEmpty() + ) + const undefinedPlaylist = new Playlist(undefinedStreams, { public: true }) + const undefinedFilepath = 'countries/undefined.m3u' + await this.storage.save(undefinedFilepath, undefinedPlaylist.toString()) + this.logFile.append( + JSON.stringify({ + type: 'country', + filepath: undefinedFilepath, + count: undefinedPlaylist.streams.count() + }) + EOL + ) + } +} diff --git a/scripts/generators/generator.ts b/scripts/generators/generator.ts index 4220df727d..bf44549064 100644 --- a/scripts/generators/generator.ts +++ b/scripts/generators/generator.ts @@ -1,3 +1,3 @@ -export interface Generator { - generate(): Promise -} +export interface Generator { + generate(): Promise +} diff --git a/scripts/generators/index.ts b/scripts/generators/index.ts index 66cf94eb4e..1cfd8a38ec 100644 --- a/scripts/generators/index.ts +++ b/scripts/generators/index.ts @@ -1,13 +1,12 @@ -export * from './categoriesGenerator' -export * from './citiesGenerator' -export * from './countriesGenerator' -export * from './indexCategoryGenerator' -export * from './indexCountryGenerator' -export * from './indexGenerator' -export * from './indexLanguageGenerator' -export * from './indexNsfwGenerator' -export * from './languagesGenerator' -export * from './rawGenerator' -export * from './regionsGenerator' -export * from './sourcesGenerator' -export * from './subdivisionsGenerator' +export * from './categoriesGenerator' +export * from './citiesGenerator' +export * from './countriesGenerator' +export * from './indexCategoryGenerator' +export * from './indexCountryGenerator' +export * from './indexGenerator' +export * from './indexLanguageGenerator' +export * from './languagesGenerator' +export * from './rawGenerator' +export * from './regionsGenerator' +export * from './sourcesGenerator' +export * from './subdivisionsGenerator' diff --git a/scripts/generators/indexCategoryGenerator.ts b/scripts/generators/indexCategoryGenerator.ts index 754a7d22f1..08ebf74be8 100644 --- a/scripts/generators/indexCategoryGenerator.ts +++ b/scripts/generators/indexCategoryGenerator.ts @@ -1,55 +1,56 @@ -import { Collection, Storage, File } from '@freearhey/core' -import { Stream, Playlist, Category } from '../models' -import { PUBLIC_DIR, EOL } from '../constants' -import { Generator } from './generator' - -type IndexCategoryGeneratorProps = { - streams: Collection - logFile: File -} - -export class IndexCategoryGenerator implements Generator { - streams: Collection - storage: Storage - logFile: File - - constructor({ streams, logFile }: IndexCategoryGeneratorProps) { - this.streams = streams.clone() - this.storage = new Storage(PUBLIC_DIR) - this.logFile = logFile - } - - async generate(): Promise { - const streams = this.streams - .orderBy(stream => stream.getTitle()) - .filter(stream => stream.isSFW()) - - let groupedStreams = new Collection() - streams.forEach((stream: Stream) => { - if (!stream.hasCategories()) { - const streamClone = stream.clone() - streamClone.groupTitle = 'Undefined' - groupedStreams.add(streamClone) - return - } - - stream.getCategories().forEach((category: Category) => { - const streamClone = stream.clone() - streamClone.groupTitle = category.name - groupedStreams.push(streamClone) - }) - }) - - groupedStreams = groupedStreams.orderBy(stream => { - if (stream.groupTitle === 'Undefined') return 'ZZ' - return stream.groupTitle - }) - - const playlist = new Playlist(groupedStreams, { public: true }) - const filepath = 'index.category.m3u' - await this.storage.save(filepath, playlist.toString()) - this.logFile.append( - JSON.stringify({ type: 'index', filepath, count: playlist.streams.count() }) + EOL - ) - } -} +import { Storage, File } from '@freearhey/storage-js' +import { PUBLIC_DIR, EOL } from '../constants' +import { Stream, Playlist } from '../models' +import { Collection } from '@freearhey/core' +import { Generator } from './generator' +import * as sdk from '@iptv-org/sdk' + +type IndexCategoryGeneratorProps = { + streams: Collection + logFile: File +} + +export class IndexCategoryGenerator implements Generator { + streams: Collection + storage: Storage + logFile: File + + constructor({ streams, logFile }: IndexCategoryGeneratorProps) { + this.streams = streams.clone() + this.storage = new Storage(PUBLIC_DIR) + this.logFile = logFile + } + + async generate(): Promise { + const streams = this.streams.sortBy(stream => stream.title).filter(stream => stream.isSFW()) + + let groupedStreams = new Collection() + streams.forEach((stream: Stream) => { + const streamCategories = stream.getCategories() + if (streamCategories.isEmpty()) { + const streamClone = stream.clone() + streamClone.groupTitle = 'Undefined' + groupedStreams.add(streamClone) + return + } + + streamCategories.forEach((category: sdk.Models.Category) => { + const streamClone = stream.clone() + streamClone.groupTitle = category.name + groupedStreams.add(streamClone) + }) + }) + + groupedStreams = groupedStreams.sortBy(stream => { + if (stream.groupTitle === 'Undefined') return 'ZZ' + return stream.groupTitle + }) + + const playlist = new Playlist(groupedStreams, { public: true }) + const filepath = 'index.category.m3u' + await this.storage.save(filepath, playlist.toString()) + this.logFile.append( + JSON.stringify({ type: 'index', filepath, count: playlist.streams.count() }) + EOL + ) + } +} diff --git a/scripts/generators/indexCountryGenerator.ts b/scripts/generators/indexCountryGenerator.ts index 016e86f731..078a1f9d6a 100644 --- a/scripts/generators/indexCountryGenerator.ts +++ b/scripts/generators/indexCountryGenerator.ts @@ -1,63 +1,67 @@ -import { Collection, Storage, File } from '@freearhey/core' -import { Stream, Playlist, Country } from '../models' -import { PUBLIC_DIR, EOL } from '../constants' -import { Generator } from './generator' - -type IndexCountryGeneratorProps = { - streams: Collection - logFile: File -} - -export class IndexCountryGenerator implements Generator { - streams: Collection - storage: Storage - logFile: File - - constructor({ streams, logFile }: IndexCountryGeneratorProps) { - this.streams = streams.clone() - this.storage = new Storage(PUBLIC_DIR) - this.logFile = logFile - } - - async generate(): Promise { - let groupedStreams = new Collection() - - this.streams - .orderBy((stream: Stream) => stream.getTitle()) - .filter((stream: Stream) => stream.isSFW()) - .forEach((stream: Stream) => { - if (!stream.hasBroadcastArea()) { - const streamClone = stream.clone() - streamClone.groupTitle = 'Undefined' - groupedStreams.add(streamClone) - return - } - - stream.getBroadcastCountries().forEach((country: Country) => { - const streamClone = stream.clone() - streamClone.groupTitle = country.name - groupedStreams.add(streamClone) - }) - - if (stream.isInternational()) { - const streamClone = stream.clone() - streamClone.groupTitle = 'International' - groupedStreams.add(streamClone) - } - }) - - groupedStreams = groupedStreams.orderBy((stream: Stream) => { - if (stream.groupTitle === 'International') return 'ZZ' - if (stream.groupTitle === 'Undefined') return 'ZZZ' - - return stream.groupTitle - }) - - const playlist = new Playlist(groupedStreams, { public: true }) - const filepath = 'index.country.m3u' - await this.storage.save(filepath, playlist.toString()) - this.logFile.append( - JSON.stringify({ type: 'index', filepath, count: playlist.streams.count() }) + EOL - ) - } -} +import { Storage, File } from '@freearhey/storage-js' +import { PUBLIC_DIR, EOL } from '../constants' +import { Stream, Playlist } from '../models' +import { Collection } from '@freearhey/core' +import { Generator } from './generator' +import * as sdk from '@iptv-org/sdk' + +type IndexCountryGeneratorProps = { + streams: Collection + logFile: File +} + +export class IndexCountryGenerator implements Generator { + streams: Collection + storage: Storage + logFile: File + + constructor({ streams, logFile }: IndexCountryGeneratorProps) { + this.streams = streams.clone() + this.storage = new Storage(PUBLIC_DIR) + this.logFile = logFile + } + + async generate(): Promise { + let groupedStreams = new Collection() + + this.streams + .sortBy((stream: Stream) => stream.title) + .filter((stream: Stream) => stream.isSFW()) + .forEach((stream: Stream) => { + const broadcastAreaCountries = stream.getBroadcastCountries() + + if (stream.getBroadcastAreaCodes().isEmpty()) { + const streamClone = stream.clone() + streamClone.groupTitle = 'Undefined' + groupedStreams.add(streamClone) + return + } + + broadcastAreaCountries.forEach((country: sdk.Models.Country) => { + const streamClone = stream.clone() + streamClone.groupTitle = country.name + groupedStreams.add(streamClone) + }) + + if (stream.isInternational()) { + const streamClone = stream.clone() + streamClone.groupTitle = 'International' + groupedStreams.add(streamClone) + } + }) + + groupedStreams = groupedStreams.sortBy((stream: Stream) => { + if (stream.groupTitle === 'International') return 'ZZ' + if (stream.groupTitle === 'Undefined') return 'ZZZ' + + return stream.groupTitle + }) + + const playlist = new Playlist(groupedStreams, { public: true }) + const filepath = 'index.country.m3u' + await this.storage.save(filepath, playlist.toString()) + this.logFile.append( + JSON.stringify({ type: 'index', filepath, count: playlist.streams.count() }) + EOL + ) + } +} diff --git a/scripts/generators/indexGenerator.ts b/scripts/generators/indexGenerator.ts index 6dacf4bba1..fdfdde19d3 100644 --- a/scripts/generators/indexGenerator.ts +++ b/scripts/generators/indexGenerator.ts @@ -1,40 +1,45 @@ -import { Collection, File, Storage } from '@freearhey/core' -import { Stream, Playlist } from '../models' -import { PUBLIC_DIR, EOL } from '../constants' -import { Generator } from './generator' - -type IndexGeneratorProps = { - streams: Collection - logFile: File -} - -export class IndexGenerator implements Generator { - streams: Collection - storage: Storage - logFile: File - - constructor({ streams, logFile }: IndexGeneratorProps) { - this.streams = streams.clone() - this.storage = new Storage(PUBLIC_DIR) - this.logFile = logFile - } - - async generate(): Promise { - const sfwStreams = this.streams - .orderBy(stream => stream.getTitle()) - .filter((stream: Stream) => stream.isSFW()) - .map((stream: Stream) => { - const groupTitle = stream.getCategoryNames().join(';') - if (groupTitle) stream.groupTitle = groupTitle - - return stream - }) - - const playlist = new Playlist(sfwStreams, { public: true }) - const filepath = 'index.m3u' - await this.storage.save(filepath, playlist.toString()) - this.logFile.append( - JSON.stringify({ type: 'index', filepath, count: playlist.streams.count() }) + EOL - ) - } -} +import { Storage, File } from '@freearhey/storage-js' +import { PUBLIC_DIR, EOL } from '../constants' +import { Stream, Playlist } from '../models' +import { Collection } from '@freearhey/core' +import { Generator } from './generator' + +type IndexGeneratorProps = { + streams: Collection + logFile: File +} + +export class IndexGenerator implements Generator { + streams: Collection + storage: Storage + logFile: File + + constructor({ streams, logFile }: IndexGeneratorProps) { + this.streams = streams.clone() + this.storage = new Storage(PUBLIC_DIR) + this.logFile = logFile + } + + async generate(): Promise { + const sfwStreams = this.streams + .sortBy(stream => stream.title) + .filter((stream: Stream) => stream.isSFW()) + .map((stream: Stream) => { + const groupTitle = stream + .getCategories() + .map(category => category.name) + .sort() + .join(';') + if (groupTitle) stream.groupTitle = groupTitle + + return stream + }) + + const playlist = new Playlist(sfwStreams, { public: true }) + const filepath = 'index.m3u' + await this.storage.save(filepath, playlist.toString()) + this.logFile.append( + JSON.stringify({ type: 'index', filepath, count: playlist.streams.count() }) + EOL + ) + } +} diff --git a/scripts/generators/indexLanguageGenerator.ts b/scripts/generators/indexLanguageGenerator.ts index 96fb17cee0..5e93a46adb 100644 --- a/scripts/generators/indexLanguageGenerator.ts +++ b/scripts/generators/indexLanguageGenerator.ts @@ -1,54 +1,57 @@ -import { Collection, Storage, File } from '@freearhey/core' -import { Stream, Playlist, Language } from '../models' -import { PUBLIC_DIR, EOL } from '../constants' -import { Generator } from './generator' - -type IndexLanguageGeneratorProps = { - streams: Collection - logFile: File -} - -export class IndexLanguageGenerator implements Generator { - streams: Collection - storage: Storage - logFile: File - - constructor({ streams, logFile }: IndexLanguageGeneratorProps) { - this.streams = streams.clone() - this.storage = new Storage(PUBLIC_DIR) - this.logFile = logFile - } - - async generate(): Promise { - let groupedStreams = new Collection() - this.streams - .orderBy((stream: Stream) => stream.getTitle()) - .filter((stream: Stream) => stream.isSFW()) - .forEach((stream: Stream) => { - if (!stream.hasLanguages()) { - const streamClone = stream.clone() - streamClone.groupTitle = 'Undefined' - groupedStreams.add(streamClone) - return - } - - stream.getLanguages().forEach((language: Language) => { - const streamClone = stream.clone() - streamClone.groupTitle = language.name - groupedStreams.add(streamClone) - }) - }) - - groupedStreams = groupedStreams.orderBy((stream: Stream) => { - if (stream.groupTitle === 'Undefined') return 'ZZ' - return stream.groupTitle - }) - - const playlist = new Playlist(groupedStreams, { public: true }) - const filepath = 'index.language.m3u' - await this.storage.save(filepath, playlist.toString()) - this.logFile.append( - JSON.stringify({ type: 'index', filepath, count: playlist.streams.count() }) + EOL - ) - } -} +import { Storage, File } from '@freearhey/storage-js' +import { PUBLIC_DIR, EOL } from '../constants' +import { Stream, Playlist } from '../models' +import { Collection } from '@freearhey/core' +import { Generator } from './generator' +import * as sdk from '@iptv-org/sdk' + +type IndexLanguageGeneratorProps = { + streams: Collection + logFile: File +} + +export class IndexLanguageGenerator implements Generator { + streams: Collection + storage: Storage + logFile: File + + constructor({ streams, logFile }: IndexLanguageGeneratorProps) { + this.streams = streams.clone() + this.storage = new Storage(PUBLIC_DIR) + this.logFile = logFile + } + + async generate(): Promise { + let groupedStreams = new Collection() + this.streams + .sortBy((stream: Stream) => stream.title) + .filter((stream: Stream) => stream.isSFW()) + .forEach((stream: Stream) => { + const streamLanguages = stream.getLanguages() + if (streamLanguages.isEmpty()) { + const streamClone = stream.clone() + streamClone.groupTitle = 'Undefined' + groupedStreams.add(streamClone) + return + } + + streamLanguages.forEach((language: sdk.Models.Language) => { + const streamClone = stream.clone() + streamClone.groupTitle = language.name + groupedStreams.add(streamClone) + }) + }) + + groupedStreams = groupedStreams.sortBy((stream: Stream) => { + if (stream.groupTitle === 'Undefined') return 'ZZ' + return stream.groupTitle + }) + + const playlist = new Playlist(groupedStreams, { public: true }) + const filepath = 'index.language.m3u' + await this.storage.save(filepath, playlist.toString()) + this.logFile.append( + JSON.stringify({ type: 'index', filepath, count: playlist.streams.count() }) + EOL + ) + } +} diff --git a/scripts/generators/indexNsfwGenerator.ts b/scripts/generators/indexNsfwGenerator.ts deleted file mode 100644 index 14f3189d51..0000000000 --- a/scripts/generators/indexNsfwGenerator.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { Collection, File, Storage } from '@freearhey/core' -import { Stream, Playlist } from '../models' -import { PUBLIC_DIR, EOL } from '../constants' -import { Generator } from './generator' - -type IndexNsfwGeneratorProps = { - streams: Collection - logFile: File -} - -export class IndexNsfwGenerator implements Generator { - streams: Collection - storage: Storage - logFile: File - - constructor({ streams, logFile }: IndexNsfwGeneratorProps) { - this.streams = streams.clone() - this.storage = new Storage(PUBLIC_DIR) - this.logFile = logFile - } - - async generate(): Promise { - const allStreams = this.streams.orderBy((stream: Stream) => stream.getTitle()) - - const playlist = new Playlist(allStreams, { public: true }) - const filepath = 'index.nsfw.m3u' - await this.storage.save(filepath, playlist.toString()) - this.logFile.append( - JSON.stringify({ type: 'index', filepath, count: playlist.streams.count() }) + EOL - ) - } -} diff --git a/scripts/generators/languagesGenerator.ts b/scripts/generators/languagesGenerator.ts index f07e984d13..28fce5241a 100644 --- a/scripts/generators/languagesGenerator.ts +++ b/scripts/generators/languagesGenerator.ts @@ -1,57 +1,58 @@ -import { Collection, Storage, File } from '@freearhey/core' -import { Playlist, Language, Stream } from '../models' -import { PUBLIC_DIR, EOL } from '../constants' -import { Generator } from './generator' - -type LanguagesGeneratorProps = { streams: Collection; logFile: File } - -export class LanguagesGenerator implements Generator { - streams: Collection - storage: Storage - logFile: File - - constructor({ streams, logFile }: LanguagesGeneratorProps) { - this.streams = streams.clone() - this.storage = new Storage(PUBLIC_DIR) - this.logFile = logFile - } - - async generate(): Promise { - const streams = this.streams - .orderBy((stream: Stream) => stream.getTitle()) - .filter((stream: Stream) => stream.isSFW()) - - let languages = new Collection() - streams.forEach((stream: Stream) => { - languages = languages.concat(stream.getLanguages()) - }) - - languages - .filter(Boolean) - .uniqBy((language: Language) => language.code) - .orderBy((language: Language) => language.name) - .forEach(async (language: Language) => { - const languageStreams = streams.filter((stream: Stream) => stream.hasLanguage(language)) - - if (languageStreams.isEmpty()) return - - const playlist = new Playlist(languageStreams, { public: true }) - const filepath = `languages/${language.code}.m3u` - await this.storage.save(filepath, playlist.toString()) - this.logFile.append( - JSON.stringify({ type: 'language', filepath, count: playlist.streams.count() }) + EOL - ) - }) - - const undefinedStreams = streams.filter((stream: Stream) => !stream.hasLanguages()) - - if (undefinedStreams.isEmpty()) return - - const playlist = new Playlist(undefinedStreams, { public: true }) - const filepath = 'languages/undefined.m3u' - await this.storage.save(filepath, playlist.toString()) - this.logFile.append( - JSON.stringify({ type: 'language', filepath, count: playlist.streams.count() }) + EOL - ) - } -} +import { Storage, File } from '@freearhey/storage-js' +import { PUBLIC_DIR, EOL } from '../constants' +import { Playlist, Stream } from '../models' +import { Collection } from '@freearhey/core' +import { Generator } from './generator' +import * as sdk from '@iptv-org/sdk' + +type LanguagesGeneratorProps = { streams: Collection; logFile: File } + +export class LanguagesGenerator implements Generator { + streams: Collection + storage: Storage + logFile: File + + constructor({ streams, logFile }: LanguagesGeneratorProps) { + this.streams = streams.clone() + this.storage = new Storage(PUBLIC_DIR) + this.logFile = logFile + } + + async generate(): Promise { + const streams: Collection = this.streams + .sortBy((stream: Stream) => stream.title) + .filter((stream: Stream) => stream.isSFW()) + + const languages = new Collection() + streams.forEach((stream: Stream) => { + languages.concat(stream.getLanguages()) + }) + + languages + .filter(Boolean) + .uniqBy((language: sdk.Models.Language) => language.code) + .sortBy((language: sdk.Models.Language) => language.name) + .forEach(async (language: sdk.Models.Language) => { + const languageStreams = streams.filter((stream: Stream) => stream.hasLanguage(language)) + + if (languageStreams.isEmpty()) return + + const playlist = new Playlist(languageStreams, { public: true }) + const filepath = `languages/${language.code}.m3u` + await this.storage.save(filepath, playlist.toString()) + this.logFile.append( + JSON.stringify({ type: 'language', filepath, count: playlist.streams.count() }) + EOL + ) + }) + + const undefinedStreams = streams.filter((stream: Stream) => stream.getLanguages().isEmpty()) + if (undefinedStreams.isEmpty()) return + + const playlist = new Playlist(undefinedStreams, { public: true }) + const filepath = 'languages/undefined.m3u' + await this.storage.save(filepath, playlist.toString()) + this.logFile.append( + JSON.stringify({ type: 'language', filepath, count: playlist.streams.count() }) + EOL + ) + } +} diff --git a/scripts/generators/rawGenerator.ts b/scripts/generators/rawGenerator.ts index 2816432d93..f16bdf76a7 100644 --- a/scripts/generators/rawGenerator.ts +++ b/scripts/generators/rawGenerator.ts @@ -1,40 +1,45 @@ -import { Collection, Storage, File } from '@freearhey/core' -import { Stream, Playlist } from '../models' -import { PUBLIC_DIR, EOL } from '../constants' -import { Generator } from './generator' - -type RawGeneratorProps = { - streams: Collection - logFile: File -} - -export class RawGenerator implements Generator { - streams: Collection - storage: Storage - logFile: File - - constructor({ streams, logFile }: RawGeneratorProps) { - this.streams = streams.clone() - this.storage = new Storage(PUBLIC_DIR) - this.logFile = logFile - } - - async generate() { - const files = this.streams.groupBy((stream: Stream) => stream.getFilename()) - - for (const filename of files.keys()) { - const streams = new Collection(files.get(filename)).map((stream: Stream) => { - const groupTitle = stream.getCategoryNames().join(';') - if (groupTitle) stream.groupTitle = groupTitle - - return stream - }) - const playlist = new Playlist(streams, { public: true }) - const filepath = `raw/${filename}` - await this.storage.save(filepath, playlist.toString()) - this.logFile.append( - JSON.stringify({ type: 'raw', filepath, count: playlist.streams.count() }) + EOL - ) - } - } -} +import { Storage, File } from '@freearhey/storage-js' +import { PUBLIC_DIR, EOL } from '../constants' +import { Stream, Playlist } from '../models' +import { Collection } from '@freearhey/core' +import { Generator } from './generator' + +type RawGeneratorProps = { + streams: Collection + logFile: File +} + +export class RawGenerator implements Generator { + streams: Collection + storage: Storage + logFile: File + + constructor({ streams, logFile }: RawGeneratorProps) { + this.streams = streams.clone() + this.storage = new Storage(PUBLIC_DIR) + this.logFile = logFile + } + + async generate() { + const files = this.streams.groupBy((stream: Stream) => stream.getFilename()) + + for (const filename of files.keys()) { + const streams = new Collection(files.get(filename)).map((stream: Stream) => { + const groupTitle = stream + .getCategories() + .map(category => category.name) + .sort() + .join(';') + if (groupTitle) stream.groupTitle = groupTitle + + return stream + }) + const playlist = new Playlist(streams, { public: true }) + const filepath = `raw/${filename}` + await this.storage.save(filepath, playlist.toString()) + this.logFile.append( + JSON.stringify({ type: 'raw', filepath, count: playlist.streams.count() }) + EOL + ) + } + } +} diff --git a/scripts/generators/regionsGenerator.ts b/scripts/generators/regionsGenerator.ts index 02112974ed..c0d669bed6 100644 --- a/scripts/generators/regionsGenerator.ts +++ b/scripts/generators/regionsGenerator.ts @@ -1,41 +1,54 @@ -import { Collection, Storage, File } from '@freearhey/core' -import { Playlist, Region, Stream } from '../models' -import { PUBLIC_DIR, EOL } from '../constants' -import { Generator } from './generator' - -type RegionsGeneratorProps = { - streams: Collection - regions: Collection - logFile: File -} - -export class RegionsGenerator implements Generator { - streams: Collection - regions: Collection - storage: Storage - logFile: File - - constructor({ streams, regions, logFile }: RegionsGeneratorProps) { - this.streams = streams.clone() - this.regions = regions - this.storage = new Storage(PUBLIC_DIR) - this.logFile = logFile - } - - async generate(): Promise { - const streams = this.streams - .orderBy((stream: Stream) => stream.getTitle()) - .filter((stream: Stream) => stream.isSFW()) - - this.regions.forEach(async (region: Region) => { - const regionStreams = streams.filter((stream: Stream) => stream.isBroadcastInRegion(region)) - - const playlist = new Playlist(regionStreams, { public: true }) - const filepath = `regions/${region.code.toLowerCase()}.m3u` - await this.storage.save(filepath, playlist.toString()) - this.logFile.append( - JSON.stringify({ type: 'region', filepath, count: playlist.streams.count() }) + EOL - ) - }) - } -} +import { Storage, File } from '@freearhey/storage-js' +import { PUBLIC_DIR, EOL } from '../constants' +import { Playlist, Stream } from '../models' +import { Collection } from '@freearhey/core' +import { Generator } from './generator' +import * as sdk from '@iptv-org/sdk' + +type RegionsGeneratorProps = { + streams: Collection + regions: Collection + logFile: File +} + +export class RegionsGenerator implements Generator { + streams: Collection + regions: Collection + storage: Storage + logFile: File + + constructor({ streams, regions, logFile }: RegionsGeneratorProps) { + this.streams = streams.clone() + this.regions = regions + this.storage = new Storage(PUBLIC_DIR) + this.logFile = logFile + } + + async generate(): Promise { + const streams = this.streams + .sortBy((stream: Stream) => stream.title) + .filter((stream: Stream) => stream.isSFW()) + + const streamsGroupedByRegionCode = {} + streams.forEach((stream: Stream) => { + stream.getBroadcastRegions().forEach((region: sdk.Models.Region) => { + if (streamsGroupedByRegionCode[region.code]) { + streamsGroupedByRegionCode[region.code].add(stream) + } else { + streamsGroupedByRegionCode[region.code] = new Collection([stream]) + } + }) + }) + + for (const regionCode in streamsGroupedByRegionCode) { + const regionStreams = streamsGroupedByRegionCode[regionCode] + + const playlist = new Playlist(regionStreams, { public: true }) + const filepath = `regions/${regionCode.toLowerCase()}.m3u` + await this.storage.save(filepath, playlist.toString()) + this.logFile.append( + JSON.stringify({ type: 'region', filepath, count: playlist.streams.count() }) + EOL + ) + } + } +} diff --git a/scripts/generators/sourcesGenerator.ts b/scripts/generators/sourcesGenerator.ts index 607c05b0e5..d90bc7f742 100644 --- a/scripts/generators/sourcesGenerator.ts +++ b/scripts/generators/sourcesGenerator.ts @@ -1,43 +1,49 @@ -import { Collection, Storage, File, type Dictionary } from '@freearhey/core' -import { Stream, Playlist } from '../models' -import { PUBLIC_DIR, EOL } from '../constants' -import { Generator } from './generator' - -type SourcesGeneratorProps = { - streams: Collection - logFile: File -} - -export class SourcesGenerator implements Generator { - streams: Collection - storage: Storage - logFile: File - - constructor({ streams, logFile }: SourcesGeneratorProps) { - this.streams = streams.clone() - this.storage = new Storage(PUBLIC_DIR) - this.logFile = logFile - } - - async generate() { - const files: Dictionary = this.streams.groupBy((stream: Stream) => stream.getFilename()) - - for (const filename of files.keys()) { - if (!filename) continue - - let streams = new Collection(files.get(filename)) - streams = streams.map((stream: Stream) => { - const groupTitle = stream.getCategoryNames().join(';') - if (groupTitle) stream.groupTitle = groupTitle - - return stream - }) - const playlist = new Playlist(streams, { public: true }) - const filepath = `sources/${filename}` - await this.storage.save(filepath, playlist.toString()) - this.logFile.append( - JSON.stringify({ type: 'source', filepath, count: playlist.streams.count() }) + EOL - ) - } - } -} +import { Collection, Dictionary } from '@freearhey/core' +import { Storage, File } from '@freearhey/storage-js' +import { PUBLIC_DIR, EOL } from '../constants' +import { Stream, Playlist } from '../models' +import { Generator } from './generator' + +type SourcesGeneratorProps = { + streams: Collection + logFile: File +} + +export class SourcesGenerator implements Generator { + streams: Collection + storage: Storage + logFile: File + + constructor({ streams, logFile }: SourcesGeneratorProps) { + this.streams = streams.clone() + this.storage = new Storage(PUBLIC_DIR) + this.logFile = logFile + } + + async generate() { + const files: Dictionary = this.streams.groupBy((stream: Stream) => + stream.getFilename() + ) + + for (const filename of files.keys()) { + if (!filename) continue + + const streams = new Collection(files.get(filename)).map((stream: Stream) => { + const groupTitle = stream + .getCategories() + .map(category => category.name) + .sort() + .join(';') + if (groupTitle) stream.groupTitle = groupTitle + + return stream + }) + const playlist = new Playlist(streams, { public: true }) + const filepath = `sources/${filename}` + await this.storage.save(filepath, playlist.toString()) + this.logFile.append( + JSON.stringify({ type: 'source', filepath, count: playlist.streams.count() }) + EOL + ) + } + } +} diff --git a/scripts/generators/subdivisionsGenerator.ts b/scripts/generators/subdivisionsGenerator.ts index 8ddce23328..758f6738f2 100644 --- a/scripts/generators/subdivisionsGenerator.ts +++ b/scripts/generators/subdivisionsGenerator.ts @@ -1,45 +1,54 @@ -import { Subdivision, Stream, Playlist } from '../models' -import { Collection, Storage, File } from '@freearhey/core' -import { PUBLIC_DIR, EOL } from '../constants' -import { Generator } from './generator' - -type SubdivisionsGeneratorProps = { - streams: Collection - subdivisions: Collection - logFile: File -} - -export class SubdivisionsGenerator implements Generator { - streams: Collection - subdivisions: Collection - storage: Storage - logFile: File - - constructor({ streams, subdivisions, logFile }: SubdivisionsGeneratorProps) { - this.streams = streams.clone() - this.subdivisions = subdivisions - this.storage = new Storage(PUBLIC_DIR) - this.logFile = logFile - } - - async generate(): Promise { - const streams = this.streams - .orderBy((stream: Stream) => stream.getTitle()) - .filter((stream: Stream) => stream.isSFW()) - - this.subdivisions.forEach(async (subdivision: Subdivision) => { - const subdivisionStreams = streams.filter((stream: Stream) => - stream.isBroadcastInSubdivision(subdivision) - ) - - if (subdivisionStreams.isEmpty()) return - - const playlist = new Playlist(subdivisionStreams, { public: true }) - const filepath = `subdivisions/${subdivision.code.toLowerCase()}.m3u` - await this.storage.save(filepath, playlist.toString()) - this.logFile.append( - JSON.stringify({ type: 'subdivision', filepath, count: playlist.streams.count() }) + EOL - ) - }) - } -} +import { Storage, File } from '@freearhey/storage-js' +import { PUBLIC_DIR, EOL } from '../constants' +import { Stream, Playlist } from '../models' +import { Collection } from '@freearhey/core' +import { Generator } from './generator' +import * as sdk from '@iptv-org/sdk' + +type SubdivisionsGeneratorProps = { + streams: Collection + subdivisions: Collection + logFile: File +} + +export class SubdivisionsGenerator implements Generator { + streams: Collection + subdivisions: Collection + storage: Storage + logFile: File + + constructor({ streams, subdivisions, logFile }: SubdivisionsGeneratorProps) { + this.streams = streams.clone() + this.subdivisions = subdivisions + this.storage = new Storage(PUBLIC_DIR) + this.logFile = logFile + } + + async generate(): Promise { + const streams = this.streams + .sortBy((stream: Stream) => stream.title) + .filter((stream: Stream) => stream.isSFW()) + + const streamsGroupedBySubdivisionCode = {} + streams.forEach((stream: Stream) => { + stream.getBroadcastSubdivisions().forEach((subdivision: sdk.Models.Subdivision) => { + if (streamsGroupedBySubdivisionCode[subdivision.code]) { + streamsGroupedBySubdivisionCode[subdivision.code].add(stream) + } else { + streamsGroupedBySubdivisionCode[subdivision.code] = new Collection([stream]) + } + }) + }) + + for (const subdivisionCode in streamsGroupedBySubdivisionCode) { + const subdivisionStreams = streamsGroupedBySubdivisionCode[subdivisionCode] + + const playlist = new Playlist(subdivisionStreams, { public: true }) + const filepath = `subdivisions/${subdivisionCode.toLowerCase()}.m3u` + await this.storage.save(filepath, playlist.toString()) + this.logFile.append( + JSON.stringify({ type: 'subdivision', filepath, count: playlist.streams.count() }) + EOL + ) + } + } +} diff --git a/scripts/models/blocklistRecord.ts b/scripts/models/blocklistRecord.ts deleted file mode 100644 index 632a1d4ddc..0000000000 --- a/scripts/models/blocklistRecord.ts +++ /dev/null @@ -1,15 +0,0 @@ -import type { BlocklistRecordData } from '../types/blocklistRecord' - -export class BlocklistRecord { - channelId: string - reason: string - ref: string - - constructor(data?: BlocklistRecordData) { - if (!data) return - - this.channelId = data.channel - this.reason = data.reason - this.ref = data.ref - } -} diff --git a/scripts/models/broadcastArea.ts b/scripts/models/broadcastArea.ts deleted file mode 100644 index da49fe5402..0000000000 --- a/scripts/models/broadcastArea.ts +++ /dev/null @@ -1,108 +0,0 @@ -import { Collection, Dictionary } from '@freearhey/core' -import { City, Subdivision, Region, Country } from './' - -export class BroadcastArea { - codes: Collection - citiesIncluded: Collection - subdivisionsIncluded: Collection - countriesIncluded: Collection - regionsIncluded: Collection - - constructor(codes: Collection) { - this.codes = codes - } - - withLocations( - citiesKeyByCode: Dictionary, - subdivisionsKeyByCode: Dictionary, - countriesKeyByCode: Dictionary, - regionsKeyByCode: Dictionary - ): this { - const citiesIncluded = new Collection() - const subdivisionsIncluded = new Collection() - const countriesIncluded = new Collection() - let regionsIncluded = new Collection() - - this.codes.forEach((value: string) => { - const [type, code] = value.split('/') - - switch (type) { - case 'ct': { - const city: City = citiesKeyByCode.get(code) - if (!city) return - citiesIncluded.add(city) - if (city.subdivision) subdivisionsIncluded.add(city.subdivision) - if (city.subdivision && city.subdivision.parent) - subdivisionsIncluded.add(city.subdivision.parent) - if (city.country) countriesIncluded.add(city.country) - regionsIncluded = regionsIncluded.concat(city.getRegions()) - break - } - case 's': { - const subdivision: Subdivision = subdivisionsKeyByCode.get(code) - if (!subdivision) return - subdivisionsIncluded.add(subdivision) - if (subdivision.country) countriesIncluded.add(subdivision.country) - regionsIncluded = regionsIncluded.concat(subdivision.getRegions()) - break - } - case 'c': { - const country: Country = countriesKeyByCode.get(code) - if (!country) return - countriesIncluded.add(country) - regionsIncluded = regionsIncluded.concat(country.getRegions()) - break - } - case 'r': { - const region: Region = regionsKeyByCode.get(code) - if (!region) return - regionsIncluded = regionsIncluded.concat(region.getRegions()) - break - } - } - }) - - this.citiesIncluded = citiesIncluded.uniqBy((city: City) => city.code) - this.subdivisionsIncluded = subdivisionsIncluded.uniqBy( - (subdivision: Subdivision) => subdivision.code - ) - this.countriesIncluded = countriesIncluded.uniqBy((country: Country) => country.code) - this.regionsIncluded = regionsIncluded.uniqBy((region: Region) => region.code) - - return this - } - - getCountries(): Collection { - return this.countriesIncluded || new Collection() - } - - getSubdivisions(): Collection { - return this.subdivisionsIncluded || new Collection() - } - - getCities(): Collection { - return this.citiesIncluded || new Collection() - } - - getRegions(): Collection { - return this.regionsIncluded || new Collection() - } - - includesCountry(country: Country): boolean { - return this.getCountries().includes((_country: Country) => _country.code === country.code) - } - - includesSubdivision(subdivision: Subdivision): boolean { - return this.getSubdivisions().includes( - (_subdivision: Subdivision) => _subdivision.code === subdivision.code - ) - } - - includesRegion(region: Region): boolean { - return this.getRegions().includes((_region: Region) => _region.code === region.code) - } - - includesCity(city: City): boolean { - return this.getCities().includes((_city: City) => _city.code === city.code) - } -} diff --git a/scripts/models/category.ts b/scripts/models/category.ts deleted file mode 100644 index 5b228a86d0..0000000000 --- a/scripts/models/category.ts +++ /dev/null @@ -1,18 +0,0 @@ -import type { CategoryData, CategorySerializedData } from '../types/category' - -export class Category { - id: string - name: string - - constructor(data: CategoryData) { - this.id = data.id - this.name = data.name - } - - serialize(): CategorySerializedData { - return { - id: this.id, - name: this.name - } - } -} diff --git a/scripts/models/channel.ts b/scripts/models/channel.ts deleted file mode 100644 index 7a90146cf0..0000000000 --- a/scripts/models/channel.ts +++ /dev/null @@ -1,233 +0,0 @@ -import { Collection, Dictionary } from '@freearhey/core' -import { Category, Country, Feed, Guide, Logo, Stream, Subdivision } from './index' -import type { ChannelData, ChannelSearchableData, ChannelSerializedData } from '../types/channel' - -export class Channel { - id: string - name: string - altNames: Collection - network?: string - owners: Collection - countryCode: string - country?: Country - subdivisionCode?: string - subdivision?: Subdivision - cityName?: string - categoryIds: Collection - categories: Collection = new Collection() - isNSFW: boolean - launched?: string - closed?: string - replacedBy?: string - isClosed: boolean - website?: string - feeds?: Collection - logos: Collection = new Collection() - - constructor(data?: ChannelData) { - if (!data) return - - 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.isClosed = !!data.closed || !!data.replaced_by - } - - withSubdivision(subdivisionsKeyByCode: Dictionary): this { - if (!this.subdivisionCode) return this - - this.subdivision = subdivisionsKeyByCode.get(this.subdivisionCode) - - return this - } - - withCountry(countriesKeyByCode: Dictionary): this { - this.country = countriesKeyByCode.get(this.countryCode) - - return this - } - - withCategories(categoriesKeyById: Dictionary): this { - this.categories = this.categoryIds - .map((id: string) => categoriesKeyById.get(id)) - .filter(Boolean) - - return this - } - - withFeeds(feedsGroupedByChannelId: Dictionary): this { - this.feeds = new Collection(feedsGroupedByChannelId.get(this.id)) - - return this - } - - withLogos(logosGroupedByChannelId: Dictionary): this { - if (this.id) this.logos = new Collection(logosGroupedByChannelId.get(this.id)) - - return this - } - - getCountry(): Country | undefined { - return this.country - } - - getSubdivision(): Subdivision | undefined { - return this.subdivision - } - - getCategories(): Collection { - return this.categories || new Collection() - } - - hasCategories(): boolean { - return !!this.categories && this.categories.notEmpty() - } - - hasCategory(category: Category): boolean { - return ( - !!this.categories && - this.categories.includes((_category: Category) => _category.id === category.id) - ) - } - - getFeeds(): Collection { - if (!this.feeds) return new Collection() - - return this.feeds - } - - getGuides(): Collection { - let guides = new Collection() - - this.getFeeds().forEach((feed: Feed) => { - guides = guides.concat(feed.getGuides()) - }) - - return guides - } - - getGuideNames(): Collection { - return this.getGuides() - .map((guide: Guide) => guide.siteName) - .uniq() - } - - getStreams(): Collection { - let streams = new Collection() - - this.getFeeds().forEach((feed: Feed) => { - streams = streams.concat(feed.getStreams()) - }) - - return streams - } - - getStreamTitles(): Collection { - return this.getStreams() - .map((stream: Stream) => stream.getTitle()) - .uniq() - } - - getFeedFullNames(): Collection { - return this.getFeeds() - .map((feed: Feed) => feed.getFullName()) - .uniq() - } - - isSFW(): boolean { - return this.isNSFW === false - } - - getLogos(): Collection { - function feed(logo: Logo): number { - if (!logo.feed) return 1 - if (logo.feed.isMain) return 1 - - return 0 - } - - function format(logo: Logo): number { - const levelByFormat = { SVG: 0, PNG: 3, APNG: 1, WebP: 1, AVIF: 1, JPEG: 2, GIF: 1 } - - return logo.format ? levelByFormat[logo.format] : 0 - } - - function size(logo: Logo): number { - return Math.abs(512 - logo.width) + Math.abs(512 - logo.height) - } - - return this.logos.orderBy([feed, format, size], ['desc', 'desc', 'asc'], false) - } - - getLogo(): Logo | undefined { - return this.getLogos().first() - } - - hasLogo(): boolean { - return this.getLogos().notEmpty() - } - - getSearchable(): ChannelSearchableData { - return { - id: this.id, - name: this.name, - altNames: this.altNames.all(), - guideNames: this.getGuideNames().all(), - streamTitles: this.getStreamTitles().all(), - feedFullNames: this.getFeedFullNames().all() - } - } - - serialize(): ChannelSerializedData { - return { - id: this.id, - name: this.name, - altNames: this.altNames.all(), - network: this.network, - owners: this.owners.all(), - countryCode: this.countryCode, - country: this.country ? this.country.serialize() : undefined, - subdivisionCode: this.subdivisionCode, - subdivision: this.subdivision ? this.subdivision.serialize() : undefined, - cityName: this.cityName, - categoryIds: this.categoryIds.all(), - categories: this.categories.map((category: Category) => category.serialize()).all(), - isNSFW: this.isNSFW, - launched: this.launched, - closed: this.closed, - replacedBy: this.replacedBy, - website: this.website - } - } - - deserialize(data: ChannelSerializedData): this { - this.id = data.id - this.name = data.name - this.altNames = new Collection(data.altNames) - this.network = data.network - this.owners = new Collection(data.owners) - this.countryCode = data.countryCode - this.country = data.country ? new Country().deserialize(data.country) : undefined - this.subdivisionCode = data.subdivisionCode - this.cityName = data.cityName - this.categoryIds = new Collection(data.categoryIds) - this.isNSFW = data.isNSFW - this.launched = data.launched - this.closed = data.closed - this.replacedBy = data.replacedBy - this.website = data.website - - return this - } -} diff --git a/scripts/models/city.ts b/scripts/models/city.ts deleted file mode 100644 index 6ce9173ac9..0000000000 --- a/scripts/models/city.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { Collection, Dictionary } from '@freearhey/core' -import { Country, Region, Subdivision } from '.' -import type { CityData, CitySerializedData } from '../types/city' - -export class City { - code: string - name: string - countryCode: string - country?: Country - subdivisionCode?: string - subdivision?: Subdivision - wikidataId: string - regions?: Collection - - constructor(data?: CityData) { - if (!data) return - - this.code = data.code - this.name = data.name - this.countryCode = data.country - this.subdivisionCode = data.subdivision || undefined - this.wikidataId = data.wikidata_id - } - - withCountry(countriesKeyByCode: Dictionary): this { - this.country = countriesKeyByCode.get(this.countryCode) - - return this - } - - withSubdivision(subdivisionsKeyByCode: Dictionary): this { - if (!this.subdivisionCode) return this - - this.subdivision = subdivisionsKeyByCode.get(this.subdivisionCode) - - return this - } - - withRegions(regions: Collection): this { - this.regions = regions.filter((region: Region) => - region.countryCodes.includes(this.countryCode) - ) - - return this - } - - getRegions(): Collection { - if (!this.regions) return new Collection() - - return this.regions - } - - serialize(): CitySerializedData { - return { - code: this.code, - name: this.name, - countryCode: this.countryCode, - country: this.country ? this.country.serialize() : undefined, - subdivisionCode: this.subdivisionCode || null, - subdivision: this.subdivision ? this.subdivision.serialize() : undefined, - wikidataId: this.wikidataId - } - } - - deserialize(data: CitySerializedData): this { - this.code = data.code - this.name = data.name - this.countryCode = data.countryCode - this.country = data.country ? new Country().deserialize(data.country) : undefined - this.subdivisionCode = data.subdivisionCode || undefined - this.subdivision = data.subdivision - ? new Subdivision().deserialize(data.subdivision) - : undefined - this.wikidataId = data.wikidataId - - return this - } -} diff --git a/scripts/models/country.ts b/scripts/models/country.ts deleted file mode 100644 index b9699f7235..0000000000 --- a/scripts/models/country.ts +++ /dev/null @@ -1,95 +0,0 @@ -import { Collection, Dictionary } from '@freearhey/core' -import { Region, Language, Subdivision } from '.' -import type { CountryData, CountrySerializedData } from '../types/country' -import { SubdivisionSerializedData } from '../types/subdivision' -import { RegionSerializedData } from '../types/region' - -export class Country { - code: string - name: string - flag: string - languageCode: string - language?: Language - subdivisions?: Collection - regions?: Collection - cities?: Collection - - constructor(data?: CountryData) { - if (!data) return - - this.code = data.code - this.name = data.name - this.flag = data.flag - this.languageCode = data.lang - } - - withSubdivisions(subdivisionsGroupedByCountryCode: Dictionary): this { - this.subdivisions = new Collection(subdivisionsGroupedByCountryCode.get(this.code)) - - return this - } - - withRegions(regions: Collection): this { - this.regions = regions.filter((region: Region) => region.includesCountryCode(this.code)) - - return this - } - - withCities(citiesGroupedByCountryCode: Dictionary): this { - this.cities = new Collection(citiesGroupedByCountryCode.get(this.code)) - - return this - } - - withLanguage(languagesKeyByCode: Dictionary): this { - this.language = languagesKeyByCode.get(this.languageCode) - - return this - } - - getLanguage(): Language | undefined { - return this.language - } - - getRegions(): Collection { - return this.regions || new Collection() - } - - getSubdivisions(): Collection { - return this.subdivisions || new Collection() - } - - getCities(): Collection { - return this.cities || new Collection() - } - - serialize(): CountrySerializedData { - return { - code: this.code, - name: this.name, - flag: this.flag, - languageCode: this.languageCode, - language: this.language ? this.language.serialize() : null, - subdivisions: this.subdivisions - ? this.subdivisions.map((subdivision: Subdivision) => subdivision.serialize()).all() - : [], - regions: this.regions ? this.regions.map((region: Region) => region.serialize()).all() : [] - } - } - - deserialize(data: CountrySerializedData): this { - this.code = data.code - this.name = data.name - this.flag = data.flag - this.languageCode = data.languageCode - this.language = data.language ? new Language().deserialize(data.language) : undefined - this.subdivisions = new Collection(data.subdivisions).map((data: SubdivisionSerializedData) => - new Subdivision().deserialize(data) - ) - this.regions = new Collection(data.regions).map((data: RegionSerializedData) => - new Region().deserialize(data) - ) - - return this - } -} diff --git a/scripts/models/feed.ts b/scripts/models/feed.ts deleted file mode 100644 index a6713e265a..0000000000 --- a/scripts/models/feed.ts +++ /dev/null @@ -1,170 +0,0 @@ -import { Country, Language, Region, Channel, Subdivision, BroadcastArea, City } from './index' -import { Collection, Dictionary } from '@freearhey/core' -import type { FeedData } from '../types/feed' - -export class Feed { - channelId: string - channel?: Channel - id: string - name: string - isMain: boolean - broadcastAreaCodes: Collection - broadcastArea?: BroadcastArea - languageCodes: Collection - languages?: Collection - timezoneIds: Collection - timezones?: Collection - videoFormat: string - guides?: Collection - streams?: Collection - - 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 - } - - withChannel(channelsKeyById: Dictionary): this { - this.channel = channelsKeyById.get(this.channelId) - - return this - } - - withStreams(streamsGroupedById: Dictionary): this { - this.streams = new Collection(streamsGroupedById.get(`${this.channelId}@${this.id}`)) - - if (this.isMain) { - this.streams = this.streams.concat(new Collection(streamsGroupedById.get(this.channelId))) - } - - return this - } - - withGuides(guidesGroupedByStreamId: Dictionary): this { - this.guides = new Collection(guidesGroupedByStreamId.get(`${this.channelId}@${this.id}`)) - - if (this.isMain) { - this.guides = this.guides.concat(new Collection(guidesGroupedByStreamId.get(this.channelId))) - } - - return this - } - - withLanguages(languagesKeyByCode: Dictionary): this { - this.languages = this.languageCodes - .map((code: string) => languagesKeyByCode.get(code)) - .filter(Boolean) - - return this - } - - withTimezones(timezonesKeyById: Dictionary): this { - this.timezones = this.timezoneIds.map((id: string) => timezonesKeyById.get(id)).filter(Boolean) - - return this - } - - withBroadcastArea( - citiesKeyByCode: Dictionary, - subdivisionsKeyByCode: Dictionary, - countriesKeyByCode: Dictionary, - regionsKeyByCode: Dictionary - ): this { - this.broadcastArea = new BroadcastArea(this.broadcastAreaCodes).withLocations( - citiesKeyByCode, - subdivisionsKeyByCode, - countriesKeyByCode, - regionsKeyByCode - ) - - return this - } - - hasBroadcastArea(): boolean { - return !!this.broadcastArea - } - - getBroadcastCountries(): Collection { - if (!this.broadcastArea) return new Collection() - - return this.broadcastArea.getCountries() - } - - getBroadcastRegions(): Collection { - if (!this.broadcastArea) return new Collection() - - return this.broadcastArea.getRegions() - } - - getTimezones(): Collection { - return this.timezones || new Collection() - } - - getLanguages(): Collection { - return this.languages || new Collection() - } - - hasLanguages(): boolean { - return !!this.languages && this.languages.notEmpty() - } - - hasLanguage(language: Language): boolean { - return ( - !!this.languages && - this.languages.includes((_language: Language) => _language.code === language.code) - ) - } - - isBroadcastInCity(city: City): boolean { - if (!this.broadcastArea) return false - - return this.broadcastArea.includesCity(city) - } - - isBroadcastInSubdivision(subdivision: Subdivision): boolean { - if (!this.broadcastArea) return false - - return this.broadcastArea.includesSubdivision(subdivision) - } - - isBroadcastInCountry(country: Country): boolean { - if (!this.broadcastArea) return false - - return this.broadcastArea.includesCountry(country) - } - - isBroadcastInRegion(region: Region): boolean { - if (!this.broadcastArea) return false - - return this.broadcastArea.includesRegion(region) - } - - isInternational(): boolean { - if (!this.broadcastArea) return false - - return this.broadcastArea.codes.join(',').includes('r/') - } - - getGuides(): Collection { - if (!this.guides) return new Collection() - - return this.guides - } - - getStreams(): Collection { - if (!this.streams) return new Collection() - - return this.streams - } - - getFullName(): string { - if (!this.channel) return '' - - return `${this.channel.name} ${this.name}` - } -} diff --git a/scripts/models/guide.ts b/scripts/models/guide.ts deleted file mode 100644 index 3bc849d86e..0000000000 --- a/scripts/models/guide.ts +++ /dev/null @@ -1,54 +0,0 @@ -import type { GuideData, GuideSerializedData } from '../types/guide' - -export class Guide { - channelId?: string - feedId?: string - siteDomain: string - siteId: string - siteName: string - languageCode: string - - constructor(data?: GuideData) { - if (!data) return - - this.channelId = data.channel - this.feedId = data.feed - this.siteDomain = data.site - this.siteId = data.site_id - this.siteName = data.site_name - this.languageCode = data.lang - } - - getUUID(): string { - return this.getStreamId() + this.siteId - } - - getStreamId(): string | undefined { - if (!this.channelId) return undefined - if (!this.feedId) return this.channelId - - return `${this.channelId}@${this.feedId}` - } - - serialize(): GuideSerializedData { - return { - channelId: this.channelId, - feedId: this.feedId, - siteDomain: this.siteDomain, - siteId: this.siteId, - siteName: this.siteName, - languageCode: this.languageCode - } - } - - deserialize(data: GuideSerializedData): this { - this.channelId = data.channelId - this.feedId = data.feedId - this.siteDomain = data.siteDomain - this.siteId = data.siteId - this.siteName = data.siteName - this.languageCode = data.languageCode - - return this - } -} diff --git a/scripts/models/index.ts b/scripts/models/index.ts index e8fe346289..f4b06f6dd5 100644 --- a/scripts/models/index.ts +++ b/scripts/models/index.ts @@ -1,16 +1,3 @@ -export * from './blocklistRecord' -export * from './broadcastArea' -export * from './category' -export * from './channel' -export * from './city' -export * from './country' -export * from './feed' -export * from './guide' -export * from './issue' -export * from './language' -export * from './logo' -export * from './playlist' -export * from './region' -export * from './stream' -export * from './subdivision' -export * from './timezone' +export * from './issue' +export * from './playlist' +export * from './stream' diff --git a/scripts/models/issue.ts b/scripts/models/issue.ts index 74602e7457..4b81d69484 100644 --- a/scripts/models/issue.ts +++ b/scripts/models/issue.ts @@ -1,19 +1,19 @@ -import { IssueData } from '../core' - -type IssueProps = { - number: number - labels: string[] - data: IssueData -} - -export class Issue { - number: number - labels: string[] - data: IssueData - - constructor({ number, labels, data }: IssueProps) { - this.number = number - this.labels = labels - this.data = data - } -} +import { IssueData } from '../core' + +type IssueProps = { + number: number + labels: string[] + data: IssueData +} + +export class Issue { + number: number + labels: string[] + data: IssueData + + constructor({ number, labels, data }: IssueProps) { + this.number = number + this.labels = labels + this.data = data + } +} diff --git a/scripts/models/language.ts b/scripts/models/language.ts deleted file mode 100644 index 1e6df829bc..0000000000 --- a/scripts/models/language.ts +++ /dev/null @@ -1,27 +0,0 @@ -import type { LanguageData, LanguageSerializedData } from '../types/language' - -export class Language { - code: string - name: string - - constructor(data?: LanguageData) { - if (!data) return - - this.code = data.code - this.name = data.name - } - - serialize(): LanguageSerializedData { - return { - code: this.code, - name: this.name - } - } - - deserialize(data: LanguageSerializedData): this { - this.code = data.code - this.name = data.name - - return this - } -} diff --git a/scripts/models/logo.ts b/scripts/models/logo.ts deleted file mode 100644 index 3cc85fb9da..0000000000 --- a/scripts/models/logo.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { Collection, type Dictionary } from '@freearhey/core' -import type { LogoData } from '../types/logo' -import { type Feed } from './feed' - -export class Logo { - channelId: string - feedId?: string - feed: Feed - tags: Collection - width: number - height: number - format?: string - url: string - - constructor(data?: LogoData) { - if (!data) return - - this.channelId = data.channel - this.feedId = data.feed || undefined - this.tags = new Collection(data.tags) - this.width = data.width - this.height = data.height - this.format = data.format || undefined - this.url = data.url - } - - withFeed(feedsKeyById: Dictionary): this { - if (!this.feedId) return this - - this.feed = feedsKeyById.get(this.feedId) - - return this - } - - getStreamId(): string { - if (!this.feedId) return this.channelId - - return `${this.channelId}@${this.feedId}` - } -} diff --git a/scripts/models/playlist.ts b/scripts/models/playlist.ts index d3022a5af6..f6a2b25d60 100644 --- a/scripts/models/playlist.ts +++ b/scripts/models/playlist.ts @@ -1,28 +1,28 @@ -import { Collection } from '@freearhey/core' -import { Stream } from '../models' - -type PlaylistOptions = { - public: boolean -} - -export class Playlist { - streams: Collection - options: { - public: boolean - } - - constructor(streams: Collection, options?: PlaylistOptions) { - this.streams = streams - this.options = options || { public: false } - } - - toString() { - let output = '#EXTM3U\r\n' - - this.streams.forEach((stream: Stream) => { - output += stream.toString(this.options) + '\r\n' - }) - - return output - } -} +import { Collection } from '@freearhey/core' +import { Stream } from '../models' + +type PlaylistOptions = { + public: boolean +} + +export class Playlist { + streams: Collection + options: { + public: boolean + } + + constructor(streams: Collection, options?: PlaylistOptions) { + this.streams = streams + this.options = options || { public: false } + } + + toString() { + let output = '#EXTM3U\r\n' + + this.streams.forEach((stream: Stream) => { + output += stream.toString(this.options) + '\r\n' + }) + + return output + } +} diff --git a/scripts/models/region.ts b/scripts/models/region.ts deleted file mode 100644 index 5fe52ad5a9..0000000000 --- a/scripts/models/region.ts +++ /dev/null @@ -1,118 +0,0 @@ -import { Collection, Dictionary } from '@freearhey/core' -import { City, Country, Subdivision } from '.' -import type { RegionData, RegionSerializedData } from '../types/region' -import { CountrySerializedData } from '../types/country' -import { SubdivisionSerializedData } from '../types/subdivision' -import { CitySerializedData } from '../types/city' - -export class Region { - code: string - name: string - countryCodes: Collection - countries?: Collection - subdivisions?: Collection - cities?: Collection - regions?: Collection - - constructor(data?: RegionData) { - if (!data) return - - this.code = data.code - this.name = data.name - this.countryCodes = new Collection(data.countries) - } - - withCountries(countriesKeyByCode: Dictionary): this { - this.countries = this.countryCodes.map((code: string) => countriesKeyByCode.get(code)) - - return this - } - - withSubdivisions(subdivisions: Collection): this { - this.subdivisions = subdivisions.filter( - (subdivision: Subdivision) => this.countryCodes.indexOf(subdivision.countryCode) > -1 - ) - - return this - } - - withCities(cities: Collection): this { - this.cities = cities.filter((city: City) => this.countryCodes.indexOf(city.countryCode) > -1) - - return this - } - - withRegions(regions: Collection): this { - this.regions = regions.filter( - (region: Region) => !region.countryCodes.intersects(this.countryCodes).isEmpty() - ) - - return this - } - - getSubdivisions(): Collection { - if (!this.subdivisions) return new Collection() - - return this.subdivisions - } - - getCountries(): Collection { - if (!this.countries) return new Collection() - - return this.countries - } - - getCities(): Collection { - if (!this.cities) return new Collection() - - return this.cities - } - - getRegions(): Collection { - if (!this.regions) return new Collection() - - return this.regions - } - - includesCountryCode(code: string): boolean { - return this.countryCodes.includes((countryCode: string) => countryCode === code) - } - - isWorldwide(): boolean { - return ['INT', 'WW'].includes(this.code) - } - - serialize(): RegionSerializedData { - return { - code: this.code, - name: this.name, - countryCodes: this.countryCodes.all(), - countries: this.getCountries() - .map((country: Country) => country.serialize()) - .all(), - subdivisions: this.getSubdivisions() - .map((subdivision: Subdivision) => subdivision.serialize()) - .all(), - cities: this.getCities() - .map((city: City) => city.serialize()) - .all() - } - } - - deserialize(data: RegionSerializedData): this { - this.code = data.code - this.name = data.name - this.countryCodes = new Collection(data.countryCodes) - this.countries = new Collection(data.countries).map((data: CountrySerializedData) => - new Country().deserialize(data) - ) - this.subdivisions = new Collection(data.subdivisions).map((data: SubdivisionSerializedData) => - new Subdivision().deserialize(data) - ) - this.cities = new Collection(data.cities).map((data: CitySerializedData) => - new City().deserialize(data) - ) - - return this - } -} diff --git a/scripts/models/stream.ts b/scripts/models/stream.ts index a465081ea6..c050930b4d 100644 --- a/scripts/models/stream.ts +++ b/scripts/models/stream.ts @@ -1,474 +1,461 @@ -import { - Feed, - Channel, - Category, - Region, - Subdivision, - Country, - Language, - Logo, - City -} from './index' -import { URL, Collection, Dictionary } from '@freearhey/core' -import type { StreamData } from '../types/stream' -import parser from 'iptv-playlist-parser' -import { IssueData } from '../core' -import path from 'node:path' - -export class Stream { - title: string - url: string - id?: string - channelId?: string - channel?: Channel - feedId?: string - feed?: Feed - logos: Collection = new Collection() - filepath?: string - line?: number - label?: string - verticalResolution?: number - isInterlaced?: boolean - referrer?: string - userAgent?: string - groupTitle: string = 'Undefined' - removed: boolean = false - directives: Collection = new Collection() - - constructor(data?: StreamData) { - if (!data) return - - const id = - data.channelId && data.feedId ? [data.channelId, data.feedId].join('@') : data.channelId - const { verticalResolution, isInterlaced } = parseQuality(data.quality) - - this.id = id || undefined - this.channelId = data.channelId || undefined - this.feedId = data.feedId || undefined - this.title = data.title || '' - this.url = data.url - this.referrer = data.referrer || undefined - this.userAgent = data.userAgent || undefined - this.verticalResolution = verticalResolution || undefined - this.isInterlaced = isInterlaced || undefined - this.label = data.label || undefined - this.directives = new Collection(data.directives) - } - - update(issueData: IssueData): this { - const data = { - label: issueData.getString('label'), - quality: issueData.getString('quality'), - httpUserAgent: issueData.getString('httpUserAgent'), - httpReferrer: issueData.getString('httpReferrer'), - newStreamUrl: issueData.getString('newStreamUrl'), - directives: issueData.getArray('directives') - } - - if (data.label !== undefined) this.label = data.label - if (data.quality !== undefined) this.setQuality(data.quality) - if (data.httpUserAgent !== undefined) this.userAgent = data.httpUserAgent - if (data.httpReferrer !== undefined) this.referrer = data.httpReferrer - if (data.newStreamUrl !== undefined) this.url = data.newStreamUrl - if (data.directives !== undefined) this.directives = new Collection(data.directives) - - return this - } - - fromPlaylistItem(data: parser.PlaylistItem): this { - function parseName(name: string): { - title: string - label: string - quality: string - } { - let title = name - const [, label] = title.match(/ \[(.*)\]$/) || [null, ''] - title = title.replace(new RegExp(` \\[${escapeRegExp(label)}\\]$`), '') - const [, quality] = title.match(/ \(([0-9]+p)\)$/) || [null, ''] - title = title.replace(new RegExp(` \\(${quality}\\)$`), '') - - return { title, label, quality } - } - - function parseDirectives(string: string) { - const directives = new Collection() - - if (!string) return directives - - const supportedDirectives = ['#EXTVLCOPT', '#KODIPROP'] - const lines = string.split('\r\n') - const regex = new RegExp(`^${supportedDirectives.join('|')}`, 'i') - - lines.forEach((line: string) => { - if (regex.test(line)) { - directives.add(line.trim()) - } - }) - - return directives - } - - if (!data.name) throw new Error('"name" property is required') - if (!data.url) throw new Error('"url" property is required') - - const [channelId, feedId] = data.tvg.id.split('@') - const { title, label, quality } = parseName(data.name) - const { verticalResolution, isInterlaced } = parseQuality(quality) - - this.id = data.tvg.id || undefined - this.feedId = feedId || undefined - this.channelId = channelId || undefined - this.line = data.line - this.label = label || undefined - this.title = title - this.verticalResolution = verticalResolution || undefined - this.isInterlaced = isInterlaced || undefined - this.url = data.url - this.referrer = data.http.referrer || undefined - this.userAgent = data.http['user-agent'] || undefined - this.directives = parseDirectives(data.raw) - - return this - } - - withChannel(channelsKeyById: Dictionary): this { - if (!this.channelId) return this - - this.channel = channelsKeyById.get(this.channelId) - - return this - } - - withFeed(feedsGroupedByChannelId: Dictionary): this { - if (!this.channelId) return this - - const channelFeeds = feedsGroupedByChannelId.get(this.channelId) || [] - if (this.feedId) this.feed = channelFeeds.find((feed: Feed) => feed.id === this.feedId) - if (!this.feedId && !this.feed) this.feed = channelFeeds.find((feed: Feed) => feed.isMain) - - return this - } - - withLogos(logosGroupedByStreamId: Dictionary): this { - if (this.id) this.logos = new Collection(logosGroupedByStreamId.get(this.id)) - - return this - } - - setId(id: string): this { - this.id = id - - return this - } - - setChannelId(channelId: string): this { - this.channelId = channelId - - return this - } - - setFeedId(feedId: string | undefined): this { - this.feedId = feedId - - return this - } - - setQuality(quality: string): this { - const { verticalResolution, isInterlaced } = parseQuality(quality) - - this.verticalResolution = verticalResolution || undefined - this.isInterlaced = isInterlaced || undefined - - return this - } - - getLine(): number { - return this.line || -1 - } - - getFilename(): string { - if (!this.filepath) return '' - - return path.basename(this.filepath) - } - - setFilepath(filepath: string): this { - this.filepath = filepath - - return this - } - - updateFilepath(): this { - if (!this.channel) return this - - this.filepath = `${this.channel.countryCode.toLowerCase()}.m3u` - - return this - } - - getChannelId(): string { - return this.channelId || '' - } - - getFeedId(): string { - if (this.feedId) return this.feedId - if (this.feed) return this.feed.id - return '' - } - - getFilepath(): string { - return this.filepath || '' - } - - getReferrer(): string { - return this.referrer || '' - } - - getUserAgent(): string { - return this.userAgent || '' - } - - getQuality(): string { - if (!this.verticalResolution) return '' - - let quality = this.verticalResolution.toString() - - if (this.isInterlaced) quality += 'i' - else quality += 'p' - - return quality - } - - hasId(): boolean { - return !!this.id - } - - hasQuality(): boolean { - return !!this.verticalResolution - } - - getVerticalResolution(): number { - if (!this.hasQuality()) return 0 - - return parseInt(this.getQuality().replace(/p|i/, '')) - } - - updateTitle(): this { - if (!this.channel) return this - - this.title = this.channel.name - if (this.feed && !this.feed.isMain) { - this.title += ` ${this.feed.name}` - } - - return this - } - - updateId(): this { - if (!this.channel) return this - if (this.feed) { - this.id = `${this.channel.id}@${this.feed.id}` - } else { - this.id = this.channel.id - } - - return this - } - - normalizeURL() { - const url = new URL(this.url) - - this.url = url.normalize().toString() - } - - clone(): Stream { - return Object.assign(Object.create(Object.getPrototypeOf(this)), this) - } - - hasChannel() { - return !!this.channel - } - - getBroadcastRegions(): Collection { - return this.feed ? this.feed.getBroadcastRegions() : new Collection() - } - - getBroadcastCountries(): Collection { - return this.feed ? this.feed.getBroadcastCountries() : new Collection() - } - - hasBroadcastArea(): boolean { - return this.feed ? this.feed.hasBroadcastArea() : false - } - - isSFW(): boolean { - return this.channel ? this.channel.isSFW() : true - } - - hasCategories(): boolean { - return this.channel ? this.channel.hasCategories() : false - } - - hasCategory(category: Category): boolean { - return this.channel ? this.channel.hasCategory(category) : false - } - - getCategoryNames(): string[] { - return this.getCategories() - .map((category: Category) => category.name) - .sort() - .all() - } - - getCategories(): Collection { - return this.channel ? this.channel.getCategories() : new Collection() - } - - getLanguages(): Collection { - return this.feed ? this.feed.getLanguages() : new Collection() - } - - hasLanguages() { - return this.feed ? this.feed.hasLanguages() : false - } - - hasLanguage(language: Language) { - return this.feed ? this.feed.hasLanguage(language) : false - } - - getBroadcastAreaCodes(): Collection { - return this.feed ? this.feed.broadcastAreaCodes : new Collection() - } - - isBroadcastInCity(city: City): boolean { - return this.feed ? this.feed.isBroadcastInCity(city) : false - } - - isBroadcastInSubdivision(subdivision: Subdivision): boolean { - return this.feed ? this.feed.isBroadcastInSubdivision(subdivision) : false - } - - isBroadcastInCountry(country: Country): boolean { - return this.feed ? this.feed.isBroadcastInCountry(country) : false - } - - isBroadcastInRegion(region: Region): boolean { - return this.feed ? this.feed.isBroadcastInRegion(region) : false - } - - isInternational(): boolean { - return this.feed ? this.feed.isInternational() : false - } - - getLogos(): Collection { - function format(logo: Logo): number { - const levelByFormat = { SVG: 0, PNG: 3, APNG: 1, WebP: 1, AVIF: 1, JPEG: 2, GIF: 1 } - - return logo.format ? levelByFormat[logo.format] : 0 - } - - function size(logo: Logo): number { - return Math.abs(512 - logo.width) + Math.abs(512 - logo.height) - } - - return this.logos.orderBy([format, size], ['desc', 'asc'], false) - } - - getLogo(): Logo | undefined { - return this.getLogos().first() - } - - hasLogo(): boolean { - return this.getLogos().notEmpty() - } - - getLogoUrl(): string { - let logo: Logo | undefined - - if (this.hasLogo()) logo = this.getLogo() - else logo = this?.channel?.getLogo() - - return logo ? logo.url : '' - } - - getTitle(): string { - return this.title || '' - } - - getFullTitle(): string { - let title = `${this.getTitle()}` - - if (this.getQuality()) { - title += ` (${this.getQuality()})` - } - - if (this.label) { - title += ` [${this.label}]` - } - - return title - } - - getLabel(): string { - return this.label || '' - } - - getId(): string { - return this.id || '' - } - - toJSON() { - return { - channel: this.channelId || null, - feed: this.feedId || null, - title: this.title, - url: this.url, - referrer: this.referrer || null, - user_agent: this.userAgent || null, - quality: this.getQuality() || null - } - } - - toString(options: { public: boolean }) { - let output = `#EXTINF:-1 tvg-id="${this.getId()}"` - - if (options.public) { - output += ` tvg-logo="${this.getLogoUrl()}" group-title="${this.groupTitle}"` - } - - if (this.referrer) { - output += ` http-referrer="${this.referrer}"` - } - - if (this.userAgent) { - output += ` http-user-agent="${this.userAgent}"` - } - - output += `,${this.getFullTitle()}` - - this.directives.forEach((prop: string) => { - output += `\r\n${prop}` - }) - - output += `\r\n${this.url}` - - return output - } -} - -function escapeRegExp(text) { - return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&') -} - -function parseQuality(quality: string | null): { - verticalResolution: number | null - isInterlaced: boolean | null -} { - if (!quality) return { verticalResolution: null, isInterlaced: null } - const [, verticalResolutionString] = quality.match(/^(\d+)/) || [null, undefined] - const isInterlaced = /i$/i.test(quality) - let verticalResolution = 0 - if (verticalResolutionString) verticalResolution = parseInt(verticalResolutionString) - - return { verticalResolution, isInterlaced } -} +import { Collection } from '@freearhey/core' +import parser from 'iptv-playlist-parser' +import { normalizeURL } from '../utils' +import * as sdk from '@iptv-org/sdk' +import { IssueData } from '../core' +import { data } from '../api' +import path from 'node:path' + +export class Stream extends sdk.Models.Stream { + directives: Collection + filepath?: string + line?: number + groupTitle: string = 'Undefined' + removed: boolean = false + tvgId?: string + label: string | null + + updateWithIssue(issueData: IssueData): this { + const data = { + label: issueData.getString('label'), + quality: issueData.getString('quality'), + httpUserAgent: issueData.getString('httpUserAgent'), + httpReferrer: issueData.getString('httpReferrer'), + newStreamUrl: issueData.getString('newStreamUrl'), + directives: issueData.getArray('directives') + } + + if (data.label !== undefined) this.label = data.label + if (data.quality !== undefined) this.quality = data.quality + if (data.httpUserAgent !== undefined) this.user_agent = data.httpUserAgent + if (data.httpReferrer !== undefined) this.referrer = data.httpReferrer + if (data.newStreamUrl !== undefined) this.url = data.newStreamUrl + if (data.directives !== undefined) this.setDirectives(data.directives) + + return this + } + + static fromPlaylistItem(data: parser.PlaylistItem): Stream { + function escapeRegExp(text) { + return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&') + } + + function parseName(name: string): { + title: string + label: string + quality: string + } { + let title = name + const [, label] = title.match(/ \[(.*)\]$/) || [null, ''] + title = title.replace(new RegExp(` \\[${escapeRegExp(label)}\\]$`), '') + const [, quality] = title.match(/ \(([0-9]+[p|i])\)$/) || [null, ''] + title = title.replace(new RegExp(` \\(${quality}\\)$`), '') + + return { title, label, quality } + } + + function parseDirectives(string: string): Collection { + const directives = new Collection() + + if (!string) return directives + + const supportedDirectives = ['#EXTVLCOPT', '#KODIPROP'] + const lines = string.split('\r\n') + const regex = new RegExp(`^${supportedDirectives.join('|')}`, 'i') + + lines.forEach((line: string) => { + if (regex.test(line)) { + directives.add(line.trim()) + } + }) + + return directives + } + + if (!data.name) throw new Error('"name" property is required') + if (!data.url) throw new Error('"url" property is required') + + const [channelId, feedId] = data.tvg.id.split('@') + const { title, label, quality } = parseName(data.name) + + const stream = new Stream({ + channel: channelId || null, + feed: feedId || null, + title: title, + quality: quality || null, + url: data.url, + referrer: data.http.referrer || null, + user_agent: data.http['user-agent'] || null + }) + + stream.tvgId = data.tvg.id + stream.line = data.line + stream.label = label || null + stream.directives = parseDirectives(data.raw) + + return stream + } + + isSFW(): boolean { + const channel = this.getChannel() + + if (!channel) return true + + return !channel.is_nsfw + } + + getUniqKey(): string { + const filepath = this.getFilepath() + const tvgId = this.getTvgId() + + return filepath + tvgId + this.url + } + + getVerticalResolution(): number { + if (!this.quality) return 0 + + const [, verticalResolutionString] = this.quality.match(/^(\d+)/) || ['', '0'] + + return parseInt(verticalResolutionString) + } + + getBroadcastCountries(): Collection { + const countries = new Collection() + + const feed = this.getFeed() + if (!feed) return countries + + feed + .getBroadcastArea() + .getLocations() + .forEach((location: sdk.Models.BroadcastAreaLocation) => { + let country: sdk.Models.Country | undefined + switch (location.type) { + case 'country': { + country = data.countriesKeyByCode.get(location.code) + break + } + case 'subdivision': { + const subdivision = data.subdivisionsKeyByCode.get(location.code) + if (!subdivision) break + country = data.countriesKeyByCode.get(subdivision.country) + break + } + case 'city': { + const city = data.citiesKeyByCode.get(location.code) + if (!city) break + country = data.countriesKeyByCode.get(city.country) + break + } + } + + if (country) countries.add(country) + }) + + return countries.uniqBy((country: sdk.Models.Country) => country.code) + } + + getBroadcastSubdivisions(): Collection { + const subdivisions = new Collection() + + const feed = this.getFeed() + if (!feed) return subdivisions + + feed + .getBroadcastArea() + .getLocations() + .forEach((location: sdk.Models.BroadcastAreaLocation) => { + switch (location.type) { + case 'subdivision': { + const subdivision = data.subdivisionsKeyByCode.get(location.code) + if (!subdivision) break + subdivisions.add(subdivision) + if (!subdivision.parent) break + const parentSubdivision = data.subdivisionsKeyByCode.get(subdivision.parent) + if (!parentSubdivision) break + subdivisions.add(parentSubdivision) + break + } + case 'city': { + const city = data.citiesKeyByCode.get(location.code) + if (!city || !city.subdivision) break + const subdivision = data.subdivisionsKeyByCode.get(city.subdivision) + if (!subdivision) break + subdivisions.add(subdivision) + if (!subdivision.parent) break + const parentSubdivision = data.subdivisionsKeyByCode.get(subdivision.parent) + if (!parentSubdivision) break + subdivisions.add(parentSubdivision) + break + } + } + }) + + return subdivisions.uniqBy((subdivision: sdk.Models.Subdivision) => subdivision.code) + } + + getBroadcastCities(): Collection { + const cities = new Collection() + + const feed = this.getFeed() + if (!feed) return cities + + feed + .getBroadcastArea() + .getLocations() + .forEach((location: sdk.Models.BroadcastAreaLocation) => { + if (location.type !== 'city') return + + const city = data.citiesKeyByCode.get(location.code) + + if (city) cities.add(city) + }) + + return cities.uniqBy((city: sdk.Models.City) => city.code) + } + + getBroadcastRegions(): Collection { + const regions = new Collection() + + const feed = this.getFeed() + if (!feed) return regions + + feed + .getBroadcastArea() + .getLocations() + .forEach((location: sdk.Models.BroadcastAreaLocation) => { + switch (location.type) { + case 'region': { + const region = data.regionsKeyByCode.get(location.code) + if (!region) break + regions.add(region) + + const relatedRegions = data.regions.filter((_region: sdk.Models.Region) => + new Collection(_region.countries) + .intersects(new Collection(region.countries)) + .isNotEmpty() + ) + regions.concat(relatedRegions) + break + } + case 'country': { + const country = data.countriesKeyByCode.get(location.code) + if (!country) break + const countryRegions = data.regions.filter((_region: sdk.Models.Region) => + new Collection(_region.countries).includes( + (code: string) => code === country.code + ) + ) + regions.concat(countryRegions) + break + } + case 'subdivision': { + const subdivision = data.subdivisionsKeyByCode.get(location.code) + if (!subdivision) break + const subdivisionRegions = data.regions.filter((_region: sdk.Models.Region) => + new Collection(_region.countries).includes( + (code: string) => code === subdivision.country + ) + ) + regions.concat(subdivisionRegions) + break + } + case 'city': { + const city = data.citiesKeyByCode.get(location.code) + if (!city) break + const cityRegions = data.regions.filter((_region: sdk.Models.Region) => + new Collection(_region.countries).includes( + (code: string) => code === city.country + ) + ) + regions.concat(cityRegions) + break + } + } + }) + + return regions.uniqBy((region: sdk.Models.Region) => region.code) + } + + isInternational(): boolean { + const feed = this.getFeed() + if (!feed) return false + + const broadcastAreaCodes = feed.getBroadcastArea().codes + if (broadcastAreaCodes.join(';').includes('r/')) return true + if (broadcastAreaCodes.filter(code => code.includes('c/')).length > 1) return true + + return false + } + + hasCategory(category: sdk.Models.Category): boolean { + const channel = this.getChannel() + + if (!channel) return false + + const found = channel.categories.find((id: string) => id === category.id) + + return !!found + } + + hasLanguage(language: sdk.Models.Language): boolean { + const found = this.getLanguages().find( + (_language: sdk.Models.Language) => _language.code === language.code + ) + + return !!found + } + + setDirectives(directives: string[]): this { + this.directives = new Collection(directives).filter((directive: string) => + /^(#KODIPROP|#EXTVLCOPT)/.test(directive) + ) + + return this + } + + updateTvgId(): this { + if (!this.channel) return this + if (this.feed) { + this.tvgId = `${this.channel}@${this.feed}` + } else { + this.tvgId = this.channel + } + + return this + } + + updateFilepath(): this { + const channel = this.getChannel() + if (!channel) return this + + this.filepath = `${channel.country.toLowerCase()}.m3u` + + return this + } + + updateTitle(): this { + const channel = this.getChannel() + + if (!channel) return this + + const feed = this.getFeed() + + this.title = channel.name + if (feed && !feed.is_main) { + this.title += ` ${feed.name}` + } + + return this + } + + normalizeURL() { + this.url = normalizeURL(this.url) + } + + getLogos(): Collection { + const logos = super.getLogos() + + if (logos.isEmpty()) return new Collection() + + function format(logo: sdk.Models.Logo): number { + const levelByFormat = { SVG: 0, PNG: 3, APNG: 1, WebP: 1, AVIF: 1, JPEG: 2, GIF: 1 } + + return logo.format ? levelByFormat[logo.format] : 0 + } + + function size(logo: sdk.Models.Logo): number { + return Math.abs(512 - logo.width) + Math.abs(512 - logo.height) + } + + return logos.sortBy([format, size], ['desc', 'asc'], false) + } + + getFilepath(): string { + return this.filepath || '' + } + + getFilename(): string { + return path.basename(this.getFilepath()) + } + + getLine(): number { + return this.line || -1 + } + + getTvgId(): string { + if (this.tvgId) return this.tvgId + + return this.getId() + } + + getTvgLogo(): string { + const logo = this.getLogos().first() + + return logo ? logo.url : '' + } + + getFullTitle(): string { + let title = `${this.title}` + + if (this.quality) { + title += ` (${this.quality})` + } + + if (this.label) { + title += ` [${this.label}]` + } + + return title + } + + toString(options: { public?: boolean } = {}) { + options = { ...{ public: false }, ...options } + + let output = `#EXTINF:-1 tvg-id="${this.getTvgId()}"` + + if (options.public) { + output += ` tvg-logo="${this.getTvgLogo()}" group-title="${this.groupTitle}"` + } + + if (this.referrer) { + output += ` http-referrer="${this.referrer}"` + } + + if (this.user_agent) { + output += ` http-user-agent="${this.user_agent}"` + } + + output += `,${this.getFullTitle()}` + + this.directives.forEach((prop: string) => { + output += `\r\n${prop}` + }) + + output += `\r\n${this.url}` + + return output + } + + toObject(): sdk.Types.StreamData { + let feedId = this.feed + if (!feedId) { + const feed = this.getFeed() + if (feed) feedId = feed.id + } + + return { + channel: this.channel, + feed: feedId, + title: this.title, + url: this.url, + quality: this.quality, + user_agent: this.user_agent, + referrer: this.referrer + } + } + + clone(): Stream { + return Object.assign(Object.create(Object.getPrototypeOf(this)), this) + } +} diff --git a/scripts/models/subdivision.ts b/scripts/models/subdivision.ts deleted file mode 100644 index b70bd4ac5b..0000000000 --- a/scripts/models/subdivision.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { SubdivisionData, SubdivisionSerializedData } from '../types/subdivision' -import { Dictionary, Collection } from '@freearhey/core' -import { Country, Region } from '.' - -export class Subdivision { - code: string - name: string - countryCode: string - country?: Country - parentCode?: string - parent?: Subdivision - regions?: Collection - cities?: Collection - - constructor(data?: SubdivisionData) { - if (!data) return - - this.code = data.code - this.name = data.name - this.countryCode = data.country - this.parentCode = data.parent || undefined - } - - withCountry(countriesKeyByCode: Dictionary): this { - this.country = countriesKeyByCode.get(this.countryCode) - - return this - } - - withRegions(regions: Collection): this { - this.regions = regions.filter((region: Region) => - region.countryCodes.includes(this.countryCode) - ) - - return this - } - - withCities(citiesGroupedBySubdivisionCode: Dictionary): this { - this.cities = new Collection(citiesGroupedBySubdivisionCode.get(this.code)) - - return this - } - - withParent(subdivisionsKeyByCode: Dictionary): this { - if (!this.parentCode) return this - - this.parent = subdivisionsKeyByCode.get(this.parentCode) - - return this - } - - getRegions(): Collection { - if (!this.regions) return new Collection() - - return this.regions - } - - getCities(): Collection { - if (!this.cities) return new Collection() - - return this.cities - } - - serialize(): SubdivisionSerializedData { - return { - code: this.code, - name: this.name, - countryCode: this.countryCode, - country: this.country ? this.country.serialize() : undefined, - parentCode: this.parentCode || null - } - } - - deserialize(data: SubdivisionSerializedData): this { - this.code = data.code - this.name = data.name - this.countryCode = data.countryCode - this.country = data.country ? new Country().deserialize(data.country) : undefined - this.parentCode = data.parentCode || undefined - - return this - } -} diff --git a/scripts/models/timezone.ts b/scripts/models/timezone.ts deleted file mode 100644 index e4071138fe..0000000000 --- a/scripts/models/timezone.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { Collection, Dictionary } from '@freearhey/core' - -type TimezoneData = { - id: string - utc_offset: string - countries: string[] -} - -export class Timezone { - id: string - utcOffset: string - countryCodes: Collection - countries?: Collection - - constructor(data: TimezoneData) { - this.id = data.id - this.utcOffset = data.utc_offset - this.countryCodes = new Collection(data.countries) - } - - withCountries(countriesKeyByCode: Dictionary): this { - this.countries = this.countryCodes.map((code: string) => countriesKeyByCode.get(code)) - - return this - } - - getCountries(): Collection { - return this.countries || new Collection() - } -} diff --git a/scripts/tables/categoriesTable.ts b/scripts/tables/categoriesTable.ts index 0b763e4162..ca1432d56e 100644 --- a/scripts/tables/categoriesTable.ts +++ b/scripts/tables/categoriesTable.ts @@ -1,56 +1,63 @@ -import { Storage, Collection, File, Dictionary } from '@freearhey/core' -import { HTMLTable, LogParser, LogItem } from '../core' -import { LOGS_DIR, README_DIR } from '../constants' -import { Category } from '../models' -import { Table } from './table' - -type CategoriesTableProps = { - categoriesKeyById: Dictionary -} - -export class CategoriesTable implements Table { - categoriesKeyById: Dictionary - - constructor({ categoriesKeyById }: CategoriesTableProps) { - this.categoriesKeyById = categoriesKeyById - } - - async make() { - const parser = new LogParser() - const logsStorage = new Storage(LOGS_DIR) - const generatorsLog = await logsStorage.load('generators.log') - - let items = new Collection() - parser - .parse(generatorsLog) - .filter((logItem: LogItem) => logItem.type === 'category') - .forEach((logItem: LogItem) => { - const file = new File(logItem.filepath) - const categoryId = file.name() - const category: Category = this.categoriesKeyById.get(categoryId) - - items.add([ - category ? category.name : 'ZZ', - category ? category.name : 'Undefined', - logItem.count, - `https://iptv-org.github.io/iptv/${logItem.filepath}` - ]) - }) - - items = items - .orderBy(item => item[0]) - .map(item => { - item.shift() - return item - }) - - const table = new HTMLTable(items.all(), [ - { name: 'Category' }, - { name: 'Channels', align: 'right' }, - { name: 'Playlist', nowrap: true } - ]) - - const readmeStorage = new Storage(README_DIR) - await readmeStorage.save('_categories.md', table.toString()) - } -} +import { HTMLTable, HTMLTableItem, LogParser, LogItem, HTMLTableColumn } from '../core' +import { Storage, File } from '@freearhey/storage-js' +import { LOGS_DIR, README_DIR } from '../constants' +import { Collection } from '@freearhey/core' +import * as sdk from '@iptv-org/sdk' +import { Table } from './table' +import { data } from '../api' + +export class CategoriesTable implements Table { + async create() { + const parser = new LogParser() + const logsStorage = new Storage(LOGS_DIR) + const generatorsLog = await logsStorage.load('generators.log') + + let items = new Collection() + parser + .parse(generatorsLog) + .filter((logItem: LogItem) => logItem.type === 'category') + .forEach((logItem: LogItem) => { + if (logItem.filepath.includes('undefined')) { + items.add([ + 'ZZ', + 'Undefined', + logItem.count.toString(), + `https://iptv-org.github.io/iptv/${logItem.filepath}` + ]) + + return + } + + const file = new File(logItem.filepath) + const categoryId = file.name() + const category: sdk.Models.Category | undefined = data.categoriesKeyById.get(categoryId) + + if (!category) return + + items.add([ + category.name, + category.name, + logItem.count.toString(), + `https://iptv-org.github.io/iptv/${logItem.filepath}` + ]) + }) + + items = items + .sortBy(item => item[0]) + .map(item => { + item.shift() + return item + }) + + const columns = new Collection([ + { name: 'Category' }, + { name: 'Channels', align: 'right' }, + { name: 'Playlist', nowrap: true } + ]) + + const table = new HTMLTable(items, columns) + + const readmeStorage = new Storage(README_DIR) + await readmeStorage.save('_categories.md', table.toString()) + } +} diff --git a/scripts/tables/countriesTable.ts b/scripts/tables/countriesTable.ts index 8c9d2173a4..95914f6d30 100644 --- a/scripts/tables/countriesTable.ts +++ b/scripts/tables/countriesTable.ts @@ -1,189 +1,176 @@ -import { Storage, Collection, Dictionary } from '@freearhey/core' -import { City, Country, Subdivision } from '../models' -import { LOGS_DIR, README_DIR } from '../constants' -import { LogParser, LogItem } from '../core' -import { Table } from './table' - -type CountriesTableProps = { - countriesKeyByCode: Dictionary - subdivisionsKeyByCode: Dictionary - countries: Collection - subdivisions: Collection - cities: Collection -} - -export class CountriesTable implements Table { - countriesKeyByCode: Dictionary - subdivisionsKeyByCode: Dictionary - countries: Collection - subdivisions: Collection - cities: Collection - - constructor({ - countriesKeyByCode, - subdivisionsKeyByCode, - countries, - subdivisions, - cities - }: CountriesTableProps) { - this.countriesKeyByCode = countriesKeyByCode - this.subdivisionsKeyByCode = subdivisionsKeyByCode - this.countries = countries - this.subdivisions = subdivisions - this.cities = cities - } - - async make() { - const parser = new LogParser() - const logsStorage = new Storage(LOGS_DIR) - const generatorsLog = await logsStorage.load('generators.log') - const parsed = parser.parse(generatorsLog) - const logCountries = parsed.filter((logItem: LogItem) => logItem.type === 'country') - const logSubdivisions = parsed.filter((logItem: LogItem) => logItem.type === 'subdivision') - const logCities = parsed.filter((logItem: LogItem) => logItem.type === 'city') - - let items = new Collection() - this.countries.forEach((country: Country) => { - const countriesLogItem = logCountries.find( - (logItem: LogItem) => logItem.filepath === `countries/${country.code.toLowerCase()}.m3u` - ) - - const countryItem = { - index: country.name, - count: 0, - link: `https://iptv-org.github.io/iptv/countries/${country.code.toLowerCase()}.m3u`, - name: `${country.flag} ${country.name}`, - children: new Collection() - } - - if (countriesLogItem) { - countryItem.count = countriesLogItem.count - } - - const countrySubdivisions = this.subdivisions.filter( - (subdivision: Subdivision) => subdivision.countryCode === country.code - ) - const countryCities = this.cities.filter((city: City) => city.countryCode === country.code) - if (countrySubdivisions.notEmpty()) { - this.subdivisions.forEach((subdivision: Subdivision) => { - if (subdivision.countryCode !== country.code) return - const subdivisionCities = countryCities.filter( - (city: City) => - (city.subdivisionCode && city.subdivisionCode === subdivision.code) || - city.countryCode === subdivision.countryCode - ) - const subdivisionsLogItem = logSubdivisions.find( - (logItem: LogItem) => - logItem.filepath === `subdivisions/${subdivision.code.toLowerCase()}.m3u` - ) - - const subdivisionItem = { - index: subdivision.name, - name: subdivision.name, - count: 0, - link: `https://iptv-org.github.io/iptv/subdivisions/${subdivision.code.toLowerCase()}.m3u`, - children: new Collection() - } - - if (subdivisionsLogItem) { - subdivisionItem.count = subdivisionsLogItem.count - } - - subdivisionCities.forEach((city: City) => { - if (city.countryCode !== country.code || city.subdivisionCode !== subdivision.code) - return - const citiesLogItem = logCities.find( - (logItem: LogItem) => logItem.filepath === `cities/${city.code.toLowerCase()}.m3u` - ) - - if (!citiesLogItem) return - - subdivisionItem.children.add({ - index: city.name, - name: city.name, - count: citiesLogItem.count, - link: `https://iptv-org.github.io/iptv/${citiesLogItem.filepath}` - }) - }) - - if (subdivisionItem.count > 0 || subdivisionItem.children.notEmpty()) { - countryItem.children.add(subdivisionItem) - } - }) - } else if (countryCities.notEmpty()) { - countryCities.forEach((city: City) => { - const citiesLogItem = logCities.find( - (logItem: LogItem) => logItem.filepath === `cities/${city.code.toLowerCase()}.m3u` - ) - - if (!citiesLogItem) return - - countryItem.children.add({ - index: city.name, - name: city.name, - count: citiesLogItem.count, - link: `https://iptv-org.github.io/iptv/${citiesLogItem.filepath}`, - children: new Collection() - }) - }) - } - - if (countryItem.count > 0 || countryItem.children.notEmpty()) { - items.add(countryItem) - } - }) - - const internationalLogItem = logCountries.find( - (logItem: LogItem) => logItem.filepath === 'countries/int.m3u' - ) - - if (internationalLogItem) { - items.push({ - index: 'ZZ', - name: '🌐 International', - count: internationalLogItem.count, - link: `https://iptv-org.github.io/iptv/${internationalLogItem.filepath}`, - children: new Collection() - }) - } - - const undefinedLogItem = logCountries.find( - (logItem: LogItem) => logItem.filepath === 'countries/undefined.m3u' - ) - - if (undefinedLogItem) { - items.push({ - index: 'ZZZ', - name: 'Undefined', - count: undefinedLogItem.count, - link: `https://iptv-org.github.io/iptv/${undefinedLogItem.filepath}`, - children: new Collection() - }) - } - - items = items.orderBy(item => item.index) - - const output = items - .map(item => { - let row = `- ${item.name} ${item.link}` - - item.children - .orderBy(item => item.index) - .forEach(item => { - row += `\r\n - ${item.name} ${item.link}` - - item.children - .orderBy(item => item.index) - .forEach(item => { - row += `\r\n - ${item.name} ${item.link}` - }) - }) - - return row - }) - .join('\r\n') - - const readmeStorage = new Storage(README_DIR) - await readmeStorage.save('_countries.md', output) - } -} +import { LOGS_DIR, README_DIR } from '../constants' +import { Storage } from '@freearhey/storage-js' +import { Collection } from '@freearhey/core' +import { LogParser, LogItem } from '../core' +import * as sdk from '@iptv-org/sdk' +import { Table } from './table' +import { data } from '../api' + +type ListItem = { + index: string + count: number + link: string + name: string + children: Collection +} + +export class CountriesTable implements Table { + async create() { + const parser = new LogParser() + const logsStorage = new Storage(LOGS_DIR) + const generatorsLog = await logsStorage.load('generators.log') + const parsed = parser.parse(generatorsLog) + const logCountries = parsed.filter((logItem: LogItem) => logItem.type === 'country') + const logSubdivisions = parsed.filter((logItem: LogItem) => logItem.type === 'subdivision') + const logCities = parsed.filter((logItem: LogItem) => logItem.type === 'city') + + let items = new Collection() + data.countries.forEach((country: sdk.Models.Country) => { + const countryCode = country.code + const countriesLogItem = logCountries.find( + (logItem: LogItem) => logItem.filepath === `countries/${countryCode.toLowerCase()}.m3u` + ) + + const countryItem: ListItem = { + index: country.name, + count: 0, + link: `https://iptv-org.github.io/iptv/countries/${countryCode.toLowerCase()}.m3u`, + name: `${country.flag} ${country.name}`, + children: new Collection() + } + + if (countriesLogItem) { + countryItem.count = countriesLogItem.count + } + + const countrySubdivisions = data.subdivisions.filter( + (subdivision: sdk.Models.Subdivision) => subdivision.country === countryCode + ) + const countryCities = data.cities.filter( + (city: sdk.Models.City) => city.country === countryCode + ) + if (countrySubdivisions.isNotEmpty()) { + data.subdivisions.forEach((subdivision: sdk.Models.Subdivision) => { + if (subdivision.country !== countryCode) return + + const subdivisionCode = subdivision.code + const subdivisionCities = countryCities.filter( + (city: sdk.Models.City) => + (city.subdivision && city.subdivision === subdivisionCode) || + city.country === subdivision.country + ) + const subdivisionsLogItem = logSubdivisions.find( + (logItem: LogItem) => + logItem.filepath === `subdivisions/${subdivisionCode.toLowerCase()}.m3u` + ) + + const subdivisionItem: ListItem = { + index: subdivision.name, + name: subdivision.name, + count: 0, + link: `https://iptv-org.github.io/iptv/subdivisions/${subdivisionCode.toLowerCase()}.m3u`, + children: new Collection() + } + + if (subdivisionsLogItem) { + subdivisionItem.count = subdivisionsLogItem.count + } + + subdivisionCities.forEach((city: sdk.Models.City) => { + if (city.country !== countryCode || city.subdivision !== subdivisionCode) return + const citiesLogItem = logCities.find( + (logItem: LogItem) => logItem.filepath === `cities/${city.code.toLowerCase()}.m3u` + ) + + if (!citiesLogItem) return + + subdivisionItem.children.add({ + index: city.name, + name: city.name, + count: citiesLogItem.count, + link: `https://iptv-org.github.io/iptv/${citiesLogItem.filepath}`, + children: new Collection() + }) + }) + + if (subdivisionItem.count > 0 || subdivisionItem.children.isNotEmpty()) { + countryItem.children.add(subdivisionItem) + } + }) + } else if (countryCities.isNotEmpty()) { + countryCities.forEach((city: sdk.Models.City) => { + const citiesLogItem = logCities.find( + (logItem: LogItem) => logItem.filepath === `cities/${city.code.toLowerCase()}.m3u` + ) + + if (!citiesLogItem) return + + countryItem.children.add({ + index: city.name, + name: city.name, + count: citiesLogItem.count, + link: `https://iptv-org.github.io/iptv/${citiesLogItem.filepath}`, + children: new Collection() + }) + }) + } + + if (countryItem.count > 0 || countryItem.children.isNotEmpty()) { + items.add(countryItem) + } + }) + + const internationalLogItem = logCountries.find( + (logItem: LogItem) => logItem.filepath === 'countries/int.m3u' + ) + + if (internationalLogItem) { + items.add({ + index: 'ZZ', + name: '🌐 International', + count: internationalLogItem.count, + link: `https://iptv-org.github.io/iptv/${internationalLogItem.filepath}`, + children: new Collection() + }) + } + + const undefinedLogItem = logCountries.find( + (logItem: LogItem) => logItem.filepath === 'countries/undefined.m3u' + ) + + if (undefinedLogItem) { + items.add({ + index: 'ZZZ', + name: 'Undefined', + count: undefinedLogItem.count, + link: `https://iptv-org.github.io/iptv/${undefinedLogItem.filepath}`, + children: new Collection() + }) + } + + items = items.sortBy(item => item.index) + + const output = items + .map((item: ListItem) => { + let row = `- ${item.name} ${item.link}` + + item.children + .sortBy((item: ListItem) => item.index) + .forEach((item: ListItem) => { + row += `\r\n - ${item.name} ${item.link}` + + item.children + .sortBy((item: ListItem) => item.index) + .forEach((item: ListItem) => { + row += `\r\n - ${item.name} ${item.link}` + }) + }) + + return row + }) + .join('\r\n') + + const readmeStorage = new Storage(README_DIR) + await readmeStorage.save('_countries.md', output) + } +} diff --git a/scripts/tables/index.ts b/scripts/tables/index.ts index f25c0a3a27..1cb7826ef3 100644 --- a/scripts/tables/index.ts +++ b/scripts/tables/index.ts @@ -1,4 +1,4 @@ -export * from './categoriesTable' -export * from './countriesTable' -export * from './languagesTable' -export * from './regionsTable' +export * from './categoriesTable' +export * from './countriesTable' +export * from './languagesTable' +export * from './regionsTable' diff --git a/scripts/tables/languagesTable.ts b/scripts/tables/languagesTable.ts index 7621907453..469166fade 100644 --- a/scripts/tables/languagesTable.ts +++ b/scripts/tables/languagesTable.ts @@ -1,56 +1,63 @@ -import { Storage, Collection, File, Dictionary } from '@freearhey/core' -import { HTMLTable, LogParser, LogItem } from '../core' -import { LOGS_DIR, README_DIR } from '../constants' -import { Language } from '../models' -import { Table } from './table' - -type LanguagesTableProps = { - languagesKeyByCode: Dictionary -} - -export class LanguagesTable implements Table { - languagesKeyByCode: Dictionary - - constructor({ languagesKeyByCode }: LanguagesTableProps) { - this.languagesKeyByCode = languagesKeyByCode - } - - async make() { - const parser = new LogParser() - const logsStorage = new Storage(LOGS_DIR) - const generatorsLog = await logsStorage.load('generators.log') - - let data = new Collection() - parser - .parse(generatorsLog) - .filter((logItem: LogItem) => logItem.type === 'language') - .forEach((logItem: LogItem) => { - const file = new File(logItem.filepath) - const languageCode = file.name() - const language: Language = this.languagesKeyByCode.get(languageCode) - - data.add([ - language ? language.name : 'ZZ', - language ? language.name : 'Undefined', - logItem.count, - `https://iptv-org.github.io/iptv/${logItem.filepath}` - ]) - }) - - data = data - .orderBy(item => item[0]) - .map(item => { - item.shift() - return item - }) - - const table = new HTMLTable(data.all(), [ - { name: 'Language', align: 'left' }, - { name: 'Channels', align: 'right' }, - { name: 'Playlist', align: 'left', nowrap: true } - ]) - - const readmeStorage = new Storage(README_DIR) - await readmeStorage.save('_languages.md', table.toString()) - } -} +import { HTMLTable, LogParser, LogItem, HTMLTableColumn, HTMLTableItem } from '../core' +import { Storage, File } from '@freearhey/storage-js' +import { LOGS_DIR, README_DIR } from '../constants' +import { Collection } from '@freearhey/core' +import * as sdk from '@iptv-org/sdk' +import { Table } from './table' +import { data } from '../api' + +export class LanguagesTable implements Table { + async create() { + const parser = new LogParser() + const logsStorage = new Storage(LOGS_DIR) + const generatorsLog = await logsStorage.load('generators.log') + + let items = new Collection() + parser + .parse(generatorsLog) + .filter((logItem: LogItem) => logItem.type === 'language') + .forEach((logItem: LogItem) => { + if (logItem.filepath.includes('undefined')) { + items.add([ + 'ZZ', + 'Undefined', + logItem.count.toString(), + `https://iptv-org.github.io/iptv/${logItem.filepath}` + ]) + + return + } + + const file = new File(logItem.filepath) + const languageCode = file.name() + const language: sdk.Models.Language | undefined = data.languagesKeyByCode.get(languageCode) + + if (!language) return + + items.add([ + language.name, + language.name, + logItem.count.toString(), + `https://iptv-org.github.io/iptv/${logItem.filepath}` + ]) + }) + + items = items + .sortBy(item => item[0]) + .map(item => { + item.shift() + return item + }) + + const columns = new Collection([ + { name: 'Language', align: 'left' }, + { name: 'Channels', align: 'right' }, + { name: 'Playlist', align: 'left', nowrap: true } + ]) + + const table = new HTMLTable(items, columns) + + const readmeStorage = new Storage(README_DIR) + await readmeStorage.save('_languages.md', table.toString()) + } +} diff --git a/scripts/tables/regionsTable.ts b/scripts/tables/regionsTable.ts index 2bf4b74f4f..39c58d98b7 100644 --- a/scripts/tables/regionsTable.ts +++ b/scripts/tables/regionsTable.ts @@ -1,52 +1,49 @@ -import { Storage, Collection } from '@freearhey/core' -import { LogParser, LogItem } from '../core' -import { LOGS_DIR, README_DIR } from '../constants' -import { Region } from '../models' -import { Table } from './table' - -type RegionsTableProps = { - regions: Collection -} - -export class RegionsTable implements Table { - regions: Collection - - constructor({ regions }: RegionsTableProps) { - this.regions = regions - } - - async make() { - const parser = new LogParser() - const logsStorage = new Storage(LOGS_DIR) - const generatorsLog = await logsStorage.load('generators.log') - const parsed = parser.parse(generatorsLog) - const logRegions = parsed.filter((logItem: LogItem) => logItem.type === 'region') - - let items = new Collection() - this.regions.forEach((region: Region) => { - const logItem = logRegions.find( - (logItem: LogItem) => logItem.filepath === `regions/${region.code.toLowerCase()}.m3u` - ) - - if (!logItem) return - - items.add({ - index: region.name, - name: region.name, - count: logItem.count, - link: `https://iptv-org.github.io/iptv/${logItem.filepath}` - }) - }) - - items = items.orderBy(item => item.index) - - const output = items - .map(item => { - return `- ${item.name} ${item.link}` - }) - .join('\r\n') - - const readmeStorage = new Storage(README_DIR) - await readmeStorage.save('_regions.md', output) - } -} +import { LOGS_DIR, README_DIR } from '../constants' +import { Storage } from '@freearhey/storage-js' +import { LogParser, LogItem } from '../core' +import { Collection } from '@freearhey/core' +import * as sdk from '@iptv-org/sdk' +import { Table } from './table' +import { data } from '../api' + +type ListItem = { + name: string + count: number + link: string +} + +export class RegionsTable implements Table { + async create() { + const parser = new LogParser() + const logsStorage = new Storage(LOGS_DIR) + const generatorsLog = await logsStorage.load('generators.log') + const parsed = parser.parse(generatorsLog) + const logRegions = parsed.filter((logItem: LogItem) => logItem.type === 'region') + + let items = new Collection() + data.regions.forEach((region: sdk.Models.Region) => { + const logItem = logRegions.find( + (logItem: LogItem) => logItem.filepath === `regions/${region.code.toLowerCase()}.m3u` + ) + + if (!logItem) return + + items.add({ + name: region.name, + count: logItem.count, + link: `https://iptv-org.github.io/iptv/${logItem.filepath}` + }) + }) + + items = items.sortBy(item => item.name) + + const output = items + .map(item => { + return `- ${item.name} ${item.link}` + }) + .join('\r\n') + + const readmeStorage = new Storage(README_DIR) + await readmeStorage.save('_regions.md', output) + } +} diff --git a/scripts/tables/table.ts b/scripts/tables/table.ts index b8bd21bd7e..b342b5e7e8 100644 --- a/scripts/tables/table.ts +++ b/scripts/tables/table.ts @@ -1,3 +1,3 @@ -export interface Table { - make(): void -} +export interface Table { + create(): void +} diff --git a/scripts/types/blocklistRecord.d.ts b/scripts/types/blocklistRecord.d.ts deleted file mode 100644 index 4b1d9e7dc8..0000000000 --- a/scripts/types/blocklistRecord.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -export type BlocklistRecordData = { - channel: string - reason: string - ref: string -} diff --git a/scripts/types/category.d.ts b/scripts/types/category.d.ts deleted file mode 100644 index e78d6c62ed..0000000000 --- a/scripts/types/category.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -export type CategorySerializedData = { - id: string - name: string -} - -export type CategoryData = { - id: string - name: string -} diff --git a/scripts/types/channel.d.ts b/scripts/types/channel.d.ts deleted file mode 100644 index 814fc53a79..0000000000 --- a/scripts/types/channel.d.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { Collection } from '@freearhey/core' -import type { CountrySerializedData } from './country' -import type { SubdivisionSerializedData } from './subdivision' -import type { CategorySerializedData } from './category' - -export type ChannelSerializedData = { - id: string - name: string - altNames: string[] - network?: string - owners: string[] - countryCode: string - country?: CountrySerializedData - subdivisionCode?: string - subdivision?: SubdivisionSerializedData - cityName?: string - categoryIds: string[] - categories?: CategorySerializedData[] - isNSFW: boolean - launched?: string - closed?: string - replacedBy?: string - website?: string -} - -export 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 -} - -export type ChannelSearchableData = { - id: string - name: string - altNames: string[] - guideNames: string[] - streamTitles: string[] - feedFullNames: string[] -} diff --git a/scripts/types/city.d.ts b/scripts/types/city.d.ts deleted file mode 100644 index 5c33ba5a9e..0000000000 --- a/scripts/types/city.d.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { CountrySerializedData } from './country' -import { SubdivisionSerializedData } from './subdivision' - -export type CitySerializedData = { - code: string - name: string - countryCode: string - country?: CountrySerializedData - subdivisionCode: string | null - subdivision?: SubdivisionSerializedData - wikidataId: string -} - -export type CityData = { - code: string - name: string - country: string - subdivision: string | null - wikidata_id: string -} diff --git a/scripts/types/country.d.ts b/scripts/types/country.d.ts deleted file mode 100644 index 9554d4c68c..0000000000 --- a/scripts/types/country.d.ts +++ /dev/null @@ -1,20 +0,0 @@ -import type { LanguageSerializedData } from './language' -import type { SubdivisionSerializedData } from './subdivision' -import type { RegionSerializedData } from './region' - -export type CountrySerializedData = { - code: string - name: string - flag: string - languageCode: string - language: LanguageSerializedData | null - subdivisions: SubdivisionSerializedData[] - regions: RegionSerializedData[] -} - -export type CountryData = { - code: string - name: string - lang: string - flag: string -} diff --git a/scripts/types/dataLoader.d.ts b/scripts/types/dataLoader.d.ts deleted file mode 100644 index 708361de99..0000000000 --- a/scripts/types/dataLoader.d.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { Storage } from '@freearhey/core' - -export type DataLoaderProps = { - storage: Storage -} - -export type DataLoaderData = { - countries: object | object[] - regions: object | object[] - subdivisions: object | object[] - languages: object | object[] - categories: object | object[] - blocklist: object | object[] - channels: object | object[] - feeds: object | object[] - logos: object | object[] - timezones: object | object[] - guides: object | object[] - streams: object | object[] - cities: object | object[] -} diff --git a/scripts/types/dataProcessor.d.ts b/scripts/types/dataProcessor.d.ts deleted file mode 100644 index bc76dc28b4..0000000000 --- a/scripts/types/dataProcessor.d.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { Collection, Dictionary } from '@freearhey/core' - -export type DataProcessorData = { - blocklistRecordsGroupedByChannelId: Dictionary - subdivisionsGroupedByCountryCode: Dictionary - feedsGroupedByChannelId: Dictionary - guidesGroupedByStreamId: Dictionary - logosGroupedByStreamId: Dictionary - subdivisionsKeyByCode: Dictionary - countriesKeyByCode: Dictionary - languagesKeyByCode: Dictionary - streamsGroupedById: Dictionary - categoriesKeyById: Dictionary - timezonesKeyById: Dictionary - regionsKeyByCode: Dictionary - blocklistRecords: Collection - channelsKeyById: Dictionary - citiesKeyByCode: Dictionary - subdivisions: Collection - categories: Collection - countries: Collection - languages: Collection - timezones: Collection - channels: Collection - regions: Collection - streams: Collection - cities: Collection - guides: Collection - feeds: Collection - logos: Collection -} diff --git a/scripts/types/feed.d.ts b/scripts/types/feed.d.ts deleted file mode 100644 index ef4aea4669..0000000000 --- a/scripts/types/feed.d.ts +++ /dev/null @@ -1,10 +0,0 @@ -export type FeedData = { - channel: string - id: string - name: string - is_main: boolean - broadcast_area: string[] - languages: string[] - timezones: string[] - video_format: string -} diff --git a/scripts/types/guide.d.ts b/scripts/types/guide.d.ts deleted file mode 100644 index 63a6ecdb19..0000000000 --- a/scripts/types/guide.d.ts +++ /dev/null @@ -1,17 +0,0 @@ -export type GuideSerializedData = { - channelId?: string - feedId?: string - siteDomain: string - siteId: string - siteName: string - languageCode: string -} - -export type GuideData = { - channel: string - feed: string - site: string - site_id: string - site_name: string - lang: string -} diff --git a/scripts/types/language.d.ts b/scripts/types/language.d.ts deleted file mode 100644 index 2b9d4525c0..0000000000 --- a/scripts/types/language.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -export type LanguageSerializedData = { - code: string - name: string -} - -export type LanguageData = { - code: string - name: string -} diff --git a/scripts/types/logo.d.ts b/scripts/types/logo.d.ts deleted file mode 100644 index 47cc384537..0000000000 --- a/scripts/types/logo.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -export type LogoData = { - channel: string - feed: string | null - tags: string[] - width: number - height: number - format: string | null - url: string -} diff --git a/scripts/types/region.d.ts b/scripts/types/region.d.ts deleted file mode 100644 index 798224ee7f..0000000000 --- a/scripts/types/region.d.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { CitySerializedData } from './city' -import { CountrySerializedData } from './country' -import { SubdivisionSerializedData } from './subdivision' - -export type RegionSerializedData = { - code: string - name: string - countryCodes: string[] - countries?: CountrySerializedData[] - subdivisions?: SubdivisionSerializedData[] - cities?: CitySerializedData[] -} - -export type RegionData = { - code: string - name: string - countries: string[] -} diff --git a/scripts/types/stream.d.ts b/scripts/types/stream.d.ts deleted file mode 100644 index aebd4bbd9f..0000000000 --- a/scripts/types/stream.d.ts +++ /dev/null @@ -1,11 +0,0 @@ -export type StreamData = { - channelId: string | null - feedId: string | null - title: string | null - url: string - referrer: string | null - userAgent: string | null - quality: string | null - label: string | null - directives: string[] -} diff --git a/scripts/types/subdivision.d.ts b/scripts/types/subdivision.d.ts deleted file mode 100644 index b2a25982dd..0000000000 --- a/scripts/types/subdivision.d.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { CountrySerializedData } from './country' - -export type SubdivisionSerializedData = { - code: string - name: string - countryCode: string - country?: CountrySerializedData - parentCode: string | null -} - -export type SubdivisionData = { - code: string - name: string - country: string - parent: string | null -} diff --git a/scripts/utils.ts b/scripts/utils.ts index 7ff419de21..d58b80406d 100644 --- a/scripts/utils.ts +++ b/scripts/utils.ts @@ -1,8 +1,23 @@ -export function isURI(string: string): boolean { - try { - new URL(string) - return true - } catch { - return false - } -} +import normalizeUrl from 'normalize-url' + +export function isURI(string: string): boolean { + try { + new URL(string) + return true + } catch { + return false + } +} + +export function normalizeURL(url: string): string { + const normalized = normalizeUrl(url, { stripWWW: false }) + + return decodeURIComponent(normalized).replace(/\s/g, '+').toString() +} + +export function truncate(string: string, limit: number = 100) { + if (!string) return string + if (string.length < limit) return string + + return string.slice(0, limit - 3) + '...' +} diff --git a/tests/__data__/expected/api_generate/.api/streams.json b/tests/__data__/expected/api_generate/.api/streams.json index 4028ae31c1..ae19fcb60c 100644 --- a/tests/__data__/expected/api_generate/.api/streams.json +++ b/tests/__data__/expected/api_generate/.api/streams.json @@ -1,66 +1,66 @@ -[ - { - "channel": null, - "feed": null, - "title": "Daawah TV", - "url": "http://51.15.246.58:8081/daawahtv/daawahtv2/playlist.m3u8", - "referrer": null, - "user_agent": null - }, - { - "channel": null, - "feed": null, - "title": "Andorra TV", - "url": "http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8", - "referrer": "http://imn.iq", - "user_agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148" - }, - { - "channel": "AndorraTV.ad", - "feed": "SD", - "title": "ATV", - "url": "https://iptv-all.lanesh4d0w.repl.co/andorra/atv|Referer=\"https://referer.xyz/\"|User-Agent=\"Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1\"|Origin=\"https://origin.xyz\"", - "referrer": null, - "user_agent": null - }, - { - "channel": "BBCNews.uk", - "feed": null, - "title": "BBC News HD", - "url": "http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8", - "referrer": null, - "user_agent": null - }, - { - "channel": "LDPRTV.ru", - "feed": null, - "title": "ЛДПР ТВ", - "url": "http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8", - "referrer": null, - "user_agent": null - }, - { - "channel": "MeteoMedia.ca", - "feed": null, - "title": "Meteomedia", - "url": "http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8", - "referrer": null, - "user_agent": null - }, - { - "channel": "VisitXTV.nl", - "feed": null, - "title": "Visit-X TV", - "url": "https://stream.visit-x.tv/vxtv/ngrp:live_all/30fps.m3u8", - "referrer": null, - "user_agent": null - }, - { - "channel": "Zoo.ad", - "feed": null, - "title": "Zoo", - "url": "https://iptv-all.lanesh4d0w.repl.co/andorra/zoo", - "referrer": null, - "user_agent": null - } +[ + { + "channel": null, + "feed": null, + "title": "Daawah TV", + "url": "http://51.15.246.58:8081/daawahtv/daawahtv2/playlist.m3u8", + "referrer": null, + "user_agent": null + }, + { + "channel": null, + "feed": null, + "title": "Andorra TV", + "url": "http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8", + "referrer": "http://imn.iq", + "user_agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148" + }, + { + "channel": "AndorraTV.ad", + "feed": "SD", + "title": "ATV", + "url": "https://iptv-all.lanesh4d0w.repl.co/andorra/atv|Referer=\"https://referer.xyz/\"|User-Agent=\"Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1\"|Origin=\"https://origin.xyz\"", + "referrer": null, + "user_agent": null + }, + { + "channel": "BBCNews.uk", + "feed": "SD", + "title": "BBC News HD", + "url": "http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8", + "referrer": null, + "user_agent": null + }, + { + "channel": "LDPRTV.ru", + "feed": "SD", + "title": "ЛДПР ТВ", + "url": "http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8", + "referrer": null, + "user_agent": null + }, + { + "channel": "MeteoMedia.ca", + "feed": "SD", + "title": "Meteomedia", + "url": "http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8", + "referrer": null, + "user_agent": null + }, + { + "channel": "VisitXTV.nl", + "feed": "SD", + "title": "Visit-X TV", + "url": "https://stream.visit-x.tv/vxtv/ngrp:live_all/30fps.m3u8", + "referrer": null, + "user_agent": null + }, + { + "channel": "Zoo.ad", + "feed": "SD", + "title": "Zoo", + "url": "https://iptv-all.lanesh4d0w.repl.co/andorra/zoo", + "referrer": null, + "user_agent": null + } ] \ No newline at end of file diff --git a/tests/__data__/expected/playlist_format/in.m3u b/tests/__data__/expected/playlist_format/in.m3u index 44a00ace12..84637bfe5c 100644 --- a/tests/__data__/expected/playlist_format/in.m3u +++ b/tests/__data__/expected/playlist_format/in.m3u @@ -1,3 +1,3 @@ -#EXTM3U -#EXTINF:-1 tvg-id="",Manorama News -2 [U3] (480p) [Geo-blocked] [Not 24/7] -https://ythls.onrender.com/channel/UCP0uG-mcMImgKnJz-VjJZmQ.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="" http-referrer="http://test.com" http-user-agent="Mozilla/5.0",Manorama News -2 [U3] (480p) [Geo-blocked] [Not 24/7] +https://ythls.onrender.com/channel/UCP0uG-mcMImgKnJz-VjJZmQ.m3u8 diff --git a/tests/__data__/expected/playlist_format/nl.m3u b/tests/__data__/expected/playlist_format/nl.m3u index feaa913a84..bf18bfa6f1 100644 --- a/tests/__data__/expected/playlist_format/nl.m3u +++ b/tests/__data__/expected/playlist_format/nl.m3u @@ -1,15 +1,15 @@ -#EXTM3U -#EXTINF:-1 tvg-id="NPO1.nl@SD",NPO 1 (342p) [Geo-blocked] -http://resolver.streaming.api.nos.nl/livestream?url=/live/npo/tvlive/npo1/npo1.isml/.m3u8 -#EXTINF:-1 tvg-id="NPO2.nl",NPO 2 (342p) -http://resolver.streaming.api.nos.nl/livestream?url=/live/npo/tvlive/npo2/npo2.isml/.m3u8 -#EXTINF:-1 tvg-id="NPO2.nl" http-referrer="http://imn.iq" http-user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",NPO 2 (302p) [Geo-blocked] -#EXTVLCOPT:http-referrer=http://imn.iq -#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 -#KODIPROP:inputstream=inputstream.adaptive -#KODIPROP:inputstream.adaptive.manifest_type=mpd -#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha -#KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=13f2e056-53fe-4469-ba6d-999970dbe549&userToken=v9ZVSksv4S7rT55o10dmYNRa4asye3z05eWCFxD%2FFYIlTJEpuf6tF8asPcyQOFq0h5opS%2B6WoMxnshWkihpHq5qrdrBEZ69piE94J9Feh385snGOqK3PYO7tLLjxmsCAe%2B9%2BNnurSSO5RCAIRsL125nSj1eOR%2F1GSKOgGH80HK2FDLiePxPkeaAxuWzacNBB%2FqnIGGxfe3GlmN65cU9F8WEpKFDlaxW%2Fv3ZSLAp3%2BZEq1aZXJ6Oz%2Fi0diD0EybH7|Content-Type=application/octet-stream|R{SSM}| -http://stream.tvtap.net:8081/live/nl-npo2.stream/playlist.m3u8?|Referer="https://referer.xyz/"|User-Agent="Mozilla/5.0+(iPhone;+CPU+iPhone+OS+17_7+like+Mac+OS+X)+AppleWebKit/605.1.15+(KHTML,+like+Gecko)+Version/18.0+Mobile/15E148+Safari/604.1"|Origin="https://origin.xyz" -#EXTINF:-1 tvg-id="NPO2.nl",NPO 2 [Geo-blocked] -http://resolver.streaming.api.nos.nl/livestream?url=/live/npo/tvlive/npo2/npo22.isml/.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="NPO1.nl@SD",NPO 1 (342p) [Geo-blocked] +http://resolver.streaming.api.nos.nl/livestream?url=/live/npo/tvlive/npo1/npo1.isml/.m3u8 +#EXTINF:-1 tvg-id="NPO2.nl@SD",NPO 2 (342p) +http://resolver.streaming.api.nos.nl/livestream?url=/live/npo/tvlive/npo2/npo2.isml/.m3u8 +#EXTINF:-1 tvg-id="NPO2.nl@SD" http-referrer="http://imn.iq" http-user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",NPO 2 (302p) [Geo-blocked] +#EXTVLCOPT:http-referrer=http://imn.iq +#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 +#KODIPROP:inputstream=inputstream.adaptive +#KODIPROP:inputstream.adaptive.manifest_type=mpd +#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha +#KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=13f2e056-53fe-4469-ba6d-999970dbe549&userToken=v9ZVSksv4S7rT55o10dmYNRa4asye3z05eWCFxD%2FFYIlTJEpuf6tF8asPcyQOFq0h5opS%2B6WoMxnshWkihpHq5qrdrBEZ69piE94J9Feh385snGOqK3PYO7tLLjxmsCAe%2B9%2BNnurSSO5RCAIRsL125nSj1eOR%2F1GSKOgGH80HK2FDLiePxPkeaAxuWzacNBB%2FqnIGGxfe3GlmN65cU9F8WEpKFDlaxW%2Fv3ZSLAp3%2BZEq1aZXJ6Oz%2Fi0diD0EybH7|Content-Type=application/octet-stream|R{SSM}| +http://stream.tvtap.net:8081/live/nl-npo2.stream/playlist.m3u8?|Referer="https://referer.xyz/"|User-Agent="Mozilla/5.0+(iPhone;+CPU+iPhone+OS+17_7+like+Mac+OS+X)+AppleWebKit/605.1.15+(KHTML,+like+Gecko)+Version/18.0+Mobile/15E148+Safari/604.1"|Origin="https://origin.xyz" +#EXTINF:-1 tvg-id="NPO2.nl@SD",NPO 2 [Geo-blocked] +http://resolver.streaming.api.nos.nl/livestream?url=/live/npo/tvlive/npo2/npo22.isml/.m3u8 diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/categories/general.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/categories/general.m3u index e9587edc70..d43fa35f64 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/categories/general.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/categories/general.m3u @@ -1,7 +1,7 @@ -#EXTM3U -#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 -#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) -http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8 -#EXTINF:-1 tvg-id="ElTR.kg" tvg-logo="https://i.ibb.co/r6czQwQ/365049798-774721644658455-5702658175909463406-n-2.png" group-title="General",ЭлТР (480p) [Not 24/7] -http://gohoski.fvds.ru:3000/mediabay/162/index.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8 +#EXTINF:-1 tvg-id="ElTR.kg" tvg-logo="https://i.ibb.co/r6czQwQ/365049798-774721644658455-5702658175909463406-n-2.png" group-title="General",ЭлТР (480p) [Not 24/7] +http://gohoski.fvds.ru:3000/mediabay/162/index.m3u8 diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/categories/legislative.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/categories/legislative.m3u index fcd718794a..7452e53aad 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/categories/legislative.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/categories/legislative.m3u @@ -1 +1 @@ -#EXTM3U +#EXTM3U diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/categories/news.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/categories/news.m3u index cf4e62a9a5..85c75b78bf 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/categories/news.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/categories/news.m3u @@ -1,3 +1,3 @@ -#EXTM3U -#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/categories/undefined.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/categories/undefined.m3u index 2a2adcdbe2..5373b79516 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/categories/undefined.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/categories/undefined.m3u @@ -1,21 +1,21 @@ -#EXTM3U -#EXTINF:-1 tvg-id="5AABTV.ca" tvg-logo="" group-title="Undefined",5AAB TV -http://158.69.124.9:1935/5aabtv/5aabtv/playlist.m3u8 -#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined" http-referrer="http://imn.iq" http-user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",Andorra TV (720p) [Not 24/7] -#EXTVLCOPT:http-referrer=http://imn.iq -#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 -#KODIPROP:inputstream=inputstream.adaptive -#KODIPROP:inputstream.adaptive.manifest_type=mpd -#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha -#KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=13f2e056-53fe-4469-ba6d-999970dbe549&userToken=v9ZVSksv4S7rT55o10dmYNRa4asye3z05eWCFxD%2FFYIlTJEpuf6tF8asPcyQOFq0h5opS%2B6WoMxnshWkihpHq5qrdrBEZ69piE94J9Feh385snGOqK3PYO7tLLjxmsCAe%2B9%2BNnurSSO5RCAIRsL125nSj1eOR%2F1GSKOgGH80HK2FDLiePxPkeaAxuWzacNBB%2FqnIGGxfe3GlmN65cU9F8WEpKFDlaxW%2Fv3ZSLAp3%2BZEq1aZXJ6Oz%2Fi0diD0EybH7|Content-Type=application/octet-stream|R{SSM}| -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8|Referer="https://referer.xyz/"|User-Agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1"|Origin="https://origin.xyz" -#EXTINF:-1 tvg-id="AndorraTV.ad@SD" tvg-logo="https://i.imgur.com/BnhTn8i.png" group-title="Undefined",ATV -https://iptv-all.lanesh4d0w.repl.co/andorra/atv -#EXTINF:-1 tvg-id="AndorraTV.ad@HD" tvg-logo="https://i.imgur.com/CnhTn8i.png" group-title="Undefined",ATV HD -https://iptv-all.lanesh4d0w.repl.co/andorra/atv_hd -#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined",Daawah TV -http://51.15.246.58:8081/daawahtv/daawahtv2/playlist.m3u8 -#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) -http://146.59.85.40:89/dunaworld/index.m3u8 -#EXTINF:-1 tvg-id="Zoo.ad@HD" tvg-logo="https://i.imgur.com/ciTJrnl.png" group-title="Undefined",Zoo (720p) -https://iptv-all.lanesh4d0w.repl.co/andorra/zoo +#EXTM3U +#EXTINF:-1 tvg-id="5AABTV.ca" tvg-logo="" group-title="Undefined",5AAB TV +http://158.69.124.9:1935/5aabtv/5aabtv/playlist.m3u8 +#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined" http-referrer="http://imn.iq" http-user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",Andorra TV (720p) [Not 24/7] +#EXTVLCOPT:http-referrer=http://imn.iq +#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 +#KODIPROP:inputstream=inputstream.adaptive +#KODIPROP:inputstream.adaptive.manifest_type=mpd +#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha +#KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=13f2e056-53fe-4469-ba6d-999970dbe549&userToken=v9ZVSksv4S7rT55o10dmYNRa4asye3z05eWCFxD%2FFYIlTJEpuf6tF8asPcyQOFq0h5opS%2B6WoMxnshWkihpHq5qrdrBEZ69piE94J9Feh385snGOqK3PYO7tLLjxmsCAe%2B9%2BNnurSSO5RCAIRsL125nSj1eOR%2F1GSKOgGH80HK2FDLiePxPkeaAxuWzacNBB%2FqnIGGxfe3GlmN65cU9F8WEpKFDlaxW%2Fv3ZSLAp3%2BZEq1aZXJ6Oz%2Fi0diD0EybH7|Content-Type=application/octet-stream|R{SSM}| +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8|Referer="https://referer.xyz/"|User-Agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1"|Origin="https://origin.xyz" +#EXTINF:-1 tvg-id="AndorraTV.ad@SD" tvg-logo="https://i.imgur.com/BnhTn8i.png" group-title="Undefined",ATV +https://iptv-all.lanesh4d0w.repl.co/andorra/atv +#EXTINF:-1 tvg-id="AndorraTV.ad@HD" tvg-logo="https://i.imgur.com/CnhTn8i.png" group-title="Undefined",ATV HD +https://iptv-all.lanesh4d0w.repl.co/andorra/atv_hd +#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined",Daawah TV +http://51.15.246.58:8081/daawahtv/daawahtv2/playlist.m3u8 +#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) +http://146.59.85.40:89/dunaworld/index.m3u8 +#EXTINF:-1 tvg-id="Zoo.ad@HD" tvg-logo="https://i.imgur.com/ciTJrnl.png" group-title="Undefined",Zoo (720p) +https://iptv-all.lanesh4d0w.repl.co/andorra/zoo diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/categories/weather.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/categories/weather.m3u index 4686c68f4b..03a6963a33 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/categories/weather.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/categories/weather.m3u @@ -1,3 +1,3 @@ -#EXTM3U -#EXTINF:-1 tvg-id="MeteoMedia.ca" tvg-logo="https://s1.twnmm.com/images/en_ca/mobile/logos/twn-mobile-logo.png" group-title="Weather",Meteomedia -http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="MeteoMedia.ca" tvg-logo="https://s1.twnmm.com/images/en_ca/mobile/logos/twn-mobile-logo.png" group-title="Weather",Meteomedia +http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8 diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/categories/xxx.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/categories/xxx.m3u index d1e3a69bcd..a6791d64b8 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/categories/xxx.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/categories/xxx.m3u @@ -1,3 +1,3 @@ -#EXTM3U -#EXTINF:-1 tvg-id="VisitXTV.nl" tvg-logo="https://i.imgur.com/RJ9wbNF.jpg" group-title="XXX",Visit-X TV -https://stream.visit-x.tv/vxtv/ngrp:live_all/30fps.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="VisitXTV.nl" tvg-logo="https://i.imgur.com/RJ9wbNF.jpg" group-title="XXX",Visit-X TV +https://stream.visit-x.tv/vxtv/ngrp:live_all/30fps.m3u8 diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/cities/adcan.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/cities/adcan.m3u index 92a59e8a10..e85626ca16 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/cities/adcan.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/cities/adcan.m3u @@ -1,3 +1,3 @@ -#EXTM3U -#EXTINF:-1 tvg-id="AndorraTV.ad@SD" tvg-logo="https://i.imgur.com/BnhTn8i.png" group-title="Undefined",ATV -https://iptv-all.lanesh4d0w.repl.co/andorra/atv +#EXTM3U +#EXTINF:-1 tvg-id="AndorraTV.ad@SD" tvg-logo="https://i.imgur.com/BnhTn8i.png" group-title="Undefined",ATV +https://iptv-all.lanesh4d0w.repl.co/andorra/atv diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/countries/ad.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/countries/ad.m3u index 92a59e8a10..e85626ca16 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/countries/ad.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/countries/ad.m3u @@ -1,3 +1,3 @@ -#EXTM3U -#EXTINF:-1 tvg-id="AndorraTV.ad@SD" tvg-logo="https://i.imgur.com/BnhTn8i.png" group-title="Undefined",ATV -https://iptv-all.lanesh4d0w.repl.co/andorra/atv +#EXTM3U +#EXTINF:-1 tvg-id="AndorraTV.ad@SD" tvg-logo="https://i.imgur.com/BnhTn8i.png" group-title="Undefined",ATV +https://iptv-all.lanesh4d0w.repl.co/andorra/atv diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/countries/ca.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/countries/ca.m3u index 8aeaaae90e..79ba1e61d2 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/countries/ca.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/countries/ca.m3u @@ -1,5 +1,5 @@ -#EXTM3U -#EXTINF:-1 tvg-id="5AABTV.ca" tvg-logo="" group-title="Undefined",5AAB TV -http://158.69.124.9:1935/5aabtv/5aabtv/playlist.m3u8 -#EXTINF:-1 tvg-id="MeteoMedia.ca" tvg-logo="https://s1.twnmm.com/images/en_ca/mobile/logos/twn-mobile-logo.png" group-title="Weather",Meteomedia -http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="5AABTV.ca" tvg-logo="" group-title="Undefined",5AAB TV +http://158.69.124.9:1935/5aabtv/5aabtv/playlist.m3u8 +#EXTINF:-1 tvg-id="MeteoMedia.ca" tvg-logo="https://s1.twnmm.com/images/en_ca/mobile/logos/twn-mobile-logo.png" group-title="Weather",Meteomedia +http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8 diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/countries/int.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/countries/int.m3u index 202cd4e3fa..8d37f3ba9b 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/countries/int.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/countries/int.m3u @@ -1,9 +1,9 @@ -#EXTM3U -#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 -#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) -http://146.59.85.40:89/dunaworld/index.m3u8 -#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) -http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8 -#EXTINF:-1 tvg-id="ElTR.kg" tvg-logo="https://i.ibb.co/r6czQwQ/365049798-774721644658455-5702658175909463406-n-2.png" group-title="General",ЭлТР (480p) [Not 24/7] -http://gohoski.fvds.ru:3000/mediabay/162/index.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) +http://146.59.85.40:89/dunaworld/index.m3u8 +#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8 +#EXTINF:-1 tvg-id="ElTR.kg" tvg-logo="https://i.ibb.co/r6czQwQ/365049798-774721644658455-5702658175909463406-n-2.png" group-title="General",ЭлТР (480p) [Not 24/7] +http://gohoski.fvds.ru:3000/mediabay/162/index.m3u8 diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/countries/ru.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/countries/ru.m3u index cbfde92492..b701890a36 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/countries/ru.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/countries/ru.m3u @@ -1,3 +1,3 @@ -#EXTM3U -#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) -http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8 diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/countries/undefined.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/countries/undefined.m3u index 1770572503..dd4df2992c 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/countries/undefined.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/countries/undefined.m3u @@ -1,15 +1,15 @@ -#EXTM3U -#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined" http-referrer="http://imn.iq" http-user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",Andorra TV (720p) [Not 24/7] -#EXTVLCOPT:http-referrer=http://imn.iq -#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 -#KODIPROP:inputstream=inputstream.adaptive -#KODIPROP:inputstream.adaptive.manifest_type=mpd -#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha -#KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=13f2e056-53fe-4469-ba6d-999970dbe549&userToken=v9ZVSksv4S7rT55o10dmYNRa4asye3z05eWCFxD%2FFYIlTJEpuf6tF8asPcyQOFq0h5opS%2B6WoMxnshWkihpHq5qrdrBEZ69piE94J9Feh385snGOqK3PYO7tLLjxmsCAe%2B9%2BNnurSSO5RCAIRsL125nSj1eOR%2F1GSKOgGH80HK2FDLiePxPkeaAxuWzacNBB%2FqnIGGxfe3GlmN65cU9F8WEpKFDlaxW%2Fv3ZSLAp3%2BZEq1aZXJ6Oz%2Fi0diD0EybH7|Content-Type=application/octet-stream|R{SSM}| -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8|Referer="https://referer.xyz/"|User-Agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1"|Origin="https://origin.xyz" -#EXTINF:-1 tvg-id="AndorraTV.ad@HD" tvg-logo="https://i.imgur.com/CnhTn8i.png" group-title="Undefined",ATV HD -https://iptv-all.lanesh4d0w.repl.co/andorra/atv_hd -#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined",Daawah TV -http://51.15.246.58:8081/daawahtv/daawahtv2/playlist.m3u8 -#EXTINF:-1 tvg-id="Zoo.ad@HD" tvg-logo="https://i.imgur.com/ciTJrnl.png" group-title="Undefined",Zoo (720p) -https://iptv-all.lanesh4d0w.repl.co/andorra/zoo +#EXTM3U +#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined" http-referrer="http://imn.iq" http-user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",Andorra TV (720p) [Not 24/7] +#EXTVLCOPT:http-referrer=http://imn.iq +#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 +#KODIPROP:inputstream=inputstream.adaptive +#KODIPROP:inputstream.adaptive.manifest_type=mpd +#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha +#KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=13f2e056-53fe-4469-ba6d-999970dbe549&userToken=v9ZVSksv4S7rT55o10dmYNRa4asye3z05eWCFxD%2FFYIlTJEpuf6tF8asPcyQOFq0h5opS%2B6WoMxnshWkihpHq5qrdrBEZ69piE94J9Feh385snGOqK3PYO7tLLjxmsCAe%2B9%2BNnurSSO5RCAIRsL125nSj1eOR%2F1GSKOgGH80HK2FDLiePxPkeaAxuWzacNBB%2FqnIGGxfe3GlmN65cU9F8WEpKFDlaxW%2Fv3ZSLAp3%2BZEq1aZXJ6Oz%2Fi0diD0EybH7|Content-Type=application/octet-stream|R{SSM}| +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8|Referer="https://referer.xyz/"|User-Agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1"|Origin="https://origin.xyz" +#EXTINF:-1 tvg-id="AndorraTV.ad@HD" tvg-logo="https://i.imgur.com/CnhTn8i.png" group-title="Undefined",ATV HD +https://iptv-all.lanesh4d0w.repl.co/andorra/atv_hd +#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined",Daawah TV +http://51.15.246.58:8081/daawahtv/daawahtv2/playlist.m3u8 +#EXTINF:-1 tvg-id="Zoo.ad@HD" tvg-logo="https://i.imgur.com/ciTJrnl.png" group-title="Undefined",Zoo (720p) +https://iptv-all.lanesh4d0w.repl.co/andorra/zoo diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/index.category.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/index.category.m3u index 3362671646..125eb49e67 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/index.category.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/index.category.m3u @@ -1,31 +1,31 @@ -#EXTM3U -#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General",BBC News HD -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 -#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) -http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8 -#EXTINF:-1 tvg-id="ElTR.kg" tvg-logo="https://i.ibb.co/r6czQwQ/365049798-774721644658455-5702658175909463406-n-2.png" group-title="General",ЭлТР (480p) [Not 24/7] -http://gohoski.fvds.ru:3000/mediabay/162/index.m3u8 -#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="News",BBC News HD -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 -#EXTINF:-1 tvg-id="MeteoMedia.ca" tvg-logo="https://s1.twnmm.com/images/en_ca/mobile/logos/twn-mobile-logo.png" group-title="Weather",Meteomedia -http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8 -#EXTINF:-1 tvg-id="5AABTV.ca" tvg-logo="" group-title="Undefined",5AAB TV -http://158.69.124.9:1935/5aabtv/5aabtv/playlist.m3u8 -#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined" http-referrer="http://imn.iq" http-user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",Andorra TV (720p) [Not 24/7] -#EXTVLCOPT:http-referrer=http://imn.iq -#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 -#KODIPROP:inputstream=inputstream.adaptive -#KODIPROP:inputstream.adaptive.manifest_type=mpd -#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha -#KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=13f2e056-53fe-4469-ba6d-999970dbe549&userToken=v9ZVSksv4S7rT55o10dmYNRa4asye3z05eWCFxD%2FFYIlTJEpuf6tF8asPcyQOFq0h5opS%2B6WoMxnshWkihpHq5qrdrBEZ69piE94J9Feh385snGOqK3PYO7tLLjxmsCAe%2B9%2BNnurSSO5RCAIRsL125nSj1eOR%2F1GSKOgGH80HK2FDLiePxPkeaAxuWzacNBB%2FqnIGGxfe3GlmN65cU9F8WEpKFDlaxW%2Fv3ZSLAp3%2BZEq1aZXJ6Oz%2Fi0diD0EybH7|Content-Type=application/octet-stream|R{SSM}| -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8|Referer="https://referer.xyz/"|User-Agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1"|Origin="https://origin.xyz" -#EXTINF:-1 tvg-id="AndorraTV.ad@SD" tvg-logo="https://i.imgur.com/BnhTn8i.png" group-title="Undefined",ATV -https://iptv-all.lanesh4d0w.repl.co/andorra/atv -#EXTINF:-1 tvg-id="AndorraTV.ad@HD" tvg-logo="https://i.imgur.com/CnhTn8i.png" group-title="Undefined",ATV HD -https://iptv-all.lanesh4d0w.repl.co/andorra/atv_hd -#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined",Daawah TV -http://51.15.246.58:8081/daawahtv/daawahtv2/playlist.m3u8 -#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) -http://146.59.85.40:89/dunaworld/index.m3u8 -#EXTINF:-1 tvg-id="Zoo.ad@HD" tvg-logo="https://i.imgur.com/ciTJrnl.png" group-title="Undefined",Zoo (720p) -https://iptv-all.lanesh4d0w.repl.co/andorra/zoo +#EXTM3U +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General",BBC News HD +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8 +#EXTINF:-1 tvg-id="ElTR.kg" tvg-logo="https://i.ibb.co/r6czQwQ/365049798-774721644658455-5702658175909463406-n-2.png" group-title="General",ЭлТР (480p) [Not 24/7] +http://gohoski.fvds.ru:3000/mediabay/162/index.m3u8 +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="News",BBC News HD +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTINF:-1 tvg-id="MeteoMedia.ca" tvg-logo="https://s1.twnmm.com/images/en_ca/mobile/logos/twn-mobile-logo.png" group-title="Weather",Meteomedia +http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8 +#EXTINF:-1 tvg-id="5AABTV.ca" tvg-logo="" group-title="Undefined",5AAB TV +http://158.69.124.9:1935/5aabtv/5aabtv/playlist.m3u8 +#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined" http-referrer="http://imn.iq" http-user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",Andorra TV (720p) [Not 24/7] +#EXTVLCOPT:http-referrer=http://imn.iq +#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 +#KODIPROP:inputstream=inputstream.adaptive +#KODIPROP:inputstream.adaptive.manifest_type=mpd +#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha +#KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=13f2e056-53fe-4469-ba6d-999970dbe549&userToken=v9ZVSksv4S7rT55o10dmYNRa4asye3z05eWCFxD%2FFYIlTJEpuf6tF8asPcyQOFq0h5opS%2B6WoMxnshWkihpHq5qrdrBEZ69piE94J9Feh385snGOqK3PYO7tLLjxmsCAe%2B9%2BNnurSSO5RCAIRsL125nSj1eOR%2F1GSKOgGH80HK2FDLiePxPkeaAxuWzacNBB%2FqnIGGxfe3GlmN65cU9F8WEpKFDlaxW%2Fv3ZSLAp3%2BZEq1aZXJ6Oz%2Fi0diD0EybH7|Content-Type=application/octet-stream|R{SSM}| +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8|Referer="https://referer.xyz/"|User-Agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1"|Origin="https://origin.xyz" +#EXTINF:-1 tvg-id="AndorraTV.ad@SD" tvg-logo="https://i.imgur.com/BnhTn8i.png" group-title="Undefined",ATV +https://iptv-all.lanesh4d0w.repl.co/andorra/atv +#EXTINF:-1 tvg-id="AndorraTV.ad@HD" tvg-logo="https://i.imgur.com/CnhTn8i.png" group-title="Undefined",ATV HD +https://iptv-all.lanesh4d0w.repl.co/andorra/atv_hd +#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined",Daawah TV +http://51.15.246.58:8081/daawahtv/daawahtv2/playlist.m3u8 +#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) +http://146.59.85.40:89/dunaworld/index.m3u8 +#EXTINF:-1 tvg-id="Zoo.ad@HD" tvg-logo="https://i.imgur.com/ciTJrnl.png" group-title="Undefined",Zoo (720p) +https://iptv-all.lanesh4d0w.repl.co/andorra/zoo diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/index.country.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/index.country.m3u index c2e0db5d9c..8d8394b09d 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/index.country.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/index.country.m3u @@ -1,31 +1,31 @@ -#EXTM3U -#EXTINF:-1 tvg-id="AndorraTV.ad@SD" tvg-logo="https://i.imgur.com/BnhTn8i.png" group-title="Andorra",ATV -https://iptv-all.lanesh4d0w.repl.co/andorra/atv -#EXTINF:-1 tvg-id="5AABTV.ca" tvg-logo="" group-title="Canada",5AAB TV -http://158.69.124.9:1935/5aabtv/5aabtv/playlist.m3u8 -#EXTINF:-1 tvg-id="MeteoMedia.ca" tvg-logo="https://s1.twnmm.com/images/en_ca/mobile/logos/twn-mobile-logo.png" group-title="Canada",Meteomedia -http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8 -#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="Russia",ЛДПР ТВ (1080p) -http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8 -#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="International",BBC News HD -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 -#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="International",Duna World (576i) -http://146.59.85.40:89/dunaworld/index.m3u8 -#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="International",ЛДПР ТВ (1080p) -http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8 -#EXTINF:-1 tvg-id="ElTR.kg" tvg-logo="https://i.ibb.co/r6czQwQ/365049798-774721644658455-5702658175909463406-n-2.png" group-title="International",ЭлТР (480p) [Not 24/7] -http://gohoski.fvds.ru:3000/mediabay/162/index.m3u8 -#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined" http-referrer="http://imn.iq" http-user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",Andorra TV (720p) [Not 24/7] -#EXTVLCOPT:http-referrer=http://imn.iq -#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 -#KODIPROP:inputstream=inputstream.adaptive -#KODIPROP:inputstream.adaptive.manifest_type=mpd -#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha -#KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=13f2e056-53fe-4469-ba6d-999970dbe549&userToken=v9ZVSksv4S7rT55o10dmYNRa4asye3z05eWCFxD%2FFYIlTJEpuf6tF8asPcyQOFq0h5opS%2B6WoMxnshWkihpHq5qrdrBEZ69piE94J9Feh385snGOqK3PYO7tLLjxmsCAe%2B9%2BNnurSSO5RCAIRsL125nSj1eOR%2F1GSKOgGH80HK2FDLiePxPkeaAxuWzacNBB%2FqnIGGxfe3GlmN65cU9F8WEpKFDlaxW%2Fv3ZSLAp3%2BZEq1aZXJ6Oz%2Fi0diD0EybH7|Content-Type=application/octet-stream|R{SSM}| -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8|Referer="https://referer.xyz/"|User-Agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1"|Origin="https://origin.xyz" -#EXTINF:-1 tvg-id="AndorraTV.ad@HD" tvg-logo="https://i.imgur.com/CnhTn8i.png" group-title="Undefined",ATV HD -https://iptv-all.lanesh4d0w.repl.co/andorra/atv_hd -#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined",Daawah TV -http://51.15.246.58:8081/daawahtv/daawahtv2/playlist.m3u8 -#EXTINF:-1 tvg-id="Zoo.ad@HD" tvg-logo="https://i.imgur.com/ciTJrnl.png" group-title="Undefined",Zoo (720p) -https://iptv-all.lanesh4d0w.repl.co/andorra/zoo +#EXTM3U +#EXTINF:-1 tvg-id="AndorraTV.ad@SD" tvg-logo="https://i.imgur.com/BnhTn8i.png" group-title="Andorra",ATV +https://iptv-all.lanesh4d0w.repl.co/andorra/atv +#EXTINF:-1 tvg-id="5AABTV.ca" tvg-logo="" group-title="Canada",5AAB TV +http://158.69.124.9:1935/5aabtv/5aabtv/playlist.m3u8 +#EXTINF:-1 tvg-id="MeteoMedia.ca" tvg-logo="https://s1.twnmm.com/images/en_ca/mobile/logos/twn-mobile-logo.png" group-title="Canada",Meteomedia +http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8 +#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="Russia",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8 +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="International",BBC News HD +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="International",Duna World (576i) +http://146.59.85.40:89/dunaworld/index.m3u8 +#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="International",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8 +#EXTINF:-1 tvg-id="ElTR.kg" tvg-logo="https://i.ibb.co/r6czQwQ/365049798-774721644658455-5702658175909463406-n-2.png" group-title="International",ЭлТР (480p) [Not 24/7] +http://gohoski.fvds.ru:3000/mediabay/162/index.m3u8 +#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined" http-referrer="http://imn.iq" http-user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",Andorra TV (720p) [Not 24/7] +#EXTVLCOPT:http-referrer=http://imn.iq +#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 +#KODIPROP:inputstream=inputstream.adaptive +#KODIPROP:inputstream.adaptive.manifest_type=mpd +#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha +#KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=13f2e056-53fe-4469-ba6d-999970dbe549&userToken=v9ZVSksv4S7rT55o10dmYNRa4asye3z05eWCFxD%2FFYIlTJEpuf6tF8asPcyQOFq0h5opS%2B6WoMxnshWkihpHq5qrdrBEZ69piE94J9Feh385snGOqK3PYO7tLLjxmsCAe%2B9%2BNnurSSO5RCAIRsL125nSj1eOR%2F1GSKOgGH80HK2FDLiePxPkeaAxuWzacNBB%2FqnIGGxfe3GlmN65cU9F8WEpKFDlaxW%2Fv3ZSLAp3%2BZEq1aZXJ6Oz%2Fi0diD0EybH7|Content-Type=application/octet-stream|R{SSM}| +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8|Referer="https://referer.xyz/"|User-Agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1"|Origin="https://origin.xyz" +#EXTINF:-1 tvg-id="AndorraTV.ad@HD" tvg-logo="https://i.imgur.com/CnhTn8i.png" group-title="Undefined",ATV HD +https://iptv-all.lanesh4d0w.repl.co/andorra/atv_hd +#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined",Daawah TV +http://51.15.246.58:8081/daawahtv/daawahtv2/playlist.m3u8 +#EXTINF:-1 tvg-id="Zoo.ad@HD" tvg-logo="https://i.imgur.com/ciTJrnl.png" group-title="Undefined",Zoo (720p) +https://iptv-all.lanesh4d0w.repl.co/andorra/zoo diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/index.language.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/index.language.m3u index 60b49b6b45..626893e3e9 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/index.language.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/index.language.m3u @@ -1,29 +1,29 @@ -#EXTM3U -#EXTINF:-1 tvg-id="AndorraTV.ad@SD" tvg-logo="https://i.imgur.com/BnhTn8i.png" group-title="Catalan",ATV -https://iptv-all.lanesh4d0w.repl.co/andorra/atv -#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="English",BBC News HD -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 -#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="Russian",ЛДПР ТВ (1080p) -http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8 -#EXTINF:-1 tvg-id="5AABTV.ca" tvg-logo="" group-title="Undefined",5AAB TV -http://158.69.124.9:1935/5aabtv/5aabtv/playlist.m3u8 -#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined" http-referrer="http://imn.iq" http-user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",Andorra TV (720p) [Not 24/7] -#EXTVLCOPT:http-referrer=http://imn.iq -#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 -#KODIPROP:inputstream=inputstream.adaptive -#KODIPROP:inputstream.adaptive.manifest_type=mpd -#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha -#KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=13f2e056-53fe-4469-ba6d-999970dbe549&userToken=v9ZVSksv4S7rT55o10dmYNRa4asye3z05eWCFxD%2FFYIlTJEpuf6tF8asPcyQOFq0h5opS%2B6WoMxnshWkihpHq5qrdrBEZ69piE94J9Feh385snGOqK3PYO7tLLjxmsCAe%2B9%2BNnurSSO5RCAIRsL125nSj1eOR%2F1GSKOgGH80HK2FDLiePxPkeaAxuWzacNBB%2FqnIGGxfe3GlmN65cU9F8WEpKFDlaxW%2Fv3ZSLAp3%2BZEq1aZXJ6Oz%2Fi0diD0EybH7|Content-Type=application/octet-stream|R{SSM}| -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8|Referer="https://referer.xyz/"|User-Agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1"|Origin="https://origin.xyz" -#EXTINF:-1 tvg-id="AndorraTV.ad@HD" tvg-logo="https://i.imgur.com/CnhTn8i.png" group-title="Undefined",ATV HD -https://iptv-all.lanesh4d0w.repl.co/andorra/atv_hd -#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined",Daawah TV -http://51.15.246.58:8081/daawahtv/daawahtv2/playlist.m3u8 -#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) -http://146.59.85.40:89/dunaworld/index.m3u8 -#EXTINF:-1 tvg-id="MeteoMedia.ca" tvg-logo="https://s1.twnmm.com/images/en_ca/mobile/logos/twn-mobile-logo.png" group-title="Undefined",Meteomedia -http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8 -#EXTINF:-1 tvg-id="Zoo.ad@HD" tvg-logo="https://i.imgur.com/ciTJrnl.png" group-title="Undefined",Zoo (720p) -https://iptv-all.lanesh4d0w.repl.co/andorra/zoo -#EXTINF:-1 tvg-id="ElTR.kg" tvg-logo="https://i.ibb.co/r6czQwQ/365049798-774721644658455-5702658175909463406-n-2.png" group-title="Undefined",ЭлТР (480p) [Not 24/7] -http://gohoski.fvds.ru:3000/mediabay/162/index.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="AndorraTV.ad@SD" tvg-logo="https://i.imgur.com/BnhTn8i.png" group-title="Catalan",ATV +https://iptv-all.lanesh4d0w.repl.co/andorra/atv +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="English",BBC News HD +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="Russian",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8 +#EXTINF:-1 tvg-id="5AABTV.ca" tvg-logo="" group-title="Undefined",5AAB TV +http://158.69.124.9:1935/5aabtv/5aabtv/playlist.m3u8 +#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined" http-referrer="http://imn.iq" http-user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",Andorra TV (720p) [Not 24/7] +#EXTVLCOPT:http-referrer=http://imn.iq +#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 +#KODIPROP:inputstream=inputstream.adaptive +#KODIPROP:inputstream.adaptive.manifest_type=mpd +#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha +#KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=13f2e056-53fe-4469-ba6d-999970dbe549&userToken=v9ZVSksv4S7rT55o10dmYNRa4asye3z05eWCFxD%2FFYIlTJEpuf6tF8asPcyQOFq0h5opS%2B6WoMxnshWkihpHq5qrdrBEZ69piE94J9Feh385snGOqK3PYO7tLLjxmsCAe%2B9%2BNnurSSO5RCAIRsL125nSj1eOR%2F1GSKOgGH80HK2FDLiePxPkeaAxuWzacNBB%2FqnIGGxfe3GlmN65cU9F8WEpKFDlaxW%2Fv3ZSLAp3%2BZEq1aZXJ6Oz%2Fi0diD0EybH7|Content-Type=application/octet-stream|R{SSM}| +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8|Referer="https://referer.xyz/"|User-Agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1"|Origin="https://origin.xyz" +#EXTINF:-1 tvg-id="AndorraTV.ad@HD" tvg-logo="https://i.imgur.com/CnhTn8i.png" group-title="Undefined",ATV HD +https://iptv-all.lanesh4d0w.repl.co/andorra/atv_hd +#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined",Daawah TV +http://51.15.246.58:8081/daawahtv/daawahtv2/playlist.m3u8 +#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) +http://146.59.85.40:89/dunaworld/index.m3u8 +#EXTINF:-1 tvg-id="MeteoMedia.ca" tvg-logo="https://s1.twnmm.com/images/en_ca/mobile/logos/twn-mobile-logo.png" group-title="Undefined",Meteomedia +http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8 +#EXTINF:-1 tvg-id="Zoo.ad@HD" tvg-logo="https://i.imgur.com/ciTJrnl.png" group-title="Undefined",Zoo (720p) +https://iptv-all.lanesh4d0w.repl.co/andorra/zoo +#EXTINF:-1 tvg-id="ElTR.kg" tvg-logo="https://i.ibb.co/r6czQwQ/365049798-774721644658455-5702658175909463406-n-2.png" group-title="Undefined",ЭлТР (480p) [Not 24/7] +http://gohoski.fvds.ru:3000/mediabay/162/index.m3u8 diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/index.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/index.m3u index da169ed076..255edf9a86 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/index.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/index.m3u @@ -1,29 +1,29 @@ -#EXTM3U -#EXTINF:-1 tvg-id="5AABTV.ca" tvg-logo="" group-title="Undefined",5AAB TV -http://158.69.124.9:1935/5aabtv/5aabtv/playlist.m3u8 -#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined" http-referrer="http://imn.iq" http-user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",Andorra TV (720p) [Not 24/7] -#EXTVLCOPT:http-referrer=http://imn.iq -#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 -#KODIPROP:inputstream=inputstream.adaptive -#KODIPROP:inputstream.adaptive.manifest_type=mpd -#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha -#KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=13f2e056-53fe-4469-ba6d-999970dbe549&userToken=v9ZVSksv4S7rT55o10dmYNRa4asye3z05eWCFxD%2FFYIlTJEpuf6tF8asPcyQOFq0h5opS%2B6WoMxnshWkihpHq5qrdrBEZ69piE94J9Feh385snGOqK3PYO7tLLjxmsCAe%2B9%2BNnurSSO5RCAIRsL125nSj1eOR%2F1GSKOgGH80HK2FDLiePxPkeaAxuWzacNBB%2FqnIGGxfe3GlmN65cU9F8WEpKFDlaxW%2Fv3ZSLAp3%2BZEq1aZXJ6Oz%2Fi0diD0EybH7|Content-Type=application/octet-stream|R{SSM}| -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8|Referer="https://referer.xyz/"|User-Agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1"|Origin="https://origin.xyz" -#EXTINF:-1 tvg-id="AndorraTV.ad@SD" tvg-logo="https://i.imgur.com/BnhTn8i.png" group-title="Undefined",ATV -https://iptv-all.lanesh4d0w.repl.co/andorra/atv -#EXTINF:-1 tvg-id="AndorraTV.ad@HD" tvg-logo="https://i.imgur.com/CnhTn8i.png" group-title="Undefined",ATV HD -https://iptv-all.lanesh4d0w.repl.co/andorra/atv_hd -#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 -#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined",Daawah TV -http://51.15.246.58:8081/daawahtv/daawahtv2/playlist.m3u8 -#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) -http://146.59.85.40:89/dunaworld/index.m3u8 -#EXTINF:-1 tvg-id="MeteoMedia.ca" tvg-logo="https://s1.twnmm.com/images/en_ca/mobile/logos/twn-mobile-logo.png" group-title="Weather",Meteomedia -http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8 -#EXTINF:-1 tvg-id="Zoo.ad@HD" tvg-logo="https://i.imgur.com/ciTJrnl.png" group-title="Undefined",Zoo (720p) -https://iptv-all.lanesh4d0w.repl.co/andorra/zoo -#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) -http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8 -#EXTINF:-1 tvg-id="ElTR.kg" tvg-logo="https://i.ibb.co/r6czQwQ/365049798-774721644658455-5702658175909463406-n-2.png" group-title="General",ЭлТР (480p) [Not 24/7] -http://gohoski.fvds.ru:3000/mediabay/162/index.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="5AABTV.ca" tvg-logo="" group-title="Undefined",5AAB TV +http://158.69.124.9:1935/5aabtv/5aabtv/playlist.m3u8 +#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined" http-referrer="http://imn.iq" http-user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",Andorra TV (720p) [Not 24/7] +#EXTVLCOPT:http-referrer=http://imn.iq +#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 +#KODIPROP:inputstream=inputstream.adaptive +#KODIPROP:inputstream.adaptive.manifest_type=mpd +#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha +#KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=13f2e056-53fe-4469-ba6d-999970dbe549&userToken=v9ZVSksv4S7rT55o10dmYNRa4asye3z05eWCFxD%2FFYIlTJEpuf6tF8asPcyQOFq0h5opS%2B6WoMxnshWkihpHq5qrdrBEZ69piE94J9Feh385snGOqK3PYO7tLLjxmsCAe%2B9%2BNnurSSO5RCAIRsL125nSj1eOR%2F1GSKOgGH80HK2FDLiePxPkeaAxuWzacNBB%2FqnIGGxfe3GlmN65cU9F8WEpKFDlaxW%2Fv3ZSLAp3%2BZEq1aZXJ6Oz%2Fi0diD0EybH7|Content-Type=application/octet-stream|R{SSM}| +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8|Referer="https://referer.xyz/"|User-Agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1"|Origin="https://origin.xyz" +#EXTINF:-1 tvg-id="AndorraTV.ad@SD" tvg-logo="https://i.imgur.com/BnhTn8i.png" group-title="Undefined",ATV +https://iptv-all.lanesh4d0w.repl.co/andorra/atv +#EXTINF:-1 tvg-id="AndorraTV.ad@HD" tvg-logo="https://i.imgur.com/CnhTn8i.png" group-title="Undefined",ATV HD +https://iptv-all.lanesh4d0w.repl.co/andorra/atv_hd +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined",Daawah TV +http://51.15.246.58:8081/daawahtv/daawahtv2/playlist.m3u8 +#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) +http://146.59.85.40:89/dunaworld/index.m3u8 +#EXTINF:-1 tvg-id="MeteoMedia.ca" tvg-logo="https://s1.twnmm.com/images/en_ca/mobile/logos/twn-mobile-logo.png" group-title="Weather",Meteomedia +http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8 +#EXTINF:-1 tvg-id="Zoo.ad@HD" tvg-logo="https://i.imgur.com/ciTJrnl.png" group-title="Undefined",Zoo (720p) +https://iptv-all.lanesh4d0w.repl.co/andorra/zoo +#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8 +#EXTINF:-1 tvg-id="ElTR.kg" tvg-logo="https://i.ibb.co/r6czQwQ/365049798-774721644658455-5702658175909463406-n-2.png" group-title="General",ЭлТР (480p) [Not 24/7] +http://gohoski.fvds.ru:3000/mediabay/162/index.m3u8 diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/languages/cat.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/languages/cat.m3u new file mode 100644 index 0000000000..e85626ca16 --- /dev/null +++ b/tests/__data__/expected/playlist_generate/.gh-pages/languages/cat.m3u @@ -0,0 +1,3 @@ +#EXTM3U +#EXTINF:-1 tvg-id="AndorraTV.ad@SD" tvg-logo="https://i.imgur.com/BnhTn8i.png" group-title="Undefined",ATV +https://iptv-all.lanesh4d0w.repl.co/andorra/atv diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/languages/eng.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/languages/eng.m3u index cf4e62a9a5..85c75b78bf 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/languages/eng.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/languages/eng.m3u @@ -1,3 +1,3 @@ -#EXTM3U -#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/languages/rus.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/languages/rus.m3u index cbfde92492..b701890a36 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/languages/rus.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/languages/rus.m3u @@ -1,3 +1,3 @@ -#EXTM3U -#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) -http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8 diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/languages/undefined.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/languages/undefined.m3u index c42bfbb582..1bca3048d0 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/languages/undefined.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/languages/undefined.m3u @@ -1,23 +1,23 @@ -#EXTM3U -#EXTINF:-1 tvg-id="5AABTV.ca" tvg-logo="" group-title="Undefined",5AAB TV -http://158.69.124.9:1935/5aabtv/5aabtv/playlist.m3u8 -#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined" http-referrer="http://imn.iq" http-user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",Andorra TV (720p) [Not 24/7] -#EXTVLCOPT:http-referrer=http://imn.iq -#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 -#KODIPROP:inputstream=inputstream.adaptive -#KODIPROP:inputstream.adaptive.manifest_type=mpd -#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha -#KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=13f2e056-53fe-4469-ba6d-999970dbe549&userToken=v9ZVSksv4S7rT55o10dmYNRa4asye3z05eWCFxD%2FFYIlTJEpuf6tF8asPcyQOFq0h5opS%2B6WoMxnshWkihpHq5qrdrBEZ69piE94J9Feh385snGOqK3PYO7tLLjxmsCAe%2B9%2BNnurSSO5RCAIRsL125nSj1eOR%2F1GSKOgGH80HK2FDLiePxPkeaAxuWzacNBB%2FqnIGGxfe3GlmN65cU9F8WEpKFDlaxW%2Fv3ZSLAp3%2BZEq1aZXJ6Oz%2Fi0diD0EybH7|Content-Type=application/octet-stream|R{SSM}| -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8|Referer="https://referer.xyz/"|User-Agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1"|Origin="https://origin.xyz" -#EXTINF:-1 tvg-id="AndorraTV.ad@HD" tvg-logo="https://i.imgur.com/CnhTn8i.png" group-title="Undefined",ATV HD -https://iptv-all.lanesh4d0w.repl.co/andorra/atv_hd -#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined",Daawah TV -http://51.15.246.58:8081/daawahtv/daawahtv2/playlist.m3u8 -#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) -http://146.59.85.40:89/dunaworld/index.m3u8 -#EXTINF:-1 tvg-id="MeteoMedia.ca" tvg-logo="https://s1.twnmm.com/images/en_ca/mobile/logos/twn-mobile-logo.png" group-title="Weather",Meteomedia -http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8 -#EXTINF:-1 tvg-id="Zoo.ad@HD" tvg-logo="https://i.imgur.com/ciTJrnl.png" group-title="Undefined",Zoo (720p) -https://iptv-all.lanesh4d0w.repl.co/andorra/zoo -#EXTINF:-1 tvg-id="ElTR.kg" tvg-logo="https://i.ibb.co/r6czQwQ/365049798-774721644658455-5702658175909463406-n-2.png" group-title="General",ЭлТР (480p) [Not 24/7] -http://gohoski.fvds.ru:3000/mediabay/162/index.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="5AABTV.ca" tvg-logo="" group-title="Undefined",5AAB TV +http://158.69.124.9:1935/5aabtv/5aabtv/playlist.m3u8 +#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined" http-referrer="http://imn.iq" http-user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",Andorra TV (720p) [Not 24/7] +#EXTVLCOPT:http-referrer=http://imn.iq +#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 +#KODIPROP:inputstream=inputstream.adaptive +#KODIPROP:inputstream.adaptive.manifest_type=mpd +#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha +#KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=13f2e056-53fe-4469-ba6d-999970dbe549&userToken=v9ZVSksv4S7rT55o10dmYNRa4asye3z05eWCFxD%2FFYIlTJEpuf6tF8asPcyQOFq0h5opS%2B6WoMxnshWkihpHq5qrdrBEZ69piE94J9Feh385snGOqK3PYO7tLLjxmsCAe%2B9%2BNnurSSO5RCAIRsL125nSj1eOR%2F1GSKOgGH80HK2FDLiePxPkeaAxuWzacNBB%2FqnIGGxfe3GlmN65cU9F8WEpKFDlaxW%2Fv3ZSLAp3%2BZEq1aZXJ6Oz%2Fi0diD0EybH7|Content-Type=application/octet-stream|R{SSM}| +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8|Referer="https://referer.xyz/"|User-Agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1"|Origin="https://origin.xyz" +#EXTINF:-1 tvg-id="AndorraTV.ad@HD" tvg-logo="https://i.imgur.com/CnhTn8i.png" group-title="Undefined",ATV HD +https://iptv-all.lanesh4d0w.repl.co/andorra/atv_hd +#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined",Daawah TV +http://51.15.246.58:8081/daawahtv/daawahtv2/playlist.m3u8 +#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) +http://146.59.85.40:89/dunaworld/index.m3u8 +#EXTINF:-1 tvg-id="MeteoMedia.ca" tvg-logo="https://s1.twnmm.com/images/en_ca/mobile/logos/twn-mobile-logo.png" group-title="Weather",Meteomedia +http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8 +#EXTINF:-1 tvg-id="Zoo.ad@HD" tvg-logo="https://i.imgur.com/ciTJrnl.png" group-title="Undefined",Zoo (720p) +https://iptv-all.lanesh4d0w.repl.co/andorra/zoo +#EXTINF:-1 tvg-id="ElTR.kg" tvg-logo="https://i.ibb.co/r6czQwQ/365049798-774721644658455-5702658175909463406-n-2.png" group-title="General",ЭлТР (480p) [Not 24/7] +http://gohoski.fvds.ru:3000/mediabay/162/index.m3u8 diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/raw/ad.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/raw/ad.m3u index 7e0f1c587c..07c75c55ac 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/raw/ad.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/raw/ad.m3u @@ -1,9 +1,9 @@ -#EXTM3U -#EXTINF:-1 tvg-id="Zoo.ad@HD" tvg-logo="https://i.imgur.com/ciTJrnl.png" group-title="Undefined",Zoo (720p) -https://iptv-all.lanesh4d0w.repl.co/andorra/zoo -#EXTINF:-1 tvg-id="AndorraTV.ad@SD" tvg-logo="https://i.imgur.com/BnhTn8i.png" group-title="Undefined",ATV -https://iptv-all.lanesh4d0w.repl.co/andorra/atv -#EXTINF:-1 tvg-id="AndorraTV.ad@HD" tvg-logo="https://i.imgur.com/CnhTn8i.png" group-title="Undefined",ATV HD -https://iptv-all.lanesh4d0w.repl.co/andorra/atv_hd -#EXTINF:-1 tvg-id="AndorraTV.ad" tvg-logo="https://i.imgur.com/CnhTn8i.png" group-title="Undefined",ATV -https://iptv-all.lanesh4d0w.repl.co/andorra/atv2 +#EXTM3U +#EXTINF:-1 tvg-id="Zoo.ad@HD" tvg-logo="https://i.imgur.com/ciTJrnl.png" group-title="Undefined",Zoo (720p) +https://iptv-all.lanesh4d0w.repl.co/andorra/zoo +#EXTINF:-1 tvg-id="AndorraTV.ad@SD" tvg-logo="https://i.imgur.com/BnhTn8i.png" group-title="Undefined",ATV +https://iptv-all.lanesh4d0w.repl.co/andorra/atv +#EXTINF:-1 tvg-id="AndorraTV.ad@HD" tvg-logo="https://i.imgur.com/CnhTn8i.png" group-title="Undefined",ATV HD +https://iptv-all.lanesh4d0w.repl.co/andorra/atv_hd +#EXTINF:-1 tvg-id="AndorraTV.ad" tvg-logo="https://i.imgur.com/BnhTn8i.png" group-title="Undefined",ATV +https://iptv-all.lanesh4d0w.repl.co/andorra/atv2 diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/raw/ca.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/raw/ca.m3u index 8aeaaae90e..79ba1e61d2 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/raw/ca.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/raw/ca.m3u @@ -1,5 +1,5 @@ -#EXTM3U -#EXTINF:-1 tvg-id="5AABTV.ca" tvg-logo="" group-title="Undefined",5AAB TV -http://158.69.124.9:1935/5aabtv/5aabtv/playlist.m3u8 -#EXTINF:-1 tvg-id="MeteoMedia.ca" tvg-logo="https://s1.twnmm.com/images/en_ca/mobile/logos/twn-mobile-logo.png" group-title="Weather",Meteomedia -http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="5AABTV.ca" tvg-logo="" group-title="Undefined",5AAB TV +http://158.69.124.9:1935/5aabtv/5aabtv/playlist.m3u8 +#EXTINF:-1 tvg-id="MeteoMedia.ca" tvg-logo="https://s1.twnmm.com/images/en_ca/mobile/logos/twn-mobile-logo.png" group-title="Weather",Meteomedia +http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8 diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/raw/in.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/raw/in.m3u index 4708e622d8..d2223daac4 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/raw/in.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/raw/in.m3u @@ -1,3 +1,3 @@ -#EXTM3U -#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined",Daawah TV -http://51.15.246.58:8081/daawahtv/daawahtv2/playlist.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined",Daawah TV +http://51.15.246.58:8081/daawahtv/daawahtv2/playlist.m3u8 diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/raw/kg.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/raw/kg.m3u index a9387b8b44..847591ab04 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/raw/kg.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/raw/kg.m3u @@ -1,3 +1,3 @@ -#EXTM3U -#EXTINF:-1 tvg-id="ElTR.kg" tvg-logo="https://i.ibb.co/r6czQwQ/365049798-774721644658455-5702658175909463406-n-2.png" group-title="General",ЭлТР (480p) [Not 24/7] -http://gohoski.fvds.ru:3000/mediabay/162/index.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="ElTR.kg" tvg-logo="https://i.ibb.co/r6czQwQ/365049798-774721644658455-5702658175909463406-n-2.png" group-title="General",ЭлТР (480p) [Not 24/7] +http://gohoski.fvds.ru:3000/mediabay/162/index.m3u8 diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/raw/uk.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/raw/uk.m3u index cf4e62a9a5..85c75b78bf 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/raw/uk.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/raw/uk.m3u @@ -1,3 +1,3 @@ -#EXTM3U -#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/raw/unsorted.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/raw/unsorted.m3u index b626b1cba0..530c218fa6 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/raw/unsorted.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/raw/unsorted.m3u @@ -1,15 +1,15 @@ -#EXTM3U -#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) -http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8 -#EXTINF:-1 tvg-id="VisitXTV.nl" tvg-logo="https://i.imgur.com/RJ9wbNF.jpg" group-title="XXX",Visit-X TV -https://stream.visit-x.tv/vxtv/ngrp:live_all/30fps.m3u8 -#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined" http-referrer="http://imn.iq" http-user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",Andorra TV (720p) [Not 24/7] -#EXTVLCOPT:http-referrer=http://imn.iq -#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 -#KODIPROP:inputstream=inputstream.adaptive -#KODIPROP:inputstream.adaptive.manifest_type=mpd -#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha -#KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=13f2e056-53fe-4469-ba6d-999970dbe549&userToken=v9ZVSksv4S7rT55o10dmYNRa4asye3z05eWCFxD%2FFYIlTJEpuf6tF8asPcyQOFq0h5opS%2B6WoMxnshWkihpHq5qrdrBEZ69piE94J9Feh385snGOqK3PYO7tLLjxmsCAe%2B9%2BNnurSSO5RCAIRsL125nSj1eOR%2F1GSKOgGH80HK2FDLiePxPkeaAxuWzacNBB%2FqnIGGxfe3GlmN65cU9F8WEpKFDlaxW%2Fv3ZSLAp3%2BZEq1aZXJ6Oz%2Fi0diD0EybH7|Content-Type=application/octet-stream|R{SSM}| -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8|Referer="https://referer.xyz/"|User-Agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1"|Origin="https://origin.xyz" -#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) -http://146.59.85.40:89/dunaworld/index.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8 +#EXTINF:-1 tvg-id="VisitXTV.nl" tvg-logo="https://i.imgur.com/RJ9wbNF.jpg" group-title="XXX",Visit-X TV +https://stream.visit-x.tv/vxtv/ngrp:live_all/30fps.m3u8 +#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined" http-referrer="http://imn.iq" http-user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",Andorra TV (720p) [Not 24/7] +#EXTVLCOPT:http-referrer=http://imn.iq +#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 +#KODIPROP:inputstream=inputstream.adaptive +#KODIPROP:inputstream.adaptive.manifest_type=mpd +#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha +#KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=13f2e056-53fe-4469-ba6d-999970dbe549&userToken=v9ZVSksv4S7rT55o10dmYNRa4asye3z05eWCFxD%2FFYIlTJEpuf6tF8asPcyQOFq0h5opS%2B6WoMxnshWkihpHq5qrdrBEZ69piE94J9Feh385snGOqK3PYO7tLLjxmsCAe%2B9%2BNnurSSO5RCAIRsL125nSj1eOR%2F1GSKOgGH80HK2FDLiePxPkeaAxuWzacNBB%2FqnIGGxfe3GlmN65cU9F8WEpKFDlaxW%2Fv3ZSLAp3%2BZEq1aZXJ6Oz%2Fi0diD0EybH7|Content-Type=application/octet-stream|R{SSM}| +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8|Referer="https://referer.xyz/"|User-Agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1"|Origin="https://origin.xyz" +#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) +http://146.59.85.40:89/dunaworld/index.m3u8 diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/regions/afr.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/regions/afr.m3u index c549c09ce1..15240af7d0 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/regions/afr.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/regions/afr.m3u @@ -1,5 +1,5 @@ -#EXTM3U -#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 -#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) -http://146.59.85.40:89/dunaworld/index.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) +http://146.59.85.40:89/dunaworld/index.m3u8 diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/regions/amer.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/regions/amer.m3u index 226aaf5de9..450e02495f 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/regions/amer.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/regions/amer.m3u @@ -1,11 +1,11 @@ -#EXTM3U -#EXTINF:-1 tvg-id="5AABTV.ca" tvg-logo="" group-title="Undefined",5AAB TV -http://158.69.124.9:1935/5aabtv/5aabtv/playlist.m3u8 -#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 -#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) -http://146.59.85.40:89/dunaworld/index.m3u8 -#EXTINF:-1 tvg-id="MeteoMedia.ca" tvg-logo="https://s1.twnmm.com/images/en_ca/mobile/logos/twn-mobile-logo.png" group-title="Weather",Meteomedia -http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8 -#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) -http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="5AABTV.ca" tvg-logo="" group-title="Undefined",5AAB TV +http://158.69.124.9:1935/5aabtv/5aabtv/playlist.m3u8 +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) +http://146.59.85.40:89/dunaworld/index.m3u8 +#EXTINF:-1 tvg-id="MeteoMedia.ca" tvg-logo="https://s1.twnmm.com/images/en_ca/mobile/logos/twn-mobile-logo.png" group-title="Weather",Meteomedia +http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8 +#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8 diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/regions/apac.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/regions/apac.m3u index c549c09ce1..15240af7d0 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/regions/apac.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/regions/apac.m3u @@ -1,5 +1,5 @@ -#EXTM3U -#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 -#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) -http://146.59.85.40:89/dunaworld/index.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) +http://146.59.85.40:89/dunaworld/index.m3u8 diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/regions/arab.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/regions/arab.m3u index c549c09ce1..15240af7d0 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/regions/arab.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/regions/arab.m3u @@ -1,5 +1,5 @@ -#EXTM3U -#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 -#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) -http://146.59.85.40:89/dunaworld/index.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) +http://146.59.85.40:89/dunaworld/index.m3u8 diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/regions/asean.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/regions/asean.m3u index c549c09ce1..15240af7d0 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/regions/asean.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/regions/asean.m3u @@ -1,5 +1,5 @@ -#EXTM3U -#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 -#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) -http://146.59.85.40:89/dunaworld/index.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) +http://146.59.85.40:89/dunaworld/index.m3u8 diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/regions/asia.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/regions/asia.m3u index 202cd4e3fa..8d37f3ba9b 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/regions/asia.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/regions/asia.m3u @@ -1,9 +1,9 @@ -#EXTM3U -#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 -#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) -http://146.59.85.40:89/dunaworld/index.m3u8 -#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) -http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8 -#EXTINF:-1 tvg-id="ElTR.kg" tvg-logo="https://i.ibb.co/r6czQwQ/365049798-774721644658455-5702658175909463406-n-2.png" group-title="General",ЭлТР (480p) [Not 24/7] -http://gohoski.fvds.ru:3000/mediabay/162/index.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) +http://146.59.85.40:89/dunaworld/index.m3u8 +#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8 +#EXTINF:-1 tvg-id="ElTR.kg" tvg-logo="https://i.ibb.co/r6czQwQ/365049798-774721644658455-5702658175909463406-n-2.png" group-title="General",ЭлТР (480p) [Not 24/7] +http://gohoski.fvds.ru:3000/mediabay/162/index.m3u8 diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/regions/carib.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/regions/carib.m3u index c549c09ce1..15240af7d0 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/regions/carib.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/regions/carib.m3u @@ -1,5 +1,5 @@ -#EXTM3U -#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 -#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) -http://146.59.85.40:89/dunaworld/index.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) +http://146.59.85.40:89/dunaworld/index.m3u8 diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/regions/cas.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/regions/cas.m3u index 4e507cf645..56b1dd594c 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/regions/cas.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/regions/cas.m3u @@ -1,7 +1,7 @@ -#EXTM3U -#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 -#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) -http://146.59.85.40:89/dunaworld/index.m3u8 -#EXTINF:-1 tvg-id="ElTR.kg" tvg-logo="https://i.ibb.co/r6czQwQ/365049798-774721644658455-5702658175909463406-n-2.png" group-title="General",ЭлТР (480p) [Not 24/7] -http://gohoski.fvds.ru:3000/mediabay/162/index.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) +http://146.59.85.40:89/dunaworld/index.m3u8 +#EXTINF:-1 tvg-id="ElTR.kg" tvg-logo="https://i.ibb.co/r6czQwQ/365049798-774721644658455-5702658175909463406-n-2.png" group-title="General",ЭлТР (480p) [Not 24/7] +http://gohoski.fvds.ru:3000/mediabay/162/index.m3u8 diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/regions/cenamer.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/regions/cenamer.m3u index c549c09ce1..15240af7d0 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/regions/cenamer.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/regions/cenamer.m3u @@ -1,5 +1,5 @@ -#EXTM3U -#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 -#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) -http://146.59.85.40:89/dunaworld/index.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) +http://146.59.85.40:89/dunaworld/index.m3u8 diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/regions/cis.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/regions/cis.m3u index 202cd4e3fa..8d37f3ba9b 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/regions/cis.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/regions/cis.m3u @@ -1,9 +1,9 @@ -#EXTM3U -#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 -#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) -http://146.59.85.40:89/dunaworld/index.m3u8 -#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) -http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8 -#EXTINF:-1 tvg-id="ElTR.kg" tvg-logo="https://i.ibb.co/r6czQwQ/365049798-774721644658455-5702658175909463406-n-2.png" group-title="General",ЭлТР (480p) [Not 24/7] -http://gohoski.fvds.ru:3000/mediabay/162/index.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) +http://146.59.85.40:89/dunaworld/index.m3u8 +#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8 +#EXTINF:-1 tvg-id="ElTR.kg" tvg-logo="https://i.ibb.co/r6czQwQ/365049798-774721644658455-5702658175909463406-n-2.png" group-title="General",ЭлТР (480p) [Not 24/7] +http://gohoski.fvds.ru:3000/mediabay/162/index.m3u8 diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/regions/emea.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/regions/emea.m3u index 9a8e344397..3d0f820ccc 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/regions/emea.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/regions/emea.m3u @@ -1,11 +1,11 @@ -#EXTM3U -#EXTINF:-1 tvg-id="AndorraTV.ad@SD" tvg-logo="https://i.imgur.com/BnhTn8i.png" group-title="Undefined",ATV -https://iptv-all.lanesh4d0w.repl.co/andorra/atv -#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 -#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) -http://146.59.85.40:89/dunaworld/index.m3u8 -#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) -http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8 -#EXTINF:-1 tvg-id="ElTR.kg" tvg-logo="https://i.ibb.co/r6czQwQ/365049798-774721644658455-5702658175909463406-n-2.png" group-title="General",ЭлТР (480p) [Not 24/7] -http://gohoski.fvds.ru:3000/mediabay/162/index.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="AndorraTV.ad@SD" tvg-logo="https://i.imgur.com/BnhTn8i.png" group-title="Undefined",ATV +https://iptv-all.lanesh4d0w.repl.co/andorra/atv +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) +http://146.59.85.40:89/dunaworld/index.m3u8 +#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8 +#EXTINF:-1 tvg-id="ElTR.kg" tvg-logo="https://i.ibb.co/r6czQwQ/365049798-774721644658455-5702658175909463406-n-2.png" group-title="General",ЭлТР (480p) [Not 24/7] +http://gohoski.fvds.ru:3000/mediabay/162/index.m3u8 diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/regions/eur.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/regions/eur.m3u index 9a8e344397..3d0f820ccc 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/regions/eur.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/regions/eur.m3u @@ -1,11 +1,11 @@ -#EXTM3U -#EXTINF:-1 tvg-id="AndorraTV.ad@SD" tvg-logo="https://i.imgur.com/BnhTn8i.png" group-title="Undefined",ATV -https://iptv-all.lanesh4d0w.repl.co/andorra/atv -#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 -#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) -http://146.59.85.40:89/dunaworld/index.m3u8 -#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) -http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8 -#EXTINF:-1 tvg-id="ElTR.kg" tvg-logo="https://i.ibb.co/r6czQwQ/365049798-774721644658455-5702658175909463406-n-2.png" group-title="General",ЭлТР (480p) [Not 24/7] -http://gohoski.fvds.ru:3000/mediabay/162/index.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="AndorraTV.ad@SD" tvg-logo="https://i.imgur.com/BnhTn8i.png" group-title="Undefined",ATV +https://iptv-all.lanesh4d0w.repl.co/andorra/atv +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) +http://146.59.85.40:89/dunaworld/index.m3u8 +#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8 +#EXTINF:-1 tvg-id="ElTR.kg" tvg-logo="https://i.ibb.co/r6czQwQ/365049798-774721644658455-5702658175909463406-n-2.png" group-title="General",ЭлТР (480p) [Not 24/7] +http://gohoski.fvds.ru:3000/mediabay/162/index.m3u8 diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/regions/hispam.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/regions/hispam.m3u index c549c09ce1..15240af7d0 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/regions/hispam.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/regions/hispam.m3u @@ -1,5 +1,5 @@ -#EXTM3U -#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 -#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) -http://146.59.85.40:89/dunaworld/index.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) +http://146.59.85.40:89/dunaworld/index.m3u8 diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/regions/lac.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/regions/lac.m3u index c549c09ce1..15240af7d0 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/regions/lac.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/regions/lac.m3u @@ -1,5 +1,5 @@ -#EXTM3U -#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 -#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) -http://146.59.85.40:89/dunaworld/index.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) +http://146.59.85.40:89/dunaworld/index.m3u8 diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/regions/latam.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/regions/latam.m3u index c549c09ce1..15240af7d0 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/regions/latam.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/regions/latam.m3u @@ -1,5 +1,5 @@ -#EXTM3U -#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 -#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) -http://146.59.85.40:89/dunaworld/index.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) +http://146.59.85.40:89/dunaworld/index.m3u8 diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/regions/maghreb.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/regions/maghreb.m3u index c549c09ce1..15240af7d0 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/regions/maghreb.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/regions/maghreb.m3u @@ -1,5 +1,5 @@ -#EXTM3U -#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 -#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) -http://146.59.85.40:89/dunaworld/index.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) +http://146.59.85.40:89/dunaworld/index.m3u8 diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/regions/mena.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/regions/mena.m3u index c549c09ce1..15240af7d0 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/regions/mena.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/regions/mena.m3u @@ -1,5 +1,5 @@ -#EXTM3U -#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 -#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) -http://146.59.85.40:89/dunaworld/index.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) +http://146.59.85.40:89/dunaworld/index.m3u8 diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/regions/mideast.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/regions/mideast.m3u index c549c09ce1..15240af7d0 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/regions/mideast.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/regions/mideast.m3u @@ -1,5 +1,5 @@ -#EXTM3U -#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 -#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) -http://146.59.85.40:89/dunaworld/index.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) +http://146.59.85.40:89/dunaworld/index.m3u8 diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/regions/nam.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/regions/nam.m3u index 226aaf5de9..450e02495f 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/regions/nam.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/regions/nam.m3u @@ -1,11 +1,11 @@ -#EXTM3U -#EXTINF:-1 tvg-id="5AABTV.ca" tvg-logo="" group-title="Undefined",5AAB TV -http://158.69.124.9:1935/5aabtv/5aabtv/playlist.m3u8 -#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 -#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) -http://146.59.85.40:89/dunaworld/index.m3u8 -#EXTINF:-1 tvg-id="MeteoMedia.ca" tvg-logo="https://s1.twnmm.com/images/en_ca/mobile/logos/twn-mobile-logo.png" group-title="Weather",Meteomedia -http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8 -#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) -http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="5AABTV.ca" tvg-logo="" group-title="Undefined",5AAB TV +http://158.69.124.9:1935/5aabtv/5aabtv/playlist.m3u8 +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) +http://146.59.85.40:89/dunaworld/index.m3u8 +#EXTINF:-1 tvg-id="MeteoMedia.ca" tvg-logo="https://s1.twnmm.com/images/en_ca/mobile/logos/twn-mobile-logo.png" group-title="Weather",Meteomedia +http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8 +#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8 diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/regions/noram.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/regions/noram.m3u index 226aaf5de9..450e02495f 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/regions/noram.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/regions/noram.m3u @@ -1,11 +1,11 @@ -#EXTM3U -#EXTINF:-1 tvg-id="5AABTV.ca" tvg-logo="" group-title="Undefined",5AAB TV -http://158.69.124.9:1935/5aabtv/5aabtv/playlist.m3u8 -#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 -#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) -http://146.59.85.40:89/dunaworld/index.m3u8 -#EXTINF:-1 tvg-id="MeteoMedia.ca" tvg-logo="https://s1.twnmm.com/images/en_ca/mobile/logos/twn-mobile-logo.png" group-title="Weather",Meteomedia -http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8 -#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) -http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="5AABTV.ca" tvg-logo="" group-title="Undefined",5AAB TV +http://158.69.124.9:1935/5aabtv/5aabtv/playlist.m3u8 +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) +http://146.59.85.40:89/dunaworld/index.m3u8 +#EXTINF:-1 tvg-id="MeteoMedia.ca" tvg-logo="https://s1.twnmm.com/images/en_ca/mobile/logos/twn-mobile-logo.png" group-title="Weather",Meteomedia +http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8 +#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8 diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/regions/nord.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/regions/nord.m3u index c549c09ce1..15240af7d0 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/regions/nord.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/regions/nord.m3u @@ -1,5 +1,5 @@ -#EXTM3U -#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 -#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) -http://146.59.85.40:89/dunaworld/index.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) +http://146.59.85.40:89/dunaworld/index.m3u8 diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/regions/oce.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/regions/oce.m3u index c549c09ce1..15240af7d0 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/regions/oce.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/regions/oce.m3u @@ -1,5 +1,5 @@ -#EXTM3U -#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 -#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) -http://146.59.85.40:89/dunaworld/index.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) +http://146.59.85.40:89/dunaworld/index.m3u8 diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/regions/sas.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/regions/sas.m3u index c549c09ce1..15240af7d0 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/regions/sas.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/regions/sas.m3u @@ -1,5 +1,5 @@ -#EXTM3U -#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 -#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) -http://146.59.85.40:89/dunaworld/index.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) +http://146.59.85.40:89/dunaworld/index.m3u8 diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/regions/southam.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/regions/southam.m3u index c549c09ce1..15240af7d0 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/regions/southam.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/regions/southam.m3u @@ -1,5 +1,5 @@ -#EXTM3U -#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 -#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) -http://146.59.85.40:89/dunaworld/index.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) +http://146.59.85.40:89/dunaworld/index.m3u8 diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/regions/ssa.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/regions/ssa.m3u index c549c09ce1..15240af7d0 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/regions/ssa.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/regions/ssa.m3u @@ -1,5 +1,5 @@ -#EXTM3U -#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 -#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) -http://146.59.85.40:89/dunaworld/index.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) +http://146.59.85.40:89/dunaworld/index.m3u8 diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/regions/wafr.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/regions/wafr.m3u index c549c09ce1..15240af7d0 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/regions/wafr.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/regions/wafr.m3u @@ -1,5 +1,5 @@ -#EXTM3U -#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 -#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) -http://146.59.85.40:89/dunaworld/index.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) +http://146.59.85.40:89/dunaworld/index.m3u8 diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/regions/ww.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/regions/ww.m3u index edb9b671dc..297163fc51 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/regions/ww.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/regions/ww.m3u @@ -1,15 +1,15 @@ -#EXTM3U -#EXTINF:-1 tvg-id="5AABTV.ca" tvg-logo="" group-title="Undefined",5AAB TV -http://158.69.124.9:1935/5aabtv/5aabtv/playlist.m3u8 -#EXTINF:-1 tvg-id="AndorraTV.ad@SD" tvg-logo="https://i.imgur.com/BnhTn8i.png" group-title="Undefined",ATV -https://iptv-all.lanesh4d0w.repl.co/andorra/atv -#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 -#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) -http://146.59.85.40:89/dunaworld/index.m3u8 -#EXTINF:-1 tvg-id="MeteoMedia.ca" tvg-logo="https://s1.twnmm.com/images/en_ca/mobile/logos/twn-mobile-logo.png" group-title="Weather",Meteomedia -http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8 -#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) -http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8 -#EXTINF:-1 tvg-id="ElTR.kg" tvg-logo="https://i.ibb.co/r6czQwQ/365049798-774721644658455-5702658175909463406-n-2.png" group-title="General",ЭлТР (480p) [Not 24/7] -http://gohoski.fvds.ru:3000/mediabay/162/index.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="5AABTV.ca" tvg-logo="" group-title="Undefined",5AAB TV +http://158.69.124.9:1935/5aabtv/5aabtv/playlist.m3u8 +#EXTINF:-1 tvg-id="AndorraTV.ad@SD" tvg-logo="https://i.imgur.com/BnhTn8i.png" group-title="Undefined",ATV +https://iptv-all.lanesh4d0w.repl.co/andorra/atv +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) +http://146.59.85.40:89/dunaworld/index.m3u8 +#EXTINF:-1 tvg-id="MeteoMedia.ca" tvg-logo="https://s1.twnmm.com/images/en_ca/mobile/logos/twn-mobile-logo.png" group-title="Weather",Meteomedia +http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8 +#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8 +#EXTINF:-1 tvg-id="ElTR.kg" tvg-logo="https://i.ibb.co/r6czQwQ/365049798-774721644658455-5702658175909463406-n-2.png" group-title="General",ЭлТР (480p) [Not 24/7] +http://gohoski.fvds.ru:3000/mediabay/162/index.m3u8 diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/sources/ad.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/sources/ad.m3u index 2894094c7e..55aaf78b41 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/sources/ad.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/sources/ad.m3u @@ -1,7 +1,7 @@ -#EXTM3U -#EXTINF:-1 tvg-id="AndorraTV.ad@HD" tvg-logo="https://i.imgur.com/CnhTn8i.png" group-title="Undefined",ATV HD -https://iptv-all.lanesh4d0w.repl.co/andorra/atv_hd -#EXTINF:-1 tvg-id="AndorraTV.ad@SD" tvg-logo="https://i.imgur.com/BnhTn8i.png" group-title="Undefined",ATV -https://iptv-all.lanesh4d0w.repl.co/andorra/atv -#EXTINF:-1 tvg-id="Zoo.ad@HD" tvg-logo="https://i.imgur.com/ciTJrnl.png" group-title="Undefined",Zoo (720p) -https://iptv-all.lanesh4d0w.repl.co/andorra/zoo +#EXTM3U +#EXTINF:-1 tvg-id="AndorraTV.ad@HD" tvg-logo="https://i.imgur.com/CnhTn8i.png" group-title="Undefined",ATV HD +https://iptv-all.lanesh4d0w.repl.co/andorra/atv_hd +#EXTINF:-1 tvg-id="AndorraTV.ad@SD" tvg-logo="https://i.imgur.com/BnhTn8i.png" group-title="Undefined",ATV +https://iptv-all.lanesh4d0w.repl.co/andorra/atv +#EXTINF:-1 tvg-id="Zoo.ad@HD" tvg-logo="https://i.imgur.com/ciTJrnl.png" group-title="Undefined",Zoo (720p) +https://iptv-all.lanesh4d0w.repl.co/andorra/zoo diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/sources/ca.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/sources/ca.m3u index 8aeaaae90e..79ba1e61d2 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/sources/ca.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/sources/ca.m3u @@ -1,5 +1,5 @@ -#EXTM3U -#EXTINF:-1 tvg-id="5AABTV.ca" tvg-logo="" group-title="Undefined",5AAB TV -http://158.69.124.9:1935/5aabtv/5aabtv/playlist.m3u8 -#EXTINF:-1 tvg-id="MeteoMedia.ca" tvg-logo="https://s1.twnmm.com/images/en_ca/mobile/logos/twn-mobile-logo.png" group-title="Weather",Meteomedia -http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="5AABTV.ca" tvg-logo="" group-title="Undefined",5AAB TV +http://158.69.124.9:1935/5aabtv/5aabtv/playlist.m3u8 +#EXTINF:-1 tvg-id="MeteoMedia.ca" tvg-logo="https://s1.twnmm.com/images/en_ca/mobile/logos/twn-mobile-logo.png" group-title="Weather",Meteomedia +http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8 diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/sources/in.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/sources/in.m3u index 4708e622d8..d2223daac4 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/sources/in.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/sources/in.m3u @@ -1,3 +1,3 @@ -#EXTM3U -#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined",Daawah TV -http://51.15.246.58:8081/daawahtv/daawahtv2/playlist.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined",Daawah TV +http://51.15.246.58:8081/daawahtv/daawahtv2/playlist.m3u8 diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/sources/kg.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/sources/kg.m3u index a9387b8b44..847591ab04 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/sources/kg.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/sources/kg.m3u @@ -1,3 +1,3 @@ -#EXTM3U -#EXTINF:-1 tvg-id="ElTR.kg" tvg-logo="https://i.ibb.co/r6czQwQ/365049798-774721644658455-5702658175909463406-n-2.png" group-title="General",ЭлТР (480p) [Not 24/7] -http://gohoski.fvds.ru:3000/mediabay/162/index.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="ElTR.kg" tvg-logo="https://i.ibb.co/r6czQwQ/365049798-774721644658455-5702658175909463406-n-2.png" group-title="General",ЭлТР (480p) [Not 24/7] +http://gohoski.fvds.ru:3000/mediabay/162/index.m3u8 diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/sources/uk.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/sources/uk.m3u index cf4e62a9a5..85c75b78bf 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/sources/uk.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/sources/uk.m3u @@ -1,3 +1,3 @@ -#EXTM3U -#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="General;News",BBC News HD +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/sources/unsorted.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/sources/unsorted.m3u index 05c8cb479f..52eb85ee4e 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/sources/unsorted.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/sources/unsorted.m3u @@ -1,15 +1,15 @@ -#EXTM3U -#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined" http-referrer="http://imn.iq" http-user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",Andorra TV (720p) [Not 24/7] -#EXTVLCOPT:http-referrer=http://imn.iq -#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 -#KODIPROP:inputstream=inputstream.adaptive -#KODIPROP:inputstream.adaptive.manifest_type=mpd -#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha -#KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=13f2e056-53fe-4469-ba6d-999970dbe549&userToken=v9ZVSksv4S7rT55o10dmYNRa4asye3z05eWCFxD%2FFYIlTJEpuf6tF8asPcyQOFq0h5opS%2B6WoMxnshWkihpHq5qrdrBEZ69piE94J9Feh385snGOqK3PYO7tLLjxmsCAe%2B9%2BNnurSSO5RCAIRsL125nSj1eOR%2F1GSKOgGH80HK2FDLiePxPkeaAxuWzacNBB%2FqnIGGxfe3GlmN65cU9F8WEpKFDlaxW%2Fv3ZSLAp3%2BZEq1aZXJ6Oz%2Fi0diD0EybH7|Content-Type=application/octet-stream|R{SSM}| -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8|Referer="https://referer.xyz/"|User-Agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1"|Origin="https://origin.xyz" -#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) -http://146.59.85.40:89/dunaworld/index.m3u8 -#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) -http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8 -#EXTINF:-1 tvg-id="VisitXTV.nl" tvg-logo="https://i.imgur.com/RJ9wbNF.jpg" group-title="XXX",Visit-X TV -https://stream.visit-x.tv/vxtv/ngrp:live_all/30fps.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="" tvg-logo="" group-title="Undefined" http-referrer="http://imn.iq" http-user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",Andorra TV (720p) [Not 24/7] +#EXTVLCOPT:http-referrer=http://imn.iq +#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 +#KODIPROP:inputstream=inputstream.adaptive +#KODIPROP:inputstream.adaptive.manifest_type=mpd +#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha +#KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=13f2e056-53fe-4469-ba6d-999970dbe549&userToken=v9ZVSksv4S7rT55o10dmYNRa4asye3z05eWCFxD%2FFYIlTJEpuf6tF8asPcyQOFq0h5opS%2B6WoMxnshWkihpHq5qrdrBEZ69piE94J9Feh385snGOqK3PYO7tLLjxmsCAe%2B9%2BNnurSSO5RCAIRsL125nSj1eOR%2F1GSKOgGH80HK2FDLiePxPkeaAxuWzacNBB%2FqnIGGxfe3GlmN65cU9F8WEpKFDlaxW%2Fv3ZSLAp3%2BZEq1aZXJ6Oz%2Fi0diD0EybH7|Content-Type=application/octet-stream|R{SSM}| +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8|Referer="https://referer.xyz/"|User-Agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1"|Origin="https://origin.xyz" +#EXTINF:-1 tvg-id="DunaWorld.hu" tvg-logo="https://i.imgur.com/uOBQJZS.png" group-title="Undefined",Duna World (576i) +http://146.59.85.40:89/dunaworld/index.m3u8 +#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8 +#EXTINF:-1 tvg-id="VisitXTV.nl" tvg-logo="https://i.imgur.com/RJ9wbNF.jpg" group-title="XXX",Visit-X TV +https://stream.visit-x.tv/vxtv/ngrp:live_all/30fps.m3u8 diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/subdivisions/ad-02.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/subdivisions/ad-02.m3u index 92a59e8a10..e85626ca16 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/subdivisions/ad-02.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/subdivisions/ad-02.m3u @@ -1,3 +1,3 @@ -#EXTM3U -#EXTINF:-1 tvg-id="AndorraTV.ad@SD" tvg-logo="https://i.imgur.com/BnhTn8i.png" group-title="Undefined",ATV -https://iptv-all.lanesh4d0w.repl.co/andorra/atv +#EXTM3U +#EXTINF:-1 tvg-id="AndorraTV.ad@SD" tvg-logo="https://i.imgur.com/BnhTn8i.png" group-title="Undefined",ATV +https://iptv-all.lanesh4d0w.repl.co/andorra/atv diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/subdivisions/ad-07.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/subdivisions/ad-07.m3u index 92a59e8a10..e85626ca16 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/subdivisions/ad-07.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/subdivisions/ad-07.m3u @@ -1,3 +1,3 @@ -#EXTM3U -#EXTINF:-1 tvg-id="AndorraTV.ad@SD" tvg-logo="https://i.imgur.com/BnhTn8i.png" group-title="Undefined",ATV -https://iptv-all.lanesh4d0w.repl.co/andorra/atv +#EXTM3U +#EXTINF:-1 tvg-id="AndorraTV.ad@SD" tvg-logo="https://i.imgur.com/BnhTn8i.png" group-title="Undefined",ATV +https://iptv-all.lanesh4d0w.repl.co/andorra/atv diff --git a/tests/__data__/expected/playlist_generate/.gh-pages/subdivisions/ca-on.m3u b/tests/__data__/expected/playlist_generate/.gh-pages/subdivisions/ca-on.m3u index 4686c68f4b..03a6963a33 100644 --- a/tests/__data__/expected/playlist_generate/.gh-pages/subdivisions/ca-on.m3u +++ b/tests/__data__/expected/playlist_generate/.gh-pages/subdivisions/ca-on.m3u @@ -1,3 +1,3 @@ -#EXTM3U -#EXTINF:-1 tvg-id="MeteoMedia.ca" tvg-logo="https://s1.twnmm.com/images/en_ca/mobile/logos/twn-mobile-logo.png" group-title="Weather",Meteomedia -http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="MeteoMedia.ca" tvg-logo="https://s1.twnmm.com/images/en_ca/mobile/logos/twn-mobile-logo.png" group-title="Weather",Meteomedia +http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8 diff --git a/tests/__data__/expected/playlist_generate/logs/generators.log b/tests/__data__/expected/playlist_generate/logs/generators.log index 19e38d5a8b..f913b380da 100644 --- a/tests/__data__/expected/playlist_generate/logs/generators.log +++ b/tests/__data__/expected/playlist_generate/logs/generators.log @@ -1,85 +1,85 @@ -{"type":"raw","filepath":"raw/ad.m3u","count":4} -{"type":"raw","filepath":"raw/ca.m3u","count":2} -{"type":"raw","filepath":"raw/in.m3u","count":1} -{"type":"raw","filepath":"raw/kg.m3u","count":1} -{"type":"raw","filepath":"raw/uk.m3u","count":1} -{"type":"raw","filepath":"raw/unsorted.m3u","count":4} -{"type":"category","filepath":"categories/auto.m3u","count":0} -{"type":"category","filepath":"categories/animation.m3u","count":0} -{"type":"category","filepath":"categories/classic.m3u","count":0} -{"type":"category","filepath":"categories/comedy.m3u","count":0} -{"type":"category","filepath":"categories/culture.m3u","count":0} -{"type":"category","filepath":"categories/documentary.m3u","count":0} -{"type":"category","filepath":"categories/business.m3u","count":0} -{"type":"category","filepath":"categories/cooking.m3u","count":0} -{"type":"category","filepath":"categories/education.m3u","count":0} -{"type":"category","filepath":"categories/family.m3u","count":0} -{"type":"category","filepath":"categories/legislative.m3u","count":0} -{"type":"category","filepath":"categories/news.m3u","count":1} -{"type":"category","filepath":"categories/kids.m3u","count":0} -{"type":"category","filepath":"categories/lifestyle.m3u","count":0} -{"type":"category","filepath":"categories/movies.m3u","count":0} -{"type":"category","filepath":"categories/religious.m3u","count":0} -{"type":"category","filepath":"categories/outdoor.m3u","count":0} -{"type":"category","filepath":"categories/general.m3u","count":3} -{"type":"category","filepath":"categories/relax.m3u","count":0} -{"type":"category","filepath":"categories/music.m3u","count":0} -{"type":"category","filepath":"categories/series.m3u","count":0} -{"type":"category","filepath":"categories/travel.m3u","count":0} -{"type":"category","filepath":"categories/sports.m3u","count":0} -{"type":"category","filepath":"categories/science.m3u","count":0} -{"type":"category","filepath":"categories/weather.m3u","count":1} -{"type":"category","filepath":"categories/shop.m3u","count":0} -{"type":"category","filepath":"categories/xxx.m3u","count":1} -{"type":"category","filepath":"categories/undefined.m3u","count":7} -{"type":"category","filepath":"categories/entertainment.m3u","count":0} -{"type":"language","filepath":"languages/cat.m3u","count":1} -{"type":"language","filepath":"languages/eng.m3u","count":1} -{"type":"language","filepath":"languages/undefined.m3u","count":8} -{"type":"language","filepath":"languages/rus.m3u","count":1} -{"type":"country","filepath":"countries/ad.m3u","count":1} -{"type":"country","filepath":"countries/ru.m3u","count":1} -{"type":"country","filepath":"countries/ca.m3u","count":2} -{"type":"country","filepath":"countries/int.m3u","count":4} -{"type":"country","filepath":"countries/undefined.m3u","count":4} -{"type":"subdivision","filepath":"subdivisions/ad-02.m3u","count":1} -{"type":"city","filepath":"cities/adcan.m3u","count":1} -{"type":"region","filepath":"regions/afr.m3u","count":2} -{"type":"source","filepath":"sources/in.m3u","count":1} -{"type":"subdivision","filepath":"subdivisions/ad-07.m3u","count":1} -{"type":"subdivision","filepath":"subdivisions/ca-on.m3u","count":1} -{"type":"region","filepath":"regions/amer.m3u","count":5} -{"type":"region","filepath":"regions/apac.m3u","count":2} -{"type":"region","filepath":"regions/cas.m3u","count":3} -{"type":"region","filepath":"regions/asean.m3u","count":2} -{"type":"region","filepath":"regions/cis.m3u","count":4} -{"type":"region","filepath":"regions/carib.m3u","count":2} -{"type":"region","filepath":"regions/arab.m3u","count":2} -{"type":"region","filepath":"regions/emea.m3u","count":5} -{"type":"region","filepath":"regions/asia.m3u","count":4} -{"type":"region","filepath":"regions/cenamer.m3u","count":2} -{"type":"region","filepath":"regions/ww.m3u","count":7} -{"type":"region","filepath":"regions/eur.m3u","count":5} -{"type":"region","filepath":"regions/lac.m3u","count":2} -{"type":"region","filepath":"regions/maghreb.m3u","count":2} -{"type":"region","filepath":"regions/latam.m3u","count":2} -{"type":"region","filepath":"regions/hispam.m3u","count":2} -{"type":"region","filepath":"regions/mena.m3u","count":2} -{"type":"region","filepath":"regions/mideast.m3u","count":2} -{"type":"region","filepath":"regions/nam.m3u","count":5} -{"type":"region","filepath":"regions/oce.m3u","count":2} -{"type":"region","filepath":"regions/nord.m3u","count":2} -{"type":"region","filepath":"regions/southam.m3u","count":2} -{"type":"region","filepath":"regions/noram.m3u","count":5} -{"type":"region","filepath":"regions/wafr.m3u","count":2} -{"type":"region","filepath":"regions/sas.m3u","count":2} -{"type":"region","filepath":"regions/ssa.m3u","count":2} -{"type":"source","filepath":"sources/unsorted.m3u","count":4} -{"type":"source","filepath":"sources/ca.m3u","count":2} -{"type":"source","filepath":"sources/ad.m3u","count":3} -{"type":"source","filepath":"sources/uk.m3u","count":1} -{"type":"source","filepath":"sources/kg.m3u","count":1} -{"type":"index","filepath":"index.m3u","count":11} -{"type":"index","filepath":"index.category.m3u","count":12} -{"type":"index","filepath":"index.country.m3u","count":12} -{"type":"index","filepath":"index.language.m3u","count":11} +{"type":"raw","filepath":"raw/ad.m3u","count":4} +{"type":"raw","filepath":"raw/ca.m3u","count":2} +{"type":"raw","filepath":"raw/in.m3u","count":1} +{"type":"raw","filepath":"raw/kg.m3u","count":1} +{"type":"raw","filepath":"raw/uk.m3u","count":1} +{"type":"raw","filepath":"raw/unsorted.m3u","count":4} +{"type":"category","filepath":"categories/auto.m3u","count":0} +{"type":"category","filepath":"categories/animation.m3u","count":0} +{"type":"category","filepath":"categories/classic.m3u","count":0} +{"type":"category","filepath":"categories/comedy.m3u","count":0} +{"type":"category","filepath":"categories/culture.m3u","count":0} +{"type":"category","filepath":"categories/documentary.m3u","count":0} +{"type":"category","filepath":"categories/business.m3u","count":0} +{"type":"category","filepath":"categories/cooking.m3u","count":0} +{"type":"category","filepath":"categories/education.m3u","count":0} +{"type":"category","filepath":"categories/family.m3u","count":0} +{"type":"category","filepath":"categories/legislative.m3u","count":0} +{"type":"category","filepath":"categories/news.m3u","count":1} +{"type":"category","filepath":"categories/kids.m3u","count":0} +{"type":"category","filepath":"categories/lifestyle.m3u","count":0} +{"type":"category","filepath":"categories/movies.m3u","count":0} +{"type":"category","filepath":"categories/religious.m3u","count":0} +{"type":"category","filepath":"categories/outdoor.m3u","count":0} +{"type":"category","filepath":"categories/general.m3u","count":3} +{"type":"category","filepath":"categories/relax.m3u","count":0} +{"type":"category","filepath":"categories/music.m3u","count":0} +{"type":"category","filepath":"categories/series.m3u","count":0} +{"type":"category","filepath":"categories/travel.m3u","count":0} +{"type":"category","filepath":"categories/sports.m3u","count":0} +{"type":"category","filepath":"categories/science.m3u","count":0} +{"type":"category","filepath":"categories/weather.m3u","count":1} +{"type":"category","filepath":"categories/shop.m3u","count":0} +{"type":"category","filepath":"categories/xxx.m3u","count":1} +{"type":"category","filepath":"categories/undefined.m3u","count":7} +{"type":"category","filepath":"categories/entertainment.m3u","count":0} +{"type":"language","filepath":"languages/cat.m3u","count":1} +{"type":"language","filepath":"languages/eng.m3u","count":1} +{"type":"language","filepath":"languages/undefined.m3u","count":8} +{"type":"language","filepath":"languages/rus.m3u","count":1} +{"type":"country","filepath":"countries/ad.m3u","count":1} +{"type":"country","filepath":"countries/ru.m3u","count":1} +{"type":"country","filepath":"countries/ca.m3u","count":2} +{"type":"country","filepath":"countries/int.m3u","count":4} +{"type":"country","filepath":"countries/undefined.m3u","count":4} +{"type":"subdivision","filepath":"subdivisions/ad-02.m3u","count":1} +{"type":"city","filepath":"cities/adcan.m3u","count":1} +{"type":"region","filepath":"regions/afr.m3u","count":2} +{"type":"source","filepath":"sources/in.m3u","count":1} +{"type":"subdivision","filepath":"subdivisions/ad-07.m3u","count":1} +{"type":"subdivision","filepath":"subdivisions/ca-on.m3u","count":1} +{"type":"region","filepath":"regions/amer.m3u","count":5} +{"type":"region","filepath":"regions/apac.m3u","count":2} +{"type":"region","filepath":"regions/cas.m3u","count":3} +{"type":"region","filepath":"regions/asean.m3u","count":2} +{"type":"region","filepath":"regions/cis.m3u","count":4} +{"type":"region","filepath":"regions/carib.m3u","count":2} +{"type":"region","filepath":"regions/arab.m3u","count":2} +{"type":"region","filepath":"regions/emea.m3u","count":5} +{"type":"region","filepath":"regions/asia.m3u","count":4} +{"type":"region","filepath":"regions/cenamer.m3u","count":2} +{"type":"region","filepath":"regions/ww.m3u","count":7} +{"type":"region","filepath":"regions/eur.m3u","count":5} +{"type":"region","filepath":"regions/lac.m3u","count":2} +{"type":"region","filepath":"regions/maghreb.m3u","count":2} +{"type":"region","filepath":"regions/latam.m3u","count":2} +{"type":"region","filepath":"regions/hispam.m3u","count":2} +{"type":"region","filepath":"regions/mena.m3u","count":2} +{"type":"region","filepath":"regions/mideast.m3u","count":2} +{"type":"region","filepath":"regions/nam.m3u","count":5} +{"type":"region","filepath":"regions/oce.m3u","count":2} +{"type":"region","filepath":"regions/nord.m3u","count":2} +{"type":"region","filepath":"regions/southam.m3u","count":2} +{"type":"region","filepath":"regions/noram.m3u","count":5} +{"type":"region","filepath":"regions/wafr.m3u","count":2} +{"type":"region","filepath":"regions/sas.m3u","count":2} +{"type":"region","filepath":"regions/ssa.m3u","count":2} +{"type":"source","filepath":"sources/unsorted.m3u","count":4} +{"type":"source","filepath":"sources/ca.m3u","count":2} +{"type":"source","filepath":"sources/ad.m3u","count":3} +{"type":"source","filepath":"sources/uk.m3u","count":1} +{"type":"source","filepath":"sources/kg.m3u","count":1} +{"type":"index","filepath":"index.m3u","count":11} +{"type":"index","filepath":"index.category.m3u","count":12} +{"type":"index","filepath":"index.country.m3u","count":12} +{"type":"index","filepath":"index.language.m3u","count":11} diff --git a/tests/__data__/expected/playlist_update/cy.m3u b/tests/__data__/expected/playlist_update/cy.m3u index 987825ca1d..13482713e9 100644 --- a/tests/__data__/expected/playlist_update/cy.m3u +++ b/tests/__data__/expected/playlist_update/cy.m3u @@ -1,3 +1,3 @@ -#EXTM3U -#EXTINF:-1 tvg-id="AdaTV.cy",AdaTV -https://ythls.onrender.com/channel/UC40TUSUx490U5uR1lZt3Ajg.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="AdaTV.cy",AdaTV +https://ythls.onrender.com/channel/UC40TUSUx490U5uR1lZt3Ajg.m3u8 diff --git a/tests/__data__/expected/playlist_update/fr.m3u b/tests/__data__/expected/playlist_update/fr.m3u index b460293dd4..fe6e40fbce 100644 --- a/tests/__data__/expected/playlist_update/fr.m3u +++ b/tests/__data__/expected/playlist_update/fr.m3u @@ -1,3 +1,3 @@ -#EXTM3U -#EXTINF:-1 tvg-id="TFX.fr" http-referrer="https://pkpakiplay.xyz/" http-user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1",TFX -https://stitcher-ipv4.pluto.tv/v1/stitch/embed/hls/channel/64c109a4798def0008a6e03e/master.m3u8?advertisingId={PSID}&appVersion=unknown&deviceDNT={TARGETOPT}&deviceId={PSID}&deviceLat=0&deviceLon=0&deviceMake=samsung&deviceModel=samsung&deviceType=samsung-tvplus&deviceVersion=unknown&embedPartner=samsung-tvplus&profileFloor=&profileLimit=&samsung_app_domain={APP_DOMAIN}&samsung_app_name={APP_NAME}&us_privacy=1YNY +#EXTM3U +#EXTINF:-1 tvg-id="TFX.fr@SD" http-referrer="https://pkpakiplay.xyz/" http-user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1",TFX +https://stitcher-ipv4.pluto.tv/v1/stitch/embed/hls/channel/64c109a4798def0008a6e03e/master.m3u8?advertisingId={PSID}&appVersion=unknown&deviceDNT={TARGETOPT}&deviceId={PSID}&deviceLat=0&deviceLon=0&deviceMake=samsung&deviceModel=samsung&deviceType=samsung-tvplus&deviceVersion=unknown&embedPartner=samsung-tvplus&profileFloor=&profileLimit=&samsung_app_domain={APP_DOMAIN}&samsung_app_name={APP_NAME}&us_privacy=1YNY diff --git a/tests/__data__/expected/playlist_update/uk.m3u b/tests/__data__/expected/playlist_update/uk.m3u index deeb47af44..ab04109e58 100644 --- a/tests/__data__/expected/playlist_update/uk.m3u +++ b/tests/__data__/expected/playlist_update/uk.m3u @@ -1,13 +1,13 @@ -#EXTM3U -#EXTINF:-1 tvg-id="BBCNews.uk",BBC News HD (720p) [Not 24/7] -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 -#EXTINF:-1 tvg-id="BBCNews.uk",BBC News HD (480p) [Geo-blocked] -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/playlist.m3u8 -#EXTINF:-1 tvg-id="BeanoTV.uk",Beano TV -#EXTVLCOPT:http-referrer=http://imn.iq -#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 -#KODIPROP:inputstream=inputstream.adaptive -#KODIPROP:inputstream.adaptive.manifest_type=mpd -#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha -#KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=13f2e056-53fe-4469-ba6d-999970dbe549&userToken=v9ZVSksv4S7rT55o10dmYNRa4asye3z05eWCFxD%2FFYIlTJEpuf6tF8asPcyQOFq0h5opS%2B6WoMxnshWkihpHq5qrdrBEZ69piE94J9Feh385snGOqK3PYO7tLLjxmsCAe%2B9%2BNnurSSO5RCAIRsL125nSj1eOR%2F1GSKOgGH80HK2FDLiePxPkeaAxuWzacNBB%2FqnIGGxfe3GlmN65cU9F8WEpKFDlaxW%2Fv3ZSLAp3%2BZEq1aZXJ6Oz%2Fi0diD0EybH7|Content-Type=application/octet-stream|R{SSM}| -https://a5b4bacecd47433dad06d3189fc7422e.mediatailor.us-east-1.amazonaws.com/v1/manifest/04fd913bb278d8775298c26fdca9d9841f37601f/RakutenTV-eu_BeanoTV/b1f233d5-847c-437d-aa4f-f73e67a85323/2.m3u8|Referer="https://referer.xyz/"|User-Agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1"|Origin="https://origin.xyz" +#EXTM3U +#EXTINF:-1 tvg-id="BBCNews.uk",BBC News HD (720p) [Not 24/7] +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTINF:-1 tvg-id="BBCNews.uk",BBC News HD (480p) [Geo-blocked] +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/playlist.m3u8 +#EXTINF:-1 tvg-id="BeanoTV.uk@SD",Beano TV +#EXTVLCOPT:http-referrer=http://imn.iq +#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 +#KODIPROP:inputstream=inputstream.adaptive +#KODIPROP:inputstream.adaptive.manifest_type=mpd +#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha +#KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=13f2e056-53fe-4469-ba6d-999970dbe549&userToken=v9ZVSksv4S7rT55o10dmYNRa4asye3z05eWCFxD%2FFYIlTJEpuf6tF8asPcyQOFq0h5opS%2B6WoMxnshWkihpHq5qrdrBEZ69piE94J9Feh385snGOqK3PYO7tLLjxmsCAe%2B9%2BNnurSSO5RCAIRsL125nSj1eOR%2F1GSKOgGH80HK2FDLiePxPkeaAxuWzacNBB%2FqnIGGxfe3GlmN65cU9F8WEpKFDlaxW%2Fv3ZSLAp3%2BZEq1aZXJ6Oz%2Fi0diD0EybH7|Content-Type=application/octet-stream|R{SSM}| +https://a5b4bacecd47433dad06d3189fc7422e.mediatailor.us-east-1.amazonaws.com/v1/manifest/04fd913bb278d8775298c26fdca9d9841f37601f/RakutenTV-eu_BeanoTV/b1f233d5-847c-437d-aa4f-f73e67a85323/2.m3u8|Referer="https://referer.xyz/"|User-Agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1"|Origin="https://origin.xyz" diff --git a/tests/__data__/expected/playlist_update/us.m3u b/tests/__data__/expected/playlist_update/us.m3u index 9ec9bde318..8f57ccc7bf 100644 --- a/tests/__data__/expected/playlist_update/us.m3u +++ b/tests/__data__/expected/playlist_update/us.m3u @@ -1,11 +1,11 @@ -#EXTM3U -#EXTINF:-1 tvg-id="BBCAmerica.us@East" http-user-agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36 Edge/12.246",BBC America East (720p) -#EXTVLCOPT:http-referrer=http://imn.iq -#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 -#KODIPROP:inputstream=inputstream.adaptive -#KODIPROP:inputstream.adaptive.manifest_type=mpd -#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha -#KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=13f2e056-53fe-4469-ba6d-999970dbe549&userToken=v9ZVSksv4S7rT55o10dmYNRa4asye3z05eWCFxD%2FFYIlTJEpuf6tF8asPcyQOFq0h5opS%2B6WoMxnshWkihpHq5qrdrBEZ69piE94J9Feh385snGOqK3PYO7tLLjxmsCAe%2B9%2BNnurSSO5RCAIRsL125nSj1eOR%2F1GSKOgGH80HK2FDLiePxPkeaAxuWzacNBB%2FqnIGGxfe3GlmN65cU9F8WEpKFDlaxW%2Fv3ZSLAp3%2BZEq1aZXJ6Oz%2Fi0diD0EybH7|Content-Type=application/octet-stream|R{SSM}| -https://xui-backend.energeek.cl/live/9/playlist.m3u8?username=ZZDemoIPTVGH&password=mdo96EuqMkTR|Referer="https://referer.xyz/"|User-Agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1"|Origin="https://origin.xyz" -#EXTINF:-1 tvg-id="FastTV.us",Fast TV -https://3fa797d5.wurl.com/manifest/f36d25e7e52f1ba8d7e56eb859c636563214f541/T05PX01vdG9yVHJlbmRGYXN0VFZfSExT/b5e5e0e2-12b3-4312-93c9-c0a7c50b41ca/4.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="BBCAmerica.us@East" http-user-agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36 Edge/12.246",BBC America East (720p) +#EXTVLCOPT:http-referrer=http://imn.iq +#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 +#KODIPROP:inputstream=inputstream.adaptive +#KODIPROP:inputstream.adaptive.manifest_type=mpd +#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha +#KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=13f2e056-53fe-4469-ba6d-999970dbe549&userToken=v9ZVSksv4S7rT55o10dmYNRa4asye3z05eWCFxD%2FFYIlTJEpuf6tF8asPcyQOFq0h5opS%2B6WoMxnshWkihpHq5qrdrBEZ69piE94J9Feh385snGOqK3PYO7tLLjxmsCAe%2B9%2BNnurSSO5RCAIRsL125nSj1eOR%2F1GSKOgGH80HK2FDLiePxPkeaAxuWzacNBB%2FqnIGGxfe3GlmN65cU9F8WEpKFDlaxW%2Fv3ZSLAp3%2BZEq1aZXJ6Oz%2Fi0diD0EybH7|Content-Type=application/octet-stream|R{SSM}| +https://xui-backend.energeek.cl/live/9/playlist.m3u8?username=ZZDemoIPTVGH&password=mdo96EuqMkTR|Referer="https://referer.xyz/"|User-Agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1"|Origin="https://origin.xyz" +#EXTINF:-1 tvg-id="FastTV.us@SD",Fast TV +https://3fa797d5.wurl.com/manifest/f36d25e7e52f1ba8d7e56eb859c636563214f541/T05PX01vdG9yVHJlbmRGYXN0VFZfSExT/b5e5e0e2-12b3-4312-93c9-c0a7c50b41ca/4.m3u8 diff --git a/tests/__data__/expected/readme_update/playlists.md b/tests/__data__/expected/readme_update/playlists.md index f643ae9b83..f54d551be3 100644 --- a/tests/__data__/expected/readme_update/playlists.md +++ b/tests/__data__/expected/readme_update/playlists.md @@ -1,177 +1,177 @@ -## Playlists - -There are several versions of playlists that differ in the way they are grouped. As of January 30th, 2024, we have stopped distributing NSFW channels. For more information, please look at [this issue](https://github.com/iptv-org/iptv/issues/15723). - -### Grouped by category - -Playlists in which channels are grouped by category. - -
-Expand -
- -``` -https://iptv-org.github.io/iptv/index.category.m3u -``` - -Same thing, but split up into separate files: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CategoryChannelsPlaylist
Animation0https://iptv-org.github.io/iptv/categories/animation.m3u
Auto0https://iptv-org.github.io/iptv/categories/auto.m3u
Business0https://iptv-org.github.io/iptv/categories/business.m3u
Classic0https://iptv-org.github.io/iptv/categories/classic.m3u
Comedy0https://iptv-org.github.io/iptv/categories/comedy.m3u
Cooking0https://iptv-org.github.io/iptv/categories/cooking.m3u
Culture0https://iptv-org.github.io/iptv/categories/culture.m3u
Documentary0https://iptv-org.github.io/iptv/categories/documentary.m3u
Education0https://iptv-org.github.io/iptv/categories/education.m3u
Entertainment0https://iptv-org.github.io/iptv/categories/entertainment.m3u
Family0https://iptv-org.github.io/iptv/categories/family.m3u
General2https://iptv-org.github.io/iptv/categories/general.m3u
Kids0https://iptv-org.github.io/iptv/categories/kids.m3u
Legislative0https://iptv-org.github.io/iptv/categories/legislative.m3u
Lifestyle0https://iptv-org.github.io/iptv/categories/lifestyle.m3u
Movies0https://iptv-org.github.io/iptv/categories/movies.m3u
Music0https://iptv-org.github.io/iptv/categories/music.m3u
News1https://iptv-org.github.io/iptv/categories/news.m3u
Outdoor0https://iptv-org.github.io/iptv/categories/outdoor.m3u
Relax0https://iptv-org.github.io/iptv/categories/relax.m3u
Religious0https://iptv-org.github.io/iptv/categories/religious.m3u
Science0https://iptv-org.github.io/iptv/categories/science.m3u
Series0https://iptv-org.github.io/iptv/categories/series.m3u
Shop0https://iptv-org.github.io/iptv/categories/shop.m3u
Sports0https://iptv-org.github.io/iptv/categories/sports.m3u
Travel0https://iptv-org.github.io/iptv/categories/travel.m3u
Weather1https://iptv-org.github.io/iptv/categories/weather.m3u
XXX1https://iptv-org.github.io/iptv/categories/xxx.m3u
Undefined3https://iptv-org.github.io/iptv/categories/undefined.m3u
- -
- -### Grouped by language - -Playlists in which channels are grouped by the language in which they are broadcast. - -
-Expand -
- -``` -https://iptv-org.github.io/iptv/index.language.m3u -``` - -Same thing, but split up into separate files: - - - - - - - - - - - - - -
LanguageChannelsPlaylist
Catalan1https://iptv-org.github.io/iptv/languages/cat.m3u
English1https://iptv-org.github.io/iptv/languages/eng.m3u
French1https://iptv-org.github.io/iptv/languages/fra.m3u
Russian1https://iptv-org.github.io/iptv/languages/rus.m3u
Undefined2https://iptv-org.github.io/iptv/languages/undefined.m3u
- -
- -### Grouped by broadcast area - -Playlists in which channels are grouped by broadcast area. - -
-Expand - -#### Countries - -``` -https://iptv-org.github.io/iptv/index.country.m3u -``` - -Same thing, but split up into separate files: - - -- 🇦🇩 Andorra https://iptv-org.github.io/iptv/countries/ad.m3u - - Canillo https://iptv-org.github.io/iptv/subdivisions/ad-02.m3u - - Canillo https://iptv-org.github.io/iptv/cities/adcan.m3u -- 🇨🇲 Cameroon https://iptv-org.github.io/iptv/countries/cm.m3u -- 🇨🇦 Canada https://iptv-org.github.io/iptv/countries/ca.m3u - - Ontario https://iptv-org.github.io/iptv/subdivisions/ca-on.m3u -- 🇨🇻 Cape Verde https://iptv-org.github.io/iptv/countries/cv.m3u -- 🇭🇰 Hong Kong https://iptv-org.github.io/iptv/countries/hk.m3u - - Sai Kung https://iptv-org.github.io/iptv/cities/hk9sk.m3u -- 🇨🇬 Republic of the Congo https://iptv-org.github.io/iptv/countries/cg.m3u -- 🇷🇪 Réunion https://iptv-org.github.io/iptv/countries/re.m3u -- 🇷🇴 Romania https://iptv-org.github.io/iptv/countries/ro.m3u -- 🇷🇺 Russia https://iptv-org.github.io/iptv/countries/ru.m3u -- 🇷🇼 Rwanda https://iptv-org.github.io/iptv/countries/rw.m3u -- 🇧🇱 Saint Barthélemy https://iptv-org.github.io/iptv/countries/bl.m3u -- 🇸🇭 Saint Helena https://iptv-org.github.io/iptv/countries/sh.m3u -- 🇰🇳 Saint Kitts and Nevis https://iptv-org.github.io/iptv/countries/kn.m3u -- 🌐 International https://iptv-org.github.io/iptv/countries/int.m3u -- Undefined https://iptv-org.github.io/iptv/countries/undefined.m3u - -#### Regions - - -- Africa https://iptv-org.github.io/iptv/regions/afr.m3u -- Americas https://iptv-org.github.io/iptv/regions/amer.m3u -- Arab world https://iptv-org.github.io/iptv/regions/arab.m3u -- Asia https://iptv-org.github.io/iptv/regions/asia.m3u -- Asia-Pacific https://iptv-org.github.io/iptv/regions/apac.m3u -- Association of Southeast Asian Nations https://iptv-org.github.io/iptv/regions/asean.m3u -- Caribbean https://iptv-org.github.io/iptv/regions/carib.m3u -- Central America https://iptv-org.github.io/iptv/regions/cenamer.m3u -- Central Asia https://iptv-org.github.io/iptv/regions/cas.m3u -- Commonwealth of Independent States https://iptv-org.github.io/iptv/regions/cis.m3u -- Europe https://iptv-org.github.io/iptv/regions/eur.m3u -- Europe, the Middle East and Africa https://iptv-org.github.io/iptv/regions/emea.m3u -- Hispanic America https://iptv-org.github.io/iptv/regions/hispam.m3u -- Latin America https://iptv-org.github.io/iptv/regions/latam.m3u -- Latin America and the Caribbean https://iptv-org.github.io/iptv/regions/lac.m3u -- Maghreb https://iptv-org.github.io/iptv/regions/maghreb.m3u -- Middle East https://iptv-org.github.io/iptv/regions/mideast.m3u -- Middle East and North Africa https://iptv-org.github.io/iptv/regions/mena.m3u -- Nordics https://iptv-org.github.io/iptv/regions/nord.m3u -- North America https://iptv-org.github.io/iptv/regions/noram.m3u -- Northern America https://iptv-org.github.io/iptv/regions/nam.m3u -- Oceania https://iptv-org.github.io/iptv/regions/oce.m3u -- South America https://iptv-org.github.io/iptv/regions/southam.m3u -- South Asia https://iptv-org.github.io/iptv/regions/sas.m3u -- Sub-Saharan Africa https://iptv-org.github.io/iptv/regions/ssa.m3u -- West Africa https://iptv-org.github.io/iptv/regions/wafr.m3u - -
- -### Grouped by sources - -Playlists in which channels are grouped by broadcast source. - -
-Expand -
- -To use the playlist, simply replace `` in the link below with the name of one of the files in the [streams](streams) folder. - -``` -https://iptv-org.github.io/iptv/sources/.m3u -``` - -
- -Also, any of our internal playlists are available in raw form (without any filtering or sorting) at this link: - -``` -https://iptv-org.github.io/iptv/raw/.m3u -``` +## Playlists + +There are several versions of playlists that differ in the way they are grouped. As of January 30th, 2024, we have stopped distributing NSFW channels. For more information, please look at [this issue](https://github.com/iptv-org/iptv/issues/15723). + +### Grouped by category + +Playlists in which channels are grouped by category. + +
+Expand +
+ +``` +https://iptv-org.github.io/iptv/index.category.m3u +``` + +Same thing, but split up into separate files: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CategoryChannelsPlaylist
Animation0https://iptv-org.github.io/iptv/categories/animation.m3u
Auto0https://iptv-org.github.io/iptv/categories/auto.m3u
Business0https://iptv-org.github.io/iptv/categories/business.m3u
Classic0https://iptv-org.github.io/iptv/categories/classic.m3u
Comedy0https://iptv-org.github.io/iptv/categories/comedy.m3u
Cooking0https://iptv-org.github.io/iptv/categories/cooking.m3u
Culture0https://iptv-org.github.io/iptv/categories/culture.m3u
Documentary0https://iptv-org.github.io/iptv/categories/documentary.m3u
Education0https://iptv-org.github.io/iptv/categories/education.m3u
Entertainment0https://iptv-org.github.io/iptv/categories/entertainment.m3u
Family0https://iptv-org.github.io/iptv/categories/family.m3u
General2https://iptv-org.github.io/iptv/categories/general.m3u
Kids0https://iptv-org.github.io/iptv/categories/kids.m3u
Legislative0https://iptv-org.github.io/iptv/categories/legislative.m3u
Lifestyle0https://iptv-org.github.io/iptv/categories/lifestyle.m3u
Movies0https://iptv-org.github.io/iptv/categories/movies.m3u
Music0https://iptv-org.github.io/iptv/categories/music.m3u
News1https://iptv-org.github.io/iptv/categories/news.m3u
Outdoor0https://iptv-org.github.io/iptv/categories/outdoor.m3u
Relax0https://iptv-org.github.io/iptv/categories/relax.m3u
Religious0https://iptv-org.github.io/iptv/categories/religious.m3u
Science0https://iptv-org.github.io/iptv/categories/science.m3u
Series0https://iptv-org.github.io/iptv/categories/series.m3u
Shop0https://iptv-org.github.io/iptv/categories/shop.m3u
Sports0https://iptv-org.github.io/iptv/categories/sports.m3u
Travel0https://iptv-org.github.io/iptv/categories/travel.m3u
Weather1https://iptv-org.github.io/iptv/categories/weather.m3u
XXX1https://iptv-org.github.io/iptv/categories/xxx.m3u
Undefined3https://iptv-org.github.io/iptv/categories/undefined.m3u
+ +
+ +### Grouped by language + +Playlists in which channels are grouped by the language in which they are broadcast. + +
+Expand +
+ +``` +https://iptv-org.github.io/iptv/index.language.m3u +``` + +Same thing, but split up into separate files: + + + + + + + + + + + + + +
LanguageChannelsPlaylist
Catalan1https://iptv-org.github.io/iptv/languages/cat.m3u
English1https://iptv-org.github.io/iptv/languages/eng.m3u
French1https://iptv-org.github.io/iptv/languages/fra.m3u
Russian1https://iptv-org.github.io/iptv/languages/rus.m3u
Undefined2https://iptv-org.github.io/iptv/languages/undefined.m3u
+ +
+ +### Grouped by broadcast area + +Playlists in which channels are grouped by broadcast area. + +
+Expand + +#### Countries + +``` +https://iptv-org.github.io/iptv/index.country.m3u +``` + +Same thing, but split up into separate files: + + +- 🇦🇩 Andorra https://iptv-org.github.io/iptv/countries/ad.m3u + - Canillo https://iptv-org.github.io/iptv/subdivisions/ad-02.m3u + - Canillo https://iptv-org.github.io/iptv/cities/adcan.m3u +- 🇨🇲 Cameroon https://iptv-org.github.io/iptv/countries/cm.m3u +- 🇨🇦 Canada https://iptv-org.github.io/iptv/countries/ca.m3u + - Ontario https://iptv-org.github.io/iptv/subdivisions/ca-on.m3u +- 🇨🇻 Cape Verde https://iptv-org.github.io/iptv/countries/cv.m3u +- 🇭🇰 Hong Kong https://iptv-org.github.io/iptv/countries/hk.m3u + - Sai Kung https://iptv-org.github.io/iptv/cities/hk9sk.m3u +- 🇨🇬 Republic of the Congo https://iptv-org.github.io/iptv/countries/cg.m3u +- 🇷🇪 Réunion https://iptv-org.github.io/iptv/countries/re.m3u +- 🇷🇴 Romania https://iptv-org.github.io/iptv/countries/ro.m3u +- 🇷🇺 Russia https://iptv-org.github.io/iptv/countries/ru.m3u +- 🇷🇼 Rwanda https://iptv-org.github.io/iptv/countries/rw.m3u +- 🇧🇱 Saint Barthélemy https://iptv-org.github.io/iptv/countries/bl.m3u +- 🇸🇭 Saint Helena https://iptv-org.github.io/iptv/countries/sh.m3u +- 🇰🇳 Saint Kitts and Nevis https://iptv-org.github.io/iptv/countries/kn.m3u +- 🌐 International https://iptv-org.github.io/iptv/countries/int.m3u +- Undefined https://iptv-org.github.io/iptv/countries/undefined.m3u + +#### Regions + + +- Africa https://iptv-org.github.io/iptv/regions/afr.m3u +- Americas https://iptv-org.github.io/iptv/regions/amer.m3u +- Arab world https://iptv-org.github.io/iptv/regions/arab.m3u +- Asia https://iptv-org.github.io/iptv/regions/asia.m3u +- Asia-Pacific https://iptv-org.github.io/iptv/regions/apac.m3u +- Association of Southeast Asian Nations https://iptv-org.github.io/iptv/regions/asean.m3u +- Caribbean https://iptv-org.github.io/iptv/regions/carib.m3u +- Central America https://iptv-org.github.io/iptv/regions/cenamer.m3u +- Central Asia https://iptv-org.github.io/iptv/regions/cas.m3u +- Commonwealth of Independent States https://iptv-org.github.io/iptv/regions/cis.m3u +- Europe https://iptv-org.github.io/iptv/regions/eur.m3u +- Europe, the Middle East and Africa https://iptv-org.github.io/iptv/regions/emea.m3u +- Hispanic America https://iptv-org.github.io/iptv/regions/hispam.m3u +- Latin America https://iptv-org.github.io/iptv/regions/latam.m3u +- Latin America and the Caribbean https://iptv-org.github.io/iptv/regions/lac.m3u +- Maghreb https://iptv-org.github.io/iptv/regions/maghreb.m3u +- Middle East https://iptv-org.github.io/iptv/regions/mideast.m3u +- Middle East and North Africa https://iptv-org.github.io/iptv/regions/mena.m3u +- Nordics https://iptv-org.github.io/iptv/regions/nord.m3u +- North America https://iptv-org.github.io/iptv/regions/noram.m3u +- Northern America https://iptv-org.github.io/iptv/regions/nam.m3u +- Oceania https://iptv-org.github.io/iptv/regions/oce.m3u +- South America https://iptv-org.github.io/iptv/regions/southam.m3u +- South Asia https://iptv-org.github.io/iptv/regions/sas.m3u +- Sub-Saharan Africa https://iptv-org.github.io/iptv/regions/ssa.m3u +- West Africa https://iptv-org.github.io/iptv/regions/wafr.m3u + +
+ +### Grouped by sources + +Playlists in which channels are grouped by broadcast source. + +
+Expand +
+ +To use the playlist, simply replace `` in the link below with the name of one of the files in the [streams](streams) folder. + +``` +https://iptv-org.github.io/iptv/sources/.m3u +``` + +
+ +Also, any of our internal playlists are available in raw form (without any filtering or sorting) at this link: + +``` +https://iptv-org.github.io/iptv/raw/.m3u +``` diff --git a/tests/__data__/input/api_generate/ad.m3u b/tests/__data__/input/api_generate/ad.m3u index 34aad90534..9cb32a9b9e 100644 --- a/tests/__data__/input/api_generate/ad.m3u +++ b/tests/__data__/input/api_generate/ad.m3u @@ -1,5 +1,5 @@ -#EXTM3U -#EXTINF:-1 tvg-id="Zoo.ad",Zoo (720p) -https://iptv-all.lanesh4d0w.repl.co/andorra/zoo -#EXTINF:-1 tvg-id="AndorraTV.ad@SD",ATV -https://iptv-all.lanesh4d0w.repl.co/andorra/atv|Referer="https://referer.xyz/"|User-Agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1"|Origin="https://origin.xyz" +#EXTM3U +#EXTINF:-1 tvg-id="Zoo.ad",Zoo (720p) +https://iptv-all.lanesh4d0w.repl.co/andorra/zoo +#EXTINF:-1 tvg-id="AndorraTV.ad@SD",ATV +https://iptv-all.lanesh4d0w.repl.co/andorra/atv|Referer="https://referer.xyz/"|User-Agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1"|Origin="https://origin.xyz" diff --git a/tests/__data__/input/api_generate/ca.m3u b/tests/__data__/input/api_generate/ca.m3u index 9c198b6829..672601d7f7 100644 --- a/tests/__data__/input/api_generate/ca.m3u +++ b/tests/__data__/input/api_generate/ca.m3u @@ -1,3 +1,3 @@ -#EXTM3U -#EXTINF:-1 tvg-id="MeteoMedia.ca",Meteomedia -http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="MeteoMedia.ca",Meteomedia +http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8 diff --git a/tests/__data__/input/api_generate/in.m3u b/tests/__data__/input/api_generate/in.m3u index 62594eb4bf..c375e17ace 100644 --- a/tests/__data__/input/api_generate/in.m3u +++ b/tests/__data__/input/api_generate/in.m3u @@ -1,3 +1,3 @@ -#EXTM3U -#EXTINF:-1 tvg-id="",Daawah TV -http://51.15.246.58:8081/daawahtv/daawahtv2/playlist.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="",Daawah TV +http://51.15.246.58:8081/daawahtv/daawahtv2/playlist.m3u8 diff --git a/tests/__data__/input/api_generate/uk.m3u b/tests/__data__/input/api_generate/uk.m3u index 5e8c7318e5..4a8a1f64ab 100644 --- a/tests/__data__/input/api_generate/uk.m3u +++ b/tests/__data__/input/api_generate/uk.m3u @@ -1,3 +1,3 @@ -#EXTM3U -#EXTINF:-1 tvg-id="BBCNews.uk",BBC News HD -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="BBCNews.uk",BBC News HD +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 diff --git a/tests/__data__/input/api_generate/unsorted.m3u b/tests/__data__/input/api_generate/unsorted.m3u index 1a9c40b9fd..96f9299e2d 100644 --- a/tests/__data__/input/api_generate/unsorted.m3u +++ b/tests/__data__/input/api_generate/unsorted.m3u @@ -1,9 +1,9 @@ -#EXTM3U -#EXTINF:-1 tvg-id="LDPRTV.ru",ЛДПР ТВ (1080p) -http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8 -#EXTINF:-1 tvg-id="VisitXTV.nl",Visit-X TV -https://stream.visit-x.tv/vxtv/ngrp:live_all/30fps.m3u8 -#EXTINF:-1 tvg-id="" user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",Andorra TV (720p) [Not 24/7] -#EXTVLCOPT:http-referrer=http://imn.iq -#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="LDPRTV.ru",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8 +#EXTINF:-1 tvg-id="VisitXTV.nl",Visit-X TV +https://stream.visit-x.tv/vxtv/ngrp:live_all/30fps.m3u8 +#EXTINF:-1 tvg-id="" user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",Andorra TV (720p) [Not 24/7] +#EXTVLCOPT:http-referrer=http://imn.iq +#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8 diff --git a/tests/__data__/input/data/channels.json b/tests/__data__/input/data/channels.json index 3f57ffe05c..1a80abb8d1 100644 --- a/tests/__data__/input/data/channels.json +++ b/tests/__data__/input/data/channels.json @@ -4,8 +4,6 @@ "name": "Andorra TV", "network": null, "country": "AD", - "subdivision": null, - "city": null, "categories": [], "is_nsfw": false }, @@ -14,8 +12,6 @@ "name": "BBC News", "network": null, "country": "UK", - "subdivision": null, - "city": null, "categories": [ "news", "general" @@ -27,8 +23,6 @@ "name": "Eve", "network": null, "country": "US", - "subdivision": null, - "city": null, "categories": [], "is_nsfw": false }, @@ -37,8 +31,6 @@ "name": "Everyday Heroes", "network": null, "country": "US", - "subdivision": null, - "city": null, "categories": [], "is_nsfw": false }, @@ -47,8 +39,6 @@ "name": "Fox Sports 1", "network": null, "country": "US", - "subdivision": null, - "city": null, "categories": [], "is_nsfw": false }, @@ -57,8 +47,6 @@ "name": "Fox Sports 2", "network": null, "country": "US", - "subdivision": null, - "city": null, "categories": [], "is_nsfw": false }, @@ -67,8 +55,6 @@ "name": "LDPR TV", "network": null, "country": "RU", - "subdivision": null, - "city": null, "categories": [ "general" ], @@ -79,8 +65,6 @@ "name": "Libyas Channel", "network": null, "country": "LY", - "subdivision": null, - "city": null, "categories": [], "is_nsfw": false }, @@ -89,8 +73,6 @@ "name": "MétéoMédia", "network": null, "country": "CA", - "subdivision": null, - "city": null, "categories": [ "weather" ], @@ -101,8 +83,6 @@ "name": "TVN", "network": null, "country": "PL", - "subdivision": null, - "city": null, "categories": [], "is_nsfw": false }, @@ -111,8 +91,6 @@ "name": "Visit-X TV", "network": null, "country": "NL", - "subdivision": null, - "city": null, "categories": [ "xxx" ], @@ -123,8 +101,6 @@ "name": "TUTV", "network": null, "country": "US", - "subdivision": null, - "city": null, "categories": [ "general" ], @@ -139,8 +115,6 @@ "Malayala Manorama Group" ], "country": "IN", - "subdivision": null, - "city": null, "categories": [ "news" ], @@ -157,8 +131,6 @@ "network": null, "owners": [], "country": "MY", - "subdivision": null, - "city": null, "categories": [ "news" ], @@ -175,8 +147,6 @@ "network": null, "owners": [], "country": "US", - "subdivision": null, - "city": null, "categories": [ "news" ], @@ -195,8 +165,6 @@ "Grupo ATV" ], "country": "PE", - "subdivision": "PE-LIM", - "city": "Lima", "categories": [ "news" ], @@ -213,8 +181,6 @@ "network": null, "owners": [], "country": "UK", - "subdivision": null, - "city": "London", "categories": [ "series" ], @@ -235,8 +201,6 @@ "AT-X Inc" ], "country": "JP", - "subdivision": null, - "city": "Tokyo", "categories": [ "animation" ], @@ -255,8 +219,6 @@ "Living Media" ], "country": "IN", - "subdivision": null, - "city": "Noida", "categories": [ "news" ], @@ -273,8 +235,6 @@ "network": null, "owners": [], "country": "JP", - "subdivision": null, - "city": null, "categories": [ "weather" ], @@ -293,8 +253,6 @@ "Meth Lanka Private Limited" ], "country": "LK", - "subdivision": null, - "city": "Athurugiriya", "categories": [ "religious" ], @@ -311,8 +269,6 @@ "network": null, "owners": [], "country": "HU", - "subdivision": null, - "city": null, "categories": [ "sports" ], @@ -334,8 +290,6 @@ "MotorTrend" ], "country": "US", - "subdivision": null, - "city": null, "categories": [], "is_nsfw": false, "launched": "2022-10-26", @@ -354,8 +308,6 @@ "Ministry of Finance" ], "country": "TH", - "subdivision": null, - "city": "Bangkok", "categories": [ "general" ], @@ -376,8 +328,6 @@ "Amarin Television" ], "country": "TH", - "subdivision": null, - "city": "Bangkok", "categories": [ "entertainment" ], @@ -396,8 +346,6 @@ "France Télévisions" ], "country": "FR", - "subdivision": null, - "city": "Paris", "categories": [ "general" ], @@ -416,8 +364,6 @@ "France Télévisions" ], "country": "FR", - "subdivision": null, - "city": "Paris", "categories": [ "general" ], @@ -436,8 +382,6 @@ "France Télévisions" ], "country": "FR", - "subdivision": null, - "city": "Paris", "categories": [ "general" ], @@ -456,8 +400,6 @@ "France Télévisions" ], "country": "FR", - "subdivision": null, - "city": "Paris", "categories": [ "general" ], @@ -476,8 +418,6 @@ "network": null, "owners": [], "country": "FR", - "subdivision": null, - "city": null, "categories": [ "entertainment" ], @@ -498,8 +438,6 @@ "TF1 Group" ], "country": "FR", - "subdivision": null, - "city": null, "categories": [ "movies" ], @@ -518,8 +456,6 @@ "Groupe TF1" ], "country": "FR", - "subdivision": null, - "city": null, "categories": [ "general" ], @@ -536,8 +472,6 @@ "network": null, "owners": [], "country": "FR", - "subdivision": null, - "city": null, "categories": [], "is_nsfw": false, "launched": null, @@ -554,8 +488,6 @@ "Malayala Manorama Group" ], "country": "IN", - "subdivision": null, - "city": "Kottayam", "categories": [ "news" ], @@ -574,8 +506,6 @@ "NBCUniversal" ], "country": "AU", - "subdivision": null, - "city": "New York City", "categories": [ "entertainment" ], @@ -590,8 +520,6 @@ "name": "Zoo", "network": null, "country": "CA", - "subdivision": null, - "city": null, "categories": [], "is_nsfw": false }, @@ -600,8 +528,6 @@ "name": "Duna World", "network": null, "country": "HU", - "subdivision": null, - "city": null, "categories": [ "General" ], @@ -622,15 +548,6 @@ "ElTR" ], "country": "KG", - "subdivision": null, - "city": "Bishkek", - "broadcast_area": [ - "r/CAS" - ], - "languages": [ - "kir", - "rus" - ], "categories": [ "general" ], @@ -645,8 +562,6 @@ "name": "ION TV", "network": null, "country": "US", - "subdivision": null, - "city": null, "categories": [], "is_nsfw": false }, @@ -655,8 +570,6 @@ "name": "NPO 1", "network": null, "country": "NL", - "subdivision": null, - "city": null, "categories": [], "is_nsfw": false }, @@ -665,8 +578,6 @@ "name": "NPO 2", "network": null, "country": "NL", - "subdivision": null, - "city": null, "categories": [], "is_nsfw": false }, @@ -675,8 +586,6 @@ "name": "5AAB TV", "network": null, "country": "CA", - "subdivision": null, - "city": null, "categories": [], "is_nsfw": false } diff --git a/tests/__data__/input/data/feeds.json b/tests/__data__/input/data/feeds.json index 1e28c47404..55dc9d1a7d 100644 --- a/tests/__data__/input/data/feeds.json +++ b/tests/__data__/input/data/feeds.json @@ -841,5 +841,21 @@ ], "languages": [], "video_format": "576i" + }, + { + "channel": "NPO2.nl", + "id": "SD", + "name": "SD", + "is_main": true, + "broadcast_area": [ + "c/CY" + ], + "languages": [ + "tur" + ], + "timezones": [ + "America/Port_of_Spain" + ], + "video_format": "576i" } ] \ No newline at end of file diff --git a/tests/__data__/input/issues.js b/tests/__data__/input/issues.js index af111b9b72..cbb6a79091 100644 --- a/tests/__data__/input/issues.js +++ b/tests/__data__/input/issues.js @@ -1,2397 +1,2397 @@ -module.exports = [ - { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/14140', - repository_url: 'https://api.github.com/repos/iptv-org/iptv', - labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14140/labels{/name}', - comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14140/comments', - events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14140/events', - html_url: 'https://github.com/iptv-org/iptv/issues/14140', - id: 1881649602, - node_id: 'I_kwDOCWUK8M5wJ7HC', - number: 14140, - title: 'Broken: RIK HD Cyprus', - user: { - login: 'ROBGagn', - id: 124619576, - node_id: 'U_kgDOB22LOA', - avatar_url: 'https://avatars.githubusercontent.com/u/124619576?v=4', - gravatar_id: '', - url: 'https://api.github.com/users/ROBGagn', - html_url: 'https://github.com/ROBGagn', - followers_url: 'https://api.github.com/users/ROBGagn/followers', - following_url: 'https://api.github.com/users/ROBGagn/following{/other_user}', - gists_url: 'https://api.github.com/users/ROBGagn/gists{/gist_id}', - starred_url: 'https://api.github.com/users/ROBGagn/starred{/owner}{/repo}', - subscriptions_url: 'https://api.github.com/users/ROBGagn/subscriptions', - organizations_url: 'https://api.github.com/users/ROBGagn/orgs', - repos_url: 'https://api.github.com/users/ROBGagn/repos', - events_url: 'https://api.github.com/users/ROBGagn/events{/privacy}', - received_events_url: 'https://api.github.com/users/ROBGagn/received_events', - type: 'User', - site_admin: false - }, - labels: [ - { - id: 1707513547, - node_id: 'MDU6TGFiZWwxNzA3NTEzNTQ3', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/broken%20stream', - name: 'broken stream', - color: 'FBCA04', - default: false, - description: 'Stream is not working properly' - }, - { - id: 3241837512, - node_id: 'MDU6TGFiZWwzMjQxODM3NTEy', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/CY', - name: 'CY', - color: '90FA7B', - default: false, - description: 'Cyprus' - } - ], - state: 'open', - locked: false, - assignee: null, - assignees: [], - milestone: null, - comments: 0, - created_at: '2023-09-05T10:09:04Z', - updated_at: '2023-09-07T00:50:06Z', - closed_at: null, - author_association: 'NONE', - active_lock_reason: null, - body: '### Broken Links\n\nhttp://l6.cloudskep.com/rikcy/rikhd/playlist.m3u8\r\nhttps://livestream.telvue.com/templeuni1/f7b44cfafd5c52223d5498196c8a2e7b.sdp/playlist.m3u8\n\n### What happened to the stream?\n\nNot loading\n\n### Possible Replacement (optional)\n\nhttp://l6.cloudskep.com/rikcy/rikhd/playlist2.m3u8\n\n### Notes (optional)\n\nToken needed...\r\nSame issue with RIK 1 and 2. May happen in the future with ANT1 Cyprus, Sigma and Omega.\n\n### Contributing Guide\n\n- [X] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md)', - reactions: { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/14140/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/iptv/issues/14140/timeline', - performed_via_github_app: null, - state_reason: null - }, - { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/14159', - repository_url: 'https://api.github.com/repos/iptv-org/iptv', - labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14159/labels{/name}', - comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14159/comments', - events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14159/events', - html_url: 'https://github.com/iptv-org/iptv/issues/14159', - id: 1881649602, - node_id: 'I_kwDOCWUK8M5wJ7HC', - number: 14159, - title: 'Broken: RIK HD Cyprus', - user: { - login: 'ROBGagn', - id: 124619576, - node_id: 'U_kgDOB22LOA', - avatar_url: 'https://avatars.githubusercontent.com/u/124619576?v=4', - gravatar_id: '', - url: 'https://api.github.com/users/ROBGagn', - html_url: 'https://github.com/ROBGagn', - followers_url: 'https://api.github.com/users/ROBGagn/followers', - following_url: 'https://api.github.com/users/ROBGagn/following{/other_user}', - gists_url: 'https://api.github.com/users/ROBGagn/gists{/gist_id}', - starred_url: 'https://api.github.com/users/ROBGagn/starred{/owner}{/repo}', - subscriptions_url: 'https://api.github.com/users/ROBGagn/subscriptions', - organizations_url: 'https://api.github.com/users/ROBGagn/orgs', - repos_url: 'https://api.github.com/users/ROBGagn/repos', - events_url: 'https://api.github.com/users/ROBGagn/events{/privacy}', - received_events_url: 'https://api.github.com/users/ROBGagn/received_events', - type: 'User', - site_admin: false - }, - labels: [ - { - id: 1707513547, - node_id: 'MDU6TGFiZWwxNzA3NTEzNTQ3', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/broken%20stream', - name: 'broken stream', - color: 'FBCA04', - default: false, - description: 'Stream is not working properly' - }, - { - id: 3241837512, - node_id: 'MDU6TGFiZWwzMjQxODM3NTEy', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/CY', - name: 'CY', - color: '90FA7B', - default: false, - description: 'Cyprus' - } - ], - state: 'open', - locked: false, - assignee: null, - assignees: [], - milestone: null, - comments: 0, - created_at: '2023-09-05T10:09:04Z', - updated_at: '2023-09-07T00:50:06Z', - closed_at: null, - author_association: 'NONE', - active_lock_reason: null, - body: '### Broken Links\n\nhttps://livestream.telvue.com/templeuni1/f7b44cfafd5c52223d5498196c8a2e7b.sdp/playlist.m3u8\r\nhttps://livestream.telvue.com/templeuni1/f7b44cfafd5c52223d5498196c8a2e7b.sdp/playlist.m3u8\n\n### What happened to the stream?\n\nNot loading\n\n### Possible Replacement (optional)\n\nhttp://l6.cloudskep.com/rikcy/rikhd/playlist2.m3u8\n\n### Notes (optional)\n\nToken needed...\r\nSame issue with RIK 1 and 2. May happen in the future with ANT1 Cyprus, Sigma and Omega.\n\n### Contributing Guide\n\n- [X] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md)', - reactions: { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/14159/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/iptv/issues/14159/timeline', - performed_via_github_app: null, - state_reason: null - }, - { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/19956', - repository_url: 'https://api.github.com/repos/iptv-org/iptv', - labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/19956/labels{/name}', - comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/19956/comments', - events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/19956/events', - html_url: 'https://github.com/iptv-org/iptv/issues/19956', - id: 2880738344, - node_id: 'I_kwDOCWUK8M6rtJQo', - number: 19956, - title: 'Find: CNBCe.tr', - user: { - login: 'M3UDay', - id: 164743332, - node_id: 'U_kgDOCdHIpA', - avatar_url: 'https://avatars.githubusercontent.com/u/164743332?v=4', - gravatar_id: '', - url: 'https://api.github.com/users/M3UDay', - html_url: 'https://github.com/M3UDay', - followers_url: 'https://api.github.com/users/M3UDay/followers', - following_url: 'https://api.github.com/users/M3UDay/following{/other_user}', - gists_url: 'https://api.github.com/users/M3UDay/gists{/gist_id}', - starred_url: 'https://api.github.com/users/M3UDay/starred{/owner}{/repo}', - subscriptions_url: 'https://api.github.com/users/M3UDay/subscriptions', - organizations_url: 'https://api.github.com/users/M3UDay/orgs', - repos_url: 'https://api.github.com/users/M3UDay/repos', - events_url: 'https://api.github.com/users/M3UDay/events{/privacy}', - received_events_url: 'https://api.github.com/users/M3UDay/received_events', - type: 'User', - user_view_type: 'public', - site_admin: false - }, - labels: [ - { - id: 8197871093, - node_id: 'LA_kwDOCWUK8M8AAAAB6KGV9Q', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/channel%20search', - name: 'channel search', - color: 'eaeaea', - default: false, - description: 'Request to find a link to a channel stream' - } - ], - state: 'open', - locked: false, - assignee: null, - assignees: [], - milestone: null, - comments: 0, - created_at: '2025-02-26T08:43:49Z', - updated_at: '2025-02-26T08:43:49Z', - closed_at: null, - author_association: 'NONE', - sub_issues_summary: { total: 0, completed: 0, percent_completed: 0 }, - active_lock_reason: null, - body: '### Channel ID (required)\n\nCNBCe.tr\n\n### Notes\n\n_No response_', - closed_by: null, - reactions: { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/19956/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/iptv/issues/19956/timeline', - performed_via_github_app: null, - state_reason: null - }, - { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/14179', - repository_url: 'https://api.github.com/repos/iptv-org/iptv', - labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14179/labels{/name}', - comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14179/comments', - events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14179/events', - html_url: 'https://github.com/iptv-org/iptv/issues/14179', - id: 1884926953, - node_id: 'I_kwDOCWUK8M5wWbPp', - number: 14179, - title: 'Add: Manorama News', - 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', - site_admin: false - }, - labels: [ - { - id: 1694119113, - node_id: 'MDU6TGFiZWwxNjk0MTE5MTEz', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/IN', - name: 'IN', - color: 'd8139a', - default: false, - description: 'India' - }, - { - id: 5923508587, - node_id: 'LA_kwDOCWUK8M8AAAABYRGRaw', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/streams:add', - name: 'streams:add', - color: '017ff9', - default: false, - description: 'Request to add a new link to a playlist' - } - ], - state: 'open', - locked: false, - assignee: null, - assignees: [], - milestone: null, - comments: 0, - created_at: '2023-09-07T00:38:55Z', - updated_at: '2023-09-07T00:48:32Z', - closed_at: null, - author_association: 'COLLABORATOR', - active_lock_reason: null, - body: '### Stream ID\n\nManoramaNews.in\n\n### Stream URL\n\nhttps://ythls.onrender.com/channel/UCP0uG-mcMImgKnJz-VjJZmQ.m3u8\n\n### Label\n\nNot 24/7\n\n### Notes (optional)\n\nSource: https://github.com/iptv-org/iptv/issues/14007#issuecomment-1686942043\n\n### Contributing Guide\n\n- [X] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md)', - reactions: { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/14179/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/iptv/issues/14179/timeline', - performed_via_github_app: null, - state_reason: null - }, - { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/14178', - repository_url: 'https://api.github.com/repos/iptv-org/iptv', - labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14178/labels{/name}', - comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14178/comments', - events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14178/events', - html_url: 'https://github.com/iptv-org/iptv/issues/14178', - id: 1884922249, - node_id: 'I_kwDOCWUK8M5wWaGJ', - number: 14178, - title: 'Add: TV3', - 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', - site_admin: false - }, - labels: [ - { - id: 1912922147, - node_id: 'MDU6TGFiZWwxOTEyOTIyMTQ3', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/MY', - name: 'MY', - color: 'ea59cf', - default: false, - description: 'Malaysia' - }, - { - id: 5923508587, - node_id: 'LA_kwDOCWUK8M8AAAABYRGRaw', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/streams:add', - name: 'streams:add', - color: '017ff9', - default: false, - description: 'Request to add a new link to a playlist' - } - ], - state: 'open', - locked: false, - assignee: null, - assignees: [], - milestone: null, - comments: 1, - created_at: '2023-09-07T00:30:51Z', - updated_at: '2023-09-07T00:48:23Z', - closed_at: null, - author_association: 'COLLABORATOR', - active_lock_reason: null, - body: '### Stream ID\n\nTV3.my\n\n### Stream URL\n\nhttps://live-streams-ssai-01.tonton.com.my/live/2dd2b7cd-1b34-4871-b669-57b5c9beca23/live.isml/.m3u8\n\n### Label\n\nNone\n\n### Notes (optional)\n\nSource: https://github.com/iptv-org/iptv/issues/14063#issuecomment-1695783106\n\n### Contributing Guide\n\n- [X] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md)', - reactions: { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/14178/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/iptv/issues/14178/timeline', - performed_via_github_app: null, - state_reason: null - }, - { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/14177', - repository_url: 'https://api.github.com/repos/iptv-org/iptv', - labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14177/labels{/name}', - comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14177/comments', - events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14177/events', - html_url: 'https://github.com/iptv-org/iptv/issues/14177', - id: 1884920274, - node_id: 'I_kwDOCWUK8M5wWZnS', - number: 14177, - title: 'Add: Temple University TV', - 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', - site_admin: false - }, - labels: [ - { - id: 1694118251, - node_id: 'MDU6TGFiZWwxNjk0MTE4MjUx', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/US', - name: 'US', - color: '463faa', - default: false, - description: 'United States' - }, - { - id: 5923508587, - node_id: 'LA_kwDOCWUK8M8AAAABYRGRaw', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/streams:add', - name: 'streams:add', - color: '017ff9', - default: false, - description: 'Request to add a new link to a playlist' - } - ], - state: 'open', - locked: false, - assignee: null, - assignees: [], - milestone: null, - comments: 1, - created_at: '2023-09-07T00:27:51Z', - updated_at: '2023-09-07T00:47:15Z', - closed_at: null, - author_association: 'COLLABORATOR', - active_lock_reason: null, - body: '### Stream ID\n\nTUTV.us\n\n### Stream URL\n\nhttps://livestream.telvue.com/templeuni1/f7b44cfafd5c52223d5498196c8a2e7b.sdp/playlist.m3u8\n\n### Label\n\nNone\n\n### Notes (optional)\n\nSource: https://github.com/iptv-org/iptv/issues/14096#issue-1874505679\n\n### Contributing Guide\n\n- [X] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md)', - reactions: { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/14177/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/iptv/issues/14177/timeline', - performed_via_github_app: null, - state_reason: null - }, - { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/14175', - repository_url: 'https://api.github.com/repos/iptv-org/iptv', - labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14175/labels{/name}', - comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14175/comments', - events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14175/events', - html_url: 'https://github.com/iptv-org/iptv/issues/14175', - id: 1884859778, - node_id: 'I_kwDOCWUK8M5wWK2C', - number: 14175, - title: 'Add: TFX', - 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', - site_admin: false - }, - labels: [ - { - id: 1694117286, - node_id: 'MDU6TGFiZWwxNjk0MTE3Mjg2', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/FR', - name: 'FR', - color: 'f7ec1b', - default: false, - description: 'France' - }, - { - id: 5923498886, - node_id: 'LA_kwDOCWUK8M8AAAABYRFrhg', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/approved', - name: 'approved', - color: '85ddde', - default: false, - description: '' - }, - { - id: 5923508587, - node_id: 'LA_kwDOCWUK8M8AAAABYRGRaw', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/streams:add', - name: 'streams:add', - color: '017ff9', - default: false, - description: 'Request to add a new link to a playlist' - } - ], - state: 'open', - locked: false, - assignee: null, - assignees: [], - milestone: null, - comments: 1, - created_at: '2023-09-06T22:54:25Z', - updated_at: '2023-09-07T00:57:11Z', - closed_at: null, - author_association: 'COLLABORATOR', - active_lock_reason: null, - body: '### Stream ID\n\nTFX.fr\n\n### Stream URL\n\nhttps://stitcher-ipv4.pluto.tv/v1/stitch/embed/hls/channel/64c109a4798def0008a6e03e/master.m3u8?advertisingId={PSID}&appVersion=unknown&deviceDNT={TARGETOPT}&deviceId={PSID}&deviceLat=0&deviceLon=0&deviceMake=samsung&deviceModel=samsung&deviceType=samsung-tvplus&deviceVersion=unknown&embedPartner=samsung-tvplus&profileFloor=&profileLimit=&samsung_app_domain={APP_DOMAIN}&samsung_app_name={APP_NAME}&us_privacy=1YNY\n\n### Label\n\nNone\n\n### HTTP User Agent\n\nMozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1\n\n### HTTP Referrer\n\nhttps://pkpakiplay.xyz/\n\n### Notes (optional)\n\nSource: https://github.com/iptv-org/iptv-org.github.io/issues/1381\n\n### Contributing Guide\n\n- [X] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md)', - reactions: { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/14175/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/iptv/issues/14175/timeline', - performed_via_github_app: null, - state_reason: null - }, - { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/14179', - repository_url: 'https://api.github.com/repos/iptv-org/iptv', - labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14179/labels{/name}', - comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14179/comments', - events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14179/events', - html_url: 'https://github.com/iptv-org/iptv/issues/14179', - id: 1884926953, - node_id: 'I_kwDOCWUK8M5wWbPp', - number: 14179, - title: 'Add: Manorama News', - 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', - site_admin: false - }, - labels: [ - { - id: 1694119113, - node_id: 'MDU6TGFiZWwxNjk0MTE5MTEz', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/IN', - name: 'IN', - color: 'd8139a', - default: false, - description: 'India' - }, - { - id: 5923498886, - node_id: 'LA_kwDOCWUK8M8AAAABYRFrhg', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/approved', - name: 'approved', - color: '85ddde', - default: false, - description: '' - }, - { - id: 5923508587, - node_id: 'LA_kwDOCWUK8M8AAAABYRGRaw', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/streams:add', - name: 'streams:add', - color: '017ff9', - default: false, - description: 'Request to add a new link to a playlist' - } - ], - state: 'open', - locked: false, - assignee: null, - assignees: [], - milestone: null, - comments: 0, - created_at: '2023-09-07T00:38:55Z', - updated_at: '2023-09-07T00:48:32Z', - closed_at: null, - author_association: 'COLLABORATOR', - active_lock_reason: null, - body: '### Stream ID\n\nManoramaNews.in\n\n### Stream URL\n\n(https://mitelefe.com/Api/Videos/GetSourceUrl/694564/0/HLS / https://ssl.cloud.telefe.com/Api/Videos/GetSourceUrl/694564/0/HLS)\n\n### Label\n\nNot 24/7\n\n### Notes (optional)\n\nSource: https://github.com/iptv-org/iptv/issues/14007#issuecomment-1686942043\n\n### Contributing Guide\n\n- [X] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md)', - reactions: { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/14179/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/iptv/issues/14179/timeline', - performed_via_github_app: null, - state_reason: null - }, - { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/14135', - repository_url: 'https://api.github.com/repos/iptv-org/iptv', - labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14135/labels{/name}', - comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14135/comments', - events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14135/events', - html_url: 'https://github.com/iptv-org/iptv/issues/14135', - id: 1880165524, - node_id: 'I_kwDOCWUK8M5wEQyU', - number: 14135, - title: 'Add: BBC World News South Asia ', - user: { - login: 'kheohoanganh', - id: 128283995, - node_id: 'U_kgDOB6V1Ww', - avatar_url: 'https://avatars.githubusercontent.com/u/128283995?v=4', - gravatar_id: '', - url: 'https://api.github.com/users/kheohoanganh', - html_url: 'https://github.com/kheohoanganh', - followers_url: 'https://api.github.com/users/kheohoanganh/followers', - following_url: 'https://api.github.com/users/kheohoanganh/following{/other_user}', - gists_url: 'https://api.github.com/users/kheohoanganh/gists{/gist_id}', - starred_url: 'https://api.github.com/users/kheohoanganh/starred{/owner}{/repo}', - subscriptions_url: 'https://api.github.com/users/kheohoanganh/subscriptions', - organizations_url: 'https://api.github.com/users/kheohoanganh/orgs', - repos_url: 'https://api.github.com/users/kheohoanganh/repos', - events_url: 'https://api.github.com/users/kheohoanganh/events{/privacy}', - received_events_url: 'https://api.github.com/users/kheohoanganh/received_events', - type: 'User', - site_admin: false - }, - labels: [ - { - id: 1694116077, - node_id: 'MDU6TGFiZWwxNjk0MTE2MDc3', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/UK', - name: 'UK', - color: '99e5e5', - default: false, - description: 'United Kingdom' - }, - { - id: 5923498886, - node_id: 'LA_kwDOCWUK8M8AAAABYRFrhg', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/approved', - name: 'approved', - color: '85ddde', - default: false, - description: '' - }, - { - id: 5923508587, - node_id: 'LA_kwDOCWUK8M8AAAABYRGRaw', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/streams:add', - name: 'streams:add', - color: '017ff9', - default: false, - description: 'Request to add a new link to a playlist' - } - ], - state: 'open', - locked: false, - assignee: null, - assignees: [], - milestone: null, - comments: 1, - created_at: '2023-09-04T12:22:50Z', - updated_at: '2023-09-07T00:50:28Z', - closed_at: null, - author_association: 'NONE', - active_lock_reason: null, - body: '### Stream ID\n\nBBCWorldNews.uk@SouthAsia\n\n### Stream URL (optional)\n\nhttp://103.199.161.254/Content/bbcworld/Live/Channel%28BBCworld%29/Stream%2801%29/index.m3u8\n\n### Notes (optional)\n\n2 links for BBCWorldNewsSouthAsia.uk\r\nhttp://103.199.161.254/Content/bbcworld/Live/Channel%28BBCworld%29/Stream%2801%29/index.m3u8\r\nhttp://103.199.161.254/Content/bbcworld/Live/Channel%28BBCworld%29/Stream%2802%29/index.m3u8\n\n### Please confirm the following\n\n- [X] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md#request-a-channel)', - reactions: { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/14135/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/iptv/issues/14135/timeline', - performed_via_github_app: null, - state_reason: null - }, - { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/14105', - repository_url: 'https://api.github.com/repos/iptv-org/iptv', - labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14105/labels{/name}', - comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14105/comments', - events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14105/events', - html_url: 'https://github.com/iptv-org/iptv/issues/14105', - id: 1876637538, - node_id: 'I_kwDOCWUK8M5v2zdi', - number: 14105, - title: 'Add: Amarin TV (720p)', - user: { - login: 'Soponwit19997', - id: 142583084, - node_id: 'U_kgDOCH-lLA', - avatar_url: 'https://avatars.githubusercontent.com/u/142583084?v=4', - gravatar_id: '', - url: 'https://api.github.com/users/Soponwit19997', - html_url: 'https://github.com/Soponwit19997', - followers_url: 'https://api.github.com/users/Soponwit19997/followers', - following_url: 'https://api.github.com/users/Soponwit19997/following{/other_user}', - gists_url: 'https://api.github.com/users/Soponwit19997/gists{/gist_id}', - starred_url: 'https://api.github.com/users/Soponwit19997/starred{/owner}{/repo}', - subscriptions_url: 'https://api.github.com/users/Soponwit19997/subscriptions', - organizations_url: 'https://api.github.com/users/Soponwit19997/orgs', - repos_url: 'https://api.github.com/users/Soponwit19997/repos', - events_url: 'https://api.github.com/users/Soponwit19997/events{/privacy}', - received_events_url: 'https://api.github.com/users/Soponwit19997/received_events', - type: 'User', - site_admin: false - }, - labels: [ - { - id: 2990740232, - node_id: 'MDU6TGFiZWwyOTkwNzQwMjMy', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/TH', - name: 'TH', - color: 'B798EA', - default: false, - description: 'Thailand' - }, - { - id: 5923498886, - node_id: 'LA_kwDOCWUK8M8AAAABYRFrhg', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/approved', - name: 'approved', - color: '85ddde', - default: false, - description: '' - }, - { - id: 5923508587, - node_id: 'LA_kwDOCWUK8M8AAAABYRGRaw', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/streams:add', - name: 'streams:add', - color: '017ff9', - default: false, - description: 'Request to add a new link to a playlist' - } - ], - state: 'open', - locked: false, - assignee: null, - assignees: [], - milestone: null, - comments: 1, - created_at: '2023-09-01T03:08:05Z', - updated_at: '2023-09-06T14:19:50Z', - closed_at: null, - author_association: 'CONTRIBUTOR', - active_lock_reason: null, - body: '### Stream ID\n\nAmarinTV.th\n\n### Stream URL (optional)\n\nhttps://cdn6.goprimetime.info/feed/202306140918/chamarin/index.m3u8\n\n### Notes (optional)\n\n_No response_\n\n### Please confirm the following\n\n- [X] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md#request-a-channel)', - reactions: { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/14105/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/iptv/issues/14105/timeline', - performed_via_github_app: null, - state_reason: null - }, - { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/14104', - repository_url: 'https://api.github.com/repos/iptv-org/iptv', - labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14104/labels{/name}', - comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14104/comments', - events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14104/events', - html_url: 'https://github.com/iptv-org/iptv/issues/14104', - id: 1876636019, - node_id: 'I_kwDOCWUK8M5v2zFz', - number: 14104, - title: 'Add: MCOT HD (720p)', - user: { - login: 'Soponwit19997', - id: 142583084, - node_id: 'U_kgDOCH-lLA', - avatar_url: 'https://avatars.githubusercontent.com/u/142583084?v=4', - gravatar_id: '', - url: 'https://api.github.com/users/Soponwit19997', - html_url: 'https://github.com/Soponwit19997', - followers_url: 'https://api.github.com/users/Soponwit19997/followers', - following_url: 'https://api.github.com/users/Soponwit19997/following{/other_user}', - gists_url: 'https://api.github.com/users/Soponwit19997/gists{/gist_id}', - starred_url: 'https://api.github.com/users/Soponwit19997/starred{/owner}{/repo}', - subscriptions_url: 'https://api.github.com/users/Soponwit19997/subscriptions', - organizations_url: 'https://api.github.com/users/Soponwit19997/orgs', - repos_url: 'https://api.github.com/users/Soponwit19997/repos', - events_url: 'https://api.github.com/users/Soponwit19997/events{/privacy}', - received_events_url: 'https://api.github.com/users/Soponwit19997/received_events', - type: 'User', - site_admin: false - }, - labels: [ - { - id: 2990740232, - node_id: 'MDU6TGFiZWwyOTkwNzQwMjMy', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/TH', - name: 'TH', - color: 'B798EA', - default: false, - description: 'Thailand' - }, - { - id: 5923498886, - node_id: 'LA_kwDOCWUK8M8AAAABYRFrhg', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/approved', - name: 'approved', - color: '85ddde', - default: false, - description: '' - }, - { - id: 5923508587, - node_id: 'LA_kwDOCWUK8M8AAAABYRGRaw', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/streams:add', - name: 'streams:add', - color: '017ff9', - default: false, - description: 'Request to add a new link to a playlist' - } - ], - state: 'open', - locked: false, - assignee: null, - assignees: [], - milestone: null, - comments: 1, - created_at: '2023-09-01T03:05:56Z', - updated_at: '2023-09-06T14:21:02Z', - closed_at: null, - author_association: 'CONTRIBUTOR', - active_lock_reason: null, - body: '### Stream ID\n\nMCOTHD.th\n\n### Stream URL (optional)\n\nhttps://cdn6.goprimetime.info/feed/202306140918/chmcothd/index.m3u8\n\n### Notes (optional)\n\n_No response_\n\n### Please confirm the following\n\n- [X] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md#request-a-channel)', - reactions: { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/14104/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/iptv/issues/14104/timeline', - performed_via_github_app: null, - state_reason: null - }, - { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/14057', - repository_url: 'https://api.github.com/repos/iptv-org/iptv', - labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14057/labels{/name}', - comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14057/comments', - events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14057/events', - html_url: 'https://github.com/iptv-org/iptv/issues/14057', - id: 1868766252, - node_id: 'I_kwDOCWUK8M5vYxws', - number: 14057, - title: 'Add: MotorTrend Fast TV', - user: { - login: 'AudioNutz', - id: 28129911, - node_id: 'MDQ6VXNlcjI4MTI5OTEx', - avatar_url: 'https://avatars.githubusercontent.com/u/28129911?v=4', - gravatar_id: '', - url: 'https://api.github.com/users/AudioNutz', - html_url: 'https://github.com/AudioNutz', - followers_url: 'https://api.github.com/users/AudioNutz/followers', - following_url: 'https://api.github.com/users/AudioNutz/following{/other_user}', - gists_url: 'https://api.github.com/users/AudioNutz/gists{/gist_id}', - starred_url: 'https://api.github.com/users/AudioNutz/starred{/owner}{/repo}', - subscriptions_url: 'https://api.github.com/users/AudioNutz/subscriptions', - organizations_url: 'https://api.github.com/users/AudioNutz/orgs', - repos_url: 'https://api.github.com/users/AudioNutz/repos', - events_url: 'https://api.github.com/users/AudioNutz/events{/privacy}', - received_events_url: 'https://api.github.com/users/AudioNutz/received_events', - type: 'User', - site_admin: false - }, - labels: [ - { - id: 1694118251, - node_id: 'MDU6TGFiZWwxNjk0MTE4MjUx', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/US', - name: 'US', - color: '463faa', - default: false, - description: 'United States' - }, - { - id: 5923498886, - node_id: 'LA_kwDOCWUK8M8AAAABYRFrhg', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/approved', - name: 'approved', - color: '85ddde', - default: false, - description: '' - }, - { - id: 5923508587, - node_id: 'LA_kwDOCWUK8M8AAAABYRGRaw', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/streams:add', - name: 'streams:add', - color: '017ff9', - default: false, - description: 'Request to add a new link to a playlist' - } - ], - state: 'open', - locked: false, - assignee: null, - assignees: [], - milestone: null, - comments: 1, - created_at: '2023-08-28T01:23:43Z', - updated_at: '2023-09-06T13:44:17Z', - closed_at: null, - author_association: 'NONE', - active_lock_reason: null, - body: '### Stream ID\r\n\r\nFastTV.us\r\n\r\n### Stream URL (optional)\r\n\r\nhttps://3fa797d5.wurl.com/manifest/f36d25e7e52f1ba8d7e56eb859c636563214f541/T05PX01vdG9yVHJlbmRGYXN0VFZfSExT/b5e5e0e2-12b3-4312-93c9-c0a7c50b41ca/4.m3u8\r\n\r\n### Notes (optional)\r\n\r\nA free stream from MotorTrend TV\r\n\r\n### Please confirm the following\r\n\r\n- [X] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md#request-a-channel)', - reactions: { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/14057/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/iptv/issues/14057/timeline', - performed_via_github_app: null, - state_reason: null - }, - { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/14034', - repository_url: 'https://api.github.com/repos/iptv-org/iptv', - labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14034/labels{/name}', - comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14034/comments', - events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14034/events', - html_url: 'https://github.com/iptv-org/iptv/issues/14034', - id: 1863678726, - node_id: 'I_kwDOCWUK8M5vFXsG', - number: 14034, - title: 'Add: match 4(hu)', - user: { - login: 'erich1997', - id: 85035390, - node_id: 'MDQ6VXNlcjg1MDM1Mzkw', - avatar_url: 'https://avatars.githubusercontent.com/u/85035390?v=4', - gravatar_id: '', - url: 'https://api.github.com/users/erich1997', - html_url: 'https://github.com/erich1997', - followers_url: 'https://api.github.com/users/erich1997/followers', - following_url: 'https://api.github.com/users/erich1997/following{/other_user}', - gists_url: 'https://api.github.com/users/erich1997/gists{/gist_id}', - starred_url: 'https://api.github.com/users/erich1997/starred{/owner}{/repo}', - subscriptions_url: 'https://api.github.com/users/erich1997/subscriptions', - organizations_url: 'https://api.github.com/users/erich1997/orgs', - repos_url: 'https://api.github.com/users/erich1997/repos', - events_url: 'https://api.github.com/users/erich1997/events{/privacy}', - received_events_url: 'https://api.github.com/users/erich1997/received_events', - type: 'User', - site_admin: false - }, - labels: [ - { - id: 1696015170, - node_id: 'MDU6TGFiZWwxNjk2MDE1MTcw', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/HU', - name: 'HU', - color: 'e89bbf', - default: false, - description: 'Hungary' - }, - { - id: 5923498886, - node_id: 'LA_kwDOCWUK8M8AAAABYRFrhg', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/approved', - name: 'approved', - color: '85ddde', - default: false, - description: '' - }, - { - id: 5923508587, - node_id: 'LA_kwDOCWUK8M8AAAABYRGRaw', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/streams:add', - name: 'streams:add', - color: '017ff9', - default: false, - description: 'Request to add a new link to a playlist' - } - ], - state: 'open', - locked: false, - assignee: null, - assignees: [], - milestone: null, - comments: 1, - created_at: '2023-08-23T16:42:47Z', - updated_at: '2023-09-06T13:07:20Z', - closed_at: null, - author_association: 'NONE', - active_lock_reason: null, - body: '### Stream ID\n\nMatch4.hu\n\n### Stream URL (optional)\n\nhttp://194.76.186.33:8000/play/a04d/index.m3u8\n\n### Notes (optional)\n\n_No response_\n\n### Please confirm the following\n\n- [X] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md#request-a-channel)', - reactions: { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/14034/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/iptv/issues/14034/timeline', - performed_via_github_app: null, - state_reason: null - }, - { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/13964', - repository_url: 'https://api.github.com/repos/iptv-org/iptv', - labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/13964/labels{/name}', - comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/13964/comments', - events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/13964/events', - html_url: 'https://github.com/iptv-org/iptv/issues/13964', - id: 1857666538, - node_id: 'I_kwDOCWUK8M5uub3q', - number: 13964, - title: 'Add: Meth TV [LK] ', - user: { - login: 'Carlinhos027', - id: 111005658, - node_id: 'U_kgDOBp3P2g', - avatar_url: 'https://avatars.githubusercontent.com/u/111005658?v=4', - gravatar_id: '', - url: 'https://api.github.com/users/Carlinhos027', - html_url: 'https://github.com/Carlinhos027', - followers_url: 'https://api.github.com/users/Carlinhos027/followers', - following_url: 'https://api.github.com/users/Carlinhos027/following{/other_user}', - gists_url: 'https://api.github.com/users/Carlinhos027/gists{/gist_id}', - starred_url: 'https://api.github.com/users/Carlinhos027/starred{/owner}{/repo}', - subscriptions_url: 'https://api.github.com/users/Carlinhos027/subscriptions', - organizations_url: 'https://api.github.com/users/Carlinhos027/orgs', - repos_url: 'https://api.github.com/users/Carlinhos027/repos', - events_url: 'https://api.github.com/users/Carlinhos027/events{/privacy}', - received_events_url: 'https://api.github.com/users/Carlinhos027/received_events', - type: 'User', - site_admin: false - }, - labels: [ - { - id: 5432228583, - node_id: 'LA_kwDOCWUK8M8AAAABQ8k65w', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/not%2024/7', - name: 'not 24/7', - color: '40715B', - default: false, - description: '' - }, - { - id: 5641193949, - node_id: 'LA_kwDOCWUK8M8AAAABUD3J3Q', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/LK', - name: 'LK', - color: '0A59ED', - default: false, - description: 'Sri Lanka' - }, - { - id: 5923498886, - node_id: 'LA_kwDOCWUK8M8AAAABYRFrhg', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/approved', - name: 'approved', - color: '85ddde', - default: false, - description: '' - }, - { - id: 5923508587, - node_id: 'LA_kwDOCWUK8M8AAAABYRGRaw', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/streams:add', - name: 'streams:add', - color: '017ff9', - default: false, - description: 'Request to add a new link to a playlist' - } - ], - state: 'open', - locked: false, - assignee: null, - assignees: [], - milestone: null, - comments: 0, - created_at: '2023-08-19T10:31:37Z', - updated_at: '2023-09-07T11:25:16Z', - closed_at: null, - author_association: 'COLLABORATOR', - active_lock_reason: null, - body: '### Stream ID\n\nMethTV.lk\n\n### Stream URL (optional)\n\nhttps://ythls.onrender.com/channel/UC7kBHRaynsJMB6JcooGLTmA.m3u8\n\n### Notes (optional)\n\n720p / Not 24/7\n\n### Please confirm the following\n\n- [X] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md#request-a-channel)', - reactions: { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/13964/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/iptv/issues/13964/timeline', - performed_via_github_app: null, - state_reason: null - }, - { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/13893', - repository_url: 'https://api.github.com/repos/iptv-org/iptv', - labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/13893/labels{/name}', - comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/13893/comments', - events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/13893/events', - html_url: 'https://github.com/iptv-org/iptv/issues/13893', - id: 1850537350, - node_id: 'I_kwDOCWUK8M5uTPWG', - number: 13893, - title: 'Add: Weathernews (JPN) via YouTube', - user: { - login: 'arecki2', - id: 18574440, - node_id: 'MDQ6VXNlcjE4NTc0NDQw', - avatar_url: 'https://avatars.githubusercontent.com/u/18574440?v=4', - gravatar_id: '', - url: 'https://api.github.com/users/arecki2', - html_url: 'https://github.com/arecki2', - followers_url: 'https://api.github.com/users/arecki2/followers', - following_url: 'https://api.github.com/users/arecki2/following{/other_user}', - gists_url: 'https://api.github.com/users/arecki2/gists{/gist_id}', - starred_url: 'https://api.github.com/users/arecki2/starred{/owner}{/repo}', - subscriptions_url: 'https://api.github.com/users/arecki2/subscriptions', - organizations_url: 'https://api.github.com/users/arecki2/orgs', - repos_url: 'https://api.github.com/users/arecki2/repos', - events_url: 'https://api.github.com/users/arecki2/events{/privacy}', - received_events_url: 'https://api.github.com/users/arecki2/received_events', - type: 'User', - site_admin: false - }, - labels: [ - { - id: 1694117140, - node_id: 'MDU6TGFiZWwxNjk0MTE3MTQw', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/JP', - name: 'JP', - color: '350bdd', - default: false, - description: 'Japan' - }, - { - id: 5923498886, - node_id: 'LA_kwDOCWUK8M8AAAABYRFrhg', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/approved', - name: 'approved', - color: '85ddde', - default: false, - description: '' - }, - { - id: 5923508587, - node_id: 'LA_kwDOCWUK8M8AAAABYRGRaw', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/streams:add', - name: 'streams:add', - color: '017ff9', - default: false, - description: 'Request to add a new link to a playlist' - } - ], - state: 'open', - locked: false, - assignee: null, - assignees: [], - milestone: null, - comments: 2, - created_at: '2023-08-14T21:04:00Z', - updated_at: '2023-09-06T14:30:57Z', - closed_at: null, - author_association: 'NONE', - active_lock_reason: null, - body: "### Stream ID\n\nWeathernews.jp\n\n### Stream URL (optional)\n\nhttps://ythls.onrender.com/channel/UCNsidkYpIAQ4QaufptQBPHQ.m3u8\n\n### Notes (optional)\n\nLet's try them 😼\r\n\r\nI've just learned that they change streams for their TV broadcasts on YouTube every 3 hours, so even with additional streams they occasionally activate (such as now during Typhoon Lan), the YT API should manage to pick the correct feed in most cases 😜\r\n\r\nOtherwise, an advantage over the two streams that already are in the database is that the YT broadcasts are in 1080p (vs 720p).\n\n### Please confirm the following\n\n- [X] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md#request-a-channel)", - reactions: { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/13893/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/iptv/issues/13893/timeline', - performed_via_github_app: null, - state_reason: null - }, - { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/13881', - repository_url: 'https://api.github.com/repos/iptv-org/iptv', - labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/13881/labels{/name}', - comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/13881/comments', - events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/13881/events', - html_url: 'https://github.com/iptv-org/iptv/issues/13881', - id: 1848780631, - node_id: 'I_kwDOCWUK8M5uMidX', - number: 13881, - title: 'Add: Aaj Tak', - user: { - login: 'R4IN2007', - id: 83226646, - node_id: 'MDQ6VXNlcjgzMjI2NjQ2', - avatar_url: 'https://avatars.githubusercontent.com/u/83226646?v=4', - gravatar_id: '', - url: 'https://api.github.com/users/R4IN2007', - html_url: 'https://github.com/R4IN2007', - followers_url: 'https://api.github.com/users/R4IN2007/followers', - following_url: 'https://api.github.com/users/R4IN2007/following{/other_user}', - gists_url: 'https://api.github.com/users/R4IN2007/gists{/gist_id}', - starred_url: 'https://api.github.com/users/R4IN2007/starred{/owner}{/repo}', - subscriptions_url: 'https://api.github.com/users/R4IN2007/subscriptions', - organizations_url: 'https://api.github.com/users/R4IN2007/orgs', - repos_url: 'https://api.github.com/users/R4IN2007/repos', - events_url: 'https://api.github.com/users/R4IN2007/events{/privacy}', - received_events_url: 'https://api.github.com/users/R4IN2007/received_events', - type: 'User', - site_admin: false - }, - labels: [ - { - id: 1694119113, - node_id: 'MDU6TGFiZWwxNjk0MTE5MTEz', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/IN', - name: 'IN', - color: 'd8139a', - default: false, - description: 'India' - }, - { - id: 5923498886, - node_id: 'LA_kwDOCWUK8M8AAAABYRFrhg', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/approved', - name: 'approved', - color: '85ddde', - default: false, - description: '' - }, - { - id: 5923508587, - node_id: 'LA_kwDOCWUK8M8AAAABYRGRaw', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/streams:add', - name: 'streams:add', - color: '017ff9', - default: false, - description: 'Request to add a new link to a playlist' - } - ], - state: 'open', - locked: false, - assignee: null, - assignees: [], - milestone: null, - comments: 1, - created_at: '2023-08-13T23:23:28Z', - updated_at: '2023-09-06T14:32:15Z', - closed_at: null, - author_association: 'NONE', - active_lock_reason: null, - body: '### Stream ID\n\nAajTak.in\n\n### Stream URL (optional)\n\nhttps://feeds.intoday.in/aajtak/api/aajtakhd/master.m3u8\n\n### Notes (optional)\n\n_No response_\n\n### Please confirm the following\n\n- [X] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md#request-a-channel)', - reactions: { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/13881/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/iptv/issues/13881/timeline', - performed_via_github_app: null, - state_reason: null - }, - { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/13793', - repository_url: 'https://api.github.com/repos/iptv-org/iptv', - labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/13793/labels{/name}', - comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/13793/comments', - events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/13793/events', - html_url: 'https://github.com/iptv-org/iptv/issues/13793', - id: 1846716551, - node_id: 'I_kwDOCWUK8M5uEqiH', - number: 13793, - title: 'Add: AT-X (JPN)', - user: { - login: 'ZXArkin', - id: 21299971, - node_id: 'MDQ6VXNlcjIxMjk5OTcx', - avatar_url: 'https://avatars.githubusercontent.com/u/21299971?v=4', - gravatar_id: '', - url: 'https://api.github.com/users/ZXArkin', - html_url: 'https://github.com/ZXArkin', - followers_url: 'https://api.github.com/users/ZXArkin/followers', - following_url: 'https://api.github.com/users/ZXArkin/following{/other_user}', - gists_url: 'https://api.github.com/users/ZXArkin/gists{/gist_id}', - starred_url: 'https://api.github.com/users/ZXArkin/starred{/owner}{/repo}', - subscriptions_url: 'https://api.github.com/users/ZXArkin/subscriptions', - organizations_url: 'https://api.github.com/users/ZXArkin/orgs', - repos_url: 'https://api.github.com/users/ZXArkin/repos', - events_url: 'https://api.github.com/users/ZXArkin/events{/privacy}', - received_events_url: 'https://api.github.com/users/ZXArkin/received_events', - type: 'User', - site_admin: false - }, - labels: [ - { - id: 1694117140, - node_id: 'MDU6TGFiZWwxNjk0MTE3MTQw', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/JP', - name: 'JP', - color: '350bdd', - default: false, - description: 'Japan' - }, - { - id: 5923498886, - node_id: 'LA_kwDOCWUK8M8AAAABYRFrhg', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/approved', - name: 'approved', - color: '85ddde', - default: false, - description: '' - }, - { - id: 5923508587, - node_id: 'LA_kwDOCWUK8M8AAAABYRGRaw', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/streams:add', - name: 'streams:add', - color: '017ff9', - default: false, - description: 'Request to add a new link to a playlist' - } - ], - state: 'open', - locked: false, - assignee: null, - assignees: [], - milestone: null, - comments: 4, - created_at: '2023-08-11T12:11:28Z', - updated_at: '2023-09-06T14:17:56Z', - closed_at: null, - author_association: 'NONE', - active_lock_reason: null, - body: '### Stream ID\r\n\r\nATX.jp\r\n\r\n### Stream URL (optional)\r\n\r\nhttp://194.233.72.249:8080/AT-X/index.m3u8\r\n\r\n### Notes (optional)\r\n\r\n![AT-X_20230705_202525 551](https://github.com/iptv-org/iptv/assets/21299971/794c1cd4-fbe4-4b35-8a16-45127953ff65)\r\nThis is test AT-X channel JP without subs\r\n720 Quality\r\n\r\n### Please confirm the following\r\n\r\n- [X] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md#request-a-channel)', - reactions: { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/13793/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/iptv/issues/13793/timeline', - performed_via_github_app: null, - state_reason: null - }, - { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/13751', - repository_url: 'https://api.github.com/repos/iptv-org/iptv', - labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/13751/labels{/name}', - comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/13751/comments', - events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/13751/events', - html_url: 'https://github.com/iptv-org/iptv/issues/13751', - id: 1838199158, - node_id: 'I_kwDOCWUK8M5tkLF2', - number: 13751, - title: 'Add: Beano TV', - user: { - login: 'Ghani201', - id: 132144620, - node_id: 'U_kgDOB-Bd7A', - avatar_url: 'https://avatars.githubusercontent.com/u/132144620?v=4', - gravatar_id: '', - url: 'https://api.github.com/users/Ghani201', - html_url: 'https://github.com/Ghani201', - followers_url: 'https://api.github.com/users/Ghani201/followers', - following_url: 'https://api.github.com/users/Ghani201/following{/other_user}', - gists_url: 'https://api.github.com/users/Ghani201/gists{/gist_id}', - starred_url: 'https://api.github.com/users/Ghani201/starred{/owner}{/repo}', - subscriptions_url: 'https://api.github.com/users/Ghani201/subscriptions', - organizations_url: 'https://api.github.com/users/Ghani201/orgs', - repos_url: 'https://api.github.com/users/Ghani201/repos', - events_url: 'https://api.github.com/users/Ghani201/events{/privacy}', - received_events_url: 'https://api.github.com/users/Ghani201/received_events', - type: 'User', - site_admin: false - }, - labels: [ - { - id: 1694116077, - node_id: 'MDU6TGFiZWwxNjk0MTE2MDc3', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/UK', - name: 'UK', - color: '99e5e5', - default: false, - description: 'United Kingdom' - }, - { - id: 5923498886, - node_id: 'LA_kwDOCWUK8M8AAAABYRFrhg', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/approved', - name: 'approved', - color: '85ddde', - default: false, - description: '' - }, - { - id: 5923508587, - node_id: 'LA_kwDOCWUK8M8AAAABYRGRaw', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/streams:add', - name: 'streams:add', - color: '017ff9', - default: false, - description: 'Request to add a new link to a playlist' - } - ], - state: 'open', - locked: false, - assignee: null, - assignees: [], - milestone: null, - comments: 2, - created_at: '2023-08-06T12:54:59Z', - updated_at: '2023-09-06T14:40:01Z', - closed_at: null, - author_association: 'NONE', - active_lock_reason: null, - body: '### Stream ID\r\n\r\nBeanoTV.uk\r\n\r\n### Stream URL (optional)\r\n\r\nhttps://a5b4bacecd47433dad06d3189fc7422e.mediatailor.us-east-1.amazonaws.com/v1/manifest/04fd913bb278d8775298c26fdca9d9841f37601f/RakutenTV-eu_BeanoTV/b1f233d5-847c-437d-aa4f-f73e67a85323/2.m3u8|Referer="https://referer.xyz/"|User-Agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1"|Origin="https://origin.xyz"\r\n\r\n### Directives (optional)\r\n\r\n#EXTVLCOPT:http-referrer=http://imn.iq\r\n\r\n#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148\r\n\r\n#KODIPROP:inputstream=inputstream.adaptive\r\n\r\n#KODIPROP:inputstream.adaptive.manifest_type=mpd\r\n\r\n#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha\r\n\r\n#KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=13f2e056-53fe-4469-ba6d-999970dbe549&userToken=v9ZVSksv4S7rT55o10dmYNRa4asye3z05eWCFxD%2FFYIlTJEpuf6tF8asPcyQOFq0h5opS%2B6WoMxnshWkihpHq5qrdrBEZ69piE94J9Feh385snGOqK3PYO7tLLjxmsCAe%2B9%2BNnurSSO5RCAIRsL125nSj1eOR%2F1GSKOgGH80HK2FDLiePxPkeaAxuWzacNBB%2FqnIGGxfe3GlmN65cU9F8WEpKFDlaxW%2Fv3ZSLAp3%2BZEq1aZXJ6Oz%2Fi0diD0EybH7|Content-Type=application/octet-stream|R{SSM}|\r\n\r\n### Notes (optional)\r\n\r\n_No response_\r\n\r\n### Please confirm the following\r\n\r\n- [X] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md#request-a-channel)', - reactions: { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/13751/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/iptv/issues/13751/timeline', - performed_via_github_app: null, - state_reason: null - }, - { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/13715', - repository_url: 'https://api.github.com/repos/iptv-org/iptv', - labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/13715/labels{/name}', - comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/13715/comments', - events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/13715/events', - html_url: 'https://github.com/iptv-org/iptv/issues/13715', - id: 1835942409, - node_id: 'I_kwDOCWUK8M5tbkIJ', - number: 13715, - title: 'Add: ATV+ HD (Perú) [Linear Version of ATV+]', - user: { - login: 'R4IN2007', - id: 83226646, - node_id: 'MDQ6VXNlcjgzMjI2NjQ2', - avatar_url: 'https://avatars.githubusercontent.com/u/83226646?v=4', - gravatar_id: '', - url: 'https://api.github.com/users/R4IN2007', - html_url: 'https://github.com/R4IN2007', - followers_url: 'https://api.github.com/users/R4IN2007/followers', - following_url: 'https://api.github.com/users/R4IN2007/following{/other_user}', - gists_url: 'https://api.github.com/users/R4IN2007/gists{/gist_id}', - starred_url: 'https://api.github.com/users/R4IN2007/starred{/owner}{/repo}', - subscriptions_url: 'https://api.github.com/users/R4IN2007/subscriptions', - organizations_url: 'https://api.github.com/users/R4IN2007/orgs', - repos_url: 'https://api.github.com/users/R4IN2007/repos', - events_url: 'https://api.github.com/users/R4IN2007/events{/privacy}', - received_events_url: 'https://api.github.com/users/R4IN2007/received_events', - type: 'User', - site_admin: false - }, - labels: [ - { - id: 3046075919, - node_id: 'MDU6TGFiZWwzMDQ2MDc1OTE5', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/PE', - name: 'PE', - color: 'E78203', - default: false, - description: 'Peru' - }, - { - id: 5923498886, - node_id: 'LA_kwDOCWUK8M8AAAABYRFrhg', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/approved', - name: 'approved', - color: '85ddde', - default: false, - description: '' - }, - { - id: 5923508587, - node_id: 'LA_kwDOCWUK8M8AAAABYRGRaw', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/streams:add', - name: 'streams:add', - color: '017ff9', - default: false, - description: 'Request to add a new link to a playlist' - } - ], - state: 'open', - locked: false, - assignee: null, - assignees: [], - milestone: null, - comments: 2, - created_at: '2023-08-04T01:48:24Z', - updated_at: '2023-09-06T14:41:57Z', - closed_at: null, - author_association: 'NONE', - active_lock_reason: null, - body: '### Stream ID\n\nATVPlus.pe\n\n### Stream URL (optional)\n\nhttps://linear-258.frequency.stream/dist/vix/258/hls/master/playlist.m3u8\n\n### Notes (optional)\n\n(Linear Version & Streaming on VIX.com a spanish televisa-univision site) Might be geo-blocked or geo-locked because by removing /dist/vix/ the m3u8 link stops working #13703 \n\n### Please confirm the following\n\n- [X] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md#request-a-channel)', - reactions: { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/13715/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/iptv/issues/13715/timeline', - performed_via_github_app: null, - state_reason: null - }, - { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/14120', - repository_url: 'https://api.github.com/repos/iptv-org/iptv', - labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14120/labels{/name}', - comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14120/comments', - events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14120/events', - html_url: 'https://github.com/iptv-org/iptv/issues/14120', - id: 1884922249, - node_id: 'I_kwDOCWUK8M5wWaGJ', - number: 14120, - title: 'Edit: Tele2000', - 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', - site_admin: false - }, - labels: [ - { - id: 5923498886, - node_id: 'LA_kwDOCWUK8M8AAAABYRFrhg', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/approved', - name: 'approved', - color: '85ddde', - default: false, - description: '' - }, - { - id: 5923508587, - node_id: 'LA_kwDOCWUK8M8AAAABYRGRaw', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/streams:edit', - name: 'streams:edit', - color: '017ff9', - default: false, - description: 'Request to add a new link to a playlist' - } - ], - state: 'open', - locked: false, - assignee: null, - assignees: [], - milestone: null, - comments: 1, - created_at: '2023-09-07T00:30:51Z', - updated_at: '2023-09-07T00:48:23Z', - closed_at: null, - author_association: 'COLLABORATOR', - active_lock_reason: null, - body: '### Stream URL\n\nhttps://livestream.telvue.com/templeuni1/f7b44cfafd5c52223d5498196c8a2e7b.sdp/playlist.m3u8\n\n### Stream ID\n\nboo.us\n\n### Quality\n\n720p\n\n### Label\n\nGeo-blocked\n\n### HTTP User-Agent\n\nMozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36 Edge/12.246\n\n### HTTP Referrer\n\n_No response_\n\n### Notes\n\n_No response_\n\n### Contributing Guide\n\n- [X] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md)', - reactions: { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/14120/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/iptv/issues/14120/timeline', - performed_via_github_app: null, - state_reason: null - }, - { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/14110', - repository_url: 'https://api.github.com/repos/iptv-org/iptv', - labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14110/labels{/name}', - comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14110/comments', - events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14110/events', - html_url: 'https://github.com/iptv-org/iptv/issues/14110', - id: 1884922249, - node_id: 'I_kwDOCWUK8M5wWaGJ', - number: 14110, - title: 'Edit: Tele2000', - 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', - site_admin: false - }, - labels: [ - { - id: 5923498886, - node_id: 'LA_kwDOCWUK8M8AAAABYRFrhg', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/approved', - name: 'approved', - color: '85ddde', - default: false, - description: '' - }, - { - id: 5923508587, - node_id: 'LA_kwDOCWUK8M8AAAABYRGRaw', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/streams:edit', - name: 'streams:edit', - color: '017ff9', - default: false, - description: 'Request to add a new link to a playlist' - } - ], - state: 'open', - locked: false, - assignee: null, - assignees: [], - milestone: null, - comments: 1, - created_at: '2023-09-07T00:30:51Z', - updated_at: '2023-09-07T00:48:23Z', - closed_at: null, - author_association: 'COLLABORATOR', - active_lock_reason: null, - body: '### Stream URL (required)\n\nhttps://servilive.com:3126/live/tele2000live.m3u8\n\n### New Stream URL\n\nhttps://xui-backend.energeek.cl/live/9/playlist.m3u8?username=ZZDemoIPTVGH&password=mdo96EuqMkTR|Referer="https://referer.xyz/"|User-Agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1"|Origin="https://origin.xyz"\n\n### Stream ID\n\nBBCAmerica.us@East\n\n### Quality\n\n720p\n\n### Label\n\n~\n\n### HTTP User-Agent\n\nMozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36 Edge/12.246\n\n### HTTP Referrer\n\n~\n\n### Directives (optional)\r\n\r\n#EXTVLCOPT:http-referrer=http://imn.iq\r\n\r\n#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148\r\n\r\n#KODIPROP:inputstream=inputstream.adaptive\r\n\r\n#KODIPROP:inputstream.adaptive.manifest_type=mpd\r\n\r\n#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha\r\n\r\n#KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=13f2e056-53fe-4469-ba6d-999970dbe549&userToken=v9ZVSksv4S7rT55o10dmYNRa4asye3z05eWCFxD%2FFYIlTJEpuf6tF8asPcyQOFq0h5opS%2B6WoMxnshWkihpHq5qrdrBEZ69piE94J9Feh385snGOqK3PYO7tLLjxmsCAe%2B9%2BNnurSSO5RCAIRsL125nSj1eOR%2F1GSKOgGH80HK2FDLiePxPkeaAxuWzacNBB%2FqnIGGxfe3GlmN65cU9F8WEpKFDlaxW%2Fv3ZSLAp3%2BZEq1aZXJ6Oz%2Fi0diD0EybH7|Content-Type=application/octet-stream|R{SSM}|\n\n### Notes\n\n_No response_\n\n### Contributing Guide\n\n- [X] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md)', - reactions: { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/14110/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/iptv/issues/14110/timeline', - performed_via_github_app: null, - state_reason: null - }, - { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/14120', - repository_url: 'https://api.github.com/repos/iptv-org/iptv', - labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14120/labels{/name}', - comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14120/comments', - events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14120/events', - html_url: 'https://github.com/iptv-org/iptv/issues/14120', - id: 1884922249, - node_id: 'I_kwDOCWUK8M5wWaGJ', - number: 14120, - title: 'Edit: Tele2000', - 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', - site_admin: false - }, - labels: [ - { - id: 5923498886, - node_id: 'LA_kwDOCWUK8M8AAAABYRFrhg', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/approved', - name: 'approved', - color: '85ddde', - default: false, - description: '' - }, - { - id: 5923508587, - node_id: 'LA_kwDOCWUK8M8AAAABYRGRaw', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/streams:edit', - name: 'streams:edit', - color: '017ff9', - default: false, - description: 'Request to add a new link to a playlist' - } - ], - state: 'open', - locked: false, - assignee: null, - assignees: [], - milestone: null, - comments: 1, - created_at: '2023-09-07T00:30:51Z', - updated_at: '2023-09-07T00:48:23Z', - closed_at: null, - author_association: 'COLLABORATOR', - active_lock_reason: null, - body: '### Stream URL\n\nhttps://ythls.onrender.com/channel/UC40TUSUx490U5uR1lZt3Ajg.m3u8\n\n### Stream ID\n\n_No response_\n\n### Quality\n\nNone\n\n### Label\n\nNone\n\n### HTTP User-Agent\n\n_No response_\n\n### HTTP Referrer\n\n_No response_\n\n### Notes\n\n_No response_\n\n### Contributing Guide\n\n- [X] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md)', - reactions: { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/14120/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/iptv/issues/14120/timeline', - performed_via_github_app: null, - state_reason: null - }, - { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/14151', - repository_url: 'https://api.github.com/repos/iptv-org/iptv', - labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14151/labels{/name}', - comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14151/comments', - events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14151/events', - html_url: 'https://github.com/iptv-org/iptv/issues/14151', - id: 1884653836, - node_id: 'I_kwDOCWUK8M5wVYkM', - number: 14151, - title: 'Remove: VTV', - user: { - login: 'kaikyoofers', - id: 67206080, - node_id: 'MDQ6VXNlcjY3MjA2MDgw', - avatar_url: 'https://avatars.githubusercontent.com/u/67206080?v=4', - gravatar_id: '', - url: 'https://api.github.com/users/kaikyoofers', - html_url: 'https://github.com/kaikyoofers', - followers_url: 'https://api.github.com/users/kaikyoofers/followers', - following_url: 'https://api.github.com/users/kaikyoofers/following{/other_user}', - gists_url: 'https://api.github.com/users/kaikyoofers/gists{/gist_id}', - starred_url: 'https://api.github.com/users/kaikyoofers/starred{/owner}{/repo}', - subscriptions_url: 'https://api.github.com/users/kaikyoofers/subscriptions', - organizations_url: 'https://api.github.com/users/kaikyoofers/orgs', - repos_url: 'https://api.github.com/users/kaikyoofers/repos', - events_url: 'https://api.github.com/users/kaikyoofers/events{/privacy}', - received_events_url: 'https://api.github.com/users/kaikyoofers/received_events', - type: 'User', - site_admin: false - }, - labels: [ - { - id: 2043160604, - node_id: 'MDU6TGFiZWwyMDQzMTYwNjA0', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/BR', - name: 'BR', - color: 'ccdcff', - default: false, - description: 'Brazil' - }, - { - id: 5923498886, - node_id: 'LA_kwDOCWUK8M8AAAABYRFrhg', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/approved', - name: 'approved', - color: '85ddde', - default: false, - description: '' - }, - { - id: 5932506810, - node_id: 'LA_kwDOCWUK8M8AAAABYZreug', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/streams:remove', - name: 'streams:remove', - color: '5373a2', - default: false, - description: '' - } - ], - state: 'open', - locked: false, - assignee: null, - assignees: [], - milestone: null, - comments: 0, - created_at: '2023-09-06T19:51:43Z', - updated_at: '2023-09-07T00:48:57Z', - closed_at: null, - author_association: 'CONTRIBUTOR', - active_lock_reason: null, - body: '### Stream URL\n\nhttps://ythls.onrender.com/channel/UC40TUSUx490U5uR1lZt3Ajg.m3u8\n\n### What happened to the stream?\n\nNot loading\n\n### Notes (optional)\n\nOne link (VTV.br) is misspelled.\n\n### Contributing Guide\n\n- [x] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md)', - reactions: { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/14151/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/iptv/issues/14151/timeline', - performed_via_github_app: null, - state_reason: null - }, - { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/14150', - repository_url: 'https://api.github.com/repos/iptv-org/iptv', - labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14150/labels{/name}', - comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14150/comments', - events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14150/events', - html_url: 'https://github.com/iptv-org/iptv/issues/14140', - id: 1881649613, - node_id: 'I_kwDOCWUK8M5wJ7HC', - number: 14150, - title: 'Broken: Cyprus Channels', - user: { - login: 'ROBGagn', - id: 124619576, - node_id: 'U_kgDOB22LOA', - avatar_url: 'https://avatars.githubusercontent.com/u/124619576?v=4', - gravatar_id: '', - url: 'https://api.github.com/users/ROBGagn', - html_url: 'https://github.com/ROBGagn', - followers_url: 'https://api.github.com/users/ROBGagn/followers', - following_url: 'https://api.github.com/users/ROBGagn/following{/other_user}', - gists_url: 'https://api.github.com/users/ROBGagn/gists{/gist_id}', - starred_url: 'https://api.github.com/users/ROBGagn/starred{/owner}{/repo}', - subscriptions_url: 'https://api.github.com/users/ROBGagn/subscriptions', - organizations_url: 'https://api.github.com/users/ROBGagn/orgs', - repos_url: 'https://api.github.com/users/ROBGagn/repos', - events_url: 'https://api.github.com/users/ROBGagn/events{/privacy}', - received_events_url: 'https://api.github.com/users/ROBGagn/received_events', - type: 'User', - site_admin: false - }, - labels: [ - { - id: 1707513547, - node_id: 'MDU6TGFiZWwxNzA3NTEzNTQ3', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/broken%20stream', - name: 'broken stream', - color: 'FBCA04', - default: false, - description: 'Stream is not working properly' - }, - { - id: 3241837512, - node_id: 'MDU6TGFiZWwzMjQxODM3NTEy', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/CY', - name: 'CY', - color: '90FA7B', - default: false, - description: 'Cyprus' - }, - { - id: 5923498886, - node_id: 'LA_kwDOCWUK8M8AAAABYRFrhg', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/approved', - name: 'approved', - color: '85ddde', - default: false, - description: '' - }, - { - id: 5932506810, - node_id: 'LA_kwDOCWUK8M8AAAABYZreug', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/streams:remove', - name: 'streams:remove', - color: '5373a2', - default: false, - description: '' - } - ], - state: 'open', - locked: false, - assignee: null, - assignees: [], - milestone: null, - comments: 0, - created_at: '2023-09-05T10:09:04Z', - updated_at: '2023-09-07T00:50:06Z', - closed_at: null, - author_association: 'NONE', - active_lock_reason: null, - body: '### Stream URL\n\nhttp://l6.cloudskep.com/rikcy/rikhd/playlist.m3u8\r\n\r\nhttp://l6.cloudskep.com/rikcy/rik2/playlist.m3u8\n\n### What happened to the stream?\n\nNot loading\n\n### Possible Replacement (optional)\n\nhttp://l6.cloudskep.com/rikcy/rikhd/playlist2.m3u8\n\n### Notes (optional)\n\nToken needed...\r\nSame issue with RIK 1 and 2. May happen in the future with ANT1 Cyprus, Sigma and Omega.\n\n### Contributing Guide\n\n- [X] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md)', - reactions: { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/14150/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/iptv/issues/14150/timeline', - performed_via_github_app: null, - state_reason: null - }, - { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/16120', - repository_url: 'https://api.github.com/repos/iptv-org/iptv', - labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/16120/labels{/name}', - comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/16120/comments', - events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/16120/events', - html_url: 'https://github.com/iptv-org/iptv/issues/16120', - id: 1878180439, - node_id: 'I_kwDOCWUK8M5v8sJX', - number: 16120, - title: 'Broken: Canal 5 (MX)', - user: { - login: 'chris202020202020', - id: 141375812, - node_id: 'U_kgDOCG05RA', - avatar_url: 'https://avatars.githubusercontent.com/u/141375812?v=4', - gravatar_id: '', - url: 'https://api.github.com/users/chris202020202020', - html_url: 'https://github.com/chris202020202020', - followers_url: 'https://api.github.com/users/chris202020202020/followers', - following_url: 'https://api.github.com/users/chris202020202020/following{/other_user}', - gists_url: 'https://api.github.com/users/chris202020202020/gists{/gist_id}', - starred_url: 'https://api.github.com/users/chris202020202020/starred{/owner}{/repo}', - subscriptions_url: 'https://api.github.com/users/chris202020202020/subscriptions', - organizations_url: 'https://api.github.com/users/chris202020202020/orgs', - repos_url: 'https://api.github.com/users/chris202020202020/repos', - events_url: 'https://api.github.com/users/chris202020202020/events{/privacy}', - received_events_url: 'https://api.github.com/users/chris202020202020/received_events', - type: 'User', - site_admin: false - }, - labels: [ - { - id: 1707513547, - node_id: 'MDU6TGFiZWwxNzA3NTEzNTQ3', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/broken%20stream', - name: 'broken stream', - color: 'FBCA04', - default: false, - description: 'Stream is not working properly' - }, - { - id: 2980444955, - node_id: 'MDU6TGFiZWwyOTgwNDQ0OTU1', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/MX', - name: 'MX', - color: '02A7D1', - default: false, - description: 'Mexico' - }, - { - id: 5923498886, - node_id: 'LA_kwDOCWUK8M8AAAABYRFrhg', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/approved', - name: 'approved', - color: '85ddde', - default: false, - description: '' - }, - { - id: 5932506810, - node_id: 'LA_kwDOCWUK8M8AAAABYZreug', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/streams:remove', - name: 'streams:remove', - color: '5373a2', - default: false, - description: '' - } - ], - state: 'open', - locked: false, - assignee: null, - assignees: [], - milestone: null, - comments: 0, - created_at: '2023-09-01T23:49:28Z', - updated_at: '2023-09-07T00:24:05Z', - closed_at: null, - author_association: 'NONE', - active_lock_reason: null, - body: '### Stream URL\n\nhttp://190.61.102.67:2000/play/a038/index.m3u8\n\n### What happened to the stream?\n\nNot loading\n\n### Possible Replacement (optional)\n\n_No response_\n\n### Notes (optional)\n\nReplacement For A Broken Stream To A New Stream For Canal 5 (MX) Please\n\n### Please confirm the following\n\n- [X] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md#report-a-broken-stream)', - reactions: { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/16120/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/iptv/issues/16120/timeline', - performed_via_github_app: null, - state_reason: null - }, - { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/19957', - repository_url: 'https://api.github.com/repos/iptv-org/iptv', - labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/19957/labels{/name}', - comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/19957/comments', - events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/19957/events', - html_url: 'https://github.com/iptv-org/iptv/issues/19957', - id: 2880738344, - node_id: 'I_kwDOCWUK8M6rtJQo', - number: 19957, - title: 'Find: CNBCe.tr', - user: { - login: 'M3UDay', - id: 164743332, - node_id: 'U_kgDOCdHIpA', - avatar_url: 'https://avatars.githubusercontent.com/u/164743332?v=4', - gravatar_id: '', - url: 'https://api.github.com/users/M3UDay', - html_url: 'https://github.com/M3UDay', - followers_url: 'https://api.github.com/users/M3UDay/followers', - following_url: 'https://api.github.com/users/M3UDay/following{/other_user}', - gists_url: 'https://api.github.com/users/M3UDay/gists{/gist_id}', - starred_url: 'https://api.github.com/users/M3UDay/starred{/owner}{/repo}', - subscriptions_url: 'https://api.github.com/users/M3UDay/subscriptions', - organizations_url: 'https://api.github.com/users/M3UDay/orgs', - repos_url: 'https://api.github.com/users/M3UDay/repos', - events_url: 'https://api.github.com/users/M3UDay/events{/privacy}', - received_events_url: 'https://api.github.com/users/M3UDay/received_events', - type: 'User', - user_view_type: 'public', - site_admin: false - }, - labels: [ - { - id: 8197871093, - node_id: 'LA_kwDOCWUK8M8AAAAB6KGV9Q', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/channel%20search', - name: 'channel search', - color: 'eaeaea', - default: false, - description: 'Request to find a link to a channel stream' - } - ], - state: 'open', - locked: false, - assignee: null, - assignees: [], - milestone: null, - comments: 0, - created_at: '2025-02-26T08:43:49Z', - updated_at: '2025-02-26T08:43:49Z', - closed_at: null, - author_association: 'NONE', - sub_issues_summary: { total: 0, completed: 0, percent_completed: 0 }, - active_lock_reason: null, - body: '### Channel ID (required)\n\n13thStreet.au\n\n### Notes\n\n_No response_', - closed_by: null, - reactions: { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/19957/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/iptv/issues/19957/timeline', - performed_via_github_app: null, - state_reason: null - }, - { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/20956', - repository_url: 'https://api.github.com/repos/iptv-org/iptv', - labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/20956/labels{/name}', - comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/20956/comments', - events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/20956/events', - html_url: 'https://github.com/iptv-org/iptv/issues/20956', - id: 2880738444, - node_id: 'I_kwDOCWUK8M6rtJQo', - number: 20956, - title: 'Find: IONTV.us', - user: { - login: 'M3UDay', - id: 164743332, - node_id: 'U_kgDOCdHIpA', - avatar_url: 'https://avatars.githubusercontent.com/u/164743332?v=4', - gravatar_id: '', - url: 'https://api.github.com/users/M3UDay', - html_url: 'https://github.com/M3UDay', - followers_url: 'https://api.github.com/users/M3UDay/followers', - following_url: 'https://api.github.com/users/M3UDay/following{/other_user}', - gists_url: 'https://api.github.com/users/M3UDay/gists{/gist_id}', - starred_url: 'https://api.github.com/users/M3UDay/starred{/owner}{/repo}', - subscriptions_url: 'https://api.github.com/users/M3UDay/subscriptions', - organizations_url: 'https://api.github.com/users/M3UDay/orgs', - repos_url: 'https://api.github.com/users/M3UDay/repos', - events_url: 'https://api.github.com/users/M3UDay/events{/privacy}', - received_events_url: 'https://api.github.com/users/M3UDay/received_events', - type: 'User', - user_view_type: 'public', - site_admin: false - }, - labels: [ - { - id: 8197871093, - node_id: 'LA_kwDOCWUK8M8AAAAB6KGV9Q', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/channel%20search', - name: 'channel search', - color: 'eaeaea', - default: false, - description: 'Request to find a link to a channel stream' - } - ], - state: 'open', - locked: false, - assignee: null, - assignees: [], - milestone: null, - comments: 0, - created_at: '2025-02-26T08:43:49Z', - updated_at: '2025-02-26T08:43:49Z', - closed_at: null, - author_association: 'NONE', - sub_issues_summary: { total: 0, completed: 0, percent_completed: 0 }, - active_lock_reason: null, - body: '### Channel ID (required)\n\nIONTV.us\n\n### Notes\n\n_No response_', - closed_by: null, - reactions: { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/20956/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/iptv/issues/20956/timeline', - performed_via_github_app: null, - state_reason: null - }, - { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/25157', - repository_url: 'https://api.github.com/repos/iptv-org/iptv', - labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/25157/labels{/name}', - comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/25157/comments', - events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/25157/events', - html_url: 'https://github.com/iptv-org/iptv/issues/25157', - id: 3245640024, - node_id: 'I_kwDOCWUK8M7BdIlY', - number: 25157, - title: 'Add: OnTime Sports SD', - user: { - login: 'zezopm300', - id: 215159878, - node_id: 'U_kgDODNMURg', - avatar_url: 'https://avatars.githubusercontent.com/u/215159878?v=4', - gravatar_id: '', - url: 'https://api.github.com/users/zezopm300', - html_url: 'https://github.com/zezopm300', - followers_url: 'https://api.github.com/users/zezopm300/followers', - following_url: 'https://api.github.com/users/zezopm300/following{/other_user}', - gists_url: 'https://api.github.com/users/zezopm300/gists{/gist_id}', - starred_url: 'https://api.github.com/users/zezopm300/starred{/owner}{/repo}', - subscriptions_url: 'https://api.github.com/users/zezopm300/subscriptions', - organizations_url: 'https://api.github.com/users/zezopm300/orgs', - repos_url: 'https://api.github.com/users/zezopm300/repos', - events_url: 'https://api.github.com/users/zezopm300/events{/privacy}', - received_events_url: 'https://api.github.com/users/zezopm300/received_events', - type: 'User', - user_view_type: 'public', - site_admin: false - }, - labels: [ - { - id: 5923508587, - node_id: 'LA_kwDOCWUK8M8AAAABYRGRaw', - url: 'https://api.github.com/repos/iptv-org/iptv/labels/streams:add', - name: 'streams:add', - color: '017ff9', - default: false, - description: 'Request to add a new link to a playlist' - } - ], - state: 'open', - locked: false, - assignee: null, - assignees: [], - milestone: null, - comments: 0, - created_at: '2025-07-19T20:44:05Z', - updated_at: '2025-07-19T20:44:05Z', - closed_at: null, - author_association: 'NONE', - type: null, - active_lock_reason: null, - sub_issues_summary: { total: 0, completed: 0, percent_completed: 0 }, - body: - '### Stream ID (required)\n' + - '\n' + - 'OnTimeSports.eg@SD\n' + - '\n' + - '### Stream URL (required)\n' + - '\n' + - ' OnTime Sports SD.mu38\n' + - '\n' + - '### Quality\n' + - '\n' + - 'None\n' + - '\n' + - '### Label\n' + - '\n' + - 'None\n' + - '\n' + - '### HTTP User Agent\n' + - '\n' + - '_No response_\n' + - '\n' + - '### HTTP Referrer\n' + - '\n' + - '_No response_\n' + - '\n' + - '### Directives\n' + - '\n' + - '_No response_\n' + - '\n' + - '### Notes\n' + - '\n' + - '_No response_\n' + - '\n' + - '### Contributing Guide\n' + - '\n' + - '- [x] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md)', - closed_by: null, - reactions: { - url: 'https://api.github.com/repos/iptv-org/iptv/issues/25157/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/iptv/issues/25157/timeline', - performed_via_github_app: null, - state_reason: null - } -] +module.exports = [ + { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/14140', + repository_url: 'https://api.github.com/repos/iptv-org/iptv', + labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14140/labels{/name}', + comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14140/comments', + events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14140/events', + html_url: 'https://github.com/iptv-org/iptv/issues/14140', + id: 1881649602, + node_id: 'I_kwDOCWUK8M5wJ7HC', + number: 14140, + title: 'Broken: RIK HD Cyprus', + user: { + login: 'ROBGagn', + id: 124619576, + node_id: 'U_kgDOB22LOA', + avatar_url: 'https://avatars.githubusercontent.com/u/124619576?v=4', + gravatar_id: '', + url: 'https://api.github.com/users/ROBGagn', + html_url: 'https://github.com/ROBGagn', + followers_url: 'https://api.github.com/users/ROBGagn/followers', + following_url: 'https://api.github.com/users/ROBGagn/following{/other_user}', + gists_url: 'https://api.github.com/users/ROBGagn/gists{/gist_id}', + starred_url: 'https://api.github.com/users/ROBGagn/starred{/owner}{/repo}', + subscriptions_url: 'https://api.github.com/users/ROBGagn/subscriptions', + organizations_url: 'https://api.github.com/users/ROBGagn/orgs', + repos_url: 'https://api.github.com/users/ROBGagn/repos', + events_url: 'https://api.github.com/users/ROBGagn/events{/privacy}', + received_events_url: 'https://api.github.com/users/ROBGagn/received_events', + type: 'User', + site_admin: false + }, + labels: [ + { + id: 1707513547, + node_id: 'MDU6TGFiZWwxNzA3NTEzNTQ3', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/broken%20stream', + name: 'broken stream', + color: 'FBCA04', + default: false, + description: 'Stream is not working properly' + }, + { + id: 3241837512, + node_id: 'MDU6TGFiZWwzMjQxODM3NTEy', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/CY', + name: 'CY', + color: '90FA7B', + default: false, + description: 'Cyprus' + } + ], + state: 'open', + locked: false, + assignee: null, + assignees: [], + milestone: null, + comments: 0, + created_at: '2023-09-05T10:09:04Z', + updated_at: '2023-09-07T00:50:06Z', + closed_at: null, + author_association: 'NONE', + active_lock_reason: null, + body: '### Broken Links\n\nhttp://l6.cloudskep.com/rikcy/rikhd/playlist.m3u8\r\nhttps://livestream.telvue.com/templeuni1/f7b44cfafd5c52223d5498196c8a2e7b.sdp/playlist.m3u8\n\n### What happened to the stream?\n\nNot loading\n\n### Possible Replacement (optional)\n\nhttp://l6.cloudskep.com/rikcy/rikhd/playlist2.m3u8\n\n### Notes (optional)\n\nToken needed...\r\nSame issue with RIK 1 and 2. May happen in the future with ANT1 Cyprus, Sigma and Omega.\n\n### Contributing Guide\n\n- [X] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md)', + reactions: { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/14140/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/iptv/issues/14140/timeline', + performed_via_github_app: null, + state_reason: null + }, + { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/14159', + repository_url: 'https://api.github.com/repos/iptv-org/iptv', + labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14159/labels{/name}', + comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14159/comments', + events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14159/events', + html_url: 'https://github.com/iptv-org/iptv/issues/14159', + id: 1881649602, + node_id: 'I_kwDOCWUK8M5wJ7HC', + number: 14159, + title: 'Broken: RIK HD Cyprus', + user: { + login: 'ROBGagn', + id: 124619576, + node_id: 'U_kgDOB22LOA', + avatar_url: 'https://avatars.githubusercontent.com/u/124619576?v=4', + gravatar_id: '', + url: 'https://api.github.com/users/ROBGagn', + html_url: 'https://github.com/ROBGagn', + followers_url: 'https://api.github.com/users/ROBGagn/followers', + following_url: 'https://api.github.com/users/ROBGagn/following{/other_user}', + gists_url: 'https://api.github.com/users/ROBGagn/gists{/gist_id}', + starred_url: 'https://api.github.com/users/ROBGagn/starred{/owner}{/repo}', + subscriptions_url: 'https://api.github.com/users/ROBGagn/subscriptions', + organizations_url: 'https://api.github.com/users/ROBGagn/orgs', + repos_url: 'https://api.github.com/users/ROBGagn/repos', + events_url: 'https://api.github.com/users/ROBGagn/events{/privacy}', + received_events_url: 'https://api.github.com/users/ROBGagn/received_events', + type: 'User', + site_admin: false + }, + labels: [ + { + id: 1707513547, + node_id: 'MDU6TGFiZWwxNzA3NTEzNTQ3', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/broken%20stream', + name: 'broken stream', + color: 'FBCA04', + default: false, + description: 'Stream is not working properly' + }, + { + id: 3241837512, + node_id: 'MDU6TGFiZWwzMjQxODM3NTEy', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/CY', + name: 'CY', + color: '90FA7B', + default: false, + description: 'Cyprus' + } + ], + state: 'open', + locked: false, + assignee: null, + assignees: [], + milestone: null, + comments: 0, + created_at: '2023-09-05T10:09:04Z', + updated_at: '2023-09-07T00:50:06Z', + closed_at: null, + author_association: 'NONE', + active_lock_reason: null, + body: '### Broken Links\n\nhttps://livestream.telvue.com/templeuni1/f7b44cfafd5c52223d5498196c8a2e7b.sdp/playlist.m3u8\r\nhttps://livestream.telvue.com/templeuni1/f7b44cfafd5c52223d5498196c8a2e7b.sdp/playlist.m3u8\n\n### What happened to the stream?\n\nNot loading\n\n### Possible Replacement (optional)\n\nhttp://l6.cloudskep.com/rikcy/rikhd/playlist2.m3u8\n\n### Notes (optional)\n\nToken needed...\r\nSame issue with RIK 1 and 2. May happen in the future with ANT1 Cyprus, Sigma and Omega.\n\n### Contributing Guide\n\n- [X] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md)', + reactions: { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/14159/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/iptv/issues/14159/timeline', + performed_via_github_app: null, + state_reason: null + }, + { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/19956', + repository_url: 'https://api.github.com/repos/iptv-org/iptv', + labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/19956/labels{/name}', + comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/19956/comments', + events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/19956/events', + html_url: 'https://github.com/iptv-org/iptv/issues/19956', + id: 2880738344, + node_id: 'I_kwDOCWUK8M6rtJQo', + number: 19956, + title: 'Find: CNBCe.tr', + user: { + login: 'M3UDay', + id: 164743332, + node_id: 'U_kgDOCdHIpA', + avatar_url: 'https://avatars.githubusercontent.com/u/164743332?v=4', + gravatar_id: '', + url: 'https://api.github.com/users/M3UDay', + html_url: 'https://github.com/M3UDay', + followers_url: 'https://api.github.com/users/M3UDay/followers', + following_url: 'https://api.github.com/users/M3UDay/following{/other_user}', + gists_url: 'https://api.github.com/users/M3UDay/gists{/gist_id}', + starred_url: 'https://api.github.com/users/M3UDay/starred{/owner}{/repo}', + subscriptions_url: 'https://api.github.com/users/M3UDay/subscriptions', + organizations_url: 'https://api.github.com/users/M3UDay/orgs', + repos_url: 'https://api.github.com/users/M3UDay/repos', + events_url: 'https://api.github.com/users/M3UDay/events{/privacy}', + received_events_url: 'https://api.github.com/users/M3UDay/received_events', + type: 'User', + user_view_type: 'public', + site_admin: false + }, + labels: [ + { + id: 8197871093, + node_id: 'LA_kwDOCWUK8M8AAAAB6KGV9Q', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/channel%20search', + name: 'channel search', + color: 'eaeaea', + default: false, + description: 'Request to find a link to a channel stream' + } + ], + state: 'open', + locked: false, + assignee: null, + assignees: [], + milestone: null, + comments: 0, + created_at: '2025-02-26T08:43:49Z', + updated_at: '2025-02-26T08:43:49Z', + closed_at: null, + author_association: 'NONE', + sub_issues_summary: { total: 0, completed: 0, percent_completed: 0 }, + active_lock_reason: null, + body: '### Channel ID (required)\n\nCNBCe.tr\n\n### Notes\n\n_No response_', + closed_by: null, + reactions: { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/19956/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/iptv/issues/19956/timeline', + performed_via_github_app: null, + state_reason: null + }, + { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/14179', + repository_url: 'https://api.github.com/repos/iptv-org/iptv', + labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14179/labels{/name}', + comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14179/comments', + events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14179/events', + html_url: 'https://github.com/iptv-org/iptv/issues/14179', + id: 1884926953, + node_id: 'I_kwDOCWUK8M5wWbPp', + number: 14179, + title: 'Add: Manorama News', + 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', + site_admin: false + }, + labels: [ + { + id: 1694119113, + node_id: 'MDU6TGFiZWwxNjk0MTE5MTEz', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/IN', + name: 'IN', + color: 'd8139a', + default: false, + description: 'India' + }, + { + id: 5923508587, + node_id: 'LA_kwDOCWUK8M8AAAABYRGRaw', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/streams:add', + name: 'streams:add', + color: '017ff9', + default: false, + description: 'Request to add a new link to a playlist' + } + ], + state: 'open', + locked: false, + assignee: null, + assignees: [], + milestone: null, + comments: 0, + created_at: '2023-09-07T00:38:55Z', + updated_at: '2023-09-07T00:48:32Z', + closed_at: null, + author_association: 'COLLABORATOR', + active_lock_reason: null, + body: '### Stream ID\n\nManoramaNews.in\n\n### Stream URL\n\nhttps://ythls.onrender.com/channel/UCP0uG-mcMImgKnJz-VjJZmQ.m3u8\n\n### Label\n\nNot 24/7\n\n### Notes (optional)\n\nSource: https://github.com/iptv-org/iptv/issues/14007#issuecomment-1686942043\n\n### Contributing Guide\n\n- [X] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md)', + reactions: { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/14179/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/iptv/issues/14179/timeline', + performed_via_github_app: null, + state_reason: null + }, + { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/14178', + repository_url: 'https://api.github.com/repos/iptv-org/iptv', + labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14178/labels{/name}', + comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14178/comments', + events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14178/events', + html_url: 'https://github.com/iptv-org/iptv/issues/14178', + id: 1884922249, + node_id: 'I_kwDOCWUK8M5wWaGJ', + number: 14178, + title: 'Add: TV3', + 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', + site_admin: false + }, + labels: [ + { + id: 1912922147, + node_id: 'MDU6TGFiZWwxOTEyOTIyMTQ3', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/MY', + name: 'MY', + color: 'ea59cf', + default: false, + description: 'Malaysia' + }, + { + id: 5923508587, + node_id: 'LA_kwDOCWUK8M8AAAABYRGRaw', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/streams:add', + name: 'streams:add', + color: '017ff9', + default: false, + description: 'Request to add a new link to a playlist' + } + ], + state: 'open', + locked: false, + assignee: null, + assignees: [], + milestone: null, + comments: 1, + created_at: '2023-09-07T00:30:51Z', + updated_at: '2023-09-07T00:48:23Z', + closed_at: null, + author_association: 'COLLABORATOR', + active_lock_reason: null, + body: '### Stream ID\n\nTV3.my\n\n### Stream URL\n\nhttps://live-streams-ssai-01.tonton.com.my/live/2dd2b7cd-1b34-4871-b669-57b5c9beca23/live.isml/.m3u8\n\n### Label\n\nNone\n\n### Notes (optional)\n\nSource: https://github.com/iptv-org/iptv/issues/14063#issuecomment-1695783106\n\n### Contributing Guide\n\n- [X] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md)', + reactions: { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/14178/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/iptv/issues/14178/timeline', + performed_via_github_app: null, + state_reason: null + }, + { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/14177', + repository_url: 'https://api.github.com/repos/iptv-org/iptv', + labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14177/labels{/name}', + comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14177/comments', + events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14177/events', + html_url: 'https://github.com/iptv-org/iptv/issues/14177', + id: 1884920274, + node_id: 'I_kwDOCWUK8M5wWZnS', + number: 14177, + title: 'Add: Temple University TV', + 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', + site_admin: false + }, + labels: [ + { + id: 1694118251, + node_id: 'MDU6TGFiZWwxNjk0MTE4MjUx', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/US', + name: 'US', + color: '463faa', + default: false, + description: 'United States' + }, + { + id: 5923508587, + node_id: 'LA_kwDOCWUK8M8AAAABYRGRaw', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/streams:add', + name: 'streams:add', + color: '017ff9', + default: false, + description: 'Request to add a new link to a playlist' + } + ], + state: 'open', + locked: false, + assignee: null, + assignees: [], + milestone: null, + comments: 1, + created_at: '2023-09-07T00:27:51Z', + updated_at: '2023-09-07T00:47:15Z', + closed_at: null, + author_association: 'COLLABORATOR', + active_lock_reason: null, + body: '### Stream ID\n\nTUTV.us\n\n### Stream URL\n\nhttps://livestream.telvue.com/templeuni1/f7b44cfafd5c52223d5498196c8a2e7b.sdp/playlist.m3u8\n\n### Label\n\nNone\n\n### Notes (optional)\n\nSource: https://github.com/iptv-org/iptv/issues/14096#issue-1874505679\n\n### Contributing Guide\n\n- [X] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md)', + reactions: { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/14177/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/iptv/issues/14177/timeline', + performed_via_github_app: null, + state_reason: null + }, + { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/14175', + repository_url: 'https://api.github.com/repos/iptv-org/iptv', + labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14175/labels{/name}', + comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14175/comments', + events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14175/events', + html_url: 'https://github.com/iptv-org/iptv/issues/14175', + id: 1884859778, + node_id: 'I_kwDOCWUK8M5wWK2C', + number: 14175, + title: 'Add: TFX', + 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', + site_admin: false + }, + labels: [ + { + id: 1694117286, + node_id: 'MDU6TGFiZWwxNjk0MTE3Mjg2', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/FR', + name: 'FR', + color: 'f7ec1b', + default: false, + description: 'France' + }, + { + id: 5923498886, + node_id: 'LA_kwDOCWUK8M8AAAABYRFrhg', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/approved', + name: 'approved', + color: '85ddde', + default: false, + description: '' + }, + { + id: 5923508587, + node_id: 'LA_kwDOCWUK8M8AAAABYRGRaw', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/streams:add', + name: 'streams:add', + color: '017ff9', + default: false, + description: 'Request to add a new link to a playlist' + } + ], + state: 'open', + locked: false, + assignee: null, + assignees: [], + milestone: null, + comments: 1, + created_at: '2023-09-06T22:54:25Z', + updated_at: '2023-09-07T00:57:11Z', + closed_at: null, + author_association: 'COLLABORATOR', + active_lock_reason: null, + body: '### Stream ID\n\nTFX.fr\n\n### Stream URL\n\nhttps://stitcher-ipv4.pluto.tv/v1/stitch/embed/hls/channel/64c109a4798def0008a6e03e/master.m3u8?advertisingId={PSID}&appVersion=unknown&deviceDNT={TARGETOPT}&deviceId={PSID}&deviceLat=0&deviceLon=0&deviceMake=samsung&deviceModel=samsung&deviceType=samsung-tvplus&deviceVersion=unknown&embedPartner=samsung-tvplus&profileFloor=&profileLimit=&samsung_app_domain={APP_DOMAIN}&samsung_app_name={APP_NAME}&us_privacy=1YNY\n\n### Label\n\nNone\n\n### HTTP User Agent\n\nMozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1\n\n### HTTP Referrer\n\nhttps://pkpakiplay.xyz/\n\n### Notes (optional)\n\nSource: https://github.com/iptv-org/iptv-org.github.io/issues/1381\n\n### Contributing Guide\n\n- [X] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md)', + reactions: { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/14175/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/iptv/issues/14175/timeline', + performed_via_github_app: null, + state_reason: null + }, + { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/14179', + repository_url: 'https://api.github.com/repos/iptv-org/iptv', + labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14179/labels{/name}', + comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14179/comments', + events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14179/events', + html_url: 'https://github.com/iptv-org/iptv/issues/14179', + id: 1884926953, + node_id: 'I_kwDOCWUK8M5wWbPp', + number: 14179, + title: 'Add: Manorama News', + 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', + site_admin: false + }, + labels: [ + { + id: 1694119113, + node_id: 'MDU6TGFiZWwxNjk0MTE5MTEz', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/IN', + name: 'IN', + color: 'd8139a', + default: false, + description: 'India' + }, + { + id: 5923498886, + node_id: 'LA_kwDOCWUK8M8AAAABYRFrhg', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/approved', + name: 'approved', + color: '85ddde', + default: false, + description: '' + }, + { + id: 5923508587, + node_id: 'LA_kwDOCWUK8M8AAAABYRGRaw', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/streams:add', + name: 'streams:add', + color: '017ff9', + default: false, + description: 'Request to add a new link to a playlist' + } + ], + state: 'open', + locked: false, + assignee: null, + assignees: [], + milestone: null, + comments: 0, + created_at: '2023-09-07T00:38:55Z', + updated_at: '2023-09-07T00:48:32Z', + closed_at: null, + author_association: 'COLLABORATOR', + active_lock_reason: null, + body: '### Stream ID\n\nManoramaNews.in\n\n### Stream URL\n\n(https://mitelefe.com/Api/Videos/GetSourceUrl/694564/0/HLS / https://ssl.cloud.telefe.com/Api/Videos/GetSourceUrl/694564/0/HLS)\n\n### Label\n\nNot 24/7\n\n### Notes (optional)\n\nSource: https://github.com/iptv-org/iptv/issues/14007#issuecomment-1686942043\n\n### Contributing Guide\n\n- [X] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md)', + reactions: { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/14179/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/iptv/issues/14179/timeline', + performed_via_github_app: null, + state_reason: null + }, + { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/14135', + repository_url: 'https://api.github.com/repos/iptv-org/iptv', + labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14135/labels{/name}', + comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14135/comments', + events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14135/events', + html_url: 'https://github.com/iptv-org/iptv/issues/14135', + id: 1880165524, + node_id: 'I_kwDOCWUK8M5wEQyU', + number: 14135, + title: 'Add: BBC World News South Asia ', + user: { + login: 'kheohoanganh', + id: 128283995, + node_id: 'U_kgDOB6V1Ww', + avatar_url: 'https://avatars.githubusercontent.com/u/128283995?v=4', + gravatar_id: '', + url: 'https://api.github.com/users/kheohoanganh', + html_url: 'https://github.com/kheohoanganh', + followers_url: 'https://api.github.com/users/kheohoanganh/followers', + following_url: 'https://api.github.com/users/kheohoanganh/following{/other_user}', + gists_url: 'https://api.github.com/users/kheohoanganh/gists{/gist_id}', + starred_url: 'https://api.github.com/users/kheohoanganh/starred{/owner}{/repo}', + subscriptions_url: 'https://api.github.com/users/kheohoanganh/subscriptions', + organizations_url: 'https://api.github.com/users/kheohoanganh/orgs', + repos_url: 'https://api.github.com/users/kheohoanganh/repos', + events_url: 'https://api.github.com/users/kheohoanganh/events{/privacy}', + received_events_url: 'https://api.github.com/users/kheohoanganh/received_events', + type: 'User', + site_admin: false + }, + labels: [ + { + id: 1694116077, + node_id: 'MDU6TGFiZWwxNjk0MTE2MDc3', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/UK', + name: 'UK', + color: '99e5e5', + default: false, + description: 'United Kingdom' + }, + { + id: 5923498886, + node_id: 'LA_kwDOCWUK8M8AAAABYRFrhg', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/approved', + name: 'approved', + color: '85ddde', + default: false, + description: '' + }, + { + id: 5923508587, + node_id: 'LA_kwDOCWUK8M8AAAABYRGRaw', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/streams:add', + name: 'streams:add', + color: '017ff9', + default: false, + description: 'Request to add a new link to a playlist' + } + ], + state: 'open', + locked: false, + assignee: null, + assignees: [], + milestone: null, + comments: 1, + created_at: '2023-09-04T12:22:50Z', + updated_at: '2023-09-07T00:50:28Z', + closed_at: null, + author_association: 'NONE', + active_lock_reason: null, + body: '### Stream ID\n\nBBCWorldNews.uk@SouthAsia\n\n### Stream URL (optional)\n\nhttp://103.199.161.254/Content/bbcworld/Live/Channel%28BBCworld%29/Stream%2801%29/index.m3u8\n\n### Notes (optional)\n\n2 links for BBCWorldNewsSouthAsia.uk\r\nhttp://103.199.161.254/Content/bbcworld/Live/Channel%28BBCworld%29/Stream%2801%29/index.m3u8\r\nhttp://103.199.161.254/Content/bbcworld/Live/Channel%28BBCworld%29/Stream%2802%29/index.m3u8\n\n### Please confirm the following\n\n- [X] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md#request-a-channel)', + reactions: { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/14135/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/iptv/issues/14135/timeline', + performed_via_github_app: null, + state_reason: null + }, + { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/14105', + repository_url: 'https://api.github.com/repos/iptv-org/iptv', + labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14105/labels{/name}', + comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14105/comments', + events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14105/events', + html_url: 'https://github.com/iptv-org/iptv/issues/14105', + id: 1876637538, + node_id: 'I_kwDOCWUK8M5v2zdi', + number: 14105, + title: 'Add: Amarin TV (720p)', + user: { + login: 'Soponwit19997', + id: 142583084, + node_id: 'U_kgDOCH-lLA', + avatar_url: 'https://avatars.githubusercontent.com/u/142583084?v=4', + gravatar_id: '', + url: 'https://api.github.com/users/Soponwit19997', + html_url: 'https://github.com/Soponwit19997', + followers_url: 'https://api.github.com/users/Soponwit19997/followers', + following_url: 'https://api.github.com/users/Soponwit19997/following{/other_user}', + gists_url: 'https://api.github.com/users/Soponwit19997/gists{/gist_id}', + starred_url: 'https://api.github.com/users/Soponwit19997/starred{/owner}{/repo}', + subscriptions_url: 'https://api.github.com/users/Soponwit19997/subscriptions', + organizations_url: 'https://api.github.com/users/Soponwit19997/orgs', + repos_url: 'https://api.github.com/users/Soponwit19997/repos', + events_url: 'https://api.github.com/users/Soponwit19997/events{/privacy}', + received_events_url: 'https://api.github.com/users/Soponwit19997/received_events', + type: 'User', + site_admin: false + }, + labels: [ + { + id: 2990740232, + node_id: 'MDU6TGFiZWwyOTkwNzQwMjMy', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/TH', + name: 'TH', + color: 'B798EA', + default: false, + description: 'Thailand' + }, + { + id: 5923498886, + node_id: 'LA_kwDOCWUK8M8AAAABYRFrhg', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/approved', + name: 'approved', + color: '85ddde', + default: false, + description: '' + }, + { + id: 5923508587, + node_id: 'LA_kwDOCWUK8M8AAAABYRGRaw', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/streams:add', + name: 'streams:add', + color: '017ff9', + default: false, + description: 'Request to add a new link to a playlist' + } + ], + state: 'open', + locked: false, + assignee: null, + assignees: [], + milestone: null, + comments: 1, + created_at: '2023-09-01T03:08:05Z', + updated_at: '2023-09-06T14:19:50Z', + closed_at: null, + author_association: 'CONTRIBUTOR', + active_lock_reason: null, + body: '### Stream ID\n\nAmarinTV.th\n\n### Stream URL (optional)\n\nhttps://cdn6.goprimetime.info/feed/202306140918/chamarin/index.m3u8\n\n### Notes (optional)\n\n_No response_\n\n### Please confirm the following\n\n- [X] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md#request-a-channel)', + reactions: { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/14105/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/iptv/issues/14105/timeline', + performed_via_github_app: null, + state_reason: null + }, + { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/14104', + repository_url: 'https://api.github.com/repos/iptv-org/iptv', + labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14104/labels{/name}', + comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14104/comments', + events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14104/events', + html_url: 'https://github.com/iptv-org/iptv/issues/14104', + id: 1876636019, + node_id: 'I_kwDOCWUK8M5v2zFz', + number: 14104, + title: 'Add: MCOT HD (720p)', + user: { + login: 'Soponwit19997', + id: 142583084, + node_id: 'U_kgDOCH-lLA', + avatar_url: 'https://avatars.githubusercontent.com/u/142583084?v=4', + gravatar_id: '', + url: 'https://api.github.com/users/Soponwit19997', + html_url: 'https://github.com/Soponwit19997', + followers_url: 'https://api.github.com/users/Soponwit19997/followers', + following_url: 'https://api.github.com/users/Soponwit19997/following{/other_user}', + gists_url: 'https://api.github.com/users/Soponwit19997/gists{/gist_id}', + starred_url: 'https://api.github.com/users/Soponwit19997/starred{/owner}{/repo}', + subscriptions_url: 'https://api.github.com/users/Soponwit19997/subscriptions', + organizations_url: 'https://api.github.com/users/Soponwit19997/orgs', + repos_url: 'https://api.github.com/users/Soponwit19997/repos', + events_url: 'https://api.github.com/users/Soponwit19997/events{/privacy}', + received_events_url: 'https://api.github.com/users/Soponwit19997/received_events', + type: 'User', + site_admin: false + }, + labels: [ + { + id: 2990740232, + node_id: 'MDU6TGFiZWwyOTkwNzQwMjMy', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/TH', + name: 'TH', + color: 'B798EA', + default: false, + description: 'Thailand' + }, + { + id: 5923498886, + node_id: 'LA_kwDOCWUK8M8AAAABYRFrhg', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/approved', + name: 'approved', + color: '85ddde', + default: false, + description: '' + }, + { + id: 5923508587, + node_id: 'LA_kwDOCWUK8M8AAAABYRGRaw', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/streams:add', + name: 'streams:add', + color: '017ff9', + default: false, + description: 'Request to add a new link to a playlist' + } + ], + state: 'open', + locked: false, + assignee: null, + assignees: [], + milestone: null, + comments: 1, + created_at: '2023-09-01T03:05:56Z', + updated_at: '2023-09-06T14:21:02Z', + closed_at: null, + author_association: 'CONTRIBUTOR', + active_lock_reason: null, + body: '### Stream ID\n\nMCOTHD.th\n\n### Stream URL (optional)\n\nhttps://cdn6.goprimetime.info/feed/202306140918/chmcothd/index.m3u8\n\n### Notes (optional)\n\n_No response_\n\n### Please confirm the following\n\n- [X] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md#request-a-channel)', + reactions: { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/14104/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/iptv/issues/14104/timeline', + performed_via_github_app: null, + state_reason: null + }, + { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/14057', + repository_url: 'https://api.github.com/repos/iptv-org/iptv', + labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14057/labels{/name}', + comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14057/comments', + events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14057/events', + html_url: 'https://github.com/iptv-org/iptv/issues/14057', + id: 1868766252, + node_id: 'I_kwDOCWUK8M5vYxws', + number: 14057, + title: 'Add: MotorTrend Fast TV', + user: { + login: 'AudioNutz', + id: 28129911, + node_id: 'MDQ6VXNlcjI4MTI5OTEx', + avatar_url: 'https://avatars.githubusercontent.com/u/28129911?v=4', + gravatar_id: '', + url: 'https://api.github.com/users/AudioNutz', + html_url: 'https://github.com/AudioNutz', + followers_url: 'https://api.github.com/users/AudioNutz/followers', + following_url: 'https://api.github.com/users/AudioNutz/following{/other_user}', + gists_url: 'https://api.github.com/users/AudioNutz/gists{/gist_id}', + starred_url: 'https://api.github.com/users/AudioNutz/starred{/owner}{/repo}', + subscriptions_url: 'https://api.github.com/users/AudioNutz/subscriptions', + organizations_url: 'https://api.github.com/users/AudioNutz/orgs', + repos_url: 'https://api.github.com/users/AudioNutz/repos', + events_url: 'https://api.github.com/users/AudioNutz/events{/privacy}', + received_events_url: 'https://api.github.com/users/AudioNutz/received_events', + type: 'User', + site_admin: false + }, + labels: [ + { + id: 1694118251, + node_id: 'MDU6TGFiZWwxNjk0MTE4MjUx', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/US', + name: 'US', + color: '463faa', + default: false, + description: 'United States' + }, + { + id: 5923498886, + node_id: 'LA_kwDOCWUK8M8AAAABYRFrhg', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/approved', + name: 'approved', + color: '85ddde', + default: false, + description: '' + }, + { + id: 5923508587, + node_id: 'LA_kwDOCWUK8M8AAAABYRGRaw', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/streams:add', + name: 'streams:add', + color: '017ff9', + default: false, + description: 'Request to add a new link to a playlist' + } + ], + state: 'open', + locked: false, + assignee: null, + assignees: [], + milestone: null, + comments: 1, + created_at: '2023-08-28T01:23:43Z', + updated_at: '2023-09-06T13:44:17Z', + closed_at: null, + author_association: 'NONE', + active_lock_reason: null, + body: '### Stream ID\r\n\r\nFastTV.us\r\n\r\n### Stream URL (optional)\r\n\r\nhttps://3fa797d5.wurl.com/manifest/f36d25e7e52f1ba8d7e56eb859c636563214f541/T05PX01vdG9yVHJlbmRGYXN0VFZfSExT/b5e5e0e2-12b3-4312-93c9-c0a7c50b41ca/4.m3u8\r\n\r\n### Notes (optional)\r\n\r\nA free stream from MotorTrend TV\r\n\r\n### Please confirm the following\r\n\r\n- [X] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md#request-a-channel)', + reactions: { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/14057/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/iptv/issues/14057/timeline', + performed_via_github_app: null, + state_reason: null + }, + { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/14034', + repository_url: 'https://api.github.com/repos/iptv-org/iptv', + labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14034/labels{/name}', + comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14034/comments', + events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14034/events', + html_url: 'https://github.com/iptv-org/iptv/issues/14034', + id: 1863678726, + node_id: 'I_kwDOCWUK8M5vFXsG', + number: 14034, + title: 'Add: match 4(hu)', + user: { + login: 'erich1997', + id: 85035390, + node_id: 'MDQ6VXNlcjg1MDM1Mzkw', + avatar_url: 'https://avatars.githubusercontent.com/u/85035390?v=4', + gravatar_id: '', + url: 'https://api.github.com/users/erich1997', + html_url: 'https://github.com/erich1997', + followers_url: 'https://api.github.com/users/erich1997/followers', + following_url: 'https://api.github.com/users/erich1997/following{/other_user}', + gists_url: 'https://api.github.com/users/erich1997/gists{/gist_id}', + starred_url: 'https://api.github.com/users/erich1997/starred{/owner}{/repo}', + subscriptions_url: 'https://api.github.com/users/erich1997/subscriptions', + organizations_url: 'https://api.github.com/users/erich1997/orgs', + repos_url: 'https://api.github.com/users/erich1997/repos', + events_url: 'https://api.github.com/users/erich1997/events{/privacy}', + received_events_url: 'https://api.github.com/users/erich1997/received_events', + type: 'User', + site_admin: false + }, + labels: [ + { + id: 1696015170, + node_id: 'MDU6TGFiZWwxNjk2MDE1MTcw', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/HU', + name: 'HU', + color: 'e89bbf', + default: false, + description: 'Hungary' + }, + { + id: 5923498886, + node_id: 'LA_kwDOCWUK8M8AAAABYRFrhg', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/approved', + name: 'approved', + color: '85ddde', + default: false, + description: '' + }, + { + id: 5923508587, + node_id: 'LA_kwDOCWUK8M8AAAABYRGRaw', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/streams:add', + name: 'streams:add', + color: '017ff9', + default: false, + description: 'Request to add a new link to a playlist' + } + ], + state: 'open', + locked: false, + assignee: null, + assignees: [], + milestone: null, + comments: 1, + created_at: '2023-08-23T16:42:47Z', + updated_at: '2023-09-06T13:07:20Z', + closed_at: null, + author_association: 'NONE', + active_lock_reason: null, + body: '### Stream ID\n\nMatch4.hu\n\n### Stream URL (optional)\n\nhttp://194.76.186.33:8000/play/a04d/index.m3u8\n\n### Notes (optional)\n\n_No response_\n\n### Please confirm the following\n\n- [X] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md#request-a-channel)', + reactions: { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/14034/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/iptv/issues/14034/timeline', + performed_via_github_app: null, + state_reason: null + }, + { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/13964', + repository_url: 'https://api.github.com/repos/iptv-org/iptv', + labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/13964/labels{/name}', + comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/13964/comments', + events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/13964/events', + html_url: 'https://github.com/iptv-org/iptv/issues/13964', + id: 1857666538, + node_id: 'I_kwDOCWUK8M5uub3q', + number: 13964, + title: 'Add: Meth TV [LK] ', + user: { + login: 'Carlinhos027', + id: 111005658, + node_id: 'U_kgDOBp3P2g', + avatar_url: 'https://avatars.githubusercontent.com/u/111005658?v=4', + gravatar_id: '', + url: 'https://api.github.com/users/Carlinhos027', + html_url: 'https://github.com/Carlinhos027', + followers_url: 'https://api.github.com/users/Carlinhos027/followers', + following_url: 'https://api.github.com/users/Carlinhos027/following{/other_user}', + gists_url: 'https://api.github.com/users/Carlinhos027/gists{/gist_id}', + starred_url: 'https://api.github.com/users/Carlinhos027/starred{/owner}{/repo}', + subscriptions_url: 'https://api.github.com/users/Carlinhos027/subscriptions', + organizations_url: 'https://api.github.com/users/Carlinhos027/orgs', + repos_url: 'https://api.github.com/users/Carlinhos027/repos', + events_url: 'https://api.github.com/users/Carlinhos027/events{/privacy}', + received_events_url: 'https://api.github.com/users/Carlinhos027/received_events', + type: 'User', + site_admin: false + }, + labels: [ + { + id: 5432228583, + node_id: 'LA_kwDOCWUK8M8AAAABQ8k65w', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/not%2024/7', + name: 'not 24/7', + color: '40715B', + default: false, + description: '' + }, + { + id: 5641193949, + node_id: 'LA_kwDOCWUK8M8AAAABUD3J3Q', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/LK', + name: 'LK', + color: '0A59ED', + default: false, + description: 'Sri Lanka' + }, + { + id: 5923498886, + node_id: 'LA_kwDOCWUK8M8AAAABYRFrhg', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/approved', + name: 'approved', + color: '85ddde', + default: false, + description: '' + }, + { + id: 5923508587, + node_id: 'LA_kwDOCWUK8M8AAAABYRGRaw', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/streams:add', + name: 'streams:add', + color: '017ff9', + default: false, + description: 'Request to add a new link to a playlist' + } + ], + state: 'open', + locked: false, + assignee: null, + assignees: [], + milestone: null, + comments: 0, + created_at: '2023-08-19T10:31:37Z', + updated_at: '2023-09-07T11:25:16Z', + closed_at: null, + author_association: 'COLLABORATOR', + active_lock_reason: null, + body: '### Stream ID\n\nMethTV.lk\n\n### Stream URL (optional)\n\nhttps://ythls.onrender.com/channel/UC7kBHRaynsJMB6JcooGLTmA.m3u8\n\n### Notes (optional)\n\n720p / Not 24/7\n\n### Please confirm the following\n\n- [X] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md#request-a-channel)', + reactions: { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/13964/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/iptv/issues/13964/timeline', + performed_via_github_app: null, + state_reason: null + }, + { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/13893', + repository_url: 'https://api.github.com/repos/iptv-org/iptv', + labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/13893/labels{/name}', + comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/13893/comments', + events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/13893/events', + html_url: 'https://github.com/iptv-org/iptv/issues/13893', + id: 1850537350, + node_id: 'I_kwDOCWUK8M5uTPWG', + number: 13893, + title: 'Add: Weathernews (JPN) via YouTube', + user: { + login: 'arecki2', + id: 18574440, + node_id: 'MDQ6VXNlcjE4NTc0NDQw', + avatar_url: 'https://avatars.githubusercontent.com/u/18574440?v=4', + gravatar_id: '', + url: 'https://api.github.com/users/arecki2', + html_url: 'https://github.com/arecki2', + followers_url: 'https://api.github.com/users/arecki2/followers', + following_url: 'https://api.github.com/users/arecki2/following{/other_user}', + gists_url: 'https://api.github.com/users/arecki2/gists{/gist_id}', + starred_url: 'https://api.github.com/users/arecki2/starred{/owner}{/repo}', + subscriptions_url: 'https://api.github.com/users/arecki2/subscriptions', + organizations_url: 'https://api.github.com/users/arecki2/orgs', + repos_url: 'https://api.github.com/users/arecki2/repos', + events_url: 'https://api.github.com/users/arecki2/events{/privacy}', + received_events_url: 'https://api.github.com/users/arecki2/received_events', + type: 'User', + site_admin: false + }, + labels: [ + { + id: 1694117140, + node_id: 'MDU6TGFiZWwxNjk0MTE3MTQw', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/JP', + name: 'JP', + color: '350bdd', + default: false, + description: 'Japan' + }, + { + id: 5923498886, + node_id: 'LA_kwDOCWUK8M8AAAABYRFrhg', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/approved', + name: 'approved', + color: '85ddde', + default: false, + description: '' + }, + { + id: 5923508587, + node_id: 'LA_kwDOCWUK8M8AAAABYRGRaw', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/streams:add', + name: 'streams:add', + color: '017ff9', + default: false, + description: 'Request to add a new link to a playlist' + } + ], + state: 'open', + locked: false, + assignee: null, + assignees: [], + milestone: null, + comments: 2, + created_at: '2023-08-14T21:04:00Z', + updated_at: '2023-09-06T14:30:57Z', + closed_at: null, + author_association: 'NONE', + active_lock_reason: null, + body: "### Stream ID\n\nWeathernews.jp\n\n### Stream URL (optional)\n\nhttps://ythls.onrender.com/channel/UCNsidkYpIAQ4QaufptQBPHQ.m3u8\n\n### Notes (optional)\n\nLet's try them 😼\r\n\r\nI've just learned that they change streams for their TV broadcasts on YouTube every 3 hours, so even with additional streams they occasionally activate (such as now during Typhoon Lan), the YT API should manage to pick the correct feed in most cases 😜\r\n\r\nOtherwise, an advantage over the two streams that already are in the database is that the YT broadcasts are in 1080p (vs 720p).\n\n### Please confirm the following\n\n- [X] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md#request-a-channel)", + reactions: { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/13893/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/iptv/issues/13893/timeline', + performed_via_github_app: null, + state_reason: null + }, + { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/13881', + repository_url: 'https://api.github.com/repos/iptv-org/iptv', + labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/13881/labels{/name}', + comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/13881/comments', + events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/13881/events', + html_url: 'https://github.com/iptv-org/iptv/issues/13881', + id: 1848780631, + node_id: 'I_kwDOCWUK8M5uMidX', + number: 13881, + title: 'Add: Aaj Tak', + user: { + login: 'R4IN2007', + id: 83226646, + node_id: 'MDQ6VXNlcjgzMjI2NjQ2', + avatar_url: 'https://avatars.githubusercontent.com/u/83226646?v=4', + gravatar_id: '', + url: 'https://api.github.com/users/R4IN2007', + html_url: 'https://github.com/R4IN2007', + followers_url: 'https://api.github.com/users/R4IN2007/followers', + following_url: 'https://api.github.com/users/R4IN2007/following{/other_user}', + gists_url: 'https://api.github.com/users/R4IN2007/gists{/gist_id}', + starred_url: 'https://api.github.com/users/R4IN2007/starred{/owner}{/repo}', + subscriptions_url: 'https://api.github.com/users/R4IN2007/subscriptions', + organizations_url: 'https://api.github.com/users/R4IN2007/orgs', + repos_url: 'https://api.github.com/users/R4IN2007/repos', + events_url: 'https://api.github.com/users/R4IN2007/events{/privacy}', + received_events_url: 'https://api.github.com/users/R4IN2007/received_events', + type: 'User', + site_admin: false + }, + labels: [ + { + id: 1694119113, + node_id: 'MDU6TGFiZWwxNjk0MTE5MTEz', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/IN', + name: 'IN', + color: 'd8139a', + default: false, + description: 'India' + }, + { + id: 5923498886, + node_id: 'LA_kwDOCWUK8M8AAAABYRFrhg', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/approved', + name: 'approved', + color: '85ddde', + default: false, + description: '' + }, + { + id: 5923508587, + node_id: 'LA_kwDOCWUK8M8AAAABYRGRaw', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/streams:add', + name: 'streams:add', + color: '017ff9', + default: false, + description: 'Request to add a new link to a playlist' + } + ], + state: 'open', + locked: false, + assignee: null, + assignees: [], + milestone: null, + comments: 1, + created_at: '2023-08-13T23:23:28Z', + updated_at: '2023-09-06T14:32:15Z', + closed_at: null, + author_association: 'NONE', + active_lock_reason: null, + body: '### Stream ID\n\nAajTak.in\n\n### Stream URL (optional)\n\nhttps://feeds.intoday.in/aajtak/api/aajtakhd/master.m3u8\n\n### Notes (optional)\n\n_No response_\n\n### Please confirm the following\n\n- [X] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md#request-a-channel)', + reactions: { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/13881/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/iptv/issues/13881/timeline', + performed_via_github_app: null, + state_reason: null + }, + { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/13793', + repository_url: 'https://api.github.com/repos/iptv-org/iptv', + labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/13793/labels{/name}', + comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/13793/comments', + events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/13793/events', + html_url: 'https://github.com/iptv-org/iptv/issues/13793', + id: 1846716551, + node_id: 'I_kwDOCWUK8M5uEqiH', + number: 13793, + title: 'Add: AT-X (JPN)', + user: { + login: 'ZXArkin', + id: 21299971, + node_id: 'MDQ6VXNlcjIxMjk5OTcx', + avatar_url: 'https://avatars.githubusercontent.com/u/21299971?v=4', + gravatar_id: '', + url: 'https://api.github.com/users/ZXArkin', + html_url: 'https://github.com/ZXArkin', + followers_url: 'https://api.github.com/users/ZXArkin/followers', + following_url: 'https://api.github.com/users/ZXArkin/following{/other_user}', + gists_url: 'https://api.github.com/users/ZXArkin/gists{/gist_id}', + starred_url: 'https://api.github.com/users/ZXArkin/starred{/owner}{/repo}', + subscriptions_url: 'https://api.github.com/users/ZXArkin/subscriptions', + organizations_url: 'https://api.github.com/users/ZXArkin/orgs', + repos_url: 'https://api.github.com/users/ZXArkin/repos', + events_url: 'https://api.github.com/users/ZXArkin/events{/privacy}', + received_events_url: 'https://api.github.com/users/ZXArkin/received_events', + type: 'User', + site_admin: false + }, + labels: [ + { + id: 1694117140, + node_id: 'MDU6TGFiZWwxNjk0MTE3MTQw', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/JP', + name: 'JP', + color: '350bdd', + default: false, + description: 'Japan' + }, + { + id: 5923498886, + node_id: 'LA_kwDOCWUK8M8AAAABYRFrhg', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/approved', + name: 'approved', + color: '85ddde', + default: false, + description: '' + }, + { + id: 5923508587, + node_id: 'LA_kwDOCWUK8M8AAAABYRGRaw', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/streams:add', + name: 'streams:add', + color: '017ff9', + default: false, + description: 'Request to add a new link to a playlist' + } + ], + state: 'open', + locked: false, + assignee: null, + assignees: [], + milestone: null, + comments: 4, + created_at: '2023-08-11T12:11:28Z', + updated_at: '2023-09-06T14:17:56Z', + closed_at: null, + author_association: 'NONE', + active_lock_reason: null, + body: '### Stream ID\r\n\r\nATX.jp\r\n\r\n### Stream URL (optional)\r\n\r\nhttp://194.233.72.249:8080/AT-X/index.m3u8\r\n\r\n### Notes (optional)\r\n\r\n![AT-X_20230705_202525 551](https://github.com/iptv-org/iptv/assets/21299971/794c1cd4-fbe4-4b35-8a16-45127953ff65)\r\nThis is test AT-X channel JP without subs\r\n720 Quality\r\n\r\n### Please confirm the following\r\n\r\n- [X] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md#request-a-channel)', + reactions: { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/13793/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/iptv/issues/13793/timeline', + performed_via_github_app: null, + state_reason: null + }, + { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/13751', + repository_url: 'https://api.github.com/repos/iptv-org/iptv', + labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/13751/labels{/name}', + comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/13751/comments', + events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/13751/events', + html_url: 'https://github.com/iptv-org/iptv/issues/13751', + id: 1838199158, + node_id: 'I_kwDOCWUK8M5tkLF2', + number: 13751, + title: 'Add: Beano TV', + user: { + login: 'Ghani201', + id: 132144620, + node_id: 'U_kgDOB-Bd7A', + avatar_url: 'https://avatars.githubusercontent.com/u/132144620?v=4', + gravatar_id: '', + url: 'https://api.github.com/users/Ghani201', + html_url: 'https://github.com/Ghani201', + followers_url: 'https://api.github.com/users/Ghani201/followers', + following_url: 'https://api.github.com/users/Ghani201/following{/other_user}', + gists_url: 'https://api.github.com/users/Ghani201/gists{/gist_id}', + starred_url: 'https://api.github.com/users/Ghani201/starred{/owner}{/repo}', + subscriptions_url: 'https://api.github.com/users/Ghani201/subscriptions', + organizations_url: 'https://api.github.com/users/Ghani201/orgs', + repos_url: 'https://api.github.com/users/Ghani201/repos', + events_url: 'https://api.github.com/users/Ghani201/events{/privacy}', + received_events_url: 'https://api.github.com/users/Ghani201/received_events', + type: 'User', + site_admin: false + }, + labels: [ + { + id: 1694116077, + node_id: 'MDU6TGFiZWwxNjk0MTE2MDc3', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/UK', + name: 'UK', + color: '99e5e5', + default: false, + description: 'United Kingdom' + }, + { + id: 5923498886, + node_id: 'LA_kwDOCWUK8M8AAAABYRFrhg', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/approved', + name: 'approved', + color: '85ddde', + default: false, + description: '' + }, + { + id: 5923508587, + node_id: 'LA_kwDOCWUK8M8AAAABYRGRaw', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/streams:add', + name: 'streams:add', + color: '017ff9', + default: false, + description: 'Request to add a new link to a playlist' + } + ], + state: 'open', + locked: false, + assignee: null, + assignees: [], + milestone: null, + comments: 2, + created_at: '2023-08-06T12:54:59Z', + updated_at: '2023-09-06T14:40:01Z', + closed_at: null, + author_association: 'NONE', + active_lock_reason: null, + body: '### Stream ID\r\n\r\nBeanoTV.uk\r\n\r\n### Stream URL (optional)\r\n\r\nhttps://a5b4bacecd47433dad06d3189fc7422e.mediatailor.us-east-1.amazonaws.com/v1/manifest/04fd913bb278d8775298c26fdca9d9841f37601f/RakutenTV-eu_BeanoTV/b1f233d5-847c-437d-aa4f-f73e67a85323/2.m3u8|Referer="https://referer.xyz/"|User-Agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1"|Origin="https://origin.xyz"\r\n\r\n### Directives (optional)\r\n\r\n#EXTVLCOPT:http-referrer=http://imn.iq\r\n\r\n#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148\r\n\r\n#KODIPROP:inputstream=inputstream.adaptive\r\n\r\n#KODIPROP:inputstream.adaptive.manifest_type=mpd\r\n\r\n#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha\r\n\r\n#KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=13f2e056-53fe-4469-ba6d-999970dbe549&userToken=v9ZVSksv4S7rT55o10dmYNRa4asye3z05eWCFxD%2FFYIlTJEpuf6tF8asPcyQOFq0h5opS%2B6WoMxnshWkihpHq5qrdrBEZ69piE94J9Feh385snGOqK3PYO7tLLjxmsCAe%2B9%2BNnurSSO5RCAIRsL125nSj1eOR%2F1GSKOgGH80HK2FDLiePxPkeaAxuWzacNBB%2FqnIGGxfe3GlmN65cU9F8WEpKFDlaxW%2Fv3ZSLAp3%2BZEq1aZXJ6Oz%2Fi0diD0EybH7|Content-Type=application/octet-stream|R{SSM}|\r\n\r\n### Notes (optional)\r\n\r\n_No response_\r\n\r\n### Please confirm the following\r\n\r\n- [X] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md#request-a-channel)', + reactions: { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/13751/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/iptv/issues/13751/timeline', + performed_via_github_app: null, + state_reason: null + }, + { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/13715', + repository_url: 'https://api.github.com/repos/iptv-org/iptv', + labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/13715/labels{/name}', + comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/13715/comments', + events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/13715/events', + html_url: 'https://github.com/iptv-org/iptv/issues/13715', + id: 1835942409, + node_id: 'I_kwDOCWUK8M5tbkIJ', + number: 13715, + title: 'Add: ATV+ HD (Perú) [Linear Version of ATV+]', + user: { + login: 'R4IN2007', + id: 83226646, + node_id: 'MDQ6VXNlcjgzMjI2NjQ2', + avatar_url: 'https://avatars.githubusercontent.com/u/83226646?v=4', + gravatar_id: '', + url: 'https://api.github.com/users/R4IN2007', + html_url: 'https://github.com/R4IN2007', + followers_url: 'https://api.github.com/users/R4IN2007/followers', + following_url: 'https://api.github.com/users/R4IN2007/following{/other_user}', + gists_url: 'https://api.github.com/users/R4IN2007/gists{/gist_id}', + starred_url: 'https://api.github.com/users/R4IN2007/starred{/owner}{/repo}', + subscriptions_url: 'https://api.github.com/users/R4IN2007/subscriptions', + organizations_url: 'https://api.github.com/users/R4IN2007/orgs', + repos_url: 'https://api.github.com/users/R4IN2007/repos', + events_url: 'https://api.github.com/users/R4IN2007/events{/privacy}', + received_events_url: 'https://api.github.com/users/R4IN2007/received_events', + type: 'User', + site_admin: false + }, + labels: [ + { + id: 3046075919, + node_id: 'MDU6TGFiZWwzMDQ2MDc1OTE5', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/PE', + name: 'PE', + color: 'E78203', + default: false, + description: 'Peru' + }, + { + id: 5923498886, + node_id: 'LA_kwDOCWUK8M8AAAABYRFrhg', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/approved', + name: 'approved', + color: '85ddde', + default: false, + description: '' + }, + { + id: 5923508587, + node_id: 'LA_kwDOCWUK8M8AAAABYRGRaw', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/streams:add', + name: 'streams:add', + color: '017ff9', + default: false, + description: 'Request to add a new link to a playlist' + } + ], + state: 'open', + locked: false, + assignee: null, + assignees: [], + milestone: null, + comments: 2, + created_at: '2023-08-04T01:48:24Z', + updated_at: '2023-09-06T14:41:57Z', + closed_at: null, + author_association: 'NONE', + active_lock_reason: null, + body: '### Stream ID\n\nATVPlus.pe\n\n### Stream URL (optional)\n\nhttps://linear-258.frequency.stream/dist/vix/258/hls/master/playlist.m3u8\n\n### Notes (optional)\n\n(Linear Version & Streaming on VIX.com a spanish televisa-univision site) Might be geo-blocked or geo-locked because by removing /dist/vix/ the m3u8 link stops working #13703 \n\n### Please confirm the following\n\n- [X] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md#request-a-channel)', + reactions: { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/13715/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/iptv/issues/13715/timeline', + performed_via_github_app: null, + state_reason: null + }, + { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/14120', + repository_url: 'https://api.github.com/repos/iptv-org/iptv', + labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14120/labels{/name}', + comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14120/comments', + events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14120/events', + html_url: 'https://github.com/iptv-org/iptv/issues/14120', + id: 1884922249, + node_id: 'I_kwDOCWUK8M5wWaGJ', + number: 14120, + title: 'Edit: Tele2000', + 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', + site_admin: false + }, + labels: [ + { + id: 5923498886, + node_id: 'LA_kwDOCWUK8M8AAAABYRFrhg', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/approved', + name: 'approved', + color: '85ddde', + default: false, + description: '' + }, + { + id: 5923508587, + node_id: 'LA_kwDOCWUK8M8AAAABYRGRaw', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/streams:edit', + name: 'streams:edit', + color: '017ff9', + default: false, + description: 'Request to add a new link to a playlist' + } + ], + state: 'open', + locked: false, + assignee: null, + assignees: [], + milestone: null, + comments: 1, + created_at: '2023-09-07T00:30:51Z', + updated_at: '2023-09-07T00:48:23Z', + closed_at: null, + author_association: 'COLLABORATOR', + active_lock_reason: null, + body: '### Stream URL\n\nhttps://livestream.telvue.com/templeuni1/f7b44cfafd5c52223d5498196c8a2e7b.sdp/playlist.m3u8\n\n### Stream ID\n\nboo.us\n\n### Quality\n\n720p\n\n### Label\n\nGeo-blocked\n\n### HTTP User-Agent\n\nMozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36 Edge/12.246\n\n### HTTP Referrer\n\n_No response_\n\n### Notes\n\n_No response_\n\n### Contributing Guide\n\n- [X] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md)', + reactions: { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/14120/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/iptv/issues/14120/timeline', + performed_via_github_app: null, + state_reason: null + }, + { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/14110', + repository_url: 'https://api.github.com/repos/iptv-org/iptv', + labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14110/labels{/name}', + comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14110/comments', + events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14110/events', + html_url: 'https://github.com/iptv-org/iptv/issues/14110', + id: 1884922249, + node_id: 'I_kwDOCWUK8M5wWaGJ', + number: 14110, + title: 'Edit: Tele2000', + 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', + site_admin: false + }, + labels: [ + { + id: 5923498886, + node_id: 'LA_kwDOCWUK8M8AAAABYRFrhg', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/approved', + name: 'approved', + color: '85ddde', + default: false, + description: '' + }, + { + id: 5923508587, + node_id: 'LA_kwDOCWUK8M8AAAABYRGRaw', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/streams:edit', + name: 'streams:edit', + color: '017ff9', + default: false, + description: 'Request to add a new link to a playlist' + } + ], + state: 'open', + locked: false, + assignee: null, + assignees: [], + milestone: null, + comments: 1, + created_at: '2023-09-07T00:30:51Z', + updated_at: '2023-09-07T00:48:23Z', + closed_at: null, + author_association: 'COLLABORATOR', + active_lock_reason: null, + body: '### Stream URL (required)\n\nhttps://servilive.com:3126/live/tele2000live.m3u8\n\n### New Stream URL\n\nhttps://xui-backend.energeek.cl/live/9/playlist.m3u8?username=ZZDemoIPTVGH&password=mdo96EuqMkTR|Referer="https://referer.xyz/"|User-Agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1"|Origin="https://origin.xyz"\n\n### Stream ID\n\nBBCAmerica.us@East\n\n### Quality\n\n720p\n\n### Label\n\n~\n\n### HTTP User-Agent\n\nMozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36 Edge/12.246\n\n### HTTP Referrer\n\n~\n\n### Directives (optional)\r\n\r\n#EXTVLCOPT:http-referrer=http://imn.iq\r\n\r\n#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148\r\n\r\n#KODIPROP:inputstream=inputstream.adaptive\r\n\r\n#KODIPROP:inputstream.adaptive.manifest_type=mpd\r\n\r\n#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha\r\n\r\n#KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=13f2e056-53fe-4469-ba6d-999970dbe549&userToken=v9ZVSksv4S7rT55o10dmYNRa4asye3z05eWCFxD%2FFYIlTJEpuf6tF8asPcyQOFq0h5opS%2B6WoMxnshWkihpHq5qrdrBEZ69piE94J9Feh385snGOqK3PYO7tLLjxmsCAe%2B9%2BNnurSSO5RCAIRsL125nSj1eOR%2F1GSKOgGH80HK2FDLiePxPkeaAxuWzacNBB%2FqnIGGxfe3GlmN65cU9F8WEpKFDlaxW%2Fv3ZSLAp3%2BZEq1aZXJ6Oz%2Fi0diD0EybH7|Content-Type=application/octet-stream|R{SSM}|\n\n### Notes\n\n_No response_\n\n### Contributing Guide\n\n- [X] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md)', + reactions: { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/14110/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/iptv/issues/14110/timeline', + performed_via_github_app: null, + state_reason: null + }, + { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/14120', + repository_url: 'https://api.github.com/repos/iptv-org/iptv', + labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14120/labels{/name}', + comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14120/comments', + events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14120/events', + html_url: 'https://github.com/iptv-org/iptv/issues/14120', + id: 1884922249, + node_id: 'I_kwDOCWUK8M5wWaGJ', + number: 14120, + title: 'Edit: Tele2000', + 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', + site_admin: false + }, + labels: [ + { + id: 5923498886, + node_id: 'LA_kwDOCWUK8M8AAAABYRFrhg', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/approved', + name: 'approved', + color: '85ddde', + default: false, + description: '' + }, + { + id: 5923508587, + node_id: 'LA_kwDOCWUK8M8AAAABYRGRaw', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/streams:edit', + name: 'streams:edit', + color: '017ff9', + default: false, + description: 'Request to add a new link to a playlist' + } + ], + state: 'open', + locked: false, + assignee: null, + assignees: [], + milestone: null, + comments: 1, + created_at: '2023-09-07T00:30:51Z', + updated_at: '2023-09-07T00:48:23Z', + closed_at: null, + author_association: 'COLLABORATOR', + active_lock_reason: null, + body: '### Stream URL\n\nhttps://ythls.onrender.com/channel/UC40TUSUx490U5uR1lZt3Ajg.m3u8\n\n### Stream ID\n\n_No response_\n\n### Quality\n\nNone\n\n### Label\n\nNone\n\n### HTTP User-Agent\n\n_No response_\n\n### HTTP Referrer\n\n_No response_\n\n### Notes\n\n_No response_\n\n### Contributing Guide\n\n- [X] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md)', + reactions: { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/14120/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/iptv/issues/14120/timeline', + performed_via_github_app: null, + state_reason: null + }, + { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/14151', + repository_url: 'https://api.github.com/repos/iptv-org/iptv', + labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14151/labels{/name}', + comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14151/comments', + events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14151/events', + html_url: 'https://github.com/iptv-org/iptv/issues/14151', + id: 1884653836, + node_id: 'I_kwDOCWUK8M5wVYkM', + number: 14151, + title: 'Remove: VTV', + user: { + login: 'kaikyoofers', + id: 67206080, + node_id: 'MDQ6VXNlcjY3MjA2MDgw', + avatar_url: 'https://avatars.githubusercontent.com/u/67206080?v=4', + gravatar_id: '', + url: 'https://api.github.com/users/kaikyoofers', + html_url: 'https://github.com/kaikyoofers', + followers_url: 'https://api.github.com/users/kaikyoofers/followers', + following_url: 'https://api.github.com/users/kaikyoofers/following{/other_user}', + gists_url: 'https://api.github.com/users/kaikyoofers/gists{/gist_id}', + starred_url: 'https://api.github.com/users/kaikyoofers/starred{/owner}{/repo}', + subscriptions_url: 'https://api.github.com/users/kaikyoofers/subscriptions', + organizations_url: 'https://api.github.com/users/kaikyoofers/orgs', + repos_url: 'https://api.github.com/users/kaikyoofers/repos', + events_url: 'https://api.github.com/users/kaikyoofers/events{/privacy}', + received_events_url: 'https://api.github.com/users/kaikyoofers/received_events', + type: 'User', + site_admin: false + }, + labels: [ + { + id: 2043160604, + node_id: 'MDU6TGFiZWwyMDQzMTYwNjA0', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/BR', + name: 'BR', + color: 'ccdcff', + default: false, + description: 'Brazil' + }, + { + id: 5923498886, + node_id: 'LA_kwDOCWUK8M8AAAABYRFrhg', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/approved', + name: 'approved', + color: '85ddde', + default: false, + description: '' + }, + { + id: 5932506810, + node_id: 'LA_kwDOCWUK8M8AAAABYZreug', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/streams:remove', + name: 'streams:remove', + color: '5373a2', + default: false, + description: '' + } + ], + state: 'open', + locked: false, + assignee: null, + assignees: [], + milestone: null, + comments: 0, + created_at: '2023-09-06T19:51:43Z', + updated_at: '2023-09-07T00:48:57Z', + closed_at: null, + author_association: 'CONTRIBUTOR', + active_lock_reason: null, + body: '### Stream URL\n\nhttps://ythls.onrender.com/channel/UC40TUSUx490U5uR1lZt3Ajg.m3u8\n\n### What happened to the stream?\n\nNot loading\n\n### Notes (optional)\n\nOne link (VTV.br) is misspelled.\n\n### Contributing Guide\n\n- [x] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md)', + reactions: { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/14151/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/iptv/issues/14151/timeline', + performed_via_github_app: null, + state_reason: null + }, + { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/14150', + repository_url: 'https://api.github.com/repos/iptv-org/iptv', + labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14150/labels{/name}', + comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14150/comments', + events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/14150/events', + html_url: 'https://github.com/iptv-org/iptv/issues/14140', + id: 1881649613, + node_id: 'I_kwDOCWUK8M5wJ7HC', + number: 14150, + title: 'Broken: Cyprus Channels', + user: { + login: 'ROBGagn', + id: 124619576, + node_id: 'U_kgDOB22LOA', + avatar_url: 'https://avatars.githubusercontent.com/u/124619576?v=4', + gravatar_id: '', + url: 'https://api.github.com/users/ROBGagn', + html_url: 'https://github.com/ROBGagn', + followers_url: 'https://api.github.com/users/ROBGagn/followers', + following_url: 'https://api.github.com/users/ROBGagn/following{/other_user}', + gists_url: 'https://api.github.com/users/ROBGagn/gists{/gist_id}', + starred_url: 'https://api.github.com/users/ROBGagn/starred{/owner}{/repo}', + subscriptions_url: 'https://api.github.com/users/ROBGagn/subscriptions', + organizations_url: 'https://api.github.com/users/ROBGagn/orgs', + repos_url: 'https://api.github.com/users/ROBGagn/repos', + events_url: 'https://api.github.com/users/ROBGagn/events{/privacy}', + received_events_url: 'https://api.github.com/users/ROBGagn/received_events', + type: 'User', + site_admin: false + }, + labels: [ + { + id: 1707513547, + node_id: 'MDU6TGFiZWwxNzA3NTEzNTQ3', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/broken%20stream', + name: 'broken stream', + color: 'FBCA04', + default: false, + description: 'Stream is not working properly' + }, + { + id: 3241837512, + node_id: 'MDU6TGFiZWwzMjQxODM3NTEy', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/CY', + name: 'CY', + color: '90FA7B', + default: false, + description: 'Cyprus' + }, + { + id: 5923498886, + node_id: 'LA_kwDOCWUK8M8AAAABYRFrhg', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/approved', + name: 'approved', + color: '85ddde', + default: false, + description: '' + }, + { + id: 5932506810, + node_id: 'LA_kwDOCWUK8M8AAAABYZreug', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/streams:remove', + name: 'streams:remove', + color: '5373a2', + default: false, + description: '' + } + ], + state: 'open', + locked: false, + assignee: null, + assignees: [], + milestone: null, + comments: 0, + created_at: '2023-09-05T10:09:04Z', + updated_at: '2023-09-07T00:50:06Z', + closed_at: null, + author_association: 'NONE', + active_lock_reason: null, + body: '### Stream URL\n\nhttp://l6.cloudskep.com/rikcy/rikhd/playlist.m3u8\r\n\r\nhttp://l6.cloudskep.com/rikcy/rik2/playlist.m3u8\n\n### What happened to the stream?\n\nNot loading\n\n### Possible Replacement (optional)\n\nhttp://l6.cloudskep.com/rikcy/rikhd/playlist2.m3u8\n\n### Notes (optional)\n\nToken needed...\r\nSame issue with RIK 1 and 2. May happen in the future with ANT1 Cyprus, Sigma and Omega.\n\n### Contributing Guide\n\n- [X] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md)', + reactions: { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/14150/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/iptv/issues/14150/timeline', + performed_via_github_app: null, + state_reason: null + }, + { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/16120', + repository_url: 'https://api.github.com/repos/iptv-org/iptv', + labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/16120/labels{/name}', + comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/16120/comments', + events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/16120/events', + html_url: 'https://github.com/iptv-org/iptv/issues/16120', + id: 1878180439, + node_id: 'I_kwDOCWUK8M5v8sJX', + number: 16120, + title: 'Broken: Canal 5 (MX)', + user: { + login: 'chris202020202020', + id: 141375812, + node_id: 'U_kgDOCG05RA', + avatar_url: 'https://avatars.githubusercontent.com/u/141375812?v=4', + gravatar_id: '', + url: 'https://api.github.com/users/chris202020202020', + html_url: 'https://github.com/chris202020202020', + followers_url: 'https://api.github.com/users/chris202020202020/followers', + following_url: 'https://api.github.com/users/chris202020202020/following{/other_user}', + gists_url: 'https://api.github.com/users/chris202020202020/gists{/gist_id}', + starred_url: 'https://api.github.com/users/chris202020202020/starred{/owner}{/repo}', + subscriptions_url: 'https://api.github.com/users/chris202020202020/subscriptions', + organizations_url: 'https://api.github.com/users/chris202020202020/orgs', + repos_url: 'https://api.github.com/users/chris202020202020/repos', + events_url: 'https://api.github.com/users/chris202020202020/events{/privacy}', + received_events_url: 'https://api.github.com/users/chris202020202020/received_events', + type: 'User', + site_admin: false + }, + labels: [ + { + id: 1707513547, + node_id: 'MDU6TGFiZWwxNzA3NTEzNTQ3', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/broken%20stream', + name: 'broken stream', + color: 'FBCA04', + default: false, + description: 'Stream is not working properly' + }, + { + id: 2980444955, + node_id: 'MDU6TGFiZWwyOTgwNDQ0OTU1', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/MX', + name: 'MX', + color: '02A7D1', + default: false, + description: 'Mexico' + }, + { + id: 5923498886, + node_id: 'LA_kwDOCWUK8M8AAAABYRFrhg', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/approved', + name: 'approved', + color: '85ddde', + default: false, + description: '' + }, + { + id: 5932506810, + node_id: 'LA_kwDOCWUK8M8AAAABYZreug', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/streams:remove', + name: 'streams:remove', + color: '5373a2', + default: false, + description: '' + } + ], + state: 'open', + locked: false, + assignee: null, + assignees: [], + milestone: null, + comments: 0, + created_at: '2023-09-01T23:49:28Z', + updated_at: '2023-09-07T00:24:05Z', + closed_at: null, + author_association: 'NONE', + active_lock_reason: null, + body: '### Stream URL\n\nhttp://190.61.102.67:2000/play/a038/index.m3u8\n\n### What happened to the stream?\n\nNot loading\n\n### Possible Replacement (optional)\n\n_No response_\n\n### Notes (optional)\n\nReplacement For A Broken Stream To A New Stream For Canal 5 (MX) Please\n\n### Please confirm the following\n\n- [X] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md#report-a-broken-stream)', + reactions: { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/16120/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/iptv/issues/16120/timeline', + performed_via_github_app: null, + state_reason: null + }, + { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/19957', + repository_url: 'https://api.github.com/repos/iptv-org/iptv', + labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/19957/labels{/name}', + comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/19957/comments', + events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/19957/events', + html_url: 'https://github.com/iptv-org/iptv/issues/19957', + id: 2880738344, + node_id: 'I_kwDOCWUK8M6rtJQo', + number: 19957, + title: 'Find: CNBCe.tr', + user: { + login: 'M3UDay', + id: 164743332, + node_id: 'U_kgDOCdHIpA', + avatar_url: 'https://avatars.githubusercontent.com/u/164743332?v=4', + gravatar_id: '', + url: 'https://api.github.com/users/M3UDay', + html_url: 'https://github.com/M3UDay', + followers_url: 'https://api.github.com/users/M3UDay/followers', + following_url: 'https://api.github.com/users/M3UDay/following{/other_user}', + gists_url: 'https://api.github.com/users/M3UDay/gists{/gist_id}', + starred_url: 'https://api.github.com/users/M3UDay/starred{/owner}{/repo}', + subscriptions_url: 'https://api.github.com/users/M3UDay/subscriptions', + organizations_url: 'https://api.github.com/users/M3UDay/orgs', + repos_url: 'https://api.github.com/users/M3UDay/repos', + events_url: 'https://api.github.com/users/M3UDay/events{/privacy}', + received_events_url: 'https://api.github.com/users/M3UDay/received_events', + type: 'User', + user_view_type: 'public', + site_admin: false + }, + labels: [ + { + id: 8197871093, + node_id: 'LA_kwDOCWUK8M8AAAAB6KGV9Q', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/channel%20search', + name: 'channel search', + color: 'eaeaea', + default: false, + description: 'Request to find a link to a channel stream' + } + ], + state: 'open', + locked: false, + assignee: null, + assignees: [], + milestone: null, + comments: 0, + created_at: '2025-02-26T08:43:49Z', + updated_at: '2025-02-26T08:43:49Z', + closed_at: null, + author_association: 'NONE', + sub_issues_summary: { total: 0, completed: 0, percent_completed: 0 }, + active_lock_reason: null, + body: '### Stream ID (required)\n\n13thStreet.au\n\n### Notes\n\n_No response_', + closed_by: null, + reactions: { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/19957/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/iptv/issues/19957/timeline', + performed_via_github_app: null, + state_reason: null + }, + { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/20956', + repository_url: 'https://api.github.com/repos/iptv-org/iptv', + labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/20956/labels{/name}', + comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/20956/comments', + events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/20956/events', + html_url: 'https://github.com/iptv-org/iptv/issues/20956', + id: 2880738444, + node_id: 'I_kwDOCWUK8M6rtJQo', + number: 20956, + title: 'Find: IONTV.us', + user: { + login: 'M3UDay', + id: 164743332, + node_id: 'U_kgDOCdHIpA', + avatar_url: 'https://avatars.githubusercontent.com/u/164743332?v=4', + gravatar_id: '', + url: 'https://api.github.com/users/M3UDay', + html_url: 'https://github.com/M3UDay', + followers_url: 'https://api.github.com/users/M3UDay/followers', + following_url: 'https://api.github.com/users/M3UDay/following{/other_user}', + gists_url: 'https://api.github.com/users/M3UDay/gists{/gist_id}', + starred_url: 'https://api.github.com/users/M3UDay/starred{/owner}{/repo}', + subscriptions_url: 'https://api.github.com/users/M3UDay/subscriptions', + organizations_url: 'https://api.github.com/users/M3UDay/orgs', + repos_url: 'https://api.github.com/users/M3UDay/repos', + events_url: 'https://api.github.com/users/M3UDay/events{/privacy}', + received_events_url: 'https://api.github.com/users/M3UDay/received_events', + type: 'User', + user_view_type: 'public', + site_admin: false + }, + labels: [ + { + id: 8197871093, + node_id: 'LA_kwDOCWUK8M8AAAAB6KGV9Q', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/channel%20search', + name: 'channel search', + color: 'eaeaea', + default: false, + description: 'Request to find a link to a channel stream' + } + ], + state: 'open', + locked: false, + assignee: null, + assignees: [], + milestone: null, + comments: 0, + created_at: '2025-02-26T08:43:49Z', + updated_at: '2025-02-26T08:43:49Z', + closed_at: null, + author_association: 'NONE', + sub_issues_summary: { total: 0, completed: 0, percent_completed: 0 }, + active_lock_reason: null, + body: '### Stream ID (required)\n\nIONTV.us\n\n### Notes\n\n_No response_', + closed_by: null, + reactions: { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/20956/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/iptv/issues/20956/timeline', + performed_via_github_app: null, + state_reason: null + }, + { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/25157', + repository_url: 'https://api.github.com/repos/iptv-org/iptv', + labels_url: 'https://api.github.com/repos/iptv-org/iptv/issues/25157/labels{/name}', + comments_url: 'https://api.github.com/repos/iptv-org/iptv/issues/25157/comments', + events_url: 'https://api.github.com/repos/iptv-org/iptv/issues/25157/events', + html_url: 'https://github.com/iptv-org/iptv/issues/25157', + id: 3245640024, + node_id: 'I_kwDOCWUK8M7BdIlY', + number: 25157, + title: 'Add: OnTime Sports SD', + user: { + login: 'zezopm300', + id: 215159878, + node_id: 'U_kgDODNMURg', + avatar_url: 'https://avatars.githubusercontent.com/u/215159878?v=4', + gravatar_id: '', + url: 'https://api.github.com/users/zezopm300', + html_url: 'https://github.com/zezopm300', + followers_url: 'https://api.github.com/users/zezopm300/followers', + following_url: 'https://api.github.com/users/zezopm300/following{/other_user}', + gists_url: 'https://api.github.com/users/zezopm300/gists{/gist_id}', + starred_url: 'https://api.github.com/users/zezopm300/starred{/owner}{/repo}', + subscriptions_url: 'https://api.github.com/users/zezopm300/subscriptions', + organizations_url: 'https://api.github.com/users/zezopm300/orgs', + repos_url: 'https://api.github.com/users/zezopm300/repos', + events_url: 'https://api.github.com/users/zezopm300/events{/privacy}', + received_events_url: 'https://api.github.com/users/zezopm300/received_events', + type: 'User', + user_view_type: 'public', + site_admin: false + }, + labels: [ + { + id: 5923508587, + node_id: 'LA_kwDOCWUK8M8AAAABYRGRaw', + url: 'https://api.github.com/repos/iptv-org/iptv/labels/streams:add', + name: 'streams:add', + color: '017ff9', + default: false, + description: 'Request to add a new link to a playlist' + } + ], + state: 'open', + locked: false, + assignee: null, + assignees: [], + milestone: null, + comments: 0, + created_at: '2025-07-19T20:44:05Z', + updated_at: '2025-07-19T20:44:05Z', + closed_at: null, + author_association: 'NONE', + type: null, + active_lock_reason: null, + sub_issues_summary: { total: 0, completed: 0, percent_completed: 0 }, + body: + '### Stream ID (required)\n' + + '\n' + + 'OnTimeSports.eg@SD\n' + + '\n' + + '### Stream URL (required)\n' + + '\n' + + ' OnTime Sports SD.mu38\n' + + '\n' + + '### Quality\n' + + '\n' + + 'None\n' + + '\n' + + '### Label\n' + + '\n' + + 'None\n' + + '\n' + + '### HTTP User Agent\n' + + '\n' + + '_No response_\n' + + '\n' + + '### HTTP Referrer\n' + + '\n' + + '_No response_\n' + + '\n' + + '### Directives\n' + + '\n' + + '_No response_\n' + + '\n' + + '### Notes\n' + + '\n' + + '_No response_\n' + + '\n' + + '### Contributing Guide\n' + + '\n' + + '- [x] I have read [Contributing Guide](https://github.com/iptv-org/iptv/blob/master/CONTRIBUTING.md)', + closed_by: null, + reactions: { + url: 'https://api.github.com/repos/iptv-org/iptv/issues/25157/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/iptv/issues/25157/timeline', + performed_via_github_app: null, + state_reason: null + } +] diff --git a/tests/__data__/input/playlist_edit/playlist.m3u b/tests/__data__/input/playlist_edit/playlist.m3u index 2ebf1ffa7a..0abd41b6f2 100644 --- a/tests/__data__/input/playlist_edit/playlist.m3u +++ b/tests/__data__/input/playlist_edit/playlist.m3u @@ -1,5 +1,5 @@ -#EXTM3U -#EXTINF:-1 tvg-id="HewadTV.af",Hewad TV (720p) [Not 24/7] -http://51.210.199.58/hls/stream.m3u8 -#EXTINF:-1 tvg-id="",Télévision française 1 (480p) +#EXTM3U +#EXTINF:-1 tvg-id="HewadTV.af",Hewad TV (720p) [Not 24/7] +http://51.210.199.58/hls/stream.m3u8 +#EXTINF:-1 tvg-id="",Télévision française 1 (480p) https://live.relentlessinnovations.net:1936/imantv/imantv/playlist.m3u8 \ No newline at end of file diff --git a/tests/__data__/input/playlist_format/in.m3u b/tests/__data__/input/playlist_format/in.m3u index 47c77da2e0..0a013ba7a1 100644 --- a/tests/__data__/input/playlist_format/in.m3u +++ b/tests/__data__/input/playlist_format/in.m3u @@ -1,3 +1,3 @@ -#EXTM3U -#EXTINF:-1 tvg-id="mn.in",Manorama News -2 [U3] (480p) [Geo-blocked] [Not 24/7] -https://ythls.onrender.com/channel/UCP0uG-mcMImgKnJz-VjJZmQ.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="mn.in" http-referrer="http://test.com" http-user-agent="Mozilla/5.0",Manorama News -2 [U3] (480p) [Geo-blocked] [Not 24/7] +https://ythls.onrender.com/channel/UCP0uG-mcMImgKnJz-VjJZmQ.m3u8 diff --git a/tests/__data__/input/playlist_format/nl.m3u b/tests/__data__/input/playlist_format/nl.m3u index b7819a6046..1d12f3b3e1 100644 --- a/tests/__data__/input/playlist_format/nl.m3u +++ b/tests/__data__/input/playlist_format/nl.m3u @@ -1,17 +1,17 @@ -#EXTM3U -#EXTINF:-1 tvg-id="NPO2.nl",NPO 2 (302p) [Geo-blocked] -#EXTVLCOPT:http-referrer=http://imn.iq -#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 -#KODIPROP:inputstream=inputstream.adaptive -#KODIPROP:inputstream.adaptive.manifest_type=mpd -#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha -#KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=13f2e056-53fe-4469-ba6d-999970dbe549&userToken=v9ZVSksv4S7rT55o10dmYNRa4asye3z05eWCFxD%2FFYIlTJEpuf6tF8asPcyQOFq0h5opS%2B6WoMxnshWkihpHq5qrdrBEZ69piE94J9Feh385snGOqK3PYO7tLLjxmsCAe%2B9%2BNnurSSO5RCAIRsL125nSj1eOR%2F1GSKOgGH80HK2FDLiePxPkeaAxuWzacNBB%2FqnIGGxfe3GlmN65cU9F8WEpKFDlaxW%2Fv3ZSLAp3%2BZEq1aZXJ6Oz%2Fi0diD0EybH7|Content-Type=application/octet-stream|R{SSM}| -http://stream.tvtap.net:8081/live/nl-npo2.stream/playlist.m3u8?|Referer="https://referer.xyz/"|User-Agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1"|Origin="https://origin.xyz" -#EXTINF:-1 tvg-id="NPO2.nl",NPO 2 [Geo-blocked] -http://resolver.streaming.api.nos.nl/livestream?url=/live/npo/tvlive/npo2/npo22.isml/.m3u8 -#EXTINF:-1 tvg-id="NPO2.nl",NPO 2 (342p) -http://resolver.streaming.api.nos.nl/livestream?url=/live/npo/tvlive/npo2/npo2.isml/.m3u8 -#EXTINF:-1 tvg-id="NPO1.nl@SD",NPO 1 (342p) [Geo-blocked] -http://resolver.streaming.api.nos.nl/livestream?url=/live/npo/tvlive/npo1/npo1.isml/.m3u8 -#EXTINF:-1 tvg-id="",NPO 2 (Duplicate) -http://resolver.streaming.api.nos.nl/livestream?url=/live/npo/tvlive/npo2/npo2.isml/.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="NPO2.nl",NPO 2 (302p) [Geo-blocked] +#EXTVLCOPT:http-referrer=http://imn.iq +#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 +#KODIPROP:inputstream=inputstream.adaptive +#KODIPROP:inputstream.adaptive.manifest_type=mpd +#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha +#KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=13f2e056-53fe-4469-ba6d-999970dbe549&userToken=v9ZVSksv4S7rT55o10dmYNRa4asye3z05eWCFxD%2FFYIlTJEpuf6tF8asPcyQOFq0h5opS%2B6WoMxnshWkihpHq5qrdrBEZ69piE94J9Feh385snGOqK3PYO7tLLjxmsCAe%2B9%2BNnurSSO5RCAIRsL125nSj1eOR%2F1GSKOgGH80HK2FDLiePxPkeaAxuWzacNBB%2FqnIGGxfe3GlmN65cU9F8WEpKFDlaxW%2Fv3ZSLAp3%2BZEq1aZXJ6Oz%2Fi0diD0EybH7|Content-Type=application/octet-stream|R{SSM}| +http://stream.tvtap.net:8081/live/nl-npo2.stream/playlist.m3u8?|Referer="https://referer.xyz/"|User-Agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1"|Origin="https://origin.xyz" +#EXTINF:-1 tvg-id="NPO2.nl",NPO 2 [Geo-blocked] +http://resolver.streaming.api.nos.nl/livestream?url=/live/npo/tvlive/npo2/npo22.isml/.m3u8 +#EXTINF:-1 tvg-id="NPO2.nl",NPO 2 (342p) +http://resolver.streaming.api.nos.nl/livestream?url=/live/npo/tvlive/npo2/npo2.isml/.m3u8 +#EXTINF:-1 tvg-id="NPO1.nl@SD",NPO 1 (342p) [Geo-blocked] +http://resolver.streaming.api.nos.nl/livestream?url=/live/npo/tvlive/npo1/npo1.isml/.m3u8 +#EXTINF:-1 tvg-id="",NPO 2 (Duplicate) +http://resolver.streaming.api.nos.nl/livestream?url=/live/npo/tvlive/npo2/npo2.isml/.m3u8 diff --git a/tests/__data__/input/playlist_generate/ad.m3u b/tests/__data__/input/playlist_generate/ad.m3u index 9a1c9e175a..3c3bcae1db 100644 --- a/tests/__data__/input/playlist_generate/ad.m3u +++ b/tests/__data__/input/playlist_generate/ad.m3u @@ -1,9 +1,9 @@ -#EXTM3U -#EXTINF:-1 tvg-id="Zoo.ad@HD",Zoo (720p) -https://iptv-all.lanesh4d0w.repl.co/andorra/zoo -#EXTINF:-1 tvg-id="AndorraTV.ad@SD",ATV -https://iptv-all.lanesh4d0w.repl.co/andorra/atv -#EXTINF:-1 tvg-id="AndorraTV.ad@HD",ATV HD -https://iptv-all.lanesh4d0w.repl.co/andorra/atv_hd -#EXTINF:-1 tvg-id="AndorraTV.ad",ATV -https://iptv-all.lanesh4d0w.repl.co/andorra/atv2 +#EXTM3U +#EXTINF:-1 tvg-id="Zoo.ad@HD",Zoo (720p) +https://iptv-all.lanesh4d0w.repl.co/andorra/zoo +#EXTINF:-1 tvg-id="AndorraTV.ad@SD",ATV +https://iptv-all.lanesh4d0w.repl.co/andorra/atv +#EXTINF:-1 tvg-id="AndorraTV.ad@HD",ATV HD +https://iptv-all.lanesh4d0w.repl.co/andorra/atv_hd +#EXTINF:-1 tvg-id="AndorraTV.ad",ATV +https://iptv-all.lanesh4d0w.repl.co/andorra/atv2 diff --git a/tests/__data__/input/playlist_generate/ca.m3u b/tests/__data__/input/playlist_generate/ca.m3u index aa108e4229..9fb032c001 100644 --- a/tests/__data__/input/playlist_generate/ca.m3u +++ b/tests/__data__/input/playlist_generate/ca.m3u @@ -1,5 +1,5 @@ -#EXTM3U -#EXTINF:-1 tvg-id="5AABTV.ca",5AAB TV -http://158.69.124.9:1935/5aabtv/5aabtv/playlist.m3u8 -#EXTINF:-1 tvg-id="MeteoMedia.ca",Meteomedia -http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="5AABTV.ca",5AAB TV +http://158.69.124.9:1935/5aabtv/5aabtv/playlist.m3u8 +#EXTINF:-1 tvg-id="MeteoMedia.ca",Meteomedia +http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8 diff --git a/tests/__data__/input/playlist_generate/in.m3u b/tests/__data__/input/playlist_generate/in.m3u index 62594eb4bf..c375e17ace 100644 --- a/tests/__data__/input/playlist_generate/in.m3u +++ b/tests/__data__/input/playlist_generate/in.m3u @@ -1,3 +1,3 @@ -#EXTM3U -#EXTINF:-1 tvg-id="",Daawah TV -http://51.15.246.58:8081/daawahtv/daawahtv2/playlist.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="",Daawah TV +http://51.15.246.58:8081/daawahtv/daawahtv2/playlist.m3u8 diff --git a/tests/__data__/input/playlist_generate/kg.m3u b/tests/__data__/input/playlist_generate/kg.m3u index 9c1d5a5755..9bf0832b51 100644 --- a/tests/__data__/input/playlist_generate/kg.m3u +++ b/tests/__data__/input/playlist_generate/kg.m3u @@ -1,3 +1,3 @@ -#EXTM3U -#EXTINF:-1 tvg-id="ElTR.kg",ЭлТР (480p) [Not 24/7] -http://gohoski.fvds.ru:3000/mediabay/162/index.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="ElTR.kg",ЭлТР (480p) [Not 24/7] +http://gohoski.fvds.ru:3000/mediabay/162/index.m3u8 diff --git a/tests/__data__/input/playlist_generate/uk.m3u b/tests/__data__/input/playlist_generate/uk.m3u index 5e8c7318e5..4a8a1f64ab 100644 --- a/tests/__data__/input/playlist_generate/uk.m3u +++ b/tests/__data__/input/playlist_generate/uk.m3u @@ -1,3 +1,3 @@ -#EXTM3U -#EXTINF:-1 tvg-id="BBCNews.uk",BBC News HD -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="BBCNews.uk",BBC News HD +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 diff --git a/tests/__data__/input/playlist_generate/unsorted.m3u b/tests/__data__/input/playlist_generate/unsorted.m3u index f282942743..4310ac744a 100644 --- a/tests/__data__/input/playlist_generate/unsorted.m3u +++ b/tests/__data__/input/playlist_generate/unsorted.m3u @@ -1,15 +1,15 @@ -#EXTM3U -#EXTINF:-1 tvg-id="LDPRTV.ru",ЛДПР ТВ (1080p) -http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8 -#EXTINF:-1 tvg-id="VisitXTV.nl",Visit-X TV -https://stream.visit-x.tv/vxtv/ngrp:live_all/30fps.m3u8 -#EXTINF:-1 tvg-id="" user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",Andorra TV (720p) [Not 24/7] -#EXTVLCOPT:http-referrer=http://imn.iq -#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 -#KODIPROP:inputstream=inputstream.adaptive -#KODIPROP:inputstream.adaptive.manifest_type=mpd -#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha -#KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=13f2e056-53fe-4469-ba6d-999970dbe549&userToken=v9ZVSksv4S7rT55o10dmYNRa4asye3z05eWCFxD%2FFYIlTJEpuf6tF8asPcyQOFq0h5opS%2B6WoMxnshWkihpHq5qrdrBEZ69piE94J9Feh385snGOqK3PYO7tLLjxmsCAe%2B9%2BNnurSSO5RCAIRsL125nSj1eOR%2F1GSKOgGH80HK2FDLiePxPkeaAxuWzacNBB%2FqnIGGxfe3GlmN65cU9F8WEpKFDlaxW%2Fv3ZSLAp3%2BZEq1aZXJ6Oz%2Fi0diD0EybH7|Content-Type=application/octet-stream|R{SSM}| -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8|Referer="https://referer.xyz/"|User-Agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1"|Origin="https://origin.xyz" -#EXTINF:-1 tvg-id="DunaWorld.hu",Duna World (576i) -http://146.59.85.40:89/dunaworld/index.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="LDPRTV.ru",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/blocked.m3u8 +#EXTINF:-1 tvg-id="VisitXTV.nl",Visit-X TV +https://stream.visit-x.tv/vxtv/ngrp:live_all/30fps.m3u8 +#EXTINF:-1 tvg-id="" user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",Andorra TV (720p) [Not 24/7] +#EXTVLCOPT:http-referrer=http://imn.iq +#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 +#KODIPROP:inputstream=inputstream.adaptive +#KODIPROP:inputstream.adaptive.manifest_type=mpd +#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha +#KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=13f2e056-53fe-4469-ba6d-999970dbe549&userToken=v9ZVSksv4S7rT55o10dmYNRa4asye3z05eWCFxD%2FFYIlTJEpuf6tF8asPcyQOFq0h5opS%2B6WoMxnshWkihpHq5qrdrBEZ69piE94J9Feh385snGOqK3PYO7tLLjxmsCAe%2B9%2BNnurSSO5RCAIRsL125nSj1eOR%2F1GSKOgGH80HK2FDLiePxPkeaAxuWzacNBB%2FqnIGGxfe3GlmN65cU9F8WEpKFDlaxW%2Fv3ZSLAp3%2BZEq1aZXJ6Oz%2Fi0diD0EybH7|Content-Type=application/octet-stream|R{SSM}| +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index2.m3u8|Referer="https://referer.xyz/"|User-Agent="Mozilla/5.0 (iPhone; CPU iPhone OS 17_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1"|Origin="https://origin.xyz" +#EXTINF:-1 tvg-id="DunaWorld.hu",Duna World (576i) +http://146.59.85.40:89/dunaworld/index.m3u8 diff --git a/tests/__data__/input/playlist_test/ag.m3u b/tests/__data__/input/playlist_test/ag.m3u index 66b32b21d7..f4716e013b 100644 --- a/tests/__data__/input/playlist_test/ag.m3u +++ b/tests/__data__/input/playlist_test/ag.m3u @@ -1,5 +1,5 @@ -#EXTM3U -#EXTINF:-1 tvg-id="ABSTV.ag",ABS TV -https://tego-cdn2a.sibercdn.com/Live_TV-ABSTV-10/tracks-v3a1/rewind-7200.m3u8?token=e5f61e7be8363eb781b4bdfe591bf917dd529c1a-SjY3NzRTbDZQNnFQVkZaNkZja2RxV3JKc1VBa05zQkdMNStJakRGV0VTTzNrOEVGVUlIQmxta1NLV0o3bzdVdQ-1736094545-1736008145 -#EXTINF:-1 tvg-id="ABSTV.ag@HD",ABS TV (1080p) [Not 24/7] +#EXTM3U +#EXTINF:-1 tvg-id="ABSTV.ag",ABS TV +https://tego-cdn2a.sibercdn.com/Live_TV-ABSTV-10/tracks-v3a1/rewind-7200.m3u8?token=e5f61e7be8363eb781b4bdfe591bf917dd529c1a-SjY3NzRTbDZQNnFQVkZaNkZja2RxV3JKc1VBa05zQkdMNStJakRGV0VTTzNrOEVGVUlIQmxta1NLV0o3bzdVdQ-1736094545-1736008145 +#EXTINF:-1 tvg-id="ABSTV.ag@HD",ABS TV (1080p) [Not 24/7] https://query-streamlink.herokuapp.com/iptv-query?streaming-ip=https://www.twitch.tv/absliveantigua3 \ No newline at end of file diff --git a/tests/__data__/input/playlist_test/results.js b/tests/__data__/input/playlist_test/results.js index 84c66492a1..1899543830 100644 --- a/tests/__data__/input/playlist_test/results.js +++ b/tests/__data__/input/playlist_test/results.js @@ -1,14 +1,14 @@ -module.exports = { - 'https://query-streamlink.herokuapp.com/iptv-query?streaming-ip=https://www.twitch.tv/absliveantigua3': - { - url: 'https://query-streamlink.herokuapp.com/iptv-query?streaming-ip=https://www.twitch.tv/absliveantigua3', - http: { referrer: '', 'user-agent': '' }, - status: { ok: false, code: 'HTTP_NOT_FOUND', message: 'HTTP 404 Not Found' } - }, - 'https://tego-cdn2a.sibercdn.com/Live_TV-ABSTV-10/tracks-v3a1/rewind-7200.m3u8?token=e5f61e7be8363eb781b4bdfe591bf917dd529c1a-SjY3NzRTbDZQNnFQVkZaNkZja2RxV3JKc1VBa05zQkdMNStJakRGV0VTTzNrOEVGVUlIQmxta1NLV0o3bzdVdQ-1736094545-1736008145': - { - url: 'https://tego-cdn2a.sibercdn.com/Live_TV-ABSTV-10/tracks-v3a1/rewind-7200.m3u8?token=e5f61e7be8363eb781b4bdfe591bf917dd529c1a-SjY3NzRTbDZQNnFQVkZaNkZja2RxV3JKc1VBa05zQkdMNStJakRGV0VTTzNrOEVGVUlIQmxta1NLV0o3bzdVdQ-1736094545-1736008145', - http: { referrer: '', 'user-agent': '' }, - status: { ok: false, code: 'HTTP_FORBIDDEN', message: 'HTTP 403 Forbidden' } - } -} +module.exports = { + 'https://query-streamlink.herokuapp.com/iptv-query?streaming-ip=https://www.twitch.tv/absliveantigua3': + { + url: 'https://query-streamlink.herokuapp.com/iptv-query?streaming-ip=https://www.twitch.tv/absliveantigua3', + http: { referrer: '', 'user-agent': '' }, + status: { ok: false, code: 'HTTP_NOT_FOUND', message: 'HTTP 404 Not Found' } + }, + 'https://tego-cdn2a.sibercdn.com/Live_TV-ABSTV-10/tracks-v3a1/rewind-7200.m3u8?token=e5f61e7be8363eb781b4bdfe591bf917dd529c1a-SjY3NzRTbDZQNnFQVkZaNkZja2RxV3JKc1VBa05zQkdMNStJakRGV0VTTzNrOEVGVUlIQmxta1NLV0o3bzdVdQ-1736094545-1736008145': + { + url: 'https://tego-cdn2a.sibercdn.com/Live_TV-ABSTV-10/tracks-v3a1/rewind-7200.m3u8?token=e5f61e7be8363eb781b4bdfe591bf917dd529c1a-SjY3NzRTbDZQNnFQVkZaNkZja2RxV3JKc1VBa05zQkdMNStJakRGV0VTTzNrOEVGVUlIQmxta1NLV0o3bzdVdQ-1736094545-1736008145', + http: { referrer: '', 'user-agent': '' }, + status: { ok: false, code: 'HTTP_FORBIDDEN', message: 'HTTP 403 Forbidden' } + } +} diff --git a/tests/__data__/input/playlist_update/br.m3u b/tests/__data__/input/playlist_update/br.m3u index 6dcdaee152..31a8698610 100644 --- a/tests/__data__/input/playlist_update/br.m3u +++ b/tests/__data__/input/playlist_update/br.m3u @@ -1,6 +1,6 @@ -#EXTM3U -#EXTINF:-1 tvg-id="",VTV [Not 24/7] -https://ythls.onrender.com/channel/UC40TUSUx490U5uR1lZt3Ajg.m3u8 -#EXTINF:-1 tvg-id="",Tele2000 [Not 24/7] -#EXTVLCOPT:http-referrer=https://example2.com/ -https://servilive.com:3126/live/tele2000live.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="",VTV [Not 24/7] +https://ythls.onrender.com/channel/UC40TUSUx490U5uR1lZt3Ajg.m3u8 +#EXTINF:-1 tvg-id="",Tele2000 [Not 24/7] +#EXTVLCOPT:http-referrer=https://example2.com/ +https://servilive.com:3126/live/tele2000live.m3u8 diff --git a/tests/__data__/input/playlist_update/cy.m3u b/tests/__data__/input/playlist_update/cy.m3u index 439794ad78..03c605e3eb 100644 --- a/tests/__data__/input/playlist_update/cy.m3u +++ b/tests/__data__/input/playlist_update/cy.m3u @@ -1,7 +1,7 @@ -#EXTM3U -#EXTINF:-1 tvg-id="",RIK HD Cyprus -http://l6.cloudskep.com/rikcy/rikhd/playlist.m3u8 -#EXTINF:-1 tvg-id="",RIK 2 -http://l6.cloudskep.com/rikcy/rik2/playlist.m3u8 -#EXTINF:-1 tvg-id="AdaTV.cy",AdaTV -https://ythls.onrender.com/channel/UC40TUSUx490U5uR1lZt3Ajg.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="",RIK HD Cyprus +http://l6.cloudskep.com/rikcy/rikhd/playlist.m3u8 +#EXTINF:-1 tvg-id="",RIK 2 +http://l6.cloudskep.com/rikcy/rik2/playlist.m3u8 +#EXTINF:-1 tvg-id="AdaTV.cy",AdaTV +https://ythls.onrender.com/channel/UC40TUSUx490U5uR1lZt3Ajg.m3u8 diff --git a/tests/__data__/input/playlist_update/uk.m3u b/tests/__data__/input/playlist_update/uk.m3u index c1deeea978..033f5a36b5 100644 --- a/tests/__data__/input/playlist_update/uk.m3u +++ b/tests/__data__/input/playlist_update/uk.m3u @@ -1,5 +1,5 @@ -#EXTM3U -#EXTINF:-1 tvg-id="BBCNews.uk",BBC News HD (720p) [Not 24/7] -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 -#EXTINF:-1 tvg-id="BBCNews.uk",BBC News HD (480p) [Geo-blocked] -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/playlist.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="BBCNews.uk",BBC News HD (720p) [Not 24/7] +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTINF:-1 tvg-id="BBCNews.uk",BBC News HD (480p) [Geo-blocked] +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/playlist.m3u8 diff --git a/tests/__data__/input/playlist_validate/us_blocked.m3u b/tests/__data__/input/playlist_validate/us_blocked.m3u index 2ffa2273b6..3a5e4bd531 100644 --- a/tests/__data__/input/playlist_validate/us_blocked.m3u +++ b/tests/__data__/input/playlist_validate/us_blocked.m3u @@ -1,7 +1,7 @@ -#EXTM3U -#EXTINF:-1 tvg-id="FoxSports2.us@Asia",Fox Sports 2 Asia (Thai) (720p) -https://example.com/playlist.m3u8 -#EXTINF:-1 tvg-id="TVN.pl",TVN -https://example.com/playlist2.m3u8 -#EXTINF:-1 tvg-id="EverydayHeroes.us",Everyday Heroes (720p) -https://a.jsrdn.com/broadcast/7b1451fa52/+0000/c.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="FoxSports2.us@Asia",Fox Sports 2 Asia (Thai) (720p) +https://example.com/playlist.m3u8 +#EXTINF:-1 tvg-id="TVN.pl",TVN +https://example.com/playlist2.m3u8 +#EXTINF:-1 tvg-id="EverydayHeroes.us",Everyday Heroes (720p) +https://a.jsrdn.com/broadcast/7b1451fa52/+0000/c.m3u8 diff --git a/tests/__data__/input/playlist_validate/wrong_id.m3u b/tests/__data__/input/playlist_validate/wrong_id.m3u index 817fb94d1d..94d9cc2bc8 100644 --- a/tests/__data__/input/playlist_validate/wrong_id.m3u +++ b/tests/__data__/input/playlist_validate/wrong_id.m3u @@ -1,9 +1,9 @@ -#EXTM3U -#EXTINF:-1 tvg-id="qib22lAq1L.us",ABC (720p) -#EXTVLCOPT:http-referrer=http://imn.iq -#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 -#KODIPROP:inputstream=inputstream.adaptive -#KODIPROP:inputstream.adaptive.manifest_type=mpd -#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha -#KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=13f2e056-53fe-4469-ba6d-999970dbe549&userToken=v9ZVSksv4S7rT55o10dmYNRa4asye3z05eWCFxD%2FFYIlTJEpuf6tF8asPcyQOFq0h5opS%2B6WoMxnshWkihpHq5qrdrBEZ69piE94J9Feh385snGOqK3PYO7tLLjxmsCAe%2B9%2BNnurSSO5RCAIRsL125nSj1eOR%2F1GSKOgGH80HK2FDLiePxPkeaAxuWzacNBB%2FqnIGGxfe3GlmN65cU9F8WEpKFDlaxW%2Fv3ZSLAp3%2BZEq1aZXJ6Oz%2Fi0diD0EybH7|Content-Type=application/octet-stream|R{SSM}| -https://example.com/playlist2.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="qib22lAq1L.us",ABC (720p) +#EXTVLCOPT:http-referrer=http://imn.iq +#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 +#KODIPROP:inputstream=inputstream.adaptive +#KODIPROP:inputstream.adaptive.manifest_type=mpd +#KODIPROP:inputstream.adaptive.license_type=com.widevine.alpha +#KODIPROP:inputstream.adaptive.license_key=https://drm.ors.at/acquire-license/widevine?BrandGuid=13f2e056-53fe-4469-ba6d-999970dbe549&userToken=v9ZVSksv4S7rT55o10dmYNRa4asye3z05eWCFxD%2FFYIlTJEpuf6tF8asPcyQOFq0h5opS%2B6WoMxnshWkihpHq5qrdrBEZ69piE94J9Feh385snGOqK3PYO7tLLjxmsCAe%2B9%2BNnurSSO5RCAIRsL125nSj1eOR%2F1GSKOgGH80HK2FDLiePxPkeaAxuWzacNBB%2FqnIGGxfe3GlmN65cU9F8WEpKFDlaxW%2Fv3ZSLAp3%2BZEq1aZXJ6Oz%2Fi0diD0EybH7|Content-Type=application/octet-stream|R{SSM}| +https://example.com/playlist2.m3u8 diff --git a/tests/__data__/input/report_create/br.m3u b/tests/__data__/input/report_create/br.m3u index 6dcdaee152..31a8698610 100644 --- a/tests/__data__/input/report_create/br.m3u +++ b/tests/__data__/input/report_create/br.m3u @@ -1,6 +1,6 @@ -#EXTM3U -#EXTINF:-1 tvg-id="",VTV [Not 24/7] -https://ythls.onrender.com/channel/UC40TUSUx490U5uR1lZt3Ajg.m3u8 -#EXTINF:-1 tvg-id="",Tele2000 [Not 24/7] -#EXTVLCOPT:http-referrer=https://example2.com/ -https://servilive.com:3126/live/tele2000live.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="",VTV [Not 24/7] +https://ythls.onrender.com/channel/UC40TUSUx490U5uR1lZt3Ajg.m3u8 +#EXTINF:-1 tvg-id="",Tele2000 [Not 24/7] +#EXTVLCOPT:http-referrer=https://example2.com/ +https://servilive.com:3126/live/tele2000live.m3u8 diff --git a/tests/__data__/input/report_create/cy.m3u b/tests/__data__/input/report_create/cy.m3u index 581d0961b6..82d0b78d44 100644 --- a/tests/__data__/input/report_create/cy.m3u +++ b/tests/__data__/input/report_create/cy.m3u @@ -1,5 +1,5 @@ -#EXTM3U -#EXTINF:-1 tvg-id="",RIK HD Cyprus -http://l6.cloudskep.com/rikcy/rikhd/playlist.m3u8 -#EXTINF:-1 tvg-id="",RIK 2 -http://l6.cloudskep.com/rikcy/rik2/playlist.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="",RIK HD Cyprus +http://l6.cloudskep.com/rikcy/rikhd/playlist.m3u8 +#EXTINF:-1 tvg-id="",RIK 2 +http://l6.cloudskep.com/rikcy/rik2/playlist.m3u8 diff --git a/tests/__data__/input/report_create/uk.m3u b/tests/__data__/input/report_create/uk.m3u index c1deeea978..033f5a36b5 100644 --- a/tests/__data__/input/report_create/uk.m3u +++ b/tests/__data__/input/report_create/uk.m3u @@ -1,5 +1,5 @@ -#EXTM3U -#EXTINF:-1 tvg-id="BBCNews.uk",BBC News HD (720p) [Not 24/7] -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 -#EXTINF:-1 tvg-id="BBCNews.uk",BBC News HD (480p) [Geo-blocked] -http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/playlist.m3u8 +#EXTM3U +#EXTINF:-1 tvg-id="BBCNews.uk",BBC News HD (720p) [Not 24/7] +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTINF:-1 tvg-id="BBCNews.uk",BBC News HD (480p) [Geo-blocked] +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/playlist.m3u8 diff --git a/tests/__data__/input/report_create/us.m3u b/tests/__data__/input/report_create/us.m3u index 491b56b03c..6a617277d9 100644 --- a/tests/__data__/input/report_create/us.m3u +++ b/tests/__data__/input/report_create/us.m3u @@ -1,5 +1,5 @@ -#EXTM3U -#EXTINF:-1 tvg-id="",TUTV -https://livestream.telvue.com/templeuni1/f7b44cfafd5c52223d5498196c8a2e7b.sdp/playlist.m3u8 -#EXTINF:-1 tvg-id="IONTV.us@East",ION TV +#EXTM3U +#EXTINF:-1 tvg-id="",TUTV +https://livestream.telvue.com/templeuni1/f7b44cfafd5c52223d5498196c8a2e7b.sdp/playlist.m3u8 +#EXTINF:-1 tvg-id="IONTV.us@East",ION TV http://fl3.moveonjoy.com/ION_TV/index.m3u8 \ No newline at end of file diff --git a/tests/commands/api/generate.test.ts b/tests/commands/api/generate.test.ts index 4959afd913..d32a2cfc27 100644 --- a/tests/commands/api/generate.test.ts +++ b/tests/commands/api/generate.test.ts @@ -1,26 +1,26 @@ -import { pathToFileURL } from 'node:url' -import { execSync } from 'child_process' -import fs from 'fs-extra' - -const ENV_VAR = - 'cross-env DATA_DIR=tests/__data__/input/data STREAMS_DIR=tests/__data__/input/api_generate API_DIR=tests/__data__/output/.api' - -beforeEach(() => { - fs.emptyDirSync('tests/__data__/output') -}) - -describe('api:generate', () => { - it('can create streams.json', () => { - const cmd = `${ENV_VAR} npm run api:generate` - const stdout = execSync(cmd, { encoding: 'utf8' }) - if (process.env.DEBUG === 'true') console.log(cmd, stdout) - - expect(content('tests/__data__/output/.api/streams.json')).toMatchObject( - content('tests/__data__/expected/api_generate/.api/streams.json') - ) - }) -}) - -function content(filepath: string) { - return JSON.parse(fs.readFileSync(pathToFileURL(filepath), { encoding: 'utf8' })) -} +import { pathToFileURL } from 'node:url' +import { execSync } from 'child_process' +import fs from 'fs-extra' + +const ENV_VAR = + 'cross-env DATA_DIR=tests/__data__/input/data STREAMS_DIR=tests/__data__/input/api_generate API_DIR=tests/__data__/output/.api' + +beforeEach(() => { + fs.emptyDirSync('tests/__data__/output') +}) + +describe('api:generate', () => { + it('can create streams.json', () => { + const cmd = `${ENV_VAR} npm run api:generate` + const stdout = execSync(cmd, { encoding: 'utf8' }) + if (process.env.DEBUG === 'true') console.log(cmd, stdout) + + expect(content('tests/__data__/output/.api/streams.json')).toMatchObject( + content('tests/__data__/expected/api_generate/.api/streams.json') + ) + }) +}) + +function content(filepath: string) { + return JSON.parse(fs.readFileSync(pathToFileURL(filepath), { encoding: 'utf8' })) +} diff --git a/tests/commands/playlist/edit.test.ts b/tests/commands/playlist/edit.test.ts index 0a770a09ce..aee61364b4 100644 --- a/tests/commands/playlist/edit.test.ts +++ b/tests/commands/playlist/edit.test.ts @@ -1,38 +1,38 @@ -import { execSync } from 'child_process' -import fs from 'fs-extra' - -type ExecError = { - status: number - stdout: string -} - -const ENV_VAR = 'cross-env DATA_DIR=tests/__data__/input/data' - -beforeEach(() => { - fs.emptyDirSync('tests/__data__/output') - fs.copySync( - 'tests/__data__/input/playlist_edit/playlist.m3u', - 'tests/__data__/output/playlist.m3u' - ) -}) - -describe('playlist:edit', () => { - it('shows list of options for a streams', () => { - const cmd = `${ENV_VAR} npm run playlist:edit --- tests/__data__/output/playlist.m3u` - try { - const stdout = execSync(cmd, { encoding: 'utf8' }) - if (process.env.DEBUG === 'true') console.log(cmd, stdout) - checkStdout(stdout) - } catch (error) { - // NOTE: for Windows only - if (process.env.DEBUG === 'true') console.log(cmd, error) - checkStdout((error as ExecError).stdout) - } - }) -}) - -function checkStdout(stdout: string) { - expect(stdout).toContain('TF1.fr (TF1, Télévision française 1)') - expect(stdout).toContain('Type...') - expect(stdout).toContain('Skip') -} +import { execSync } from 'child_process' +import fs from 'fs-extra' + +type ExecError = { + status: number + stdout: string +} + +const ENV_VAR = 'cross-env DATA_DIR=tests/__data__/input/data' + +beforeEach(() => { + fs.emptyDirSync('tests/__data__/output') + fs.copySync( + 'tests/__data__/input/playlist_edit/playlist.m3u', + 'tests/__data__/output/playlist.m3u' + ) +}) + +describe('playlist:edit', () => { + it('shows list of options for a streams', () => { + const cmd = `${ENV_VAR} npm run playlist:edit --- tests/__data__/output/playlist.m3u` + try { + const stdout = execSync(cmd, { encoding: 'utf8' }) + if (process.env.DEBUG === 'true') console.log(cmd, stdout) + checkStdout(stdout) + } catch (error) { + // NOTE: for Windows only + if (process.env.DEBUG === 'true') console.log(cmd, error) + checkStdout((error as ExecError).stdout) + } + }) +}) + +function checkStdout(stdout: string) { + expect(stdout).toContain('TF1.fr (TF1, Télévision française 1)') + expect(stdout).toContain('Type...') + expect(stdout).toContain('Skip') +} diff --git a/tests/commands/playlist/format.test.ts b/tests/commands/playlist/format.test.ts index 49345f61f4..f169322d84 100644 --- a/tests/commands/playlist/format.test.ts +++ b/tests/commands/playlist/format.test.ts @@ -1,36 +1,37 @@ -import { pathToFileURL } from 'node:url' -import { execSync } from 'child_process' -import * as fs from 'fs-extra' -import { glob } from 'glob' - -const ENV_VAR = 'cross-env STREAMS_DIR=tests/__data__/output/streams DATA_DIR=tests/__data__/input/data' - -beforeEach(() => { - fs.emptyDirSync('tests/__data__/output') - fs.copySync('tests/__data__/input/playlist_format', 'tests/__data__/output/streams') -}) - -describe('playlist:format', () => { - it('can format playlists', () => { - const cmd = `${ENV_VAR} npm run playlist:format` - const stdout = execSync(cmd, { encoding: 'utf8' }) - if (process.env.DEBUG === 'true') console.log(cmd, stdout) - - const files = glob.sync('tests/__data__/expected/playlist_format/*.m3u').map(filepath => { - const fileUrl = pathToFileURL(filepath).toString() - const pathToRemove = pathToFileURL('tests/__data__/expected/playlist_format/').toString() - - return fileUrl.replace(pathToRemove, '') - }) - - files.forEach(filepath => { - expect(content(`tests/__data__/output/streams/${filepath}`)).toBe( - content(`tests/__data__/expected/playlist_format/${filepath}`) - ) - }) - }) -}) - -function content(filepath: string) { - return fs.readFileSync(pathToFileURL(filepath), { encoding: 'utf8' }) -} +import { pathToFileURL } from 'node:url' +import { execSync } from 'child_process' +import * as fs from 'fs-extra' +import { glob } from 'glob' + +const ENV_VAR = + 'cross-env STREAMS_DIR=tests/__data__/output/streams DATA_DIR=tests/__data__/input/data' + +beforeEach(() => { + fs.emptyDirSync('tests/__data__/output') + fs.copySync('tests/__data__/input/playlist_format', 'tests/__data__/output/streams') +}) + +describe('playlist:format', () => { + it('can format playlists', () => { + const cmd = `${ENV_VAR} npm run playlist:format` + const stdout = execSync(cmd, { encoding: 'utf8' }) + if (process.env.DEBUG === 'true') console.log(cmd, stdout) + + const files = glob.sync('tests/__data__/expected/playlist_format/*.m3u').map(filepath => { + const fileUrl = pathToFileURL(filepath).toString() + const pathToRemove = pathToFileURL('tests/__data__/expected/playlist_format/').toString() + + return fileUrl.replace(pathToRemove, '') + }) + + files.forEach(filepath => { + expect(content(`tests/__data__/output/streams/${filepath}`)).toBe( + content(`tests/__data__/expected/playlist_format/${filepath}`) + ) + }) + }) +}) + +function content(filepath: string) { + return fs.readFileSync(pathToFileURL(filepath), { encoding: 'utf8' }) +} diff --git a/tests/commands/playlist/generate.test.ts b/tests/commands/playlist/generate.test.ts index 39f38a8f36..37efbf67f1 100644 --- a/tests/commands/playlist/generate.test.ts +++ b/tests/commands/playlist/generate.test.ts @@ -1,43 +1,43 @@ -import { pathToFileURL } from 'node:url' -import { execSync } from 'child_process' -import { EOL } from 'node:os' -import * as fs from 'fs-extra' -import * as glob from 'glob' - -const ENV_VAR = - 'cross-env STREAMS_DIR=tests/__data__/input/playlist_generate DATA_DIR=tests/__data__/input/data PUBLIC_DIR=tests/__data__/output/.gh-pages LOGS_DIR=tests/__data__/output/logs' - -beforeEach(() => { - fs.emptyDirSync('tests/__data__/output') -}) - -describe('playlist:generate', () => { - it('can generate playlists and logs', () => { - const cmd = `${ENV_VAR} npm run playlist:generate` - const stdout = execSync(cmd, { encoding: 'utf8' }) - if (process.env.DEBUG === 'true') console.log(cmd, stdout) - - const playlists = glob - .sync('tests/__data__/expected/playlist_generate/.gh-pages/**/*.m3u') - .map(filepath => { - const fileUrl = pathToFileURL(filepath).toString() - const pathToRemove = pathToFileURL('tests/__data__/expected/playlist_generate/').toString() - - return fileUrl.replace(pathToRemove, '') - }) - - playlists.forEach((filepath: string) => { - expect(content(`tests/__data__/output/${filepath}`), filepath).toBe( - content(`tests/__data__/expected/playlist_generate/${filepath}`) - ) - }) - - expect(content('tests/__data__/output/logs/generators.log').split(EOL).sort()).toStrictEqual( - content('tests/__data__/expected/playlist_generate/logs/generators.log').split(EOL).sort() - ) - }) -}) - -function content(filepath: string) { - return fs.readFileSync(pathToFileURL(filepath), { encoding: 'utf8' }) -} +import { pathToFileURL } from 'node:url' +import { execSync } from 'child_process' +import { EOL } from 'node:os' +import * as fs from 'fs-extra' +import * as glob from 'glob' + +const ENV_VAR = + 'cross-env STREAMS_DIR=tests/__data__/input/playlist_generate DATA_DIR=tests/__data__/input/data PUBLIC_DIR=tests/__data__/output/.gh-pages LOGS_DIR=tests/__data__/output/logs' + +beforeEach(() => { + fs.emptyDirSync('tests/__data__/output') +}) + +describe('playlist:generate', () => { + it('can generate playlists and logs', () => { + const cmd = `${ENV_VAR} npm run playlist:generate` + const stdout = execSync(cmd, { encoding: 'utf8' }) + if (process.env.DEBUG === 'true') console.log(cmd, stdout) + + const playlists = glob + .sync('tests/__data__/expected/playlist_generate/.gh-pages/**/*.m3u') + .map(filepath => { + const fileUrl = pathToFileURL(filepath).toString() + const pathToRemove = pathToFileURL('tests/__data__/expected/playlist_generate/').toString() + + return fileUrl.replace(pathToRemove, '') + }) + + playlists.forEach((filepath: string) => { + expect(content(`tests/__data__/output/${filepath}`), filepath).toBe( + content(`tests/__data__/expected/playlist_generate/${filepath}`) + ) + }) + + expect(content('tests/__data__/output/logs/generators.log').split(EOL).sort()).toStrictEqual( + content('tests/__data__/expected/playlist_generate/logs/generators.log').split(EOL).sort() + ) + }) +}) + +function content(filepath: string) { + return fs.readFileSync(pathToFileURL(filepath), { encoding: 'utf8' }) +} diff --git a/tests/commands/playlist/test.test.ts b/tests/commands/playlist/test.test.ts index ec14499089..1bf978b016 100644 --- a/tests/commands/playlist/test.test.ts +++ b/tests/commands/playlist/test.test.ts @@ -1,21 +1,21 @@ -import { execSync } from 'child_process' - -type ExecError = { - status: number - stdout: string -} - -const ENV_VAR = 'cross-env ROOT_DIR=tests/__data__/input DATA_DIR=tests/__data__/input/data' - -describe('playlist:test', () => { - it('shows an error if the playlist contains a broken link', () => { - const cmd = `${ENV_VAR} npm run playlist:test playlist_test/ag.m3u` - try { - execSync(cmd, { encoding: 'utf8' }) - } catch (error) { - if (process.env.DEBUG === 'true') console.log(cmd, error) - expect((error as ExecError).stdout).toContain('playlist_test/ag.m3u') - expect((error as ExecError).stdout).toContain('2 problems (1 errors, 1 warnings)') - } - }) -}) +import { execSync } from 'child_process' + +type ExecError = { + status: number + stdout: string +} + +const ENV_VAR = 'cross-env ROOT_DIR=tests/__data__/input DATA_DIR=tests/__data__/input/data' + +describe('playlist:test', () => { + it('shows an error if the playlist contains a broken link', () => { + const cmd = `${ENV_VAR} npm run playlist:test playlist_test/ag.m3u` + try { + execSync(cmd, { encoding: 'utf8' }) + } catch (error) { + if (process.env.DEBUG === 'true') console.log(cmd, error) + expect((error as ExecError).stdout).toContain('playlist_test/ag.m3u') + expect((error as ExecError).stdout).toContain('2 problems (1 errors, 1 warnings)') + } + }) +}) diff --git a/tests/commands/playlist/update.test.ts b/tests/commands/playlist/update.test.ts index db4258442d..d8552e3d25 100644 --- a/tests/commands/playlist/update.test.ts +++ b/tests/commands/playlist/update.test.ts @@ -1,40 +1,49 @@ -import { pathToFileURL } from 'node:url' -import { execSync } from 'child_process' -import * as fs from 'fs-extra' -import { glob } from 'glob' - -const ENV_VAR = 'cross-env DATA_DIR=tests/__data__/input/data STREAMS_DIR=tests/__data__/output/streams' - -beforeEach(() => { - fs.emptyDirSync('tests/__data__/output') - fs.copySync('tests/__data__/input/playlist_update', 'tests/__data__/output/streams') -}) - -describe('playlist:update', () => { - it('can update playlists', () => { - const cmd = `${ENV_VAR} npm run playlist:update --silent` - const stdout = execSync(cmd, { encoding: 'utf8' }) - if (process.env.DEBUG === 'true') console.log(cmd, stdout) - - const files = glob.sync('tests/__data__/expected/playlist_update/*.m3u').map(filepath => { - const fileUrl = pathToFileURL(filepath).toString() - const pathToRemove = pathToFileURL('tests/__data__/expected/playlist_update/').toString() - - return fileUrl.replace(pathToRemove, '') - }) - - files.forEach(filepath => { - expect(content(`tests/__data__/output/streams/${filepath}`)).toBe( - content(`tests/__data__/expected/playlist_update/${filepath}`) - ) - }) - - expect(stdout).toBe( - 'OUTPUT=closes #14151, closes #14150, closes #14110, closes #14120, closes #14175, closes #14105, closes #14104, closes #14057, closes #14034, closes #13964, closes #13893, closes #13881, closes #13793, closes #13751, closes #13715\n' - ) - }) -}) - -function content(filepath: string) { - return fs.readFileSync(pathToFileURL(filepath), { encoding: 'utf8' }) -} +import { pathToFileURL } from 'node:url' +import { execSync } from 'child_process' +import * as fs from 'fs-extra' +import { glob } from 'glob' + +const ENV_VAR = + 'cross-env DATA_DIR=tests/__data__/input/data STREAMS_DIR=tests/__data__/output/streams' + +beforeEach(() => { + fs.emptyDirSync('tests/__data__/output') + fs.copySync('tests/__data__/input/playlist_update', 'tests/__data__/output/streams') +}) + +describe('playlist:update', () => { + it('can update playlists', done => { + let cmd = `${ENV_VAR} npm run playlist:update` + if (!process.env.DEBUG) cmd += ' --silent' + try { + const stdout = execSync(cmd, { encoding: 'utf8' }) + if (process.env.DEBUG === 'true') console.log(cmd, stdout) + + const files = glob.sync('tests/__data__/expected/playlist_update/*.m3u').map(filepath => { + const fileUrl = pathToFileURL(filepath).toString() + const pathToRemove = pathToFileURL('tests/__data__/expected/playlist_update/').toString() + + return fileUrl.replace(pathToRemove, '') + }) + + files.forEach(filepath => { + expect(content(`tests/__data__/output/streams/${filepath}`)).toBe( + content(`tests/__data__/expected/playlist_update/${filepath}`) + ) + }) + + expect(stdout).toBe( + 'OUTPUT=closes #14151, closes #14150, closes #14110, closes #14120, closes #14175, closes #14105, closes #14104, closes #14057, closes #14034, closes #13964, closes #13893, closes #13881, closes #13793, closes #13751, closes #13715\n' + ) + + done() + } catch (err) { + if (process.env.DEBUG === 'true') console.log(cmd, err.stdout) + done(err) + } + }) +}) + +function content(filepath: string) { + return fs.readFileSync(pathToFileURL(filepath), { encoding: 'utf8' }) +} diff --git a/tests/commands/playlist/validate.test.ts b/tests/commands/playlist/validate.test.ts index a2532933fd..597916c49a 100644 --- a/tests/commands/playlist/validate.test.ts +++ b/tests/commands/playlist/validate.test.ts @@ -1,44 +1,45 @@ -import { execSync } from 'child_process' - -type ExecError = { - status: number - stdout: string -} - -const ENV_VAR = 'cross-env DATA_DIR=tests/__data__/input/data ROOT_DIR=tests/__data__/input/playlist_validate' - -describe('playlist:validate', () => { - it('show an error if channel id in the blocklist', () => { - const cmd = `${ENV_VAR} npm run playlist:validate -- us_blocked.m3u` - try { - execSync(cmd, { encoding: 'utf8' }) - } catch (error) { - if (process.env.DEBUG === 'true') console.log(cmd, error) - expect((error as ExecError).stdout).toContain('us_blocked.m3u') - expect((error as ExecError).stdout).toContain( - '2 error "FoxSports2.us" is on the blocklist due to claims of copyright holders (https://github.com/iptv-org/iptv/issues/0002)' - ) - expect((error as ExecError).stdout).toContain( - '4 error "TVN.pl" is on the blocklist due to NSFW content (https://github.com/iptv-org/iptv/issues/0003)' - ) - expect((error as ExecError).stdout).toContain('2 problems (2 errors, 0 warnings)') - } - }) - - it('show a warning if channel has wrong id', () => { - const cmd = `${ENV_VAR} npm run playlist:validate -- wrong_id.m3u` - try { - execSync(cmd, { encoding: 'utf8' }) - } catch (error) { - if (process.env.DEBUG === 'true') console.log(cmd, error) - expect((error as ExecError).stdout).toContain( - 'wrong_id.m3u\n 2 warning "qib22lAq1L.us" is not in the database\n\n1 problems (0 errors, 1 warnings)\n' - ) - } - }) - - it('skip the file if it does not exist', () => { - const cmd = `${ENV_VAR} npm run playlist:validate -- missing.m3u` - execSync(cmd, { encoding: 'utf8' }) - }) -}) +import { execSync } from 'child_process' + +type ExecError = { + status: number + stdout: string +} + +const ENV_VAR = + 'cross-env DATA_DIR=tests/__data__/input/data ROOT_DIR=tests/__data__/input/playlist_validate' + +describe('playlist:validate', () => { + it('show an error if channel id in the blocklist', () => { + const cmd = `${ENV_VAR} npm run playlist:validate -- us_blocked.m3u` + try { + execSync(cmd, { encoding: 'utf8' }) + } catch (error) { + if (process.env.DEBUG === 'true') console.log(cmd, error) + expect((error as ExecError).stdout).toContain('us_blocked.m3u') + expect((error as ExecError).stdout).toContain( + '2 error "FoxSports2.us" is on the blocklist due to claims of copyright holders (https://github.com/iptv-org/iptv/issues/0002)' + ) + expect((error as ExecError).stdout).toContain( + '4 error "TVN.pl" is on the blocklist due to NSFW content (https://github.com/iptv-org/iptv/issues/0003)' + ) + expect((error as ExecError).stdout).toContain('2 problems (2 errors, 0 warnings)') + } + }) + + it('show a warning if channel has wrong id', () => { + const cmd = `${ENV_VAR} npm run playlist:validate -- wrong_id.m3u` + try { + execSync(cmd, { encoding: 'utf8' }) + } catch (error) { + if (process.env.DEBUG === 'true') console.log(cmd, error) + expect((error as ExecError).stdout).toContain( + 'wrong_id.m3u\n 2 warning "qib22lAq1L.us" is not in the database\n\n1 problems (0 errors, 1 warnings)\n' + ) + } + }) + + it('skip the file if it does not exist', () => { + const cmd = `${ENV_VAR} npm run playlist:validate -- missing.m3u` + execSync(cmd, { encoding: 'utf8' }) + }) +}) diff --git a/tests/commands/readme/update.test.ts b/tests/commands/readme/update.test.ts index 12bfece329..422a52d54f 100644 --- a/tests/commands/readme/update.test.ts +++ b/tests/commands/readme/update.test.ts @@ -1,26 +1,26 @@ -import { pathToFileURL } from 'node:url' -import { execSync } from 'child_process' -import fs from 'fs-extra' - -const ENV_VAR = - 'cross-env DATA_DIR=tests/__data__/input/data LOGS_DIR=tests/__data__/input/readme_update ROOT_DIR=tests/__data__/output' - -beforeEach(() => { - fs.emptyDirSync('tests/__data__/output') -}) - -describe('readme:update', () => { - it('can update readme.md', () => { - const cmd = `${ENV_VAR} npm run readme:update` - const stdout = execSync(cmd, { encoding: 'utf8' }) - if (process.env.DEBUG === 'true') console.log(cmd, stdout) - - expect(content('tests/__data__/output/PLAYLISTS.md')).toEqual( - content('tests/__data__/expected/readme_update/playlists.md') - ) - }) -}) - -function content(filepath: string) { - return JSON.stringify(fs.readFileSync(pathToFileURL(filepath), { encoding: 'utf8' })) -} +import { pathToFileURL } from 'node:url' +import { execSync } from 'child_process' +import fs from 'fs-extra' + +const ENV_VAR = + 'cross-env DATA_DIR=tests/__data__/input/data LOGS_DIR=tests/__data__/input/readme_update ROOT_DIR=tests/__data__/output' + +beforeEach(() => { + fs.emptyDirSync('tests/__data__/output') +}) + +describe('readme:update', () => { + it('can update readme.md', () => { + const cmd = `${ENV_VAR} npm run readme:update` + const stdout = execSync(cmd, { encoding: 'utf8' }) + if (process.env.DEBUG === 'true') console.log(cmd, stdout) + + expect(content('tests/__data__/output/PLAYLISTS.md')).toEqual( + content('tests/__data__/expected/readme_update/playlists.md') + ) + }) +}) + +function content(filepath: string) { + return JSON.stringify(fs.readFileSync(pathToFileURL(filepath), { encoding: 'utf8' })) +} diff --git a/tests/commands/report/create.test.ts b/tests/commands/report/create.test.ts index 344a33aea9..cb9fd3ab98 100644 --- a/tests/commands/report/create.test.ts +++ b/tests/commands/report/create.test.ts @@ -1,29 +1,30 @@ -import { execSync } from 'child_process' - -const ENV_VAR = 'cross-env DATA_DIR=tests/__data__/input/data STREAMS_DIR=tests/__data__/input/report_create' - -describe('report:create', () => { - it('can create report', () => { - const cmd = `${ENV_VAR} npm run report:create` - const stdout = execSync(cmd, { encoding: 'utf8' }) - if (process.env.DEBUG === 'true') console.log(cmd, stdout) - - expect( - stdout.includes(` -┌─────────┬─────────────┬──────────────────┬─────────────────────────────┬───────────────────────────────────────────────────────────────────────────────────────────────────────────┬────────────────┐ -│ (index) │ issueNumber │ type │ streamId │ streamUrl │ status │ -├─────────┼─────────────┼──────────────────┼─────────────────────────────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────┼────────────────┤ -│ 0 │ 14120 │ 'streams:edit' │ 'boo.us' │ 'https://livestream.telvue.com/templeuni1/f7b44cfafd5c52223d5498196c8a2e7b.sdp/playlist.m3u8' │ 'invalid_id' │ -│ 1 │ 14135 │ 'streams:add' │ 'BBCWorldNews.uk@SouthAsia' │ 'http://103.199.161.254/Content/bbcworld/Live/Channel%28BBCworld%29/Stream%2801%29/index.m3u8' │ 'wrong_id' │ -│ 2 │ 14177 │ 'streams:add' │ 'TUTV.us' │ 'https://livestream.telvue.com/templeuni1/f7b44cfafd5c52223d5498196c8a2e7b.sdp/playlist.m3u8' │ 'on_playlist' │ -│ 3 │ 14178 │ 'streams:add' │ 'TV3.my' │ 'https://live-streams-ssai-01.tonton.com.my/live/2dd2b7cd-1b34-4871-b669-57b5c9beca23/live.isml/.m3u8...' │ 'blocked' │ -│ 4 │ 14179 │ 'streams:add' │ 'ManoramaNews.in' │ '(https://mitelefe.com/Api/Videos/GetSourceUrl/694564/0/HLS / https://ssl.cloud.telefe.com/Api/Videos...' │ 'invalid_link' │ -│ 5 │ 16120 │ 'streams:remove' │ undefined │ 'http://190.61.102.67:2000/play/a038/index.m3u8' │ 'wrong_link' │ -│ 6 │ 19956 │ 'channel search' │ 'CNBCe.tr' │ undefined │ 'invalid_id' │ -│ 7 │ 19957 │ 'channel search' │ '13thStreet.au' │ undefined │ 'closed' │ -│ 8 │ 20956 │ 'channel search' │ 'IONTV.us' │ undefined │ 'fulfilled' │ -│ 9 │ 25157 │ 'streams:add' │ 'OnTimeSports.eg@SD' │ 'OnTime Sports SD.mu38' │ 'invalid_link' │ -└─────────┴─────────────┴──────────────────┴─────────────────────────────┴───────────────────────────────────────────────────────────────────────────────────────────────────────────┴────────────────┘`) - ).toBe(true) - }) -}) +import { execSync } from 'child_process' + +const ENV_VAR = + 'cross-env DATA_DIR=tests/__data__/input/data STREAMS_DIR=tests/__data__/input/report_create' + +describe('report:create', () => { + it('can create report', () => { + const cmd = `${ENV_VAR} npm run report:create` + const stdout = execSync(cmd, { encoding: 'utf8' }) + if (process.env.DEBUG === 'true') console.log(cmd, stdout) + + expect( + stdout.includes(` +┌─────────┬─────────────┬──────────────────┬─────────────────────────────┬────────────────────────────────────────────────────────────────────────────────────────────────────────┬──────────────────────┐ +│ (index) │ issueNumber │ type │ streamId │ streamUrl │ status │ +├─────────┼─────────────┼──────────────────┼─────────────────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────────────────────┤ +│ 0 │ 14120 │ 'streams:edit' │ 'boo.us' │ 'https://livestream.telvue.com/templeuni1/f7b44cfafd5c52223d5498196c8a2e7b.sdp/playlist.m3u8' │ 'invalid_channel_id' │ +│ 1 │ 14135 │ 'streams:add' │ 'BBCWorldNews.uk@SouthAsia' │ 'http://103.199.161.254/Content/bbcworld/Live/Channel%28BBCworld%29/Stream%2801%29/index.m3u8' │ 'invalid_channel_id' │ +│ 2 │ 14177 │ 'streams:add' │ 'TUTV.us' │ 'https://livestream.telvue.com/templeuni1/f7b44cfafd5c52223d5498196c8a2e7b.sdp/playlist.m3u8' │ 'duplicate_link' │ +│ 3 │ 14178 │ 'streams:add' │ 'TV3.my' │ 'https://live-streams-ssai-01.tonton.com.my/live/2dd2b7cd-1b34-4871-b669-57b5c9beca23/live.isml/.m...' │ 'channel_blocked' │ +│ 4 │ 14179 │ 'streams:add' │ 'ManoramaNews.in' │ '(https://mitelefe.com/Api/Videos/GetSourceUrl/694564/0/HLS / https://ssl.cloud.telefe.com/Api/Vid...' │ 'invalid_stream_url' │ +│ 5 │ 16120 │ 'streams:remove' │ undefined │ 'http://190.61.102.67:2000/play/a038/index.m3u8' │ 'nonexistent_link' │ +│ 6 │ 19956 │ 'channel search' │ 'CNBCe.tr' │ undefined │ 'invalid_channel_id' │ +│ 7 │ 19957 │ 'channel search' │ '13thStreet.au' │ undefined │ 'channel_closed' │ +│ 8 │ 20956 │ 'channel search' │ 'IONTV.us' │ undefined │ 'fulfilled' │ +│ 9 │ 25157 │ 'streams:add' │ 'OnTimeSports.eg@SD' │ 'OnTime Sports SD.mu38' │ 'invalid_stream_url' │ +└─────────┴─────────────┴──────────────────┴─────────────────────────────┴────────────────────────────────────────────────────────────────────────────────────────────────────────┴──────────────────────┘`) + ).toBe(true) + }) +}) diff --git a/tsconfig.json b/tsconfig.json index f1ad2f4b13..657998950d 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,20 +1,20 @@ -{ - "compilerOptions": { - "strict": true, - "target": "es2022", - "module": "nodeNext", - "moduleResolution": "nodeNext", - "typeRoots": [ - "./scripts/types", - "./node_modules/@types" - ], - "esModuleInterop": true - }, - "ts-node": { - "esm": true, - "transpileOnly": true - }, - "files": [ - "node_modules/jest-expect-message/types/index.d.ts" - ] +{ + "compilerOptions": { + "strict": true, + "target": "es2022", + "module": "nodeNext", + "moduleResolution": "nodeNext", + "typeRoots": [ + "./scripts/types", + "./node_modules/@types" + ], + "esModuleInterop": true + }, + "ts-node": { + "esm": true, + "transpileOnly": true + }, + "files": [ + "node_modules/jest-expect-message/types/index.d.ts" + ] } \ No newline at end of file