From f52c07c77d9ecb7a2a425dca7da1eb43c42329bd Mon Sep 17 00:00:00 2001 From: Aleksandr Statciuk Date: Sun, 12 Dec 2021 07:08:26 +0300 Subject: [PATCH 01/34] Update auto-update.yml --- .github/workflows/auto-update.yml | 313 +++++++----------------------- 1 file changed, 72 insertions(+), 241 deletions(-) diff --git a/.github/workflows/auto-update.yml b/.github/workflows/auto-update.yml index dec1f3be64..5fc625e2bf 100644 --- a/.github/workflows/auto-update.yml +++ b/.github/workflows/auto-update.yml @@ -4,279 +4,110 @@ on: schedule: - cron: '0 0,12 * * *' jobs: - create-branch: + setup: runs-on: ubuntu-latest - outputs: - branch_name: ${{ steps.set-branch-name.outputs.branch_name }} steps: - - name: Checkout - uses: actions/checkout@v2 - with: - ref: ${{ github.ref }} - - name: Set Branch Name - id: set-branch-name - run: echo "::set-output name=branch_name::$(date +'bot/auto-update-%Y%m%d%H%M00')" - - name: Create Branch - uses: peterjgrainger/action-create-branch@v2.0.1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - branch: ${{ steps.set-branch-name.outputs.branch_name }} - create-matrix: - runs-on: ubuntu-latest - needs: create-branch - outputs: - matrix: ${{ steps.set-matrix.outputs.matrix }} - steps: - - name: Checkout - uses: actions/checkout@v2 - with: - ref: ${{ needs.create-branch.outputs.branch_name }} - - name: Setup Node - uses: actions/setup-node@v2 + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 + if: ${{ !env.ACT }} with: node-version: '14' cache: 'npm' - - name: Install Dependencies - run: npm install - - name: Create Matrix - id: set-matrix - run: node scripts/create-matrix.js - format: + - run: npm install + - run: node scripts/commands/create-database.js + - run: node scripts/commands/create-matrix.js + id: create-matrix + - uses: actions/upload-artifact@v2 + with: + name: database + path: scripts/channels.db + outputs: + matrix: ${{ steps.create-matrix.outputs.matrix }} + load: runs-on: ubuntu-latest - needs: [create-matrix, create-branch] + needs: setup continue-on-error: true strategy: fail-fast: false - matrix: ${{fromJSON(needs.create-matrix.outputs.matrix)}} + matrix: ${{ fromJson(needs.setup.outputs.matrix) }} steps: - - name: Checkout - uses: actions/checkout@v2 + - uses: actions/checkout@v2 + - uses: actions/download-artifact@v2 with: - ref: ${{ needs.create-branch.outputs.branch_name }} - - name: Setup FFmpeg - uses: FedericoCarboni/setup-ffmpeg@v1 - - name: Setup Node - uses: actions/setup-node@v2 + name: database + path: scripts + - uses: FedericoCarboni/setup-ffmpeg@v1 + - uses: actions/setup-node@v2 + if: ${{ !env.ACT }} with: node-version: '14' - cache: 'npm' - - name: Install Dependencies - run: npm install - - name: Format Playlists - run: node scripts/format.js --country=${{ matrix.country }} --debug - - name: Upload Artifact - uses: actions/upload-artifact@v2 + - run: npm install + - run: node scripts/commands/check-streams.js --cluster-id=${{ matrix.cluster_id }} + - uses: actions/upload-artifact@v2 with: - name: channels - path: channels/${{ matrix.country }}.m3u - commit-changes: + name: logs + path: scripts/logs + update: runs-on: ubuntu-latest - needs: [format, create-branch] + needs: load steps: - - name: Checkout - uses: actions/checkout@v2 + - uses: actions/checkout@v2 + - run: echo "::set-output name=branch_name::$(date +'bot/auto-update-%s')" + id: create-branch-name + - run: | + git config user.name 'iptv-bot[bot]' + git config user.email '84861620+iptv-bot[bot]@users.noreply.github.com' + - run: git checkout -b ${{ steps.create-branch-name.outputs.branch_name }} + - run: curl -L -o scripts/data/codes.json https://iptv-org.github.io/epg/codes.json + - uses: actions/download-artifact@v2 with: - ref: ${{ needs.create-branch.outputs.branch_name }} - - name: Download Artifacts - uses: actions/download-artifact@v2 + name: database + path: scripts + - uses: actions/download-artifact@v2 with: - name: channels - path: channels - - name: Commit Changes - uses: stefanzweifel/git-auto-commit-action@v4 - with: - commit_message: '[Bot] Format playlists' - commit_user_name: iptv-bot - commit_user_email: 84861620+iptv-bot[bot]@users.noreply.github.com - commit_author: 'iptv-bot[bot] <84861620+iptv-bot[bot]@users.noreply.github.com>' - branch: ${{ needs.create-branch.outputs.branch_name }} - file_pattern: channels/* - remove-duplicates: - runs-on: ubuntu-latest - needs: [commit-changes, create-branch] - steps: - - name: Checkout - uses: actions/checkout@v2 - with: - ref: ${{ needs.create-branch.outputs.branch_name }} - - name: Setup Node - uses: actions/setup-node@v2 - with: - node-version: '14' - cache: 'npm' - - name: Install Dependencies - run: npm install - - name: Remove Duplicates - run: node scripts/remove-duplicates.js - - name: Commit Changes - uses: stefanzweifel/git-auto-commit-action@v4 - with: - commit_message: '[Bot] Remove duplicates' - commit_user_name: iptv-bot - commit_user_email: 84861620+iptv-bot[bot]@users.noreply.github.com - commit_author: 'iptv-bot[bot] <84861620+iptv-bot[bot]@users.noreply.github.com>' - branch: ${{ needs.create-branch.outputs.branch_name }} - file_pattern: channels/* - sort: - runs-on: ubuntu-latest - needs: [remove-duplicates, create-branch] - steps: - - name: Checkout - uses: actions/checkout@v2 - with: - ref: ${{ needs.create-branch.outputs.branch_name }} - - name: Setup Node - uses: actions/setup-node@v2 - with: - node-version: '14' - cache: 'npm' - - name: Install Dependencies - run: npm install - - name: Sort Channels - run: node scripts/sort.js - - name: Commit Changes - uses: stefanzweifel/git-auto-commit-action@v4 - with: - commit_message: '[Bot] Sort channels' - commit_user_name: iptv-bot - commit_user_email: 84861620+iptv-bot[bot]@users.noreply.github.com - commit_author: 'iptv-bot[bot] <84861620+iptv-bot[bot]@users.noreply.github.com>' - branch: ${{ needs.create-branch.outputs.branch_name }} - file_pattern: channels/* - filter: - runs-on: ubuntu-latest - needs: [sort, create-branch] - steps: - - name: Checkout - uses: actions/checkout@v2 - with: - ref: ${{ needs.create-branch.outputs.branch_name }} - - name: Setup Node - uses: actions/setup-node@v2 - with: - node-version: '14' - cache: 'npm' - - name: Install Dependencies - run: npm install - - name: Filter Playlists - run: node scripts/filter.js - - name: Commit Changes - uses: stefanzweifel/git-auto-commit-action@v4 - with: - commit_message: '[Bot] Filter channels' - commit_user_name: iptv-bot - commit_user_email: 84861620+iptv-bot[bot]@users.noreply.github.com - commit_author: 'iptv-bot[bot] <84861620+iptv-bot[bot]@users.noreply.github.com>' - branch: ${{ needs.create-branch.outputs.branch_name }} - file_pattern: channels/* - generate: - runs-on: ubuntu-latest - needs: [filter, create-branch] - steps: - - name: Checkout - uses: actions/checkout@v2 - with: - ref: ${{ needs.create-branch.outputs.branch_name }} - - name: Setup Node - uses: actions/setup-node@v2 - with: - node-version: '14' - cache: 'npm' - - name: Install Dependencies - run: npm install - - name: Generate Playlists - run: node scripts/generate.js - - name: Upload Artifact - uses: actions/upload-artifact@v2 - with: - name: gh-pages - path: .gh-pages/ - deploy: - runs-on: ubuntu-latest - needs: [generate, create-branch] - steps: - - name: Checkout - uses: actions/checkout@v2 - with: - ref: ${{ needs.create-branch.outputs.branch_name }} - - name: Download Artifacts - uses: actions/download-artifact@v2 - with: - name: gh-pages - path: .gh-pages - - name: Generate Token - uses: tibdex/github-app-token@v1 - id: generate-token + name: logs + path: scripts/logs + - run: npm install + - run: node scripts/commands/update-database.js + - run: node scripts/commands/update-playlists.js + - run: | + git add channels/* + git commit -m "[Bot] Update playlists" + - run: node scripts/commands/generate-playlists.js + - run: node scripts/commands/update-readme.js + - run: | + git add README.md + git commit -m "[Bot] Update README.md" + - uses: tibdex/github-app-token@v1 + if: ${{ !env.ACT }} + id: create-app-token with: app_id: ${{ secrets.APP_ID }} private_key: ${{ secrets.APP_PRIVATE_KEY }} - - name: Deploy to GitHub Pages + - uses: JamesIves/github-pages-deploy-action@4.1.1 if: ${{ github.ref == 'refs/heads/master' }} - uses: JamesIves/github-pages-deploy-action@4.1.1 with: branch: gh-pages folder: .gh-pages - token: ${{ steps.generate-token.outputs.token }} - git-config-name: iptv-bot + 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' - update-readme: - runs-on: ubuntu-latest - needs: [generate, create-branch] - steps: - - name: Checkout - uses: actions/checkout@v2 + commit-message: '[Bot] Generate playlists' + - uses: repo-sync/pull-request@v2 + if: ${{ !env.ACT }} + id: pull-request with: - ref: ${{ needs.create-branch.outputs.branch_name }} - - name: Setup Node - uses: actions/setup-node@v2 - with: - node-version: '14' - cache: 'npm' - - name: Install Dependencies - run: npm install - - name: Update README.md - run: node scripts/update-readme.js - - name: Commit Changes - uses: stefanzweifel/git-auto-commit-action@v4 - with: - commit_message: '[Bot] Update README.md' - commit_user_name: iptv-bot - commit_user_email: 84861620+iptv-bot[bot]@users.noreply.github.com - commit_author: 'iptv-bot[bot] <84861620+iptv-bot[bot]@users.noreply.github.com>' - branch: ${{ needs.create-branch.outputs.branch_name }} - file_pattern: README.md - pull-request: - if: ${{ github.ref == 'refs/heads/master' }} - needs: [update-readme, create-branch] - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v2 - with: - ref: ${{ needs.create-branch.outputs.branch_name }} - - name: Generate Token - uses: tibdex/github-app-token@v1 - id: generate-token - with: - app_id: ${{ secrets.APP_ID }} - private_key: ${{ secrets.APP_PRIVATE_KEY }} - - name: Create Pull Request - id: pr - uses: repo-sync/pull-request@v2 - with: - source_branch: ${{ needs.create-branch.outputs.branch_name }} + github_token: ${{ steps.create-app-token.outputs.token }} + source_branch: ${{ steps.create-branch-name.outputs.branch_name }} destination_branch: 'master' - pr_title: '[Bot] Update playlists' + pr_title: '[Bot] Daily playlists update' pr_body: | This pull request is created by [auto-update][1] workflow. [1]: https://github.com/iptv-org/iptv/actions/runs/${{ github.run_id }} - github_token: ${{ steps.generate-token.outputs.token }} - - name: Merge Pull Request - uses: juliangruber/merge-pull-request-action@v1 + - uses: juliangruber/merge-pull-request-action@v1 + if: ${{ github.ref == 'refs/heads/master' }} with: github-token: ${{ secrets.PAT }} - number: ${{ steps.pr.outputs.pr_number }} + number: ${{ steps.pull-request.outputs.pr_number }} method: squash From c02b14c785bbcb62182538e29e1dd812f8dd90fc Mon Sep 17 00:00:00 2001 From: Aleksandr Statciuk Date: Sun, 12 Dec 2021 07:08:29 +0300 Subject: [PATCH 02/34] Update check.yml --- .github/workflows/check.yml | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index a557daedf1..6792edc057 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -4,12 +4,15 @@ on: pull_request: types: [opened, synchronize, reopened, edited] jobs: - lint: + check: runs-on: ubuntu-latest steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Install Dependencies - run: npm install - - name: Check Playlists - run: npm run lint + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 + if: ${{ !env.ACT }} + with: + node-version: '14' + cache: 'npm' + - run: npm install + - run: npm run lint + - run: npm run validate From cd0d26d08a1a286a0af15d7054d8268e3fefb239 Mon Sep 17 00:00:00 2001 From: Aleksandr Statciuk Date: Sun, 12 Dec 2021 07:08:31 +0300 Subject: [PATCH 03/34] Update cleanup.yml --- .github/workflows/cleanup.yml | 79 ++++++++++------------------------- 1 file changed, 23 insertions(+), 56 deletions(-) diff --git a/.github/workflows/cleanup.yml b/.github/workflows/cleanup.yml index a030d6bc67..fb7a67d447 100644 --- a/.github/workflows/cleanup.yml +++ b/.github/workflows/cleanup.yml @@ -2,65 +2,32 @@ name: cleanup on: workflow_dispatch: jobs: - create-branch: + cleanup: runs-on: ubuntu-latest steps: - - name: Checkout - uses: actions/checkout@v2 - with: - ref: ${{ github.ref }} - - name: Create Branch - uses: peterjgrainger/action-create-branch@v2.0.1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - branch: 'bot/cleanup' - remove-broken-links: - runs-on: ubuntu-latest - needs: create-branch - steps: - - name: Checkout - uses: actions/checkout@v2 - with: - ref: bot/cleanup - - name: Install Dependencies - run: npm install - - name: Remove Broken Links - run: node scripts/remove-broken-links.js - - name: Commit Changes - uses: stefanzweifel/git-auto-commit-action@v4 - with: - commit_message: '[Bot] Remove broken links' - commit_user_name: iptv-bot - commit_user_email: 84861620+iptv-bot[bot]@users.noreply.github.com - commit_author: 'iptv-bot[bot] <84861620+iptv-bot[bot]@users.noreply.github.com>' - branch: bot/cleanup - file_pattern: channels/* - pull-request: - if: ${{ github.ref == 'refs/heads/master' }} - runs-on: ubuntu-latest - needs: remove-broken-links - steps: - - name: Checkout - uses: actions/checkout@v2 - with: - ref: bot/cleanup - - name: Generate Token - uses: tibdex/github-app-token@v1 - id: generate-token + - uses: actions/checkout@v2 + - run: npm install + - run: node scripts/commands/create-database.js + - run: node scripts/commands/cleanup-database.js + - run: node scripts/commands/update-playlists.js + - uses: tibdex/github-app-token@v1 + if: ${{ !env.ACT }} + id: create-app-token with: app_id: ${{ secrets.APP_ID }} private_key: ${{ secrets.APP_PRIVATE_KEY }} - - name: Create Pull Request - id: pr - uses: repo-sync/pull-request@v2 - with: - source_branch: 'bot/cleanup' - destination_branch: 'master' - pr_title: '[Bot] Cleaning playlists' - pr_body: | - This pull request is created by [cleanup][1] workflow. + - uses: peter-evans/create-pull-request@v3 + if: ${{ github.ref == 'refs/heads/master' }} + token: ${{ steps.create-app-token.outputs.token }} + commit-message: '[Bot] Update playlists' + committer: 'iptv-bot[bot] <84861620+iptv-bot[bot]@users.noreply.github.com>' + author: 'iptv-bot[bot] <84861620+iptv-bot[bot]@users.noreply.github.com>' + branch: bot/cleanup + branch-suffix: timestamp + delete-branch: true + base: master + title: '[Bot] Remove broken links' + body: | + This pull request is created by [cleanup][1] workflow. - [1]: https://github.com/iptv-org/iptv/actions/runs/${{ github.run_id }} - pr_draft: true - github_token: ${{ steps.generate-token.outputs.token }} + [1]: https://github.com/iptv-org/iptv/actions/runs/${{ github.run_id }} From 28c2fdf3a4a1f6e1d875de8f0e947e7f4807fdc8 Mon Sep 17 00:00:00 2001 From: Aleksandr Statciuk Date: Sun, 12 Dec 2021 07:08:34 +0300 Subject: [PATCH 04/34] Update .gitignore --- .gitignore | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index b512c09d47..91905e1feb 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,6 @@ -node_modules \ No newline at end of file +node_modules +database +.artifacts +.secrets +.actrc +.DS_Store \ No newline at end of file From 11952218326da6e75d0fca8b03776612ced40675 Mon Sep 17 00:00:00 2001 From: Aleksandr Statciuk Date: Sun, 12 Dec 2021 07:08:39 +0300 Subject: [PATCH 05/34] Update .gitignore --- .readme/.gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.readme/.gitignore b/.readme/.gitignore index 778ddef3ca..a2ac441348 100644 --- a/.readme/.gitignore +++ b/.readme/.gitignore @@ -1,3 +1,4 @@ _categories.md _countries.md -_languages.md \ No newline at end of file +_languages.md +_regions.md \ No newline at end of file From 952e8192a23c9eace6e80808847bcdf3e5ede3ff Mon Sep 17 00:00:00 2001 From: Aleksandr Statciuk Date: Sun, 12 Dec 2021 07:09:11 +0300 Subject: [PATCH 06/34] Rename to supported-regions.md --- .readme/{supported-region-codes.md => supported-regions.md} | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename .readme/{supported-region-codes.md => supported-regions.md} (92%) diff --git a/.readme/supported-region-codes.md b/.readme/supported-regions.md similarity index 92% rename from .readme/supported-region-codes.md rename to .readme/supported-regions.md index a575740c6d..0b0a9656c6 100644 --- a/.readme/supported-region-codes.md +++ b/.readme/supported-regions.md @@ -1,4 +1,4 @@ -## Supported Region Codes +## Supported Regions | Code | Description | | ------------------------------------------------------------------------ | ---------------------------------- | @@ -10,11 +10,11 @@ | [CARIB](https://en.wikipedia.org/wiki/Caribbean) | Caribbean | | [CAS](https://en.wikipedia.org/wiki/Central_Asia) | Central Asia | | [CIS](https://en.wikipedia.org/wiki/Commonwealth_of_Independent_States) | Commonwealth of Independent States | -| [EMEA](https://en.wikipedia.org/wiki/Europe,_the_Middle_East_and_Africa) | Europe, Middle East and Africa | +| [EMEA](https://en.wikipedia.org/wiki/Europe,_the_Middle_East_and_Africa) | Europe, the Middle East and Africa | | [EUR](https://en.wikipedia.org/wiki/Europe) | Europe | | [HISPAM](https://en.wikipedia.org/wiki/Hispanic_America) | Hispanic America | | [LATAM](https://en.wikipedia.org/wiki/Latin_America) | Latin America | -| [MAGHRIB](https://en.wikipedia.org/wiki/Maghreb) | Maghrib | +| [MAGHREB](https://en.wikipedia.org/wiki/Maghreb) | Maghreb | | [MENA](https://en.wikipedia.org/wiki/MENA) | Middle East and North Africa | | [MIDEAST](https://en.wikipedia.org/wiki/Middle_East) | Middle East | | [NORAM](https://en.wikipedia.org/wiki/North_America) | North America | From 09b1ebc6871aa6dffd65f38a8d2649f465899fb4 Mon Sep 17 00:00:00 2001 From: Aleksandr Statciuk Date: Sun, 12 Dec 2021 07:09:13 +0300 Subject: [PATCH 07/34] Create supported-statuses.md --- .readme/supported-statuses.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .readme/supported-statuses.md diff --git a/.readme/supported-statuses.md b/.readme/supported-statuses.md new file mode 100644 index 0000000000..ec5f076065 --- /dev/null +++ b/.readme/supported-statuses.md @@ -0,0 +1,8 @@ +## Supported Statuses + +| Label | Description | +| ----------- | ------------------------------------------------- | +| Geo-blocked | Channel is only available in selected countries. | +| Not 24/7 | Broadcast is not available 24 hours a day. | +| Timeout | Server does not respond for more than 60 seconds. | +| Offline | The broadcast does not work for any other reason. | From 631fbe7f78f90da9579a38fed5c9931517592a43 Mon Sep 17 00:00:00 2001 From: Aleksandr Statciuk Date: Sun, 12 Dec 2021 07:09:18 +0300 Subject: [PATCH 08/34] Update template.md --- .readme/template.md | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/.readme/template.md b/.readme/template.md index 43dce5682d..ba3185499e 100644 --- a/.readme/template.md +++ b/.readme/template.md @@ -14,9 +14,10 @@ To watch IPTV you just need to paste this link `https://iptv-org.github.io/iptv/ Also you can instead use one of these playlists: -- `https://iptv-org.github.io/iptv/index.country.m3u` (grouped by country) - `https://iptv-org.github.io/iptv/index.category.m3u` (grouped by category) - `https://iptv-org.github.io/iptv/index.language.m3u` (grouped by language) +- `https://iptv-org.github.io/iptv/index.country.m3u` (grouped by country) +- `https://iptv-org.github.io/iptv/index.region.m3u` (grouped by region) - `https://iptv-org.github.io/iptv/index.nsfw.m3u` (includes adult channels) Or select one of the playlists from the list below. @@ -43,6 +44,17 @@ Or select one of the playlists from the list below. +### Playlists by region + +
+Expand +
+ + +#include "./.readme/_regions.md" + +
+ ### Playlists by country
@@ -77,11 +89,10 @@ If successful, you should get the following response: "name": "CNN", "logo": "https://i.imgur.com/ilZJT5s.png", "url": "http://ott-cdn.ucom.am/s27/index.m3u8", - "category": "News", - "languages": [ + "categories": [ { - "code": "eng", - "name": "English" + "name": "News", + "slug": "news" } ], "countries": [ @@ -94,6 +105,12 @@ If successful, you should get the following response: "name": "Canada" } ], + "languages": [ + { + "code": "eng", + "name": "English" + } + ], "tvg": { "id": "cnn.us", "name": "CNN", From 3b7e5c9a972e5b7dfc23d1290634ce322d73fcd7 Mon Sep 17 00:00:00 2001 From: Aleksandr Statciuk Date: Sun, 12 Dec 2021 07:09:21 +0300 Subject: [PATCH 09/34] Update CONTRIBUTING.md --- CONTRIBUTING.md | 64 ++++++++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 35 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2d835b3e83..0fb17cabf1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -11,15 +11,15 @@ Before submitting your contribution, please make sure to take a moment and read ### Request a Channel -To request a channel, create an [issue](https://github.com/iptv-org/iptv/issues/new?assignees=&labels=channel+request&template=------channel-request.md&title=Add%3A+xxx) and complete all details requested. (**IMPORTANT:** the issue should contain a request for only one channel, otherwise it will be closed immediately). Understand that our community of volunteers will try to help you, but if a public link cannot be found, there is little we can do. +To request a channel, create an [issue](https://github.com/iptv-org/iptv/issues/new?assignees=&labels=channel+request&template=------channel-request.md) and complete all details requested. Understand that our community of volunteers will try to help you, but if a public link cannot be found, there is little we can do. (**IMPORTANT:** the issue should contain a request for only one channel, otherwise it will be closed immediately) ### Report a Broken Stream -To report a broadcast that is not working, create an [issue](https://github.com/iptv-org/iptv/issues/new?assignees=&labels=broken+stream&template=----broken-stream.md&title=Fix%3A+xxx) with a description of the channel (**IMPORTANT:** an issue should contain a report for only one channel, otherwise it will be closed immediately). +To report a broadcast that is not working, create an [issue](https://github.com/iptv-org/iptv/issues/new?assignees=&labels=broken+stream&template=----broken-stream.md) with a description of the channel. (**IMPORTANT:** an issue should contain a report for only one channel, otherwise it will be closed immediately) ### Request Channel Removal -Publish your DMCA notice somewhere and send us a link to it through this [form](https://github.com/iptv-org/iptv/issues/new?assignees=&labels=DMCA&template=--remove-channel.md&title=Remove%3A+xxx). +Publish your DMCA notice somewhere and send us a link to it through this [form](https://github.com/iptv-org/iptv/issues/new?assignees=&labels=DMCA&template=--remove-channel.md). ## Pull Request Guidelines @@ -29,12 +29,13 @@ If you would like to replace a broken stream or add a new one, please do the fol - make sure that the link you want to add works by using a program like [VLC media player](https://www.videolan.org/vlc/index.html) - check if the channel is working outside your country by using a VPN or use a service like [streamtest.in](https://streamtest.in/) -- if the broadcast is not available outside of a certain country, add the label `[Geo-blocked]` to the end of the channel name - find out from which country the channel is being broadcasted. This information can usually be found on [lyngsat.com](https://www.lyngsat.com/search.html) or [wikipedia.org](https://www.wikipedia.org/). If you are unable to determine which country the channel belongs to, add the channel onto the `channels/unsorted.m3u` playlist - find the corresponding [ISO_3166-2 code](https://en.wikipedia.org/wiki/ISO_3166-2) for the country - open the `/channels` folder and find the file that has the same code in its name and open it - if broken, find the broken link in this file and replace it with working one - if new, at the very end of this file add a link to the channel with a description +- if the broadcast is not available outside of a certain country, add the label `[Geo-blocked]` to the end of the channel name and list these countries in the `tvg-country` attribute +- if the broadcast is not available 24 hours a day, add the label `[Not 24/7]` - commit all changes and send a pull request ### Add a Category to a Channel @@ -77,7 +78,7 @@ If a channel is broadcasted in several countries at once, you can specify them a http://example.com/cnn.m3u8 ``` -If a channel is broadcast for an entire region, you can use one of the [supported region code](https://github.com/iptv-org/iptv/blob/master/.readme/supported-region-codes.md) to avoid listing all countries. In this case the channel will be added to the playlists of all countries from that region. +If a channel is broadcast for an entire region, you can use one of the [supported region code](https://github.com/iptv-org/iptv/blob/master/.readme/supported-regions.md) to avoid listing all countries. In this case the channel will be added to the playlists of all countries from that region. In case the channel is broadcast worldwide you can use the code `INT`: @@ -117,31 +118,31 @@ For a channel to be approved, its description must follow this template: STREAM_URL ``` -| Attribute | Description | -| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `EPG_ID` | Channel ID that is used to load EPG. Must match `id` from the EPG file. (optional) | -| `COUNTRY` | The code of the country in which the channel is broadcast. The code of the country must conform to the standard [ISO_3166-2](https://en.wikipedia.org/wiki/ISO_3166-2). If the channel is broadcast in several countries you can list them separated by a semicolon. You can also use one of these [region codes](#supported-region-codes). (optional) | -| `LANGUAGE` | Channel language. The name of the language must conform to the standard [ISO 639-3](https://iso639-3.sil.org/code_tables/639/data?title=&field_iso639_cd_st_mmbrshp_639_1_tid=94671&name_3=&field_iso639_element_scope_tid=All&field_iso639_language_type_tid=51&items_per_page=500). If the channel is broadcast in several languages you can list them separated by a semicolon. (optional) | -| `LOGO_URL` | The logo of the channel that will be displayed if the player supports it. Supports files in png, jpeg and gif format. (optional) | -| `CATEGORY` | The category to which the channel belongs. The list of currently supported categories can be found [here](https://github.com/iptv-org/iptv#playlists-by-category). (optional) | -| `FULL_NAME` | Full name of the channel. It is recommended to use the name listed on [lyngsat](https://www.lyngsat.com/search.html) or [wikipedia](https://www.wikipedia.org/) if possible. May contain any characters except round and square brackets. | -| `STREAM_TIME_SHIFT` | Must be specified if the channel is broadcast with a shift in time relative to the main stream. Should only contain a number and a sign. (optional) | -| `ALTERNATIVE_NAME` | Can be used to specify a short name or name in another language. May contain any characters except round and square brackets. (optional) | -| `STREAM_RESOLUTION` | The maximum height of the frame with a "p" at the end. In case of VLC Player this information can be found in `Window > Media Information... > Codec Details`. (optional) | -| `STREAM_STATUS` | Specified if the broadcast for some reason is interrupted or does not work in a particular application. May contain any characters except round and square brackets. (optional) | -| `STREAM_URL` | Channel broadcast URL. | +| Attribute | Description | +| ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `EPG_ID` | Channel ID that is used to load EPG. The same ID is used in [iptv-org/epg](https://iptv-org.github.io/epg/index.html) to search for the corresponding program. (optional) | +| `COUNTRY` | The code of the country in which the channel is broadcast. The code of the country must conform to the standard [ISO_3166-2](https://en.wikipedia.org/wiki/ISO_3166-2). If the channel is broadcast in several countries you can list them separated by a semicolon. You can also use one of these [region codes](https://github.com/iptv-org/iptv/blob/master/.readme/supported-regions.md). (optional) | +| `LANGUAGE` | Channel language. The name of the language must conform to the standard [ISO 639-3](https://iso639-3.sil.org/code_tables/639/data?title=&field_iso639_cd_st_mmbrshp_639_1_tid=94671&name_3=&field_iso639_element_scope_tid=All&field_iso639_language_type_tid=51&items_per_page=500). If the channel is broadcast in several languages you can list them separated by a semicolon. (optional) | +| `LOGO_URL` | The logo of the channel that will be displayed if the player supports it. Supports files in png, jpeg and gif format. (optional) | +| `CATEGORY` | The category to which the channel belongs. The list of currently supported categories can be found [here](https://github.com/iptv-org/iptv/blob/master/.readme/supported-categories.md). (optional) | +| `FULL_NAME` | Full name of the channel. It is recommended to use the name listed on [lyngsat](https://www.lyngsat.com/search.html) or [wikipedia](https://www.wikipedia.org/) if possible. May contain any characters except round and square brackets. | +| `STREAM_TIME_SHIFT` | Must be specified if the channel is broadcast with a shift in time relative to the main stream. Should only contain a number and a sign. (optional) | +| `ALTERNATIVE_NAME` | Can be used to specify a short name or name in another language. May contain any characters except round and square brackets. (optional) | +| `STREAM_RESOLUTION` | The maximum height of the frame with a "p" at the end. In case of VLC Player this information can be found in `Window > Media Information... > Codec Details`. (optional) | +| `STREAM_STATUS` | Specified if the broadcast for some reason is interrupted or does not work in a particular application. The list of currently supported statuses can be found [here](https://github.com/iptv-org/iptv/blob/master/.readme/supported-statuses.md). (optional) | +| `STREAM_URL` | Channel broadcast URL. | Example: ```xml -#EXTINF:-1 tvg-id="example.ua" tvg-country="UA" tvg-language="Ukrainian;Russian" tvg-logo="https://i.imgur.com/bu12f89.png" group-title="Kids",Example TV +3 (Пример ТВ) (720p) [not 24/7] +#EXTINF:-1 tvg-id="ExampleTVPlus3.ua" tvg-country="UA" tvg-language="Ukrainian;Russian" tvg-logo="https://i.imgur.com/bu12f89.png" group-title="Kids",Example TV +3 (Пример ТВ) (720p) [not 24/7] https://example.com/playlist.m3u8 ``` Also, if necessary, you can specify custom HTTP User-Agent or Referrer via the `#EXTVLCOPT` tag: ```xml -#EXTINF:-1 tvg-id="exampletv.us" tvg-country="US" tvg-language="English" tvg-logo="http://example.com/channel-logo.png" group-title="News",Example TV +#EXTINF:-1 tvg-id="ExampleTV.us" tvg-country="US" tvg-language="English" tvg-logo="http://example.com/channel-logo.png" group-title="News",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 @@ -152,29 +153,22 @@ http://example.com/stream.m3u8 - `.github/` - `ISSUE_TEMPLATE/`: issue templates for this repository. - `workflows/` - - `auto-update.yml`: GitHub workflow that automatically updates all playlists every day. - - `check.yml`: GitHub workflow that automatically checks every pull request for syntax errors. - - `cleanup.yml`: GitHub workflow that automatically removes broken links every week. + - `auto-update.yml`: GitHub workflow that launches daily playlist updates (at 0:00 and 12:00 UTC). + - `check.yml`: GitHub workflow that checks every pull request for syntax errors. + - `cleanup.yml`: GitHub workflow that removes broken links by request. + - `validate.yml`: GitHub workflow that compares channel names with the blocklist each time a pull request is made. - `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 `README.md` file. - `preview.png`: image displayed in the `README.md`. - `supported-categories.md`: list of supported categories. - - `supported-region-codes.md`: list of supported region codes. + - `supported-statuses.md`: list of supported statuses. + - `supported-regions.md`: list of supported regions. - `template.md`: template for `README.md`. - `channels/`: contains all channels broken down by the country from which they are broadcast. - ... - `unsorted.m3u`: playlist with channels not yet sorted. -- `scripts/` - - `data/`: data used in scripts. - - `helpers/`: helper scripts. - - `create-matrix.js`: used within GitHub workflow to create matrix of files to process. - - `filter.js`: used within GitHub workflow to remove blacklisted channels from playlists. - - `format.js`: used within GitHub workflow to format channel descriptions. - - `generate.js`: used within GitHub workflow to generate all additional playlists. - - `remove-broken-links.js`: used in GitHub workflow to remove broken links from the playlist. - - `remove-duplicates.js`: used in GitHub workflow to remove duplicates from the playlist. - - `sort.js`: used within GitHub workflow to sort channels by name. - - `update-readme.js`: used within GitHub workflow to update the `README.md` file. +- `scripts/`: contains all the scripts used in GitHub workflows. +- `tests/`: contains tests to check the scripts in the folder above. - `CONTRIBUTING.md`: file you are currently reading. - `README.md`: project description generated from the contents of the `.readme/` folder. From b31e5a680e8d5a6d821429e42b0342707cd2ae13 Mon Sep 17 00:00:00 2001 From: Aleksandr Statciuk Date: Sun, 12 Dec 2021 07:09:35 +0300 Subject: [PATCH 10/34] Update package.json --- package.json | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index f9d4990522..a6473023e2 100644 --- a/package.json +++ b/package.json @@ -1,25 +1,31 @@ { "name": "iptv", "scripts": { - "lint": "npx m3u-linter -c m3u-linter.json" + "validate": "node scripts/commands/validate.js", + "lint": "npx m3u-linter -c m3u-linter.json", + "test": "jest --runInBand" + }, + "jest": { + "testRegex": "tests/(.*?/)?.*test.js$" }, - "pre-push": [ - "lint" - ], "author": "Arhey", "private": true, "license": "MIT", "dependencies": { - "axios": "^0.21.4", + "chunk": "^0.0.3", "commander": "^7.0.0", - "iptv-checker": "^0.21.0", - "iptv-playlist-parser": "^0.9.0", + "crypto": "^1.0.1", + "dayjs": "^1.10.7", + "iptv-checker": "^0.22.0", + "iptv-playlist-parser": "^0.10.2", + "jest": "^27.4.3", + "lodash": "^4.17.21", "m3u-linter": "^0.2.2", "markdown-include": "^0.4.3", - "natural-orderby": "^2.0.3", + "mz": "^2.7.0", + "nedb-promises": "^5.0.2", "normalize-url": "^6.1.0", - "pre-push": "^0.1.1", - "progress": "^2.0.3", - "transliteration": "^2.2.0" + "transliteration": "^2.2.0", + "winston": "^3.3.3" } } From eb5ee814e5fe6f7a332fd9acacc04ce08b7fdca7 Mon Sep 17 00:00:00 2001 From: Aleksandr Statciuk Date: Sun, 12 Dec 2021 07:09:37 +0300 Subject: [PATCH 11/34] Update package-lock.json --- package-lock.json | 5405 ++++++++------------------------------------- 1 file changed, 942 insertions(+), 4463 deletions(-) diff --git a/package-lock.json b/package-lock.json index 79b5aac5e7..f319e70611 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,3871 +1,35 @@ { "name": "iptv", - "lockfileVersion": 2, "requires": true, - "packages": { - "": { - "name": "iptv", - "license": "MIT", - "dependencies": { - "axios": "^0.21.4", - "commander": "^7.0.0", - "iptv-checker": "^0.21.0", - "iptv-playlist-parser": "^0.9.0", - "m3u-linter": "^0.2.2", - "markdown-include": "^0.4.3", - "natural-orderby": "^2.0.3", - "normalize-url": "^6.1.0", - "pre-push": "^0.1.1", - "progress": "^2.0.3", - "transliteration": "^2.2.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", - "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==", - "dependencies": { - "@babel/highlight": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.15.0.tgz", - "integrity": "sha512-0NqAC1IJE0S0+lL1SWFMxMkz1pKCNCjI4tr2Zx4LJSXxCLAdr6KyArnY+sno5m3yH9g737ygOyPABDsnXkpxiA==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.15.0.tgz", - "integrity": "sha512-tXtmTminrze5HEUPn/a0JtOzzfp0nk+UEXQ/tqIJo3WDGypl/2OFQEMll/zSFU8f/lfmfLXvTaORHF3cfXIQMw==", - "dependencies": { - "@babel/code-frame": "^7.14.5", - "@babel/generator": "^7.15.0", - "@babel/helper-compilation-targets": "^7.15.0", - "@babel/helper-module-transforms": "^7.15.0", - "@babel/helpers": "^7.14.8", - "@babel/parser": "^7.15.0", - "@babel/template": "^7.14.5", - "@babel/traverse": "^7.15.0", - "@babel/types": "^7.15.0", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.1.2", - "semver": "^6.3.0", - "source-map": "^0.5.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/core/node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@babel/generator": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.15.0.tgz", - "integrity": "sha512-eKl4XdMrbpYvuB505KTta4AV9g+wWzmVBW69tX0H2NwKVKd2YJbKgyK6M8j/rgLbmHOYJn6rUklV677nOyJrEQ==", - "dependencies": { - "@babel/types": "^7.15.0", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/generator/node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.15.0.tgz", - "integrity": "sha512-h+/9t0ncd4jfZ8wsdAsoIxSa61qhBYlycXiHWqJaQBCXAhDCMbPRSMTGnZIkkmt1u4ag+UQmuqcILwqKzZ4N2A==", - "dependencies": { - "@babel/compat-data": "^7.15.0", - "@babel/helper-validator-option": "^7.14.5", - "browserslist": "^4.16.6", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.14.5.tgz", - "integrity": "sha512-Gjna0AsXWfFvrAuX+VKcN/aNNWonizBj39yGwUzVDVTlMYJMK2Wp6xdpy72mfArFq5uK+NOuexfzZlzI1z9+AQ==", - "dependencies": { - "@babel/helper-get-function-arity": "^7.14.5", - "@babel/template": "^7.14.5", - "@babel/types": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-get-function-arity": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.14.5.tgz", - "integrity": "sha512-I1Db4Shst5lewOM4V+ZKJzQ0JGGaZ6VY1jYvMghRjqs6DWgxLCIyFt30GlnKkfUeFLpJt2vzbMVEXVSXlIFYUg==", - "dependencies": { - "@babel/types": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-hoist-variables": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.14.5.tgz", - "integrity": "sha512-R1PXiz31Uc0Vxy4OEOm07x0oSjKAdPPCh3tPivn/Eo8cvz6gveAeuyUUPB21Hoiif0uoPQSSdhIPS3352nvdyQ==", - "dependencies": { - "@babel/types": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.15.0.tgz", - "integrity": "sha512-Jq8H8U2kYiafuj2xMTPQwkTBnEEdGKpT35lJEQsRRjnG0LW3neucsaMWLgKcwu3OHKNeYugfw+Z20BXBSEs2Lg==", - "dependencies": { - "@babel/types": "^7.15.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.14.5.tgz", - "integrity": "sha512-SwrNHu5QWS84XlHwGYPDtCxcA0hrSlL2yhWYLgeOc0w7ccOl2qv4s/nARI0aYZW+bSwAL5CukeXA47B/1NKcnQ==", - "dependencies": { - "@babel/types": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.15.0.tgz", - "integrity": "sha512-RkGiW5Rer7fpXv9m1B3iHIFDZdItnO2/BLfWVW/9q7+KqQSDY5kUfQEbzdXM1MVhJGcugKV7kRrNVzNxmk7NBg==", - "dependencies": { - "@babel/helper-module-imports": "^7.14.5", - "@babel/helper-replace-supers": "^7.15.0", - "@babel/helper-simple-access": "^7.14.8", - "@babel/helper-split-export-declaration": "^7.14.5", - "@babel/helper-validator-identifier": "^7.14.9", - "@babel/template": "^7.14.5", - "@babel/traverse": "^7.15.0", - "@babel/types": "^7.15.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.14.5.tgz", - "integrity": "sha512-IqiLIrODUOdnPU9/F8ib1Fx2ohlgDhxnIDU7OEVi+kAbEZcyiF7BLU8W6PfvPi9LzztjS7kcbzbmL7oG8kD6VA==", - "dependencies": { - "@babel/types": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz", - "integrity": "sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-replace-supers": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.15.0.tgz", - "integrity": "sha512-6O+eWrhx+HEra/uJnifCwhwMd6Bp5+ZfZeJwbqUTuqkhIT6YcRhiZCOOFChRypOIe0cV46kFrRBlm+t5vHCEaA==", - "dependencies": { - "@babel/helper-member-expression-to-functions": "^7.15.0", - "@babel/helper-optimise-call-expression": "^7.14.5", - "@babel/traverse": "^7.15.0", - "@babel/types": "^7.15.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-simple-access": { - "version": "7.14.8", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.14.8.tgz", - "integrity": "sha512-TrFN4RHh9gnWEU+s7JloIho2T76GPwRHhdzOWLqTrMnlas8T9O7ec+oEDNsRXndOmru9ymH9DFrEOxpzPoSbdg==", - "dependencies": { - "@babel/types": "^7.14.8" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.14.5.tgz", - "integrity": "sha512-hprxVPu6e5Kdp2puZUmvOGjaLv9TCe58E/Fl6hRq4YiVQxIcNvuq6uTM2r1mT/oPskuS9CgR+I94sqAYv0NGKA==", - "dependencies": { - "@babel/types": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.14.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz", - "integrity": "sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz", - "integrity": "sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.14.8", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.14.8.tgz", - "integrity": "sha512-ZRDmI56pnV+p1dH6d+UN6GINGz7Krps3+270qqI9UJ4wxYThfAIcI5i7j5vXC4FJ3Wap+S9qcebxeYiqn87DZw==", - "dependencies": { - "@babel/template": "^7.14.5", - "@babel/traverse": "^7.14.8", - "@babel/types": "^7.14.8" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", - "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", - "dependencies": { - "@babel/helper-validator-identifier": "^7.14.5", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" - }, - "node_modules/@babel/highlight/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/parser": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.15.0.tgz", - "integrity": "sha512-0v7oNOjr6YT9Z2RAOTv4T9aP+ubfx4Q/OhVtAet7PFDt0t9Oy6Jn+/rfC6b8HJ5zEqrQCiMxJfgtHpmIminmJQ==", - "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==", - "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==", - "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==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" - }, - "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==", - "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==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.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==", - "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==", - "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==", - "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==", - "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==", - "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==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.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==", - "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.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.14.5.tgz", - "integrity": "sha512-u6OXzDaIXjEstBRRoBCQ/uKQKlbuaeE5in0RvWdA4pN6AhqxTIwUsnHPU1CFZA/amYObMsuWhYfRl3Ch90HD0Q==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/template": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.14.5.tgz", - "integrity": "sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g==", - "dependencies": { - "@babel/code-frame": "^7.14.5", - "@babel/parser": "^7.14.5", - "@babel/types": "^7.14.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.15.0.tgz", - "integrity": "sha512-392d8BN0C9eVxVWd8H6x9WfipgVH5IaIoLp23334Sc1vbKKWINnvwRpb4us0xtPaCumlwbTtIYNA0Dv/32sVFw==", - "dependencies": { - "@babel/code-frame": "^7.14.5", - "@babel/generator": "^7.15.0", - "@babel/helper-function-name": "^7.14.5", - "@babel/helper-hoist-variables": "^7.14.5", - "@babel/helper-split-export-declaration": "^7.14.5", - "@babel/parser": "^7.15.0", - "@babel/types": "^7.15.0", - "debug": "^4.1.0", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/types": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.0.tgz", - "integrity": "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==", - "dependencies": { - "@babel/helper-validator-identifier": "^7.14.9", - "to-fast-properties": "^2.0.0" - }, - "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==" - }, - "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==", - "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/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/console": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.0.6.tgz", - "integrity": "sha512-fMlIBocSHPZ3JxgWiDNW/KPj6s+YRd0hicb33IrmelCcjXo/pXPwvuiKFmZz+XuqI/1u7nbUK10zSsWL/1aegg==", - "dependencies": { - "@jest/types": "^27.0.6", - "@types/node": "*", - "chalk": "^4.0.0", - "jest-message-util": "^27.0.6", - "jest-util": "^27.0.6", - "slash": "^3.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/@jest/core": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-27.0.6.tgz", - "integrity": "sha512-SsYBm3yhqOn5ZLJCtccaBcvD/ccTLCeuDv8U41WJH/V1MW5eKUkeMHT9U+Pw/v1m1AIWlnIW/eM2XzQr0rEmow==", - "dependencies": { - "@jest/console": "^27.0.6", - "@jest/reporters": "^27.0.6", - "@jest/test-result": "^27.0.6", - "@jest/transform": "^27.0.6", - "@jest/types": "^27.0.6", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "emittery": "^0.8.1", - "exit": "^0.1.2", - "graceful-fs": "^4.2.4", - "jest-changed-files": "^27.0.6", - "jest-config": "^27.0.6", - "jest-haste-map": "^27.0.6", - "jest-message-util": "^27.0.6", - "jest-regex-util": "^27.0.6", - "jest-resolve": "^27.0.6", - "jest-resolve-dependencies": "^27.0.6", - "jest-runner": "^27.0.6", - "jest-runtime": "^27.0.6", - "jest-snapshot": "^27.0.6", - "jest-util": "^27.0.6", - "jest-validate": "^27.0.6", - "jest-watcher": "^27.0.6", - "micromatch": "^4.0.4", - "p-each-series": "^2.1.0", - "rimraf": "^3.0.0", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/@jest/environment": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.0.6.tgz", - "integrity": "sha512-4XywtdhwZwCpPJ/qfAkqExRsERW+UaoSRStSHCCiQTUpoYdLukj+YJbQSFrZjhlUDRZeNiU9SFH0u7iNimdiIg==", - "dependencies": { - "@jest/fake-timers": "^27.0.6", - "@jest/types": "^27.0.6", - "@types/node": "*", - "jest-mock": "^27.0.6" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/@jest/fake-timers": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.0.6.tgz", - "integrity": "sha512-sqd+xTWtZ94l3yWDKnRTdvTeZ+A/V7SSKrxsrOKSqdyddb9CeNRF8fbhAU0D7ZJBpTTW2nbp6MftmKJDZfW2LQ==", - "dependencies": { - "@jest/types": "^27.0.6", - "@sinonjs/fake-timers": "^7.0.2", - "@types/node": "*", - "jest-message-util": "^27.0.6", - "jest-mock": "^27.0.6", - "jest-util": "^27.0.6" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/@jest/globals": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.0.6.tgz", - "integrity": "sha512-DdTGCP606rh9bjkdQ7VvChV18iS7q0IMJVP1piwTWyWskol4iqcVwthZmoJEf7obE1nc34OpIyoVGPeqLC+ryw==", - "dependencies": { - "@jest/environment": "^27.0.6", - "@jest/types": "^27.0.6", - "expect": "^27.0.6" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/@jest/reporters": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-27.0.6.tgz", - "integrity": "sha512-TIkBt09Cb2gptji3yJXb3EE+eVltW6BjO7frO7NEfjI9vSIYoISi5R3aI3KpEDXlB1xwB+97NXIqz84qYeYsfA==", - "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^27.0.6", - "@jest/test-result": "^27.0.6", - "@jest/transform": "^27.0.6", - "@jest/types": "^27.0.6", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.2", - "graceful-fs": "^4.2.4", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^4.0.3", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.0.2", - "jest-haste-map": "^27.0.6", - "jest-resolve": "^27.0.6", - "jest-util": "^27.0.6", - "jest-worker": "^27.0.6", - "slash": "^3.0.0", - "source-map": "^0.6.0", - "string-length": "^4.0.1", - "terminal-link": "^2.0.0", - "v8-to-istanbul": "^8.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/@jest/source-map": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.0.6.tgz", - "integrity": "sha512-Fek4mi5KQrqmlY07T23JRi0e7Z9bXTOOD86V/uS0EIW4PClvPDqZOyFlLpNJheS6QI0FNX1CgmPjtJ4EA/2M+g==", - "dependencies": { - "callsites": "^3.0.0", - "graceful-fs": "^4.2.4", - "source-map": "^0.6.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/@jest/test-result": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.0.6.tgz", - "integrity": "sha512-ja/pBOMTufjX4JLEauLxE3LQBPaI2YjGFtXexRAjt1I/MbfNlMx0sytSX3tn5hSLzQsR3Qy2rd0hc1BWojtj9w==", - "dependencies": { - "@jest/console": "^27.0.6", - "@jest/types": "^27.0.6", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/@jest/test-sequencer": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-27.0.6.tgz", - "integrity": "sha512-bISzNIApazYOlTHDum9PwW22NOyDa6VI31n6JucpjTVM0jD6JDgqEZ9+yn575nDdPF0+4csYDxNNW13NvFQGZA==", - "dependencies": { - "@jest/test-result": "^27.0.6", - "graceful-fs": "^4.2.4", - "jest-haste-map": "^27.0.6", - "jest-runtime": "^27.0.6" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/@jest/transform": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.0.6.tgz", - "integrity": "sha512-rj5Dw+mtIcntAUnMlW/Vju5mr73u8yg+irnHwzgtgoeI6cCPOvUwQ0D1uQtc/APmWgvRweEb1g05pkUpxH3iCA==", - "dependencies": { - "@babel/core": "^7.1.0", - "@jest/types": "^27.0.6", - "babel-plugin-istanbul": "^6.0.0", - "chalk": "^4.0.0", - "convert-source-map": "^1.4.0", - "fast-json-stable-stringify": "^2.0.0", - "graceful-fs": "^4.2.4", - "jest-haste-map": "^27.0.6", - "jest-regex-util": "^27.0.6", - "jest-util": "^27.0.6", - "micromatch": "^4.0.4", - "pirates": "^4.0.1", - "slash": "^3.0.0", - "source-map": "^0.6.1", - "write-file-atomic": "^3.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/@jest/types": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.0.6.tgz", - "integrity": "sha512-aSquT1qa9Pik26JK5/3rvnYb4bGtm1VFNesHKmNTwmPIgOrixvhL2ghIvFRNEpzy3gU+rUgjIF/KodbkFAl++g==", - "dependencies": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^16.0.0", - "chalk": "^4.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/@sinonjs/commons": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", - "integrity": "sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==", - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/@sinonjs/fake-timers": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-7.1.2.tgz", - "integrity": "sha512-iQADsW4LBMISqZ6Ci1dupJL9pprqwcVFTcOsEmQOEhW+KLCVn/Y4Jrvg2k19fIHCp+iFprriYPTdRcQR8NbUPg==", - "dependencies": { - "@sinonjs/commons": "^1.7.0" - } - }, - "node_modules/@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "engines": { - "node": ">= 6" - } - }, - "node_modules/@types/babel__core": { - "version": "7.1.15", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.15.tgz", - "integrity": "sha512-bxlMKPDbY8x5h6HBwVzEOk2C8fb6SLfYQ5Jw3uBYuYF1lfWk/kbLd81la82vrIkBb0l+JdmrZaDikPrNxpS/Ew==", - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "node_modules/@types/babel__generator": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.3.tgz", - "integrity": "sha512-/GWCmzJWqV7diQW54smJZzWbSFf4QYtF71WCKhcx6Ru/tFyQIY2eiiITcCAeuPbNSvT9YCGkVMqqvSk2Z0mXiA==", - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__template": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz", - "integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==", - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__traverse": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.14.2.tgz", - "integrity": "sha512-K2waXdXBi2302XUdcHcR1jCeU0LL4TD9HRs/gk0N2Xvrht+G/BfJa4QObBQZfhMdxiCpV3COl5Nfq4uKTeTnJA==", - "dependencies": { - "@babel/types": "^7.3.0" - } - }, - "node_modules/@types/graceful-fs": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", - "integrity": "sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz", - "integrity": "sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw==" - }, - "node_modules/@types/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", - "dependencies": { - "@types/istanbul-lib-coverage": "*" - } - }, - "node_modules/@types/istanbul-reports": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz", - "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==", - "dependencies": { - "@types/istanbul-lib-report": "*" - } - }, - "node_modules/@types/node": { - "version": "16.4.13", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.4.13.tgz", - "integrity": "sha512-bLL69sKtd25w7p1nvg9pigE4gtKVpGTPojBFLMkGHXuUgap2sLqQt2qUnqmVCDfzGUL0DRNZP+1prIZJbMeAXg==" - }, - "node_modules/@types/prettier": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.3.2.tgz", - "integrity": "sha512-eI5Yrz3Qv4KPUa/nSIAi0h+qX0XyewOliug5F2QAtuRg6Kjg6jfmxe1GIwoIRhZspD1A0RP8ANrPwvEXXtRFog==" - }, - "node_modules/@types/stack-utils": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", - "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==" - }, - "node_modules/@types/yargs": { - "version": "16.0.4", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", - "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", - "dependencies": { - "@types/yargs-parser": "*" - } - }, - "node_modules/@types/yargs-parser": { - "version": "20.2.1", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.1.tgz", - "integrity": "sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw==" - }, - "node_modules/abab": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz", - "integrity": "sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==" - }, - "node_modules/acorn": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.4.1.tgz", - "integrity": "sha512-asabaBSkEKosYKMITunzX177CXxQ4Q8BSSzMTKD+FefUhipQC70gfW5SiUDhYQ3vk8G+81HqQk7Fv9OXwwn9KA==", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-globals": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", - "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", - "dependencies": { - "acorn": "^7.1.1", - "acorn-walk": "^7.1.1" - } - }, - "node_modules/acorn-globals/node_modules/acorn": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-walk": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", - "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "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": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "engines": { - "node": ">=8" - } - }, - "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" - } - }, - "node_modules/anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" - }, - "node_modules/axios": { - "version": "0.21.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", - "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", - "dependencies": { - "follow-redirects": "^1.14.0" - } - }, - "node_modules/babel-jest": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.0.6.tgz", - "integrity": "sha512-iTJyYLNc4wRofASmofpOc5NK9QunwMk+TLFgGXsTFS8uEqmd8wdI7sga0FPe2oVH3b5Agt/EAK1QjPEuKL8VfA==", - "dependencies": { - "@jest/transform": "^27.0.6", - "@jest/types": "^27.0.6", - "@types/babel__core": "^7.1.14", - "babel-plugin-istanbul": "^6.0.0", - "babel-preset-jest": "^27.0.6", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.4", - "slash": "^3.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.8.0" - } - }, - "node_modules/babel-plugin-istanbul": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.0.0.tgz", - "integrity": "sha512-AF55rZXpe7trmEylbaE1Gv54wn6rwU03aptvRoVIGP8YykoSxqdVLV1TfwflBCE/QtHmqtP8SWlTENqbK8GCSQ==", - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^4.0.0", - "test-exclude": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/babel-plugin-jest-hoist": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.0.6.tgz", - "integrity": "sha512-CewFeM9Vv2gM7Yr9n5eyyLVPRSiBnk6lKZRjgwYnGKSl9M14TMn2vkN02wTF04OGuSDLEzlWiMzvjXuW9mB6Gw==", - "dependencies": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.0.0", - "@types/babel__traverse": "^7.0.6" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/babel-preset-current-node-syntax": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz", - "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==", - "dependencies": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.8.3", - "@babel/plugin-syntax-import-meta": "^7.8.3", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.8.3", - "@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-top-level-await": "^7.8.3" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/babel-preset-jest": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.0.6.tgz", - "integrity": "sha512-WObA0/Biw2LrVVwZkF/2GqbOdzhKD6Fkdwhoy9ASIrOWr/zodcSpQh72JOkEn6NWyjmnPDjNSqaGN4KnpKzhXw==", - "dependencies": { - "babel-plugin-jest-hoist": "^27.0.6", - "babel-preset-current-node-syntax": "^1.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.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/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browser-process-hrtime": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", - "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==" - }, - "node_modules/browserslist": { - "version": "4.16.7", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.7.tgz", - "integrity": "sha512-7I4qVwqZltJ7j37wObBe3SoTz+nS8APaNcrBOlgoirb6/HbEU2XxW/LpUDTCngM6iauwFqmRTuOMfyKnFGY5JA==", - "dependencies": { - "caniuse-lite": "^1.0.30001248", - "colorette": "^1.2.2", - "electron-to-chromium": "^1.3.793", - "escalade": "^3.1.1", - "node-releases": "^1.1.73" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - } - }, - "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==", - "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==" - }, - "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==", - "engines": { - "node": ">=6" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001249", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001249.tgz", - "integrity": "sha512-vcX4U8lwVXPdqzPWi6cAJ3FnQaqXbBqy/GZseKNQzRj37J7qZdGcBtxq/QLFNLLlfsoXLUdHw8Iwenri86Tagw==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - } - }, - "node_modules/chalk": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", - "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "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==", - "engines": { - "node": ">=10" - } - }, - "node_modules/ci-info": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.2.0.tgz", - "integrity": "sha512-dVqRX7fLUm8J6FgHJ418XuIgDLZDkYcDFTeL6TA2gt5WlIZUQrrH6EZrNClwT/H0FateUsZkGIOPRrLbP+PR9A==" - }, - "node_modules/cjs-module-lexer": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", - "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==" - }, - "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "engines": { - "iojs": ">= 1.0.0", - "node": ">= 0.12.0" - } - }, - "node_modules/collect-v8-coverage": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", - "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==" - }, - "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/colorette": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", - "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==" - }, - "node_modules/colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", - "engines": { - "node": ">=0.1.90" - } - }, - "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/command-exists": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", - "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==" - }, - "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/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "node_modules/convert-source-map": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", - "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", - "dependencies": { - "safe-buffer": "~5.1.1" - } - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/cssom": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", - "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==" - }, - "node_modules/cssstyle": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", - "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", - "dependencies": { - "cssom": "~0.3.6" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cssstyle/node_modules/cssom": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==" - }, - "node_modules/data-urls": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", - "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", - "dependencies": { - "abab": "^2.0.3", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^8.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/dateformat": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", - "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", - "engines": { - "node": "*" - } - }, - "node_modules/debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decimal.js": { - "version": "10.3.1", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.3.1.tgz", - "integrity": "sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==" - }, - "node_modules/dedent": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", - "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=" - }, - "node_modules/deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" - }, - "node_modules/deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", - "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": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "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==", - "engines": { - "node": ">=8" - } - }, - "node_modules/diff-sequences": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.0.6.tgz", - "integrity": "sha512-ag6wfpBFyNXZ0p8pcuIDS//D8H062ZQJ3fzYxjpmeKjnz8W4pekL3AI8VohmyZmsWW2PWaHgjsmqR6L13101VQ==", - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/domexception": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", - "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", - "dependencies": { - "webidl-conversions": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/domexception/node_modules/webidl-conversions": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", - "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", - "engines": { - "node": ">=8" - } - }, - "node_modules/electron-to-chromium": { - "version": "1.3.799", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.799.tgz", - "integrity": "sha512-V2rbYWdGvSqrg+95KjkVuSi41bGfrhrOzjl1tSi2VLnm0mRe3FsSvhiqidSiSll9WiMhrQAhpDcW/wcqK3c+Yw==" - }, - "node_modules/emittery": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz", - "integrity": "sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==", - "engines": { - "node": ">=10" - }, - "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/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "engines": { - "node": ">=6" - } - }, - "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==", - "engines": { - "node": ">=8" - } - }, - "node_modules/escodegen": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", - "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", - "dependencies": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1" - }, - "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" - }, - "engines": { - "node": ">=6.0" - }, - "optionalDependencies": { - "source-map": "~0.6.1" - } - }, - "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==", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "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==", - "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/exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/expect": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/expect/-/expect-27.0.6.tgz", - "integrity": "sha512-psNLt8j2kwg42jGBDSfAlU49CEZxejN1f1PlANWDZqIhBOVU/c2Pm888FcjWJzFewhIsNWfZJeLjUjtKGiPuSw==", - "dependencies": { - "@jest/types": "^27.0.6", - "ansi-styles": "^5.0.0", - "jest-get-type": "^27.0.6", - "jest-matcher-utils": "^27.0.6", - "jest-message-util": "^27.0.6", - "jest-regex-util": "^27.0.6" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/expect/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==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "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": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=" - }, - "node_modules/fb-watchman": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.1.tgz", - "integrity": "sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==", - "dependencies": { - "bser": "2.1.1" - } - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "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==", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/follow-redirects": { - "version": "1.14.4", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.4.tgz", - "integrity": "sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/form-data": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", - "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" - }, - "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==", - "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-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/get-stdin": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-7.0.0.tgz", - "integrity": "sha512-zRKcywvrXlXsA0v0i9Io4KDRaAw7+a1ZpjRwl9Wox8PFlVCCHra7E9c4kqXCoCM9nR5tBkaTTZRBoCm60bFqTQ==", - "engines": { - "node": ">=8" - } - }, - "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==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - } - }, - "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "engines": { - "node": ">=4" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", - "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==" - }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, - "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==", - "engines": { - "node": ">=8" - } - }, - "node_modules/html-encoding-sniffer": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", - "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", - "dependencies": { - "whatwg-encoding": "^1.0.5" - }, - "engines": { - "node": ">=10" - } - }, - "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==" - }, - "node_modules/http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "dependencies": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "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==", - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/import-local": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.2.tgz", - "integrity": "sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA==", - "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "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==" - }, - "node_modules/iptv-checker": { - "version": "0.21.0", - "resolved": "https://registry.npmjs.org/iptv-checker/-/iptv-checker-0.21.0.tgz", - "integrity": "sha512-qWqq8mLl+qRgV0/fmBpZm8/Cf7FwSnIA1gt9PFlYbzilRDFtPoTRDm0eP9fCWHVwwZZsImE1aMLx8qkikL5Aog==", - "dependencies": { - "axios": "^0.21.1", - "colors": "^1.4.0", - "command-exists": "^1.2.9", - "commander": "^2.20.0", - "dateformat": "^3.0.3", - "get-stdin": "^7.0.0", - "iptv-playlist-parser": "^0.5.4", - "jest": "^27.0.6", - "lodash.chunk": "^4.2.0", - "progress": "^2.0.3", - "valid-url": "^1.0.9" - }, - "bin": { - "iptv-checker": "bin/iptv-checker.js" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/iptv-checker/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" - }, - "node_modules/iptv-checker/node_modules/iptv-playlist-parser": { - "version": "0.5.4", - "resolved": "https://registry.npmjs.org/iptv-playlist-parser/-/iptv-playlist-parser-0.5.4.tgz", - "integrity": "sha512-sgzJ83LFLJQX8RhnWvjxEyeYwelLf+vPdNLWYwlozkmSl8IxU/y2qBxyGCvyqCKpIQDdU35wkrZ3k1nMpI3KGQ==" - }, - "node_modules/iptv-playlist-parser": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/iptv-playlist-parser/-/iptv-playlist-parser-0.9.0.tgz", - "integrity": "sha512-F+aGQv1uBu6iWWlYfFjMhdk8vUofkeCMIbzvYiPBwYQOQBHd/OhFHxNTCCsFRGas2CjOSxDa29FNr0EZSkK/uw==" - }, - "node_modules/is-ci": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.0.tgz", - "integrity": "sha512-kDXyttuLeslKAHYL/K28F2YkM3x5jvFPEw3yXbRptXydjD9rpLEz+C5K5iutY9ZiUu6AP41JdvRQwF4Iqs4ZCQ==", - "dependencies": { - "ci-info": "^3.1.1" - }, - "bin": { - "is-ci": "bin.js" - } - }, - "node_modules/is-core-module": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.5.0.tgz", - "integrity": "sha512-TXCMSDsEHMEEZ6eCA8rwRDbLu55MRGmrctljsBX/2v1d9/GzqHOxW5c5oPSgrUt2vBFXebu9rGqckXGPWOlYpg==", - "dependencies": { - "has": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "engines": { - "node": ">=6" - } - }, - "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==", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-potential-custom-element-name": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", - "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==" - }, - "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==", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" - }, - "node_modules/istanbul-lib-coverage": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz", - "integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==", - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-instrument": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", - "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", - "dependencies": { - "@babel/core": "^7.7.5", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.0.0", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-source-maps": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz", - "integrity": "sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg==", - "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-reports": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.2.tgz", - "integrity": "sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw==", - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest/-/jest-27.0.6.tgz", - "integrity": "sha512-EjV8aETrsD0wHl7CKMibKwQNQc3gIRBXlTikBmmHUeVMKaPFxdcUIBfoDqTSXDoGJIivAYGqCWVlzCSaVjPQsA==", - "dependencies": { - "@jest/core": "^27.0.6", - "import-local": "^3.0.2", - "jest-cli": "^27.0.6" - }, - "bin": { - "jest": "bin/jest.js" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.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": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-27.0.6.tgz", - "integrity": "sha512-BuL/ZDauaq5dumYh5y20sn4IISnf1P9A0TDswTxUi84ORGtVa86ApuBHqICL0vepqAnZiY6a7xeSPWv2/yy4eA==", - "dependencies": { - "@jest/types": "^27.0.6", - "execa": "^5.0.0", - "throat": "^6.0.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-circus": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-27.0.6.tgz", - "integrity": "sha512-OJlsz6BBeX9qR+7O9lXefWoc2m9ZqcZ5Ohlzz0pTEAG4xMiZUJoacY8f4YDHxgk0oKYxj277AfOk9w6hZYvi1Q==", - "dependencies": { - "@jest/environment": "^27.0.6", - "@jest/test-result": "^27.0.6", - "@jest/types": "^27.0.6", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "dedent": "^0.7.0", - "expect": "^27.0.6", - "is-generator-fn": "^2.0.0", - "jest-each": "^27.0.6", - "jest-matcher-utils": "^27.0.6", - "jest-message-util": "^27.0.6", - "jest-runtime": "^27.0.6", - "jest-snapshot": "^27.0.6", - "jest-util": "^27.0.6", - "pretty-format": "^27.0.6", - "slash": "^3.0.0", - "stack-utils": "^2.0.3", - "throat": "^6.0.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-cli": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-27.0.6.tgz", - "integrity": "sha512-qUUVlGb9fdKir3RDE+B10ULI+LQrz+MCflEH2UJyoUjoHHCbxDrMxSzjQAPUMsic4SncI62ofYCcAvW6+6rhhg==", - "dependencies": { - "@jest/core": "^27.0.6", - "@jest/test-result": "^27.0.6", - "@jest/types": "^27.0.6", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.4", - "import-local": "^3.0.2", - "jest-config": "^27.0.6", - "jest-util": "^27.0.6", - "jest-validate": "^27.0.6", - "prompts": "^2.0.1", - "yargs": "^16.0.3" - }, - "bin": { - "jest": "bin/jest.js" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/jest-config": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-27.0.6.tgz", - "integrity": "sha512-JZRR3I1Plr2YxPBhgqRspDE2S5zprbga3swYNrvY3HfQGu7p/GjyLOqwrYad97tX3U3mzT53TPHVmozacfP/3w==", - "dependencies": { - "@babel/core": "^7.1.0", - "@jest/test-sequencer": "^27.0.6", - "@jest/types": "^27.0.6", - "babel-jest": "^27.0.6", - "chalk": "^4.0.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.1", - "graceful-fs": "^4.2.4", - "is-ci": "^3.0.0", - "jest-circus": "^27.0.6", - "jest-environment-jsdom": "^27.0.6", - "jest-environment-node": "^27.0.6", - "jest-get-type": "^27.0.6", - "jest-jasmine2": "^27.0.6", - "jest-regex-util": "^27.0.6", - "jest-resolve": "^27.0.6", - "jest-runner": "^27.0.6", - "jest-util": "^27.0.6", - "jest-validate": "^27.0.6", - "micromatch": "^4.0.4", - "pretty-format": "^27.0.6" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - }, - "peerDependencies": { - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "ts-node": { - "optional": true - } - } - }, - "node_modules/jest-diff": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.0.6.tgz", - "integrity": "sha512-Z1mqgkTCSYaFgwTlP/NUiRzdqgxmmhzHY1Tq17zL94morOHfHu3K4bgSgl+CR4GLhpV8VxkuOYuIWnQ9LnFqmg==", - "dependencies": { - "chalk": "^4.0.0", - "diff-sequences": "^27.0.6", - "jest-get-type": "^27.0.6", - "pretty-format": "^27.0.6" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-docblock": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-27.0.6.tgz", - "integrity": "sha512-Fid6dPcjwepTFraz0YxIMCi7dejjJ/KL9FBjPYhBp4Sv1Y9PdhImlKZqYU555BlN4TQKaTc+F2Av1z+anVyGkA==", - "dependencies": { - "detect-newline": "^3.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-each": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-27.0.6.tgz", - "integrity": "sha512-m6yKcV3bkSWrUIjxkE9OC0mhBZZdhovIW5ergBYirqnkLXkyEn3oUUF/QZgyecA1cF1QFyTE8bRRl8Tfg1pfLA==", - "dependencies": { - "@jest/types": "^27.0.6", - "chalk": "^4.0.0", - "jest-get-type": "^27.0.6", - "jest-util": "^27.0.6", - "pretty-format": "^27.0.6" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-environment-jsdom": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-27.0.6.tgz", - "integrity": "sha512-FvetXg7lnXL9+78H+xUAsra3IeZRTiegA3An01cWeXBspKXUhAwMM9ycIJ4yBaR0L7HkoMPaZsozCLHh4T8fuw==", - "dependencies": { - "@jest/environment": "^27.0.6", - "@jest/fake-timers": "^27.0.6", - "@jest/types": "^27.0.6", - "@types/node": "*", - "jest-mock": "^27.0.6", - "jest-util": "^27.0.6", - "jsdom": "^16.6.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-environment-node": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.0.6.tgz", - "integrity": "sha512-+Vi6yLrPg/qC81jfXx3IBlVnDTI6kmRr08iVa2hFCWmJt4zha0XW7ucQltCAPhSR0FEKEoJ3i+W4E6T0s9is0w==", - "dependencies": { - "@jest/environment": "^27.0.6", - "@jest/fake-timers": "^27.0.6", - "@jest/types": "^27.0.6", - "@types/node": "*", - "jest-mock": "^27.0.6", - "jest-util": "^27.0.6" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-get-type": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.0.6.tgz", - "integrity": "sha512-XTkK5exIeUbbveehcSR8w0bhH+c0yloW/Wpl+9vZrjzztCPWrxhHwkIFpZzCt71oRBsgxmuUfxEqOYoZI2macg==", - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-haste-map": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.0.6.tgz", - "integrity": "sha512-4ldjPXX9h8doB2JlRzg9oAZ2p6/GpQUNAeiYXqcpmrKbP0Qev0wdZlxSMOmz8mPOEnt4h6qIzXFLDi8RScX/1w==", - "dependencies": { - "@jest/types": "^27.0.6", - "@types/graceful-fs": "^4.1.2", - "@types/node": "*", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "graceful-fs": "^4.2.4", - "jest-regex-util": "^27.0.6", - "jest-serializer": "^27.0.6", - "jest-util": "^27.0.6", - "jest-worker": "^27.0.6", - "micromatch": "^4.0.4", - "walker": "^1.0.7" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - }, - "optionalDependencies": { - "fsevents": "^2.3.2" - } - }, - "node_modules/jest-jasmine2": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-27.0.6.tgz", - "integrity": "sha512-cjpH2sBy+t6dvCeKBsHpW41mjHzXgsavaFMp+VWRf0eR4EW8xASk1acqmljFtK2DgyIECMv2yCdY41r2l1+4iA==", - "dependencies": { - "@babel/traverse": "^7.1.0", - "@jest/environment": "^27.0.6", - "@jest/source-map": "^27.0.6", - "@jest/test-result": "^27.0.6", - "@jest/types": "^27.0.6", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "expect": "^27.0.6", - "is-generator-fn": "^2.0.0", - "jest-each": "^27.0.6", - "jest-matcher-utils": "^27.0.6", - "jest-message-util": "^27.0.6", - "jest-runtime": "^27.0.6", - "jest-snapshot": "^27.0.6", - "jest-util": "^27.0.6", - "pretty-format": "^27.0.6", - "throat": "^6.0.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-leak-detector": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-27.0.6.tgz", - "integrity": "sha512-2/d6n2wlH5zEcdctX4zdbgX8oM61tb67PQt4Xh8JFAIy6LRKUnX528HulkaG6nD5qDl5vRV1NXejCe1XRCH5gQ==", - "dependencies": { - "jest-get-type": "^27.0.6", - "pretty-format": "^27.0.6" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-matcher-utils": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.0.6.tgz", - "integrity": "sha512-OFgF2VCQx9vdPSYTHWJ9MzFCehs20TsyFi6bIHbk5V1u52zJOnvF0Y/65z3GLZHKRuTgVPY4Z6LVePNahaQ+tA==", - "dependencies": { - "chalk": "^4.0.0", - "jest-diff": "^27.0.6", - "jest-get-type": "^27.0.6", - "pretty-format": "^27.0.6" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-message-util": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.0.6.tgz", - "integrity": "sha512-rBxIs2XK7rGy+zGxgi+UJKP6WqQ+KrBbD1YMj517HYN3v2BG66t3Xan3FWqYHKZwjdB700KiAJ+iES9a0M+ixw==", - "dependencies": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^27.0.6", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.4", - "micromatch": "^4.0.4", - "pretty-format": "^27.0.6", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-mock": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.0.6.tgz", - "integrity": "sha512-lzBETUoK8cSxts2NYXSBWT+EJNzmUVtVVwS1sU9GwE1DLCfGsngg+ZVSIe0yd0ZSm+y791esiuo+WSwpXJQ5Bw==", - "dependencies": { - "@jest/types": "^27.0.6", - "@types/node": "*" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-pnp-resolver": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", - "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==", - "engines": { - "node": ">=6" - }, - "peerDependencies": { - "jest-resolve": "*" - }, - "peerDependenciesMeta": { - "jest-resolve": { - "optional": true - } - } - }, - "node_modules/jest-regex-util": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.0.6.tgz", - "integrity": "sha512-SUhPzBsGa1IKm8hx2F4NfTGGp+r7BXJ4CulsZ1k2kI+mGLG+lxGrs76veN2LF/aUdGosJBzKgXmNCw+BzFqBDQ==", - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-resolve": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.0.6.tgz", - "integrity": "sha512-yKmIgw2LgTh7uAJtzv8UFHGF7Dm7XfvOe/LQ3Txv101fLM8cx2h1QVwtSJ51Q/SCxpIiKfVn6G2jYYMDNHZteA==", - "dependencies": { - "@jest/types": "^27.0.6", - "chalk": "^4.0.0", - "escalade": "^3.1.1", - "graceful-fs": "^4.2.4", - "jest-pnp-resolver": "^1.2.2", - "jest-util": "^27.0.6", - "jest-validate": "^27.0.6", - "resolve": "^1.20.0", - "slash": "^3.0.0" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-resolve-dependencies": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-27.0.6.tgz", - "integrity": "sha512-mg9x9DS3BPAREWKCAoyg3QucCr0n6S8HEEsqRCKSPjPcu9HzRILzhdzY3imsLoZWeosEbJZz6TKasveczzpJZA==", - "dependencies": { - "@jest/types": "^27.0.6", - "jest-regex-util": "^27.0.6", - "jest-snapshot": "^27.0.6" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-runner": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-27.0.6.tgz", - "integrity": "sha512-W3Bz5qAgaSChuivLn+nKOgjqNxM7O/9JOJoKDCqThPIg2sH/d4A/lzyiaFgnb9V1/w29Le11NpzTJSzga1vyYQ==", - "dependencies": { - "@jest/console": "^27.0.6", - "@jest/environment": "^27.0.6", - "@jest/test-result": "^27.0.6", - "@jest/transform": "^27.0.6", - "@jest/types": "^27.0.6", - "@types/node": "*", - "chalk": "^4.0.0", - "emittery": "^0.8.1", - "exit": "^0.1.2", - "graceful-fs": "^4.2.4", - "jest-docblock": "^27.0.6", - "jest-environment-jsdom": "^27.0.6", - "jest-environment-node": "^27.0.6", - "jest-haste-map": "^27.0.6", - "jest-leak-detector": "^27.0.6", - "jest-message-util": "^27.0.6", - "jest-resolve": "^27.0.6", - "jest-runtime": "^27.0.6", - "jest-util": "^27.0.6", - "jest-worker": "^27.0.6", - "source-map-support": "^0.5.6", - "throat": "^6.0.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-runtime": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.0.6.tgz", - "integrity": "sha512-BhvHLRVfKibYyqqEFkybsznKwhrsu7AWx2F3y9G9L95VSIN3/ZZ9vBpm/XCS2bS+BWz3sSeNGLzI3TVQ0uL85Q==", - "dependencies": { - "@jest/console": "^27.0.6", - "@jest/environment": "^27.0.6", - "@jest/fake-timers": "^27.0.6", - "@jest/globals": "^27.0.6", - "@jest/source-map": "^27.0.6", - "@jest/test-result": "^27.0.6", - "@jest/transform": "^27.0.6", - "@jest/types": "^27.0.6", - "@types/yargs": "^16.0.0", - "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.4", - "jest-haste-map": "^27.0.6", - "jest-message-util": "^27.0.6", - "jest-mock": "^27.0.6", - "jest-regex-util": "^27.0.6", - "jest-resolve": "^27.0.6", - "jest-snapshot": "^27.0.6", - "jest-util": "^27.0.6", - "jest-validate": "^27.0.6", - "slash": "^3.0.0", - "strip-bom": "^4.0.0", - "yargs": "^16.0.3" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-serializer": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.0.6.tgz", - "integrity": "sha512-PtGdVK9EGC7dsaziskfqaAPib6wTViY3G8E5wz9tLVPhHyiDNTZn/xjZ4khAw+09QkoOVpn7vF5nPSN6dtBexA==", - "dependencies": { - "@types/node": "*", - "graceful-fs": "^4.2.4" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-snapshot": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.0.6.tgz", - "integrity": "sha512-NTHaz8He+ATUagUgE7C/UtFcRoHqR2Gc+KDfhQIyx+VFgwbeEMjeP+ILpUTLosZn/ZtbNdCF5LkVnN/l+V751A==", - "dependencies": { - "@babel/core": "^7.7.2", - "@babel/generator": "^7.7.2", - "@babel/parser": "^7.7.2", - "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/traverse": "^7.7.2", - "@babel/types": "^7.0.0", - "@jest/transform": "^27.0.6", - "@jest/types": "^27.0.6", - "@types/babel__traverse": "^7.0.4", - "@types/prettier": "^2.1.5", - "babel-preset-current-node-syntax": "^1.0.0", - "chalk": "^4.0.0", - "expect": "^27.0.6", - "graceful-fs": "^4.2.4", - "jest-diff": "^27.0.6", - "jest-get-type": "^27.0.6", - "jest-haste-map": "^27.0.6", - "jest-matcher-utils": "^27.0.6", - "jest-message-util": "^27.0.6", - "jest-resolve": "^27.0.6", - "jest-util": "^27.0.6", - "natural-compare": "^1.4.0", - "pretty-format": "^27.0.6", - "semver": "^7.3.2" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-snapshot/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/jest-util": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.0.6.tgz", - "integrity": "sha512-1JjlaIh+C65H/F7D11GNkGDDZtDfMEM8EBXsvd+l/cxtgQ6QhxuloOaiayt89DxUvDarbVhqI98HhgrM1yliFQ==", - "dependencies": { - "@jest/types": "^27.0.6", - "@types/node": "*", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.4", - "is-ci": "^3.0.0", - "picomatch": "^2.2.3" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-validate": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-27.0.6.tgz", - "integrity": "sha512-yhZZOaMH3Zg6DC83n60pLmdU1DQE46DW+KLozPiPbSbPhlXXaiUTDlhHQhHFpaqIFRrInko1FHXjTRpjWRuWfA==", - "dependencies": { - "@jest/types": "^27.0.6", - "camelcase": "^6.2.0", - "chalk": "^4.0.0", - "jest-get-type": "^27.0.6", - "leven": "^3.1.0", - "pretty-format": "^27.0.6" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-validate/node_modules/camelcase": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", - "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/jest-watcher": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-27.0.6.tgz", - "integrity": "sha512-/jIoKBhAP00/iMGnTwUBLgvxkn7vsOweDrOTSPzc7X9uOyUtJIDthQBTI1EXz90bdkrxorUZVhJwiB69gcHtYQ==", - "dependencies": { - "@jest/test-result": "^27.0.6", - "@jest/types": "^27.0.6", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "jest-util": "^27.0.6", - "string-length": "^4.0.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" - } - }, - "node_modules/jest-worker": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.0.6.tgz", - "integrity": "sha512-qupxcj/dRuA3xHPMUd40gr2EaAurFbkwzOh7wfPaeE9id7hyjURRQoqNfHifHK3XjJU6YJJUQKILGUnwGPEOCA==", - "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": ">= 10.13.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==", - "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==" - }, - "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==", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsdom": { - "version": "16.7.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.7.0.tgz", - "integrity": "sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==", - "dependencies": { - "abab": "^2.0.5", - "acorn": "^8.2.4", - "acorn-globals": "^6.0.0", - "cssom": "^0.4.4", - "cssstyle": "^2.3.0", - "data-urls": "^2.0.0", - "decimal.js": "^10.2.1", - "domexception": "^2.0.1", - "escodegen": "^2.0.0", - "form-data": "^3.0.0", - "html-encoding-sniffer": "^2.0.1", - "http-proxy-agent": "^4.0.1", - "https-proxy-agent": "^5.0.0", - "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.0", - "parse5": "6.0.1", - "saxes": "^5.0.1", - "symbol-tree": "^3.2.4", - "tough-cookie": "^4.0.0", - "w3c-hr-time": "^1.0.2", - "w3c-xmlserializer": "^2.0.0", - "webidl-conversions": "^6.1.0", - "whatwg-encoding": "^1.0.5", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^8.5.0", - "ws": "^7.4.6", - "xml-name-validator": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "canvas": "^2.5.0" - }, - "peerDependenciesMeta": { - "canvas": { - "optional": true - } - } - }, - "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/json5": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", - "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", - "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "engines": { - "node": ">=6" - } - }, - "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==", - "engines": { - "node": ">=6" - } - }, - "node_modules/levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dependencies": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "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==", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "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.chunk": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.chunk/-/lodash.chunk-4.2.0.tgz", - "integrity": "sha1-ZuXOH3btJ7QwPYxlEujRIW6BBrw=" - }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/m3u-linter": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/m3u-linter/-/m3u-linter-0.2.2.tgz", - "integrity": "sha512-2U6HOmt7MlQNuo3KASb/Z+INHMp+WFj2npUb9qfKRZludrPRzvtuJxjHZvFQuDUrwFFKp0yqzms2wVNTAYt5HQ==", - "dependencies": { - "chalk": "^4.1.1", - "commander": "^7.2.0", - "glob": "^7.1.6" - }, - "bin": { - "m3u-linter": "bin/m3u-linter.js" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/makeerror": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.11.tgz", - "integrity": "sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw=", - "dependencies": { - "tmpl": "1.0.x" - } - }, - "node_modules/markdown-include": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/markdown-include/-/markdown-include-0.4.3.tgz", - "integrity": "sha1-usZVVALG2pOg9SlSIl37mmzMcxs=", - "dependencies": { - "q": "^1.2.0" - }, - "bin": { - "markdown-include": "bin/cli.js" - } - }, - "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==" - }, - "node_modules/micromatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", - "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", - "dependencies": { - "braces": "^3.0.1", - "picomatch": "^2.2.3" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime-db": { - "version": "1.49.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.49.0.tgz", - "integrity": "sha512-CIc8j9URtOVApSFCQIF+VBkX1RwXp/oMMOrqdyXSBXq5RWNEsRfyj1kiRnQgmNXmHxPoFIxOroKA3zcU9P+nAA==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.32", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.32.tgz", - "integrity": "sha512-hJGaVS4G4c9TSMYh2n6SQAGrC4RnfU+daP8G7cSCmaqNjiOoUY0VHCMS42pxnQmVF1GWwFhbHWn3RIxCqTmZ9A==", - "dependencies": { - "mime-db": "1.49.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==", - "engines": { - "node": ">=6" - } - }, - "node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=" - }, - "node_modules/natural-orderby": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/natural-orderby/-/natural-orderby-2.0.3.tgz", - "integrity": "sha512-p7KTHxU0CUrcOXe62Zfrb5Z13nLvPhSWR/so3kFulUQU0sgUll2Z0LwpsLN351eOOD+hRGu/F1g+6xDfPeD++Q==", - "engines": { - "node": "*" - } - }, - "node_modules/node-int64": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=" - }, - "node_modules/node-modules-regexp": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz", - "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/node-releases": { - "version": "1.1.73", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.73.tgz", - "integrity": "sha512-uW7fodD6pyW2FZNZnp/Z3hvWKeEW1Y8R1+1CnErE8cXFXzl5blBOoVB41CvMer6P6Q0S5FXDwcHgFd1Wj0U9zg==" - }, - "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==", - "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==", - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/nwsapi": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", - "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==" - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "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==", - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dependencies": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/p-each-series": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-2.2.0.tgz", - "integrity": "sha512-ycIL2+1V32th+8scbpTvyHNaHe02z0sjgh91XXjAk+ZeXoPN4Z46DVUnzdso0aX4KckKw0FNNFHdjZ2UsZvxiA==", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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==", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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==", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "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==", - "engines": { - "node": ">=6" - } - }, - "node_modules/parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" - }, - "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": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "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-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" - }, - "node_modules/picomatch": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", - "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pirates": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.1.tgz", - "integrity": "sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA==", - "dependencies": { - "node-modules-regexp": "^1.0.0" - }, - "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==", - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/pre-push": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pre-push/-/pre-push-0.1.1.tgz", - "integrity": "sha1-Kip5gn0kOnbJEImJescH9F5xaqw=", - "dependencies": { - "shelljs": "0.3.x" - } - }, - "node_modules/prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/pretty-format": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.0.6.tgz", - "integrity": "sha512-8tGD7gBIENgzqA+UBzObyWqQ5B778VIFZA/S66cclyd5YkFLYs2Js7gxDKf0MXtTc9zcS7t1xhdfcElJ3YIvkQ==", - "dependencies": { - "@jest/types": "^27.0.6", - "ansi-regex": "^5.0.0", - "ansi-styles": "^5.0.0", - "react-is": "^17.0.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.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==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/prompts": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.1.tgz", - "integrity": "sha512-EQyfIuO2hPDsX1L/blblV+H7I0knhgAd82cVneCwcdND9B8AuCDuRcBH6yIcG4dFzlOUqbazQqwGjx5xmsNLuQ==", - "dependencies": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/psl": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", - "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" - }, - "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "engines": { - "node": ">=6" - } - }, - "node_modules/q": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", - "engines": { - "node": ">=0.6.0", - "teleport": ">=0.2.0" - } - }, - "node_modules/react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", - "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", - "dependencies": { - "is-core-module": "^2.2.0", - "path-parse": "^1.0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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==", - "dependencies": { - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "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==", - "engines": { - "node": ">=8" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "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/saxes": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", - "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", - "dependencies": { - "xmlchars": "^2.2.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "bin": { - "semver": "bin/semver.js" - } - }, - "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/shelljs": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.3.0.tgz", - "integrity": "sha1-NZbmMHp4FUT1kfN9phg2DzHbV7E=", - "bin": { - "shjs": "bin/shjs" - }, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/signal-exit": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" - }, - "node_modules/sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "engines": { - "node": ">=8" - } - }, - "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==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.19", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", - "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" - }, - "node_modules/stack-utils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.3.tgz", - "integrity": "sha512-gL//fkxfWUsIlFL2Tl42Cl6+HFALEaB1FU76I/Fy+oZjRreP7OPMXFlGbxM7NQsI0ZpUfw76sHnv0WNYuTb7Iw==", - "dependencies": { - "escape-string-regexp": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "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==", - "dependencies": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/string-width": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", - "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dependencies": { - "ansi-regex": "^5.0.0" - }, - "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==", - "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==", - "engines": { - "node": ">=6" - } - }, - "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==", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-hyperlinks": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz", - "integrity": "sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==", - "dependencies": { - "has-flag": "^4.0.0", - "supports-color": "^7.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/symbol-tree": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==" - }, - "node_modules/terminal-link": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", - "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", - "dependencies": { - "ansi-escapes": "^4.2.1", - "supports-hyperlinks": "^2.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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==", - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/throat": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.1.tgz", - "integrity": "sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==" - }, - "node_modules/tmpl": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz", - "integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=" - }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "engines": { - "node": ">=4" - } - }, - "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==", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/tough-cookie": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz", - "integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==", - "dependencies": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.1.2" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/tr46": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.1.0.tgz", - "integrity": "sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==", - "dependencies": { - "punycode": "^2.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/transliteration": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/transliteration/-/transliteration-2.2.0.tgz", - "integrity": "sha512-o29GDWtecNoK4TNfnJQesGluFPiza+U8NoiKrErU8eTNlVgma6w1LV/tTiGo+waFLkhtL9WxrW0lXhZKmm7msQ==", - "dependencies": { - "yargs": "^16.1.0" - }, - "bin": { - "slugify": "dist/bin/slugify", - "transliterate": "dist/bin/transliterate" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dependencies": { - "prelude-ls": "~1.1.2" - }, - "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==", - "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/typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "dependencies": { - "is-typedarray": "^1.0.0" - } - }, - "node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/v8-to-istanbul": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.0.0.tgz", - "integrity": "sha512-LkmXi8UUNxnCC+JlH7/fsfsKr5AU110l+SYGJimWNkWhxbN5EyeOtm1MJ0hhvqMMOhGwBj1Fp70Yv9i+hX0QAg==", - "dependencies": { - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.0", - "source-map": "^0.7.3" - }, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/v8-to-istanbul/node_modules/source-map": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", - "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/valid-url": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/valid-url/-/valid-url-1.0.9.tgz", - "integrity": "sha1-HBRHm0DxOXp1eC8RXkCGRHQzogA=" - }, - "node_modules/w3c-hr-time": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", - "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", - "dependencies": { - "browser-process-hrtime": "^1.0.0" - } - }, - "node_modules/w3c-xmlserializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", - "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", - "dependencies": { - "xml-name-validator": "^3.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/walker": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.7.tgz", - "integrity": "sha1-L3+bj9ENZ3JisYqITijRlhjgKPs=", - "dependencies": { - "makeerror": "1.0.x" - } - }, - "node_modules/webidl-conversions": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", - "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", - "engines": { - "node": ">=10.4" - } - }, - "node_modules/whatwg-encoding": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", - "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", - "dependencies": { - "iconv-lite": "0.4.24" - } - }, - "node_modules/whatwg-mimetype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", - "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==" - }, - "node_modules/whatwg-url": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.7.0.tgz", - "integrity": "sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==", - "dependencies": { - "lodash": "^4.7.0", - "tr46": "^2.1.0", - "webidl-conversions": "^6.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "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.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "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" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "node_modules/write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", - "dependencies": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" - } - }, - "node_modules/ws": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.3.tgz", - "integrity": "sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg==", - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/xml-name-validator": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", - "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==" - }, - "node_modules/xmlchars": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", - "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==" - }, - "node_modules/y18n": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.5.tgz", - "integrity": "sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg==", - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-parser": { - "version": "20.2.6", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.6.tgz", - "integrity": "sha512-AP1+fQIWSM/sMiET8fyayjx/J+JmTPt2Mr0FkrgqB4todtfa53sOsrSAcIrJRD5XS20bKUwaDIuMkWKCEiQLKA==", - "engines": { - "node": ">=10" - } - } - }, + "lockfileVersion": 1, "dependencies": { "@babel/code-frame": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", - "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.0.tgz", + "integrity": "sha512-IF4EOMEV+bfYwOmNxGzSnjR2EmQod7f1UXOpZM3l4i4o4QNwzjtJAu/HxdjHq0aYBvdqMuQEY1eg0nqW9ZPORA==", "requires": { - "@babel/highlight": "^7.14.5" + "@babel/highlight": "^7.16.0" } }, "@babel/compat-data": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.15.0.tgz", - "integrity": "sha512-0NqAC1IJE0S0+lL1SWFMxMkz1pKCNCjI4tr2Zx4LJSXxCLAdr6KyArnY+sno5m3yH9g737ygOyPABDsnXkpxiA==" + "version": "7.16.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.16.4.tgz", + "integrity": "sha512-1o/jo7D+kC9ZjHX5v+EHrdjl3PhxMrLSOTGsOdHJ+KL8HCaEK6ehrVL2RS6oHDZp+L7xLirLrPmQtEng769J/Q==" }, "@babel/core": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.15.0.tgz", - "integrity": "sha512-tXtmTminrze5HEUPn/a0JtOzzfp0nk+UEXQ/tqIJo3WDGypl/2OFQEMll/zSFU8f/lfmfLXvTaORHF3cfXIQMw==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.16.0.tgz", + "integrity": "sha512-mYZEvshBRHGsIAiyH5PzCFTCfbWfoYbO/jcSdXQSUQu1/pW0xDZAUP7KEc32heqWTAfAHhV9j1vH8Sav7l+JNQ==", "requires": { - "@babel/code-frame": "^7.14.5", - "@babel/generator": "^7.15.0", - "@babel/helper-compilation-targets": "^7.15.0", - "@babel/helper-module-transforms": "^7.15.0", - "@babel/helpers": "^7.14.8", - "@babel/parser": "^7.15.0", - "@babel/template": "^7.14.5", - "@babel/traverse": "^7.15.0", - "@babel/types": "^7.15.0", + "@babel/code-frame": "^7.16.0", + "@babel/generator": "^7.16.0", + "@babel/helper-compilation-targets": "^7.16.0", + "@babel/helper-module-transforms": "^7.16.0", + "@babel/helpers": "^7.16.0", + "@babel/parser": "^7.16.0", + "@babel/template": "^7.16.0", + "@babel/traverse": "^7.16.0", + "@babel/types": "^7.16.0", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -3882,11 +46,11 @@ } }, "@babel/generator": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.15.0.tgz", - "integrity": "sha512-eKl4XdMrbpYvuB505KTta4AV9g+wWzmVBW69tX0H2NwKVKd2YJbKgyK6M8j/rgLbmHOYJn6rUklV677nOyJrEQ==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.16.0.tgz", + "integrity": "sha512-RR8hUCfRQn9j9RPKEVXo9LiwoxLPYn6hNZlvUOR8tSnaxlD0p0+la00ZP9/SnRt6HchKr+X0fO2r8vrETiJGew==", "requires": { - "@babel/types": "^7.15.0", + "@babel/types": "^7.16.0", "jsesc": "^2.5.1", "source-map": "^0.5.0" }, @@ -3899,79 +63,79 @@ } }, "@babel/helper-compilation-targets": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.15.0.tgz", - "integrity": "sha512-h+/9t0ncd4jfZ8wsdAsoIxSa61qhBYlycXiHWqJaQBCXAhDCMbPRSMTGnZIkkmt1u4ag+UQmuqcILwqKzZ4N2A==", + "version": "7.16.3", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.3.tgz", + "integrity": "sha512-vKsoSQAyBmxS35JUOOt+07cLc6Nk/2ljLIHwmq2/NM6hdioUaqEXq/S+nXvbvXbZkNDlWOymPanJGOc4CBjSJA==", "requires": { - "@babel/compat-data": "^7.15.0", + "@babel/compat-data": "^7.16.0", "@babel/helper-validator-option": "^7.14.5", - "browserslist": "^4.16.6", + "browserslist": "^4.17.5", "semver": "^6.3.0" } }, "@babel/helper-function-name": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.14.5.tgz", - "integrity": "sha512-Gjna0AsXWfFvrAuX+VKcN/aNNWonizBj39yGwUzVDVTlMYJMK2Wp6xdpy72mfArFq5uK+NOuexfzZlzI1z9+AQ==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.16.0.tgz", + "integrity": "sha512-BZh4mEk1xi2h4HFjWUXRQX5AEx4rvaZxHgax9gcjdLWdkjsY7MKt5p0otjsg5noXw+pB+clMCjw+aEVYADMjog==", "requires": { - "@babel/helper-get-function-arity": "^7.14.5", - "@babel/template": "^7.14.5", - "@babel/types": "^7.14.5" + "@babel/helper-get-function-arity": "^7.16.0", + "@babel/template": "^7.16.0", + "@babel/types": "^7.16.0" } }, "@babel/helper-get-function-arity": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.14.5.tgz", - "integrity": "sha512-I1Db4Shst5lewOM4V+ZKJzQ0JGGaZ6VY1jYvMghRjqs6DWgxLCIyFt30GlnKkfUeFLpJt2vzbMVEXVSXlIFYUg==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.0.tgz", + "integrity": "sha512-ASCquNcywC1NkYh/z7Cgp3w31YW8aojjYIlNg4VeJiHkqyP4AzIvr4qx7pYDb4/s8YcsZWqqOSxgkvjUz1kpDQ==", "requires": { - "@babel/types": "^7.14.5" + "@babel/types": "^7.16.0" } }, "@babel/helper-hoist-variables": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.14.5.tgz", - "integrity": "sha512-R1PXiz31Uc0Vxy4OEOm07x0oSjKAdPPCh3tPivn/Eo8cvz6gveAeuyUUPB21Hoiif0uoPQSSdhIPS3352nvdyQ==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.0.tgz", + "integrity": "sha512-1AZlpazjUR0EQZQv3sgRNfM9mEVWPK3M6vlalczA+EECcPz3XPh6VplbErL5UoMpChhSck5wAJHthlj1bYpcmg==", "requires": { - "@babel/types": "^7.14.5" + "@babel/types": "^7.16.0" } }, "@babel/helper-member-expression-to-functions": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.15.0.tgz", - "integrity": "sha512-Jq8H8U2kYiafuj2xMTPQwkTBnEEdGKpT35lJEQsRRjnG0LW3neucsaMWLgKcwu3OHKNeYugfw+Z20BXBSEs2Lg==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.0.tgz", + "integrity": "sha512-bsjlBFPuWT6IWhl28EdrQ+gTvSvj5tqVP5Xeftp07SEuz5pLnsXZuDkDD3Rfcxy0IsHmbZ+7B2/9SHzxO0T+sQ==", "requires": { - "@babel/types": "^7.15.0" + "@babel/types": "^7.16.0" } }, "@babel/helper-module-imports": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.14.5.tgz", - "integrity": "sha512-SwrNHu5QWS84XlHwGYPDtCxcA0hrSlL2yhWYLgeOc0w7ccOl2qv4s/nARI0aYZW+bSwAL5CukeXA47B/1NKcnQ==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.0.tgz", + "integrity": "sha512-kkH7sWzKPq0xt3H1n+ghb4xEMP8k0U7XV3kkB+ZGy69kDk2ySFW1qPi06sjKzFY3t1j6XbJSqr4mF9L7CYVyhg==", "requires": { - "@babel/types": "^7.14.5" + "@babel/types": "^7.16.0" } }, "@babel/helper-module-transforms": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.15.0.tgz", - "integrity": "sha512-RkGiW5Rer7fpXv9m1B3iHIFDZdItnO2/BLfWVW/9q7+KqQSDY5kUfQEbzdXM1MVhJGcugKV7kRrNVzNxmk7NBg==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.16.0.tgz", + "integrity": "sha512-My4cr9ATcaBbmaEa8M0dZNA74cfI6gitvUAskgDtAFmAqyFKDSHQo5YstxPbN+lzHl2D9l/YOEFqb2mtUh4gfA==", "requires": { - "@babel/helper-module-imports": "^7.14.5", - "@babel/helper-replace-supers": "^7.15.0", - "@babel/helper-simple-access": "^7.14.8", - "@babel/helper-split-export-declaration": "^7.14.5", - "@babel/helper-validator-identifier": "^7.14.9", - "@babel/template": "^7.14.5", - "@babel/traverse": "^7.15.0", - "@babel/types": "^7.15.0" + "@babel/helper-module-imports": "^7.16.0", + "@babel/helper-replace-supers": "^7.16.0", + "@babel/helper-simple-access": "^7.16.0", + "@babel/helper-split-export-declaration": "^7.16.0", + "@babel/helper-validator-identifier": "^7.15.7", + "@babel/template": "^7.16.0", + "@babel/traverse": "^7.16.0", + "@babel/types": "^7.16.0" } }, "@babel/helper-optimise-call-expression": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.14.5.tgz", - "integrity": "sha512-IqiLIrODUOdnPU9/F8ib1Fx2ohlgDhxnIDU7OEVi+kAbEZcyiF7BLU8W6PfvPi9LzztjS7kcbzbmL7oG8kD6VA==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.0.tgz", + "integrity": "sha512-SuI467Gi2V8fkofm2JPnZzB/SUuXoJA5zXe/xzyPP2M04686RzFKFHPK6HDVN6JvWBIEW8tt9hPR7fXdn2Lgpw==", "requires": { - "@babel/types": "^7.14.5" + "@babel/types": "^7.16.0" } }, "@babel/helper-plugin-utils": { @@ -3980,36 +144,36 @@ "integrity": "sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ==" }, "@babel/helper-replace-supers": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.15.0.tgz", - "integrity": "sha512-6O+eWrhx+HEra/uJnifCwhwMd6Bp5+ZfZeJwbqUTuqkhIT6YcRhiZCOOFChRypOIe0cV46kFrRBlm+t5vHCEaA==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.16.0.tgz", + "integrity": "sha512-TQxuQfSCdoha7cpRNJvfaYxxxzmbxXw/+6cS7V02eeDYyhxderSoMVALvwupA54/pZcOTtVeJ0xccp1nGWladA==", "requires": { - "@babel/helper-member-expression-to-functions": "^7.15.0", - "@babel/helper-optimise-call-expression": "^7.14.5", - "@babel/traverse": "^7.15.0", - "@babel/types": "^7.15.0" + "@babel/helper-member-expression-to-functions": "^7.16.0", + "@babel/helper-optimise-call-expression": "^7.16.0", + "@babel/traverse": "^7.16.0", + "@babel/types": "^7.16.0" } }, "@babel/helper-simple-access": { - "version": "7.14.8", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.14.8.tgz", - "integrity": "sha512-TrFN4RHh9gnWEU+s7JloIho2T76GPwRHhdzOWLqTrMnlas8T9O7ec+oEDNsRXndOmru9ymH9DFrEOxpzPoSbdg==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.16.0.tgz", + "integrity": "sha512-o1rjBT/gppAqKsYfUdfHq5Rk03lMQrkPHG1OWzHWpLgVXRH4HnMM9Et9CVdIqwkCQlobnGHEJMsgWP/jE1zUiw==", "requires": { - "@babel/types": "^7.14.8" + "@babel/types": "^7.16.0" } }, "@babel/helper-split-export-declaration": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.14.5.tgz", - "integrity": "sha512-hprxVPu6e5Kdp2puZUmvOGjaLv9TCe58E/Fl6hRq4YiVQxIcNvuq6uTM2r1mT/oPskuS9CgR+I94sqAYv0NGKA==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.0.tgz", + "integrity": "sha512-0YMMRpuDFNGTHNRiiqJX19GjNXA4H0E8jZ2ibccfSxaCogbm3am5WN/2nQNj0YnQwGWM1J06GOcQ2qnh3+0paw==", "requires": { - "@babel/types": "^7.14.5" + "@babel/types": "^7.16.0" } }, "@babel/helper-validator-identifier": { - "version": "7.14.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.9.tgz", - "integrity": "sha512-pQYxPY0UP6IHISRitNe8bsijHex4TWZXi2HwKVsjPiltzlhse2znVcm9Ace510VT1kxIHjGJCZZQBX2gJDbo0g==" + "version": "7.15.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz", + "integrity": "sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w==" }, "@babel/helper-validator-option": { "version": "7.14.5", @@ -4017,21 +181,21 @@ "integrity": "sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow==" }, "@babel/helpers": { - "version": "7.14.8", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.14.8.tgz", - "integrity": "sha512-ZRDmI56pnV+p1dH6d+UN6GINGz7Krps3+270qqI9UJ4wxYThfAIcI5i7j5vXC4FJ3Wap+S9qcebxeYiqn87DZw==", + "version": "7.16.3", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.16.3.tgz", + "integrity": "sha512-Xn8IhDlBPhvYTvgewPKawhADichOsbkZuzN7qz2BusOM0brChsyXMDJvldWaYMMUNiCQdQzNEioXTp3sC8Nt8w==", "requires": { - "@babel/template": "^7.14.5", - "@babel/traverse": "^7.14.8", - "@babel/types": "^7.14.8" + "@babel/template": "^7.16.0", + "@babel/traverse": "^7.16.3", + "@babel/types": "^7.16.0" } }, "@babel/highlight": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", - "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.0.tgz", + "integrity": "sha512-t8MH41kUQylBtu2+4IQA3atqevA2lRgqA2wyVB/YiWmsDSuylZZuXOUy9ric30hfzauEFfdsuk/eXTRrGrfd0g==", "requires": { - "@babel/helper-validator-identifier": "^7.14.5", + "@babel/helper-validator-identifier": "^7.15.7", "chalk": "^2.0.0", "js-tokens": "^4.0.0" }, @@ -4067,11 +231,6 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" - }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", @@ -4088,9 +247,9 @@ } }, "@babel/parser": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.15.0.tgz", - "integrity": "sha512-0v7oNOjr6YT9Z2RAOTv4T9aP+ubfx4Q/OhVtAet7PFDt0t9Oy6Jn+/rfC6b8HJ5zEqrQCiMxJfgtHpmIminmJQ==" + "version": "7.16.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.16.4.tgz", + "integrity": "sha512-6V0qdPUaiVHH3RtZeLIsc+6pDhbYzHR8ogA8w+f+Wc77DuXto19g2QUwveINoS34Uw+W8/hQDGJCx+i4n7xcng==" }, "@babel/plugin-syntax-async-generators": { "version": "7.8.4", @@ -4189,45 +348,45 @@ } }, "@babel/plugin-syntax-typescript": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.14.5.tgz", - "integrity": "sha512-u6OXzDaIXjEstBRRoBCQ/uKQKlbuaeE5in0RvWdA4pN6AhqxTIwUsnHPU1CFZA/amYObMsuWhYfRl3Ch90HD0Q==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.0.tgz", + "integrity": "sha512-Xv6mEXqVdaqCBfJFyeab0fH2DnUoMsDmhamxsSi4j8nLd4Vtw213WMJr55xxqipC/YVWyPY3K0blJncPYji+dQ==", "requires": { "@babel/helper-plugin-utils": "^7.14.5" } }, "@babel/template": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.14.5.tgz", - "integrity": "sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.0.tgz", + "integrity": "sha512-MnZdpFD/ZdYhXwiunMqqgyZyucaYsbL0IrjoGjaVhGilz+x8YB++kRfygSOIj1yOtWKPlx7NBp+9I1RQSgsd5A==", "requires": { - "@babel/code-frame": "^7.14.5", - "@babel/parser": "^7.14.5", - "@babel/types": "^7.14.5" + "@babel/code-frame": "^7.16.0", + "@babel/parser": "^7.16.0", + "@babel/types": "^7.16.0" } }, "@babel/traverse": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.15.0.tgz", - "integrity": "sha512-392d8BN0C9eVxVWd8H6x9WfipgVH5IaIoLp23334Sc1vbKKWINnvwRpb4us0xtPaCumlwbTtIYNA0Dv/32sVFw==", + "version": "7.16.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.16.3.tgz", + "integrity": "sha512-eolumr1vVMjqevCpwVO99yN/LoGL0EyHiLO5I043aYQvwOJ9eR5UsZSClHVCzfhBduMAsSzgA/6AyqPjNayJag==", "requires": { - "@babel/code-frame": "^7.14.5", - "@babel/generator": "^7.15.0", - "@babel/helper-function-name": "^7.14.5", - "@babel/helper-hoist-variables": "^7.14.5", - "@babel/helper-split-export-declaration": "^7.14.5", - "@babel/parser": "^7.15.0", - "@babel/types": "^7.15.0", + "@babel/code-frame": "^7.16.0", + "@babel/generator": "^7.16.0", + "@babel/helper-function-name": "^7.16.0", + "@babel/helper-hoist-variables": "^7.16.0", + "@babel/helper-split-export-declaration": "^7.16.0", + "@babel/parser": "^7.16.3", + "@babel/types": "^7.16.0", "debug": "^4.1.0", "globals": "^11.1.0" } }, "@babel/types": { - "version": "7.15.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.15.0.tgz", - "integrity": "sha512-OBvfqnllOIdX4ojTHpwZbpvz4j3EWyjkZEdmjH0/cgsd6QOdSgU8rLSk6ard/pcW7rlmjdVSX/AWOaORR1uNOQ==", + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.16.0.tgz", + "integrity": "sha512-PJgg/k3SdLsGb3hhisFvtLOw5ts113klrpLuIPtCJIU+BB24fqq6lf8RWqKJEjzqXR9AEH1rIb5XTqwBHB+kQg==", "requires": { - "@babel/helper-validator-identifier": "^7.14.9", + "@babel/helper-validator-identifier": "^7.15.7", "to-fast-properties": "^2.0.0" } }, @@ -4236,6 +395,16 @@ "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==" }, + "@dabh/diagnostics": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.2.tgz", + "integrity": "sha512-+A1YivoVDNNVCdfozHSR8v/jyuuLTMXwjWuxPFlFlUapXoGc+Gj9mDlTDDfrwl7rXCl2tNZ0kE8sIBO6YOn96Q==", + "requires": { + "colorspace": "1.1.x", + "enabled": "2.0.x", + "kuler": "^2.0.0" + } + }, "@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -4254,98 +423,98 @@ "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==" }, "@jest/console": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.0.6.tgz", - "integrity": "sha512-fMlIBocSHPZ3JxgWiDNW/KPj6s+YRd0hicb33IrmelCcjXo/pXPwvuiKFmZz+XuqI/1u7nbUK10zSsWL/1aegg==", + "version": "27.4.2", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-27.4.2.tgz", + "integrity": "sha512-xknHThRsPB/To1FUbi6pCe43y58qFC03zfb6R7fDb/FfC7k2R3i1l+izRBJf8DI46KhYGRaF14Eo9A3qbBoixg==", "requires": { - "@jest/types": "^27.0.6", + "@jest/types": "^27.4.2", "@types/node": "*", "chalk": "^4.0.0", - "jest-message-util": "^27.0.6", - "jest-util": "^27.0.6", + "jest-message-util": "^27.4.2", + "jest-util": "^27.4.2", "slash": "^3.0.0" } }, "@jest/core": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-27.0.6.tgz", - "integrity": "sha512-SsYBm3yhqOn5ZLJCtccaBcvD/ccTLCeuDv8U41WJH/V1MW5eKUkeMHT9U+Pw/v1m1AIWlnIW/eM2XzQr0rEmow==", + "version": "27.4.3", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-27.4.3.tgz", + "integrity": "sha512-V9ms3zSxUHxh1E/ZLAiXF7SLejsdFnjWTFizWotMOWvjho0lW5kSjZymhQSodNW0T0ZMQRiha7f8+NcFVm3hJQ==", "requires": { - "@jest/console": "^27.0.6", - "@jest/reporters": "^27.0.6", - "@jest/test-result": "^27.0.6", - "@jest/transform": "^27.0.6", - "@jest/types": "^27.0.6", + "@jest/console": "^27.4.2", + "@jest/reporters": "^27.4.2", + "@jest/test-result": "^27.4.2", + "@jest/transform": "^27.4.2", + "@jest/types": "^27.4.2", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "emittery": "^0.8.1", "exit": "^0.1.2", "graceful-fs": "^4.2.4", - "jest-changed-files": "^27.0.6", - "jest-config": "^27.0.6", - "jest-haste-map": "^27.0.6", - "jest-message-util": "^27.0.6", - "jest-regex-util": "^27.0.6", - "jest-resolve": "^27.0.6", - "jest-resolve-dependencies": "^27.0.6", - "jest-runner": "^27.0.6", - "jest-runtime": "^27.0.6", - "jest-snapshot": "^27.0.6", - "jest-util": "^27.0.6", - "jest-validate": "^27.0.6", - "jest-watcher": "^27.0.6", + "jest-changed-files": "^27.4.2", + "jest-config": "^27.4.3", + "jest-haste-map": "^27.4.2", + "jest-message-util": "^27.4.2", + "jest-regex-util": "^27.4.0", + "jest-resolve": "^27.4.2", + "jest-resolve-dependencies": "^27.4.2", + "jest-runner": "^27.4.3", + "jest-runtime": "^27.4.2", + "jest-snapshot": "^27.4.2", + "jest-util": "^27.4.2", + "jest-validate": "^27.4.2", + "jest-watcher": "^27.4.2", "micromatch": "^4.0.4", - "p-each-series": "^2.1.0", "rimraf": "^3.0.0", "slash": "^3.0.0", "strip-ansi": "^6.0.0" } }, "@jest/environment": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.0.6.tgz", - "integrity": "sha512-4XywtdhwZwCpPJ/qfAkqExRsERW+UaoSRStSHCCiQTUpoYdLukj+YJbQSFrZjhlUDRZeNiU9SFH0u7iNimdiIg==", + "version": "27.4.2", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-27.4.2.tgz", + "integrity": "sha512-uSljKxh/rGlHlmhyeG4ZoVK9hOec+EPBkwTHkHKQ2EqDu5K+MaG9uJZ8o1CbRsSdZqSuhXvJCYhBWsORPPg6qw==", "requires": { - "@jest/fake-timers": "^27.0.6", - "@jest/types": "^27.0.6", + "@jest/fake-timers": "^27.4.2", + "@jest/types": "^27.4.2", "@types/node": "*", - "jest-mock": "^27.0.6" + "jest-mock": "^27.4.2" } }, "@jest/fake-timers": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.0.6.tgz", - "integrity": "sha512-sqd+xTWtZ94l3yWDKnRTdvTeZ+A/V7SSKrxsrOKSqdyddb9CeNRF8fbhAU0D7ZJBpTTW2nbp6MftmKJDZfW2LQ==", + "version": "27.4.2", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-27.4.2.tgz", + "integrity": "sha512-f/Xpzn5YQk5adtqBgvw1V6bF8Nx3hY0OIRRpCvWcfPl0EAjdqWPdhH3t/3XpiWZqtjIEHDyMKP9ajpva1l4Zmg==", "requires": { - "@jest/types": "^27.0.6", - "@sinonjs/fake-timers": "^7.0.2", + "@jest/types": "^27.4.2", + "@sinonjs/fake-timers": "^8.0.1", "@types/node": "*", - "jest-message-util": "^27.0.6", - "jest-mock": "^27.0.6", - "jest-util": "^27.0.6" + "jest-message-util": "^27.4.2", + "jest-mock": "^27.4.2", + "jest-util": "^27.4.2" } }, "@jest/globals": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.0.6.tgz", - "integrity": "sha512-DdTGCP606rh9bjkdQ7VvChV18iS7q0IMJVP1piwTWyWskol4iqcVwthZmoJEf7obE1nc34OpIyoVGPeqLC+ryw==", + "version": "27.4.2", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-27.4.2.tgz", + "integrity": "sha512-KkfaHEttlGpXYAQTZHgrESiEPx2q/DKAFLGLFda1uGVrqc17snd3YVPhOxlXOHIzVPs+lQ/SDB2EIvxyGzb3Ew==", "requires": { - "@jest/environment": "^27.0.6", - "@jest/types": "^27.0.6", - "expect": "^27.0.6" + "@jest/environment": "^27.4.2", + "@jest/types": "^27.4.2", + "expect": "^27.4.2" } }, "@jest/reporters": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-27.0.6.tgz", - "integrity": "sha512-TIkBt09Cb2gptji3yJXb3EE+eVltW6BjO7frO7NEfjI9vSIYoISi5R3aI3KpEDXlB1xwB+97NXIqz84qYeYsfA==", + "version": "27.4.2", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-27.4.2.tgz", + "integrity": "sha512-sp4aqmdBJtjKetEakzDPcZggPcVIF6w9QLkYBbaWDV6e/SIsHnF1S4KtIH91eEc2fp7ep6V/e1xvdfEoho1d2w==", "requires": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^27.0.6", - "@jest/test-result": "^27.0.6", - "@jest/transform": "^27.0.6", - "@jest/types": "^27.0.6", + "@jest/console": "^27.4.2", + "@jest/test-result": "^27.4.2", + "@jest/transform": "^27.4.2", + "@jest/types": "^27.4.2", + "@types/node": "*", "chalk": "^4.0.0", "collect-v8-coverage": "^1.0.0", "exit": "^0.1.2", @@ -4356,21 +525,21 @@ "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.0.2", - "jest-haste-map": "^27.0.6", - "jest-resolve": "^27.0.6", - "jest-util": "^27.0.6", - "jest-worker": "^27.0.6", + "jest-haste-map": "^27.4.2", + "jest-resolve": "^27.4.2", + "jest-util": "^27.4.2", + "jest-worker": "^27.4.2", "slash": "^3.0.0", "source-map": "^0.6.0", "string-length": "^4.0.1", "terminal-link": "^2.0.0", - "v8-to-istanbul": "^8.0.0" + "v8-to-istanbul": "^8.1.0" } }, "@jest/source-map": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.0.6.tgz", - "integrity": "sha512-Fek4mi5KQrqmlY07T23JRi0e7Z9bXTOOD86V/uS0EIW4PClvPDqZOyFlLpNJheS6QI0FNX1CgmPjtJ4EA/2M+g==", + "version": "27.4.0", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-27.4.0.tgz", + "integrity": "sha512-Ntjx9jzP26Bvhbm93z/AKcPRj/9wrkI88/gK60glXDx1q+IeI0rf7Lw2c89Ch6ofonB0On/iRDreQuQ6te9pgQ==", "requires": { "callsites": "^3.0.0", "graceful-fs": "^4.2.4", @@ -4378,42 +547,42 @@ } }, "@jest/test-result": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.0.6.tgz", - "integrity": "sha512-ja/pBOMTufjX4JLEauLxE3LQBPaI2YjGFtXexRAjt1I/MbfNlMx0sytSX3tn5hSLzQsR3Qy2rd0hc1BWojtj9w==", + "version": "27.4.2", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-27.4.2.tgz", + "integrity": "sha512-kr+bCrra9jfTgxHXHa2UwoQjxvQk3Am6QbpAiJ5x/50LW8llOYrxILkqY0lZRW/hu8FXesnudbql263+EW9iNA==", "requires": { - "@jest/console": "^27.0.6", - "@jest/types": "^27.0.6", + "@jest/console": "^27.4.2", + "@jest/types": "^27.4.2", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" } }, "@jest/test-sequencer": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-27.0.6.tgz", - "integrity": "sha512-bISzNIApazYOlTHDum9PwW22NOyDa6VI31n6JucpjTVM0jD6JDgqEZ9+yn575nDdPF0+4csYDxNNW13NvFQGZA==", + "version": "27.4.2", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-27.4.2.tgz", + "integrity": "sha512-HmHp5mlh9f9GyNej5yCS1JZIFfUGnP9+jEOH5zoq5EmsuZeYD+dGULqyvGDPtuzzbyAFJ6R4+z4SS0VvnFwwGQ==", "requires": { - "@jest/test-result": "^27.0.6", + "@jest/test-result": "^27.4.2", "graceful-fs": "^4.2.4", - "jest-haste-map": "^27.0.6", - "jest-runtime": "^27.0.6" + "jest-haste-map": "^27.4.2", + "jest-runtime": "^27.4.2" } }, "@jest/transform": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.0.6.tgz", - "integrity": "sha512-rj5Dw+mtIcntAUnMlW/Vju5mr73u8yg+irnHwzgtgoeI6cCPOvUwQ0D1uQtc/APmWgvRweEb1g05pkUpxH3iCA==", + "version": "27.4.2", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-27.4.2.tgz", + "integrity": "sha512-RTKcPZllfcmLfnlxBya7aypofhdz05+E6QITe55Ex0rxyerkgjmmpMlvVn11V0cP719Ps6WcDYCnDzxnnJUwKg==", "requires": { "@babel/core": "^7.1.0", - "@jest/types": "^27.0.6", + "@jest/types": "^27.4.2", "babel-plugin-istanbul": "^6.0.0", "chalk": "^4.0.0", "convert-source-map": "^1.4.0", "fast-json-stable-stringify": "^2.0.0", "graceful-fs": "^4.2.4", - "jest-haste-map": "^27.0.6", - "jest-regex-util": "^27.0.6", - "jest-util": "^27.0.6", + "jest-haste-map": "^27.4.2", + "jest-regex-util": "^27.4.0", + "jest-util": "^27.4.2", "micromatch": "^4.0.4", "pirates": "^4.0.1", "slash": "^3.0.0", @@ -4422,9 +591,9 @@ } }, "@jest/types": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.0.6.tgz", - "integrity": "sha512-aSquT1qa9Pik26JK5/3rvnYb4bGtm1VFNesHKmNTwmPIgOrixvhL2ghIvFRNEpzy3gU+rUgjIF/KodbkFAl++g==", + "version": "27.4.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.4.2.tgz", + "integrity": "sha512-j35yw0PMTPpZsUoOBiuHzr1zTYoad1cVIE0ajEjcrJONxxrko/IRGKkXx3os0Nsi4Hu3+5VmDbVfq5WhG/pWAg==", "requires": { "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", @@ -4433,6 +602,21 @@ "chalk": "^4.0.0" } }, + "@seald-io/binary-search-tree": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@seald-io/binary-search-tree/-/binary-search-tree-1.0.2.tgz", + "integrity": "sha512-+pYGvPFAk7wUR+ONMOlc6A+LUN4kOCFwyPLjyaeS7wVibADPHWYJNYsNtyIAwjF1AXQkuaXElnIc4XjKt55QZA==" + }, + "@seald-io/nedb": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@seald-io/nedb/-/nedb-2.2.0.tgz", + "integrity": "sha512-whkcx3hpcowNhoSEbIsrfe8TXxDwyj8SJJut2EqF7DSX2GGqQlL7Ix/vzwwOo4FJolzDhZD2DaUTVKmTQS3Rog==", + "requires": { + "@seald-io/binary-search-tree": "^1.0.2", + "async": "0.2.10", + "localforage": "^1.9.0" + } + }, "@sinonjs/commons": { "version": "1.8.3", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", @@ -4442,9 +626,9 @@ } }, "@sinonjs/fake-timers": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-7.1.2.tgz", - "integrity": "sha512-iQADsW4LBMISqZ6Ci1dupJL9pprqwcVFTcOsEmQOEhW+KLCVn/Y4Jrvg2k19fIHCp+iFprriYPTdRcQR8NbUPg==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz", + "integrity": "sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==", "requires": { "@sinonjs/commons": "^1.7.0" } @@ -4455,9 +639,9 @@ "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==" }, "@types/babel__core": { - "version": "7.1.15", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.15.tgz", - "integrity": "sha512-bxlMKPDbY8x5h6HBwVzEOk2C8fb6SLfYQ5Jw3uBYuYF1lfWk/kbLd81la82vrIkBb0l+JdmrZaDikPrNxpS/Ew==", + "version": "7.1.17", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.17.tgz", + "integrity": "sha512-6zzkezS9QEIL8yCBvXWxPTJPNuMeECJVxSOhxNY/jfq9LxOTHivaYTqr37n9LknWWRTIkzqH2UilS5QFvfa90A==", "requires": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0", @@ -4521,14 +705,14 @@ } }, "@types/node": { - "version": "16.4.13", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.4.13.tgz", - "integrity": "sha512-bLL69sKtd25w7p1nvg9pigE4gtKVpGTPojBFLMkGHXuUgap2sLqQt2qUnqmVCDfzGUL0DRNZP+1prIZJbMeAXg==" + "version": "16.11.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.12.tgz", + "integrity": "sha512-+2Iggwg7PxoO5Kyhvsq9VarmPbIelXP070HMImEpbtGCoyWNINQj4wzjbQCXzdHTRXnqufutJb5KAURZANNBAw==" }, "@types/prettier": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.3.2.tgz", - "integrity": "sha512-eI5Yrz3Qv4KPUa/nSIAi0h+qX0XyewOliug5F2QAtuRg6Kjg6jfmxe1GIwoIRhZspD1A0RP8ANrPwvEXXtRFog==" + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.4.2.tgz", + "integrity": "sha512-ekoj4qOQYp7CvjX8ZDBgN86w3MqQhLE1hczEJbEIjgFEumDy+na/4AJAbLXfgEWFNB2pKadM5rPFtuSGMWK7xA==" }, "@types/stack-utils": { "version": "2.0.1", @@ -4554,9 +738,9 @@ "integrity": "sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==" }, "acorn": { - "version": "8.4.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.4.1.tgz", - "integrity": "sha512-asabaBSkEKosYKMITunzX177CXxQ4Q8BSSzMTKD+FefUhipQC70gfW5SiUDhYQ3vk8G+81HqQk7Fv9OXwwn9KA==" + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.6.0.tgz", + "integrity": "sha512-U1riIR+lBSNi3IbxtaHOIKdH8sLFv3NYfNv8sg7ZsNhcfl4HF2++BfqqrNAxoCLQW1iiylOj76ecnaUxz+z9yw==" }, "acorn-globals": { "version": "6.0.0", @@ -4596,9 +780,9 @@ } }, "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" }, "ansi-styles": { "version": "4.3.0", @@ -4608,6 +792,11 @@ "color-convert": "^2.0.1" } }, + "any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" + }, "anymatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", @@ -4625,6 +814,11 @@ "sprintf-js": "~1.0.2" } }, + "async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=" + }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -4639,36 +833,50 @@ } }, "babel-jest": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.0.6.tgz", - "integrity": "sha512-iTJyYLNc4wRofASmofpOc5NK9QunwMk+TLFgGXsTFS8uEqmd8wdI7sga0FPe2oVH3b5Agt/EAK1QjPEuKL8VfA==", + "version": "27.4.2", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.4.2.tgz", + "integrity": "sha512-MADrjb3KBO2eyZCAc6QaJg6RT5u+6oEdDyHO5HEalnpwQ6LrhTsQF2Kj1Wnz2t6UPXIXPk18dSXXOT0wF5yTxA==", "requires": { - "@jest/transform": "^27.0.6", - "@jest/types": "^27.0.6", + "@jest/transform": "^27.4.2", + "@jest/types": "^27.4.2", "@types/babel__core": "^7.1.14", "babel-plugin-istanbul": "^6.0.0", - "babel-preset-jest": "^27.0.6", + "babel-preset-jest": "^27.4.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.4", "slash": "^3.0.0" } }, "babel-plugin-istanbul": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.0.0.tgz", - "integrity": "sha512-AF55rZXpe7trmEylbaE1Gv54wn6rwU03aptvRoVIGP8YykoSxqdVLV1TfwflBCE/QtHmqtP8SWlTENqbK8GCSQ==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", "requires": { "@babel/helper-plugin-utils": "^7.0.0", "@istanbuljs/load-nyc-config": "^1.0.0", "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^4.0.0", + "istanbul-lib-instrument": "^5.0.4", "test-exclude": "^6.0.0" + }, + "dependencies": { + "istanbul-lib-instrument": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.1.0.tgz", + "integrity": "sha512-czwUz525rkOFDJxfKK6mYfIs9zBKILyrZQxjz3ABhjQXhbhFsSbo1HW/BFcsDnfJYJWA6thRR5/TUY2qs5W99Q==", + "requires": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + } + } } }, "babel-plugin-jest-hoist": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.0.6.tgz", - "integrity": "sha512-CewFeM9Vv2gM7Yr9n5eyyLVPRSiBnk6lKZRjgwYnGKSl9M14TMn2vkN02wTF04OGuSDLEzlWiMzvjXuW9mB6Gw==", + "version": "27.4.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.4.0.tgz", + "integrity": "sha512-Jcu7qS4OX5kTWBc45Hz7BMmgXuJqRnhatqpUhnzGC3OBYpOmf2tv6jFNwZpwM7wU7MUuv2r9IPS/ZlYOuburVw==", "requires": { "@babel/template": "^7.3.3", "@babel/types": "^7.3.3", @@ -4696,11 +904,11 @@ } }, "babel-preset-jest": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.0.6.tgz", - "integrity": "sha512-WObA0/Biw2LrVVwZkF/2GqbOdzhKD6Fkdwhoy9ASIrOWr/zodcSpQh72JOkEn6NWyjmnPDjNSqaGN4KnpKzhXw==", + "version": "27.4.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-27.4.0.tgz", + "integrity": "sha512-NK4jGYpnBvNxcGo7/ZpZJr51jCGT+3bwwpVIDY2oNfTxJJldRtB4VAcYdgp1loDE50ODuTu+yBjpMAswv5tlpg==", "requires": { - "babel-plugin-jest-hoist": "^27.0.6", + "babel-plugin-jest-hoist": "^27.4.0", "babel-preset-current-node-syntax": "^1.0.0" } }, @@ -4732,15 +940,15 @@ "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==" }, "browserslist": { - "version": "4.16.7", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.7.tgz", - "integrity": "sha512-7I4qVwqZltJ7j37wObBe3SoTz+nS8APaNcrBOlgoirb6/HbEU2XxW/LpUDTCngM6iauwFqmRTuOMfyKnFGY5JA==", + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.18.1.tgz", + "integrity": "sha512-8ScCzdpPwR2wQh8IT82CA2VgDwjHyqMovPBZSNH54+tm4Jk2pCuv90gmAdH6J84OCRWi0b4gMe6O6XPXuJnjgQ==", "requires": { - "caniuse-lite": "^1.0.30001248", - "colorette": "^1.2.2", - "electron-to-chromium": "^1.3.793", + "caniuse-lite": "^1.0.30001280", + "electron-to-chromium": "^1.3.896", "escalade": "^3.1.1", - "node-releases": "^1.1.73" + "node-releases": "^2.0.1", + "picocolors": "^1.0.0" } }, "bser": { @@ -4767,9 +975,9 @@ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" }, "caniuse-lite": { - "version": "1.0.30001249", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001249.tgz", - "integrity": "sha512-vcX4U8lwVXPdqzPWi6cAJ3FnQaqXbBqy/GZseKNQzRj37J7qZdGcBtxq/QLFNLLlfsoXLUdHw8Iwenri86Tagw==" + "version": "1.0.30001285", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001285.tgz", + "integrity": "sha512-KAOkuUtcQ901MtmvxfKD+ODHH9YVDYnBt+TGYSz2KIfnq22CiArbUxXPN9067gNbgMlnNYRSwho8OPXZPALB9Q==" }, "chalk": { "version": "4.1.1", @@ -4785,10 +993,15 @@ "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==" }, + "chunk": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/chunk/-/chunk-0.0.3.tgz", + "integrity": "sha512-oGfwvhjGRW3Ks4GTdGoJhZWKEO1eomjOC26001R+5H0TIlP7vBCO+/XcNcPCA6ayYC7RQSq1/NsN4679Odcm5A==" + }, "ci-info": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.2.0.tgz", - "integrity": "sha512-dVqRX7fLUm8J6FgHJ418XuIgDLZDkYcDFTeL6TA2gt5WlIZUQrrH6EZrNClwT/H0FateUsZkGIOPRrLbP+PR9A==" + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.0.tgz", + "integrity": "sha512-riT/3vI5YpVH6/qomlDnJow6TBee2PBKSEpx3O32EGPYbWGIRsIlGRms3Sm74wYE1JMo8RnO04Hb12+v1J5ICw==" }, "cjs-module-lexer": { "version": "1.2.2", @@ -4815,6 +1028,30 @@ "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==" }, + "color": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", + "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", + "requires": { + "color-convert": "^1.9.3", + "color-string": "^1.6.0" + }, + "dependencies": { + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + } + } + }, "color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -4828,16 +1065,29 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, - "colorette": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", - "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==" + "color-string": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.7.4.tgz", + "integrity": "sha512-nVdUvPVgZMpRQad5dcsCMOSB5BXLljklTiaxS6ehhKxDsAI5sD7k5VmFuBt1y3Rlym8uulc/ANUN/bMWtBu6Sg==", + "requires": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } }, "colors": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" }, + "colorspace": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz", + "integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==", + "requires": { + "color": "^3.1.3", + "text-hex": "1.0.x" + } + }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -4869,6 +1119,11 @@ "safe-buffer": "~5.1.1" } }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, "cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -4879,6 +1134,11 @@ "which": "^2.0.1" } }, + "crypto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/crypto/-/crypto-1.0.1.tgz", + "integrity": "sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig==" + }, "cssom": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", @@ -4914,10 +1174,15 @@ "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==" }, + "dayjs": { + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.10.7.tgz", + "integrity": "sha512-P6twpd70BcPK34K26uJ1KT3wlhpuOAPoMwJzpsIWUxHZ7wpmbdZL/hQqBDfz7hGurYSa5PhzdhDHtt319hL3ig==" + }, "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", "requires": { "ms": "2.1.2" } @@ -4933,9 +1198,9 @@ "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=" }, "deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" + "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==" }, "deepmerge": { "version": "4.2.2", @@ -4953,9 +1218,9 @@ "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==" }, "diff-sequences": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.0.6.tgz", - "integrity": "sha512-ag6wfpBFyNXZ0p8pcuIDS//D8H062ZQJ3fzYxjpmeKjnz8W4pekL3AI8VohmyZmsWW2PWaHgjsmqR6L13101VQ==" + "version": "27.4.0", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-27.4.0.tgz", + "integrity": "sha512-YqiQzkrsmHMH5uuh8OdQFU9/ZpADnwzml8z0O5HvRNda+5UZsaX/xN+AAxfR2hWq1Y7HZnAzO9J5lJXOuDz2Ww==" }, "domexception": { "version": "2.0.1", @@ -4973,9 +1238,9 @@ } }, "electron-to-chromium": { - "version": "1.3.799", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.799.tgz", - "integrity": "sha512-V2rbYWdGvSqrg+95KjkVuSi41bGfrhrOzjl1tSi2VLnm0mRe3FsSvhiqidSiSll9WiMhrQAhpDcW/wcqK3c+Yw==" + "version": "1.4.12", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.12.tgz", + "integrity": "sha512-zjfhG9Us/hIy8AlQ5OzfbR/C4aBv1Dg/ak4GX35CELYlJ4tDAtoEcQivXvyBdqdNQ+R6PhlgQqV8UNPJmhkJog==" }, "emittery": { "version": "0.8.1", @@ -4987,15 +1252,20 @@ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, + "enabled": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", + "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==" + }, "escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" }, "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==" + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, "escodegen": { "version": "2.0.0", @@ -5015,9 +1285,9 @@ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" }, "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==" + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==" }, "esutils": { "version": "2.0.3", @@ -5046,16 +1316,16 @@ "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=" }, "expect": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/expect/-/expect-27.0.6.tgz", - "integrity": "sha512-psNLt8j2kwg42jGBDSfAlU49CEZxejN1f1PlANWDZqIhBOVU/c2Pm888FcjWJzFewhIsNWfZJeLjUjtKGiPuSw==", + "version": "27.4.2", + "resolved": "https://registry.npmjs.org/expect/-/expect-27.4.2.tgz", + "integrity": "sha512-BjAXIDC6ZOW+WBFNg96J22D27Nq5ohn+oGcuP2rtOtcjuxNoV9McpQ60PcQWhdFOSBIQdR72e+4HdnbZTFSTyg==", "requires": { - "@jest/types": "^27.0.6", + "@jest/types": "^27.4.2", "ansi-styles": "^5.0.0", - "jest-get-type": "^27.0.6", - "jest-matcher-utils": "^27.0.6", - "jest-message-util": "^27.0.6", - "jest-regex-util": "^27.0.6" + "jest-get-type": "^27.4.0", + "jest-matcher-utils": "^27.4.2", + "jest-message-util": "^27.4.2", + "jest-regex-util": "^27.4.0" }, "dependencies": { "ansi-styles": { @@ -5083,6 +1353,11 @@ "bser": "2.1.1" } }, + "fecha": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.1.tgz", + "integrity": "sha512-MMMQ0ludy/nBs1/o0zVOiKTpG7qMbonKUzjJgQFEuvq6INZ1OraKPRAWkBq5vlKLOUMpmNYG1JoN3oDPUQ9m3Q==" + }, "fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -5100,6 +1375,11 @@ "path-exists": "^4.0.0" } }, + "fn.name": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", + "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" + }, "follow-redirects": { "version": "1.14.4", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.4.tgz", @@ -5237,10 +1517,15 @@ "safer-buffer": ">= 2.1.2 < 3" } }, + "immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=" + }, "import-local": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.2.tgz", - "integrity": "sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.3.tgz", + "integrity": "sha512-bE9iaUY3CXH8Cwfan/abDKAxe1KGT9kyGsBPqf6DMK/z0a2OzAsrukeYNgIH6cH5Xr452jb1TUL8rSfCLjZ9uA==", "requires": { "pkg-dir": "^4.2.0", "resolve-cwd": "^3.0.0" @@ -5266,9 +1551,9 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "iptv-checker": { - "version": "0.21.0", - "resolved": "https://registry.npmjs.org/iptv-checker/-/iptv-checker-0.21.0.tgz", - "integrity": "sha512-qWqq8mLl+qRgV0/fmBpZm8/Cf7FwSnIA1gt9PFlYbzilRDFtPoTRDm0eP9fCWHVwwZZsImE1aMLx8qkikL5Aog==", + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/iptv-checker/-/iptv-checker-0.22.0.tgz", + "integrity": "sha512-94dnViRK9DaegiVkRR1BGzsDvfo+t4ZkQJgVvSrzbcpvKaNnMUHHtm2hlwKejfz+A/Ci/wBVWkcVe0pZB1KODQ==", "requires": { "axios": "^0.21.1", "colors": "^1.4.0", @@ -5296,22 +1581,19 @@ } }, "iptv-playlist-parser": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/iptv-playlist-parser/-/iptv-playlist-parser-0.9.0.tgz", - "integrity": "sha512-F+aGQv1uBu6iWWlYfFjMhdk8vUofkeCMIbzvYiPBwYQOQBHd/OhFHxNTCCsFRGas2CjOSxDa29FNr0EZSkK/uw==" + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/iptv-playlist-parser/-/iptv-playlist-parser-0.10.2.tgz", + "integrity": "sha512-Ls2mKaSgbLtW46KyFd0EVmzLV5lfZzU9lJZTOTrchTsF+sRVGziA6JthtgvhIhPDitruedZRlsa8RdSKGBtDfA==" }, - "is-ci": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.0.tgz", - "integrity": "sha512-kDXyttuLeslKAHYL/K28F2YkM3x5jvFPEw3yXbRptXydjD9rpLEz+C5K5iutY9ZiUu6AP41JdvRQwF4Iqs4ZCQ==", - "requires": { - "ci-info": "^3.1.1" - } + "is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" }, "is-core-module": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.5.0.tgz", - "integrity": "sha512-TXCMSDsEHMEEZ6eCA8rwRDbLu55MRGmrctljsBX/2v1d9/GzqHOxW5c5oPSgrUt2vBFXebu9rGqckXGPWOlYpg==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.0.tgz", + "integrity": "sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==", "requires": { "has": "^1.0.3" } @@ -5346,15 +1628,20 @@ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, "istanbul-lib-coverage": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz", - "integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==" + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==" }, "istanbul-lib-instrument": { "version": "4.0.3", @@ -5378,9 +1665,9 @@ } }, "istanbul-lib-source-maps": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz", - "integrity": "sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", "requires": { "debug": "^4.1.1", "istanbul-lib-coverage": "^3.0.0", @@ -5388,372 +1675,375 @@ } }, "istanbul-reports": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.2.tgz", - "integrity": "sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.1.tgz", + "integrity": "sha512-q1kvhAXWSsXfMjCdNHNPKZZv94OlspKnoGv+R9RGbnqOOQ0VbNfLFgQDVgi7hHenKsndGq3/o0OBdzDXthWcNw==", "requires": { "html-escaper": "^2.0.0", "istanbul-lib-report": "^3.0.0" } }, "jest": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest/-/jest-27.0.6.tgz", - "integrity": "sha512-EjV8aETrsD0wHl7CKMibKwQNQc3gIRBXlTikBmmHUeVMKaPFxdcUIBfoDqTSXDoGJIivAYGqCWVlzCSaVjPQsA==", + "version": "27.4.3", + "resolved": "https://registry.npmjs.org/jest/-/jest-27.4.3.tgz", + "integrity": "sha512-jwsfVABBzuN3Atm+6h6vIEpTs9+VApODLt4dk2qv1WMOpb1weI1IIZfuwpMiWZ62qvWj78MvdvMHIYdUfqrFaA==", "requires": { - "@jest/core": "^27.0.6", + "@jest/core": "^27.4.3", "import-local": "^3.0.2", - "jest-cli": "^27.0.6" + "jest-cli": "^27.4.3" + }, + "dependencies": { + "jest-cli": { + "version": "27.4.3", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-27.4.3.tgz", + "integrity": "sha512-zZSJBXNC/i8UnJPwcKWsqnhGgIF3uoTYP7th32Zej7KNQJdxzOMj+wCfy2Ox3kU7nXErJ36DtYyXDhfiqaiDRw==", + "requires": { + "@jest/core": "^27.4.3", + "@jest/test-result": "^27.4.2", + "@jest/types": "^27.4.2", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.4", + "import-local": "^3.0.2", + "jest-config": "^27.4.3", + "jest-util": "^27.4.2", + "jest-validate": "^27.4.2", + "prompts": "^2.0.1", + "yargs": "^16.2.0" + } + } } }, "jest-changed-files": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-27.0.6.tgz", - "integrity": "sha512-BuL/ZDauaq5dumYh5y20sn4IISnf1P9A0TDswTxUi84ORGtVa86ApuBHqICL0vepqAnZiY6a7xeSPWv2/yy4eA==", + "version": "27.4.2", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-27.4.2.tgz", + "integrity": "sha512-/9x8MjekuzUQoPjDHbBiXbNEBauhrPU2ct7m8TfCg69ywt1y/N+yYwGh3gCpnqUS3klYWDU/lSNgv+JhoD2k1A==", "requires": { - "@jest/types": "^27.0.6", + "@jest/types": "^27.4.2", "execa": "^5.0.0", "throat": "^6.0.1" } }, "jest-circus": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-27.0.6.tgz", - "integrity": "sha512-OJlsz6BBeX9qR+7O9lXefWoc2m9ZqcZ5Ohlzz0pTEAG4xMiZUJoacY8f4YDHxgk0oKYxj277AfOk9w6hZYvi1Q==", + "version": "27.4.2", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-27.4.2.tgz", + "integrity": "sha512-2ePUSru1BGMyzxsMvRfu+tNb+PW60rUyMLJBfw1Nrh5zC8RoTPfF+zbE0JToU31a6ZVe4nnrNKWYRzlghAbL0A==", "requires": { - "@jest/environment": "^27.0.6", - "@jest/test-result": "^27.0.6", - "@jest/types": "^27.0.6", + "@jest/environment": "^27.4.2", + "@jest/test-result": "^27.4.2", + "@jest/types": "^27.4.2", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", "dedent": "^0.7.0", - "expect": "^27.0.6", + "expect": "^27.4.2", "is-generator-fn": "^2.0.0", - "jest-each": "^27.0.6", - "jest-matcher-utils": "^27.0.6", - "jest-message-util": "^27.0.6", - "jest-runtime": "^27.0.6", - "jest-snapshot": "^27.0.6", - "jest-util": "^27.0.6", - "pretty-format": "^27.0.6", + "jest-each": "^27.4.2", + "jest-matcher-utils": "^27.4.2", + "jest-message-util": "^27.4.2", + "jest-runtime": "^27.4.2", + "jest-snapshot": "^27.4.2", + "jest-util": "^27.4.2", + "pretty-format": "^27.4.2", "slash": "^3.0.0", "stack-utils": "^2.0.3", "throat": "^6.0.1" } }, - "jest-cli": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-27.0.6.tgz", - "integrity": "sha512-qUUVlGb9fdKir3RDE+B10ULI+LQrz+MCflEH2UJyoUjoHHCbxDrMxSzjQAPUMsic4SncI62ofYCcAvW6+6rhhg==", - "requires": { - "@jest/core": "^27.0.6", - "@jest/test-result": "^27.0.6", - "@jest/types": "^27.0.6", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.4", - "import-local": "^3.0.2", - "jest-config": "^27.0.6", - "jest-util": "^27.0.6", - "jest-validate": "^27.0.6", - "prompts": "^2.0.1", - "yargs": "^16.0.3" - } - }, "jest-config": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-27.0.6.tgz", - "integrity": "sha512-JZRR3I1Plr2YxPBhgqRspDE2S5zprbga3swYNrvY3HfQGu7p/GjyLOqwrYad97tX3U3mzT53TPHVmozacfP/3w==", + "version": "27.4.3", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-27.4.3.tgz", + "integrity": "sha512-DQ10HTSqYtC2pO7s9j2jw+li4xUnm2wLYWH2o7K1ftB8NyvToHsXoLlXxtsGh3AW9gUQR6KY/4B7G+T/NswJBw==", "requires": { "@babel/core": "^7.1.0", - "@jest/test-sequencer": "^27.0.6", - "@jest/types": "^27.0.6", - "babel-jest": "^27.0.6", + "@jest/test-sequencer": "^27.4.2", + "@jest/types": "^27.4.2", + "babel-jest": "^27.4.2", "chalk": "^4.0.0", + "ci-info": "^3.2.0", "deepmerge": "^4.2.2", "glob": "^7.1.1", "graceful-fs": "^4.2.4", - "is-ci": "^3.0.0", - "jest-circus": "^27.0.6", - "jest-environment-jsdom": "^27.0.6", - "jest-environment-node": "^27.0.6", - "jest-get-type": "^27.0.6", - "jest-jasmine2": "^27.0.6", - "jest-regex-util": "^27.0.6", - "jest-resolve": "^27.0.6", - "jest-runner": "^27.0.6", - "jest-util": "^27.0.6", - "jest-validate": "^27.0.6", + "jest-circus": "^27.4.2", + "jest-environment-jsdom": "^27.4.3", + "jest-environment-node": "^27.4.2", + "jest-get-type": "^27.4.0", + "jest-jasmine2": "^27.4.2", + "jest-regex-util": "^27.4.0", + "jest-resolve": "^27.4.2", + "jest-runner": "^27.4.3", + "jest-util": "^27.4.2", + "jest-validate": "^27.4.2", "micromatch": "^4.0.4", - "pretty-format": "^27.0.6" + "pretty-format": "^27.4.2", + "slash": "^3.0.0" } }, "jest-diff": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.0.6.tgz", - "integrity": "sha512-Z1mqgkTCSYaFgwTlP/NUiRzdqgxmmhzHY1Tq17zL94morOHfHu3K4bgSgl+CR4GLhpV8VxkuOYuIWnQ9LnFqmg==", + "version": "27.4.2", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-27.4.2.tgz", + "integrity": "sha512-ujc9ToyUZDh9KcqvQDkk/gkbf6zSaeEg9AiBxtttXW59H/AcqEYp1ciXAtJp+jXWva5nAf/ePtSsgWwE5mqp4Q==", "requires": { "chalk": "^4.0.0", - "diff-sequences": "^27.0.6", - "jest-get-type": "^27.0.6", - "pretty-format": "^27.0.6" + "diff-sequences": "^27.4.0", + "jest-get-type": "^27.4.0", + "pretty-format": "^27.4.2" } }, "jest-docblock": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-27.0.6.tgz", - "integrity": "sha512-Fid6dPcjwepTFraz0YxIMCi7dejjJ/KL9FBjPYhBp4Sv1Y9PdhImlKZqYU555BlN4TQKaTc+F2Av1z+anVyGkA==", + "version": "27.4.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-27.4.0.tgz", + "integrity": "sha512-7TBazUdCKGV7svZ+gh7C8esAnweJoG+SvcF6Cjqj4l17zA2q1cMwx2JObSioubk317H+cjcHgP+7fTs60paulg==", "requires": { "detect-newline": "^3.0.0" } }, "jest-each": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-27.0.6.tgz", - "integrity": "sha512-m6yKcV3bkSWrUIjxkE9OC0mhBZZdhovIW5ergBYirqnkLXkyEn3oUUF/QZgyecA1cF1QFyTE8bRRl8Tfg1pfLA==", + "version": "27.4.2", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-27.4.2.tgz", + "integrity": "sha512-53V2MNyW28CTruB3lXaHNk6PkiIFuzdOC9gR3C6j8YE/ACfrPnz+slB0s17AgU1TtxNzLuHyvNlLJ+8QYw9nBg==", "requires": { - "@jest/types": "^27.0.6", + "@jest/types": "^27.4.2", "chalk": "^4.0.0", - "jest-get-type": "^27.0.6", - "jest-util": "^27.0.6", - "pretty-format": "^27.0.6" + "jest-get-type": "^27.4.0", + "jest-util": "^27.4.2", + "pretty-format": "^27.4.2" } }, "jest-environment-jsdom": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-27.0.6.tgz", - "integrity": "sha512-FvetXg7lnXL9+78H+xUAsra3IeZRTiegA3An01cWeXBspKXUhAwMM9ycIJ4yBaR0L7HkoMPaZsozCLHh4T8fuw==", + "version": "27.4.3", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-27.4.3.tgz", + "integrity": "sha512-x1AUVz3G14LpEJs7KIFUaTINT2n0unOUmvdAby3s/sldUpJJetOJifHo1O/EUQC5fNBowggwJbVulko18y6OWw==", "requires": { - "@jest/environment": "^27.0.6", - "@jest/fake-timers": "^27.0.6", - "@jest/types": "^27.0.6", + "@jest/environment": "^27.4.2", + "@jest/fake-timers": "^27.4.2", + "@jest/types": "^27.4.2", "@types/node": "*", - "jest-mock": "^27.0.6", - "jest-util": "^27.0.6", + "jest-mock": "^27.4.2", + "jest-util": "^27.4.2", "jsdom": "^16.6.0" } }, "jest-environment-node": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.0.6.tgz", - "integrity": "sha512-+Vi6yLrPg/qC81jfXx3IBlVnDTI6kmRr08iVa2hFCWmJt4zha0XW7ucQltCAPhSR0FEKEoJ3i+W4E6T0s9is0w==", + "version": "27.4.2", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-27.4.2.tgz", + "integrity": "sha512-nzTZ5nJ+FabuZPH2YVci7SZIHpvtNRHPt8+vipLkCnAgXGjVzHm7XJWdnNqXbAkExIgiKeVEkVMNZOZE/LeiIg==", "requires": { - "@jest/environment": "^27.0.6", - "@jest/fake-timers": "^27.0.6", - "@jest/types": "^27.0.6", + "@jest/environment": "^27.4.2", + "@jest/fake-timers": "^27.4.2", + "@jest/types": "^27.4.2", "@types/node": "*", - "jest-mock": "^27.0.6", - "jest-util": "^27.0.6" + "jest-mock": "^27.4.2", + "jest-util": "^27.4.2" } }, "jest-get-type": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.0.6.tgz", - "integrity": "sha512-XTkK5exIeUbbveehcSR8w0bhH+c0yloW/Wpl+9vZrjzztCPWrxhHwkIFpZzCt71oRBsgxmuUfxEqOYoZI2macg==" + "version": "27.4.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-27.4.0.tgz", + "integrity": "sha512-tk9o+ld5TWq41DkK14L4wox4s2D9MtTpKaAVzXfr5CUKm5ZK2ExcaFE0qls2W71zE/6R2TxxrK9w2r6svAFDBQ==" }, "jest-haste-map": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.0.6.tgz", - "integrity": "sha512-4ldjPXX9h8doB2JlRzg9oAZ2p6/GpQUNAeiYXqcpmrKbP0Qev0wdZlxSMOmz8mPOEnt4h6qIzXFLDi8RScX/1w==", + "version": "27.4.2", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-27.4.2.tgz", + "integrity": "sha512-foiyAEePORUN2eeJnOtcM1y8qW0ShEd9kTjWVL4sVaMcuCJM6gtHegvYPBRT0mpI/bs4ueThM90+Eoj2ncoNsA==", "requires": { - "@jest/types": "^27.0.6", + "@jest/types": "^27.4.2", "@types/graceful-fs": "^4.1.2", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "fsevents": "^2.3.2", "graceful-fs": "^4.2.4", - "jest-regex-util": "^27.0.6", - "jest-serializer": "^27.0.6", - "jest-util": "^27.0.6", - "jest-worker": "^27.0.6", + "jest-regex-util": "^27.4.0", + "jest-serializer": "^27.4.0", + "jest-util": "^27.4.2", + "jest-worker": "^27.4.2", "micromatch": "^4.0.4", "walker": "^1.0.7" } }, "jest-jasmine2": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-27.0.6.tgz", - "integrity": "sha512-cjpH2sBy+t6dvCeKBsHpW41mjHzXgsavaFMp+VWRf0eR4EW8xASk1acqmljFtK2DgyIECMv2yCdY41r2l1+4iA==", + "version": "27.4.2", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-27.4.2.tgz", + "integrity": "sha512-VO/fyAJSH9u0THjbteFiL8qc93ufU+yW+bdieDc8tzTCWwlWzO53UHS5nFK1qmE8izb5Smkn+XHlVt6/l06MKQ==", "requires": { "@babel/traverse": "^7.1.0", - "@jest/environment": "^27.0.6", - "@jest/source-map": "^27.0.6", - "@jest/test-result": "^27.0.6", - "@jest/types": "^27.0.6", + "@jest/environment": "^27.4.2", + "@jest/source-map": "^27.4.0", + "@jest/test-result": "^27.4.2", + "@jest/types": "^27.4.2", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", - "expect": "^27.0.6", + "expect": "^27.4.2", "is-generator-fn": "^2.0.0", - "jest-each": "^27.0.6", - "jest-matcher-utils": "^27.0.6", - "jest-message-util": "^27.0.6", - "jest-runtime": "^27.0.6", - "jest-snapshot": "^27.0.6", - "jest-util": "^27.0.6", - "pretty-format": "^27.0.6", + "jest-each": "^27.4.2", + "jest-matcher-utils": "^27.4.2", + "jest-message-util": "^27.4.2", + "jest-runtime": "^27.4.2", + "jest-snapshot": "^27.4.2", + "jest-util": "^27.4.2", + "pretty-format": "^27.4.2", "throat": "^6.0.1" } }, "jest-leak-detector": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-27.0.6.tgz", - "integrity": "sha512-2/d6n2wlH5zEcdctX4zdbgX8oM61tb67PQt4Xh8JFAIy6LRKUnX528HulkaG6nD5qDl5vRV1NXejCe1XRCH5gQ==", + "version": "27.4.2", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-27.4.2.tgz", + "integrity": "sha512-ml0KvFYZllzPBJWDei3mDzUhyp/M4ubKebX++fPaudpe8OsxUE+m+P6ciVLboQsrzOCWDjE20/eXew9QMx/VGw==", "requires": { - "jest-get-type": "^27.0.6", - "pretty-format": "^27.0.6" + "jest-get-type": "^27.4.0", + "pretty-format": "^27.4.2" } }, "jest-matcher-utils": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.0.6.tgz", - "integrity": "sha512-OFgF2VCQx9vdPSYTHWJ9MzFCehs20TsyFi6bIHbk5V1u52zJOnvF0Y/65z3GLZHKRuTgVPY4Z6LVePNahaQ+tA==", + "version": "27.4.2", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-27.4.2.tgz", + "integrity": "sha512-jyP28er3RRtMv+fmYC/PKG8wvAmfGcSNproVTW2Y0P/OY7/hWUOmsPfxN1jOhM+0u2xU984u2yEagGivz9OBGQ==", "requires": { "chalk": "^4.0.0", - "jest-diff": "^27.0.6", - "jest-get-type": "^27.0.6", - "pretty-format": "^27.0.6" + "jest-diff": "^27.4.2", + "jest-get-type": "^27.4.0", + "pretty-format": "^27.4.2" } }, "jest-message-util": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.0.6.tgz", - "integrity": "sha512-rBxIs2XK7rGy+zGxgi+UJKP6WqQ+KrBbD1YMj517HYN3v2BG66t3Xan3FWqYHKZwjdB700KiAJ+iES9a0M+ixw==", + "version": "27.4.2", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-27.4.2.tgz", + "integrity": "sha512-OMRqRNd9E0DkBLZpFtZkAGYOXl6ZpoMtQJWTAREJKDOFa0M6ptB7L67tp+cszMBkvSgKOhNtQp2Vbcz3ZZKo/w==", "requires": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^27.0.6", + "@jest/types": "^27.4.2", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.4", "micromatch": "^4.0.4", - "pretty-format": "^27.0.6", + "pretty-format": "^27.4.2", "slash": "^3.0.0", "stack-utils": "^2.0.3" } }, "jest-mock": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.0.6.tgz", - "integrity": "sha512-lzBETUoK8cSxts2NYXSBWT+EJNzmUVtVVwS1sU9GwE1DLCfGsngg+ZVSIe0yd0ZSm+y791esiuo+WSwpXJQ5Bw==", + "version": "27.4.2", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-27.4.2.tgz", + "integrity": "sha512-PDDPuyhoukk20JrQKeofK12hqtSka7mWH0QQuxSNgrdiPsrnYYLS6wbzu/HDlxZRzji5ylLRULeuI/vmZZDrYA==", "requires": { - "@jest/types": "^27.0.6", + "@jest/types": "^27.4.2", "@types/node": "*" } }, "jest-pnp-resolver": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", - "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==", - "requires": {} + "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==" }, "jest-regex-util": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.0.6.tgz", - "integrity": "sha512-SUhPzBsGa1IKm8hx2F4NfTGGp+r7BXJ4CulsZ1k2kI+mGLG+lxGrs76veN2LF/aUdGosJBzKgXmNCw+BzFqBDQ==" + "version": "27.4.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-27.4.0.tgz", + "integrity": "sha512-WeCpMpNnqJYMQoOjm1nTtsgbR4XHAk1u00qDoNBQoykM280+/TmgA5Qh5giC1ecy6a5d4hbSsHzpBtu5yvlbEg==" }, "jest-resolve": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.0.6.tgz", - "integrity": "sha512-yKmIgw2LgTh7uAJtzv8UFHGF7Dm7XfvOe/LQ3Txv101fLM8cx2h1QVwtSJ51Q/SCxpIiKfVn6G2jYYMDNHZteA==", + "version": "27.4.2", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-27.4.2.tgz", + "integrity": "sha512-d/zqPjxCzMqHlOdRTg8cTpO9jY+1/T74KazT8Ws/LwmwxV5sRMWOkiLjmzUCDj/5IqA5XHNK4Hkmlq9Kdpb9Sg==", "requires": { - "@jest/types": "^27.0.6", + "@jest/types": "^27.4.2", "chalk": "^4.0.0", - "escalade": "^3.1.1", "graceful-fs": "^4.2.4", + "jest-haste-map": "^27.4.2", "jest-pnp-resolver": "^1.2.2", - "jest-util": "^27.0.6", - "jest-validate": "^27.0.6", + "jest-util": "^27.4.2", + "jest-validate": "^27.4.2", "resolve": "^1.20.0", + "resolve.exports": "^1.1.0", "slash": "^3.0.0" } }, "jest-resolve-dependencies": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-27.0.6.tgz", - "integrity": "sha512-mg9x9DS3BPAREWKCAoyg3QucCr0n6S8HEEsqRCKSPjPcu9HzRILzhdzY3imsLoZWeosEbJZz6TKasveczzpJZA==", + "version": "27.4.2", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-27.4.2.tgz", + "integrity": "sha512-hb++cTpqvOWfU49MCP/JQkxmnrhKoAVqXWFjgYXswRSVGk8Q6bDTSvhbCeYXDtXaymY0y7WrrSIlKogClcKJuw==", "requires": { - "@jest/types": "^27.0.6", - "jest-regex-util": "^27.0.6", - "jest-snapshot": "^27.0.6" + "@jest/types": "^27.4.2", + "jest-regex-util": "^27.4.0", + "jest-snapshot": "^27.4.2" } }, "jest-runner": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-27.0.6.tgz", - "integrity": "sha512-W3Bz5qAgaSChuivLn+nKOgjqNxM7O/9JOJoKDCqThPIg2sH/d4A/lzyiaFgnb9V1/w29Le11NpzTJSzga1vyYQ==", + "version": "27.4.3", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-27.4.3.tgz", + "integrity": "sha512-JgR6Om/j22Fd6ZUUIGTWNcCtuZVYbNrecb4k89W4UyFJoRtHpo2zMKWkmFFFJoqwWGrfrcPLnVBIgkJiTV3cyA==", "requires": { - "@jest/console": "^27.0.6", - "@jest/environment": "^27.0.6", - "@jest/test-result": "^27.0.6", - "@jest/transform": "^27.0.6", - "@jest/types": "^27.0.6", + "@jest/console": "^27.4.2", + "@jest/environment": "^27.4.2", + "@jest/test-result": "^27.4.2", + "@jest/transform": "^27.4.2", + "@jest/types": "^27.4.2", "@types/node": "*", "chalk": "^4.0.0", "emittery": "^0.8.1", "exit": "^0.1.2", "graceful-fs": "^4.2.4", - "jest-docblock": "^27.0.6", - "jest-environment-jsdom": "^27.0.6", - "jest-environment-node": "^27.0.6", - "jest-haste-map": "^27.0.6", - "jest-leak-detector": "^27.0.6", - "jest-message-util": "^27.0.6", - "jest-resolve": "^27.0.6", - "jest-runtime": "^27.0.6", - "jest-util": "^27.0.6", - "jest-worker": "^27.0.6", + "jest-docblock": "^27.4.0", + "jest-environment-jsdom": "^27.4.3", + "jest-environment-node": "^27.4.2", + "jest-haste-map": "^27.4.2", + "jest-leak-detector": "^27.4.2", + "jest-message-util": "^27.4.2", + "jest-resolve": "^27.4.2", + "jest-runtime": "^27.4.2", + "jest-util": "^27.4.2", + "jest-worker": "^27.4.2", "source-map-support": "^0.5.6", "throat": "^6.0.1" } }, "jest-runtime": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.0.6.tgz", - "integrity": "sha512-BhvHLRVfKibYyqqEFkybsznKwhrsu7AWx2F3y9G9L95VSIN3/ZZ9vBpm/XCS2bS+BWz3sSeNGLzI3TVQ0uL85Q==", + "version": "27.4.2", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-27.4.2.tgz", + "integrity": "sha512-eqPgcBaUNaw6j8T5M+dnfAEh6MIrh2YmtskCr9sl50QYpD22Sg+QqHw3J3nmaLzVMbBtOMHFFxLF0Qx8MsZVFQ==", "requires": { - "@jest/console": "^27.0.6", - "@jest/environment": "^27.0.6", - "@jest/fake-timers": "^27.0.6", - "@jest/globals": "^27.0.6", - "@jest/source-map": "^27.0.6", - "@jest/test-result": "^27.0.6", - "@jest/transform": "^27.0.6", - "@jest/types": "^27.0.6", + "@jest/console": "^27.4.2", + "@jest/environment": "^27.4.2", + "@jest/globals": "^27.4.2", + "@jest/source-map": "^27.4.0", + "@jest/test-result": "^27.4.2", + "@jest/transform": "^27.4.2", + "@jest/types": "^27.4.2", "@types/yargs": "^16.0.0", "chalk": "^4.0.0", "cjs-module-lexer": "^1.0.0", "collect-v8-coverage": "^1.0.0", + "execa": "^5.0.0", "exit": "^0.1.2", "glob": "^7.1.3", "graceful-fs": "^4.2.4", - "jest-haste-map": "^27.0.6", - "jest-message-util": "^27.0.6", - "jest-mock": "^27.0.6", - "jest-regex-util": "^27.0.6", - "jest-resolve": "^27.0.6", - "jest-snapshot": "^27.0.6", - "jest-util": "^27.0.6", - "jest-validate": "^27.0.6", + "jest-haste-map": "^27.4.2", + "jest-message-util": "^27.4.2", + "jest-mock": "^27.4.2", + "jest-regex-util": "^27.4.0", + "jest-resolve": "^27.4.2", + "jest-snapshot": "^27.4.2", + "jest-util": "^27.4.2", + "jest-validate": "^27.4.2", "slash": "^3.0.0", "strip-bom": "^4.0.0", - "yargs": "^16.0.3" + "yargs": "^16.2.0" } }, "jest-serializer": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.0.6.tgz", - "integrity": "sha512-PtGdVK9EGC7dsaziskfqaAPib6wTViY3G8E5wz9tLVPhHyiDNTZn/xjZ4khAw+09QkoOVpn7vF5nPSN6dtBexA==", + "version": "27.4.0", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-27.4.0.tgz", + "integrity": "sha512-RDhpcn5f1JYTX2pvJAGDcnsNTnsV9bjYPU8xcV+xPwOXnUPOQwf4ZEuiU6G9H1UztH+OapMgu/ckEVwO87PwnQ==", "requires": { "@types/node": "*", "graceful-fs": "^4.2.4" } }, "jest-snapshot": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.0.6.tgz", - "integrity": "sha512-NTHaz8He+ATUagUgE7C/UtFcRoHqR2Gc+KDfhQIyx+VFgwbeEMjeP+ILpUTLosZn/ZtbNdCF5LkVnN/l+V751A==", + "version": "27.4.2", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-27.4.2.tgz", + "integrity": "sha512-DI7lJlNIu6WSQ+esqhnJzEzU70+dV+cNjoF1c+j5FagWEd3KtOyZvVliAH0RWNQ6KSnAAnKSU0qxJ8UXOOhuUQ==", "requires": { "@babel/core": "^7.7.2", "@babel/generator": "^7.7.2", @@ -5761,23 +2051,23 @@ "@babel/plugin-syntax-typescript": "^7.7.2", "@babel/traverse": "^7.7.2", "@babel/types": "^7.0.0", - "@jest/transform": "^27.0.6", - "@jest/types": "^27.0.6", + "@jest/transform": "^27.4.2", + "@jest/types": "^27.4.2", "@types/babel__traverse": "^7.0.4", "@types/prettier": "^2.1.5", "babel-preset-current-node-syntax": "^1.0.0", "chalk": "^4.0.0", - "expect": "^27.0.6", + "expect": "^27.4.2", "graceful-fs": "^4.2.4", - "jest-diff": "^27.0.6", - "jest-get-type": "^27.0.6", - "jest-haste-map": "^27.0.6", - "jest-matcher-utils": "^27.0.6", - "jest-message-util": "^27.0.6", - "jest-resolve": "^27.0.6", - "jest-util": "^27.0.6", + "jest-diff": "^27.4.2", + "jest-get-type": "^27.4.0", + "jest-haste-map": "^27.4.2", + "jest-matcher-utils": "^27.4.2", + "jest-message-util": "^27.4.2", + "jest-resolve": "^27.4.2", + "jest-util": "^27.4.2", "natural-compare": "^1.4.0", - "pretty-format": "^27.0.6", + "pretty-format": "^27.4.2", "semver": "^7.3.2" }, "dependencies": { @@ -5792,56 +2082,56 @@ } }, "jest-util": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.0.6.tgz", - "integrity": "sha512-1JjlaIh+C65H/F7D11GNkGDDZtDfMEM8EBXsvd+l/cxtgQ6QhxuloOaiayt89DxUvDarbVhqI98HhgrM1yliFQ==", + "version": "27.4.2", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-27.4.2.tgz", + "integrity": "sha512-YuxxpXU6nlMan9qyLuxHaMMOzXAl5aGZWCSzben5DhLHemYQxCc4YK+4L3ZrCutT8GPQ+ui9k5D8rUJoDioMnA==", "requires": { - "@jest/types": "^27.0.6", + "@jest/types": "^27.4.2", "@types/node": "*", "chalk": "^4.0.0", + "ci-info": "^3.2.0", "graceful-fs": "^4.2.4", - "is-ci": "^3.0.0", "picomatch": "^2.2.3" } }, "jest-validate": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-27.0.6.tgz", - "integrity": "sha512-yhZZOaMH3Zg6DC83n60pLmdU1DQE46DW+KLozPiPbSbPhlXXaiUTDlhHQhHFpaqIFRrInko1FHXjTRpjWRuWfA==", + "version": "27.4.2", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-27.4.2.tgz", + "integrity": "sha512-hWYsSUej+Fs8ZhOm5vhWzwSLmVaPAxRy+Mr+z5MzeaHm9AxUpXdoVMEW4R86y5gOobVfBsMFLk4Rb+QkiEpx1A==", "requires": { - "@jest/types": "^27.0.6", + "@jest/types": "^27.4.2", "camelcase": "^6.2.0", "chalk": "^4.0.0", - "jest-get-type": "^27.0.6", + "jest-get-type": "^27.4.0", "leven": "^3.1.0", - "pretty-format": "^27.0.6" + "pretty-format": "^27.4.2" }, "dependencies": { "camelcase": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", - "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==" + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.1.tgz", + "integrity": "sha512-tVI4q5jjFV5CavAU8DXfza/TJcZutVKo/5Foskmsqcm0MsL91moHvwiGNnqaa2o6PF/7yT5ikDRcVcl8Rj6LCA==" } } }, "jest-watcher": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-27.0.6.tgz", - "integrity": "sha512-/jIoKBhAP00/iMGnTwUBLgvxkn7vsOweDrOTSPzc7X9uOyUtJIDthQBTI1EXz90bdkrxorUZVhJwiB69gcHtYQ==", + "version": "27.4.2", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-27.4.2.tgz", + "integrity": "sha512-NJvMVyyBeXfDezhWzUOCOYZrUmkSCiatpjpm+nFUid74OZEHk6aMLrZAukIiFDwdbqp6mTM6Ui1w4oc+8EobQg==", "requires": { - "@jest/test-result": "^27.0.6", - "@jest/types": "^27.0.6", + "@jest/test-result": "^27.4.2", + "@jest/types": "^27.4.2", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", - "jest-util": "^27.0.6", + "jest-util": "^27.4.2", "string-length": "^4.0.1" } }, "jest-worker": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.0.6.tgz", - "integrity": "sha512-qupxcj/dRuA3xHPMUd40gr2EaAurFbkwzOh7wfPaeE9id7hyjURRQoqNfHifHK3XjJU6YJJUQKILGUnwGPEOCA==", + "version": "27.4.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.4.2.tgz", + "integrity": "sha512-0QMy/zPovLfUPyHuOuuU4E+kGACXXE84nRnq6lBVI9GJg5DCBiA97SATi+ZP8CpiJwEQy1oCPjRBf8AnLjN+Ag==", "requires": { "@types/node": "*", "merge-stream": "^2.0.0", @@ -5924,6 +2214,11 @@ "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==" }, + "kuler": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", + "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==" + }, "leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", @@ -5938,6 +2233,22 @@ "type-check": "~0.3.2" } }, + "lie": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz", + "integrity": "sha1-mkNrLMd0bKWd56QfpGmz77dr2H4=", + "requires": { + "immediate": "~3.0.5" + } + }, + "localforage": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/localforage/-/localforage-1.10.0.tgz", + "integrity": "sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==", + "requires": { + "lie": "3.1.1" + } + }, "locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", @@ -5956,6 +2267,18 @@ "resolved": "https://registry.npmjs.org/lodash.chunk/-/lodash.chunk-4.2.0.tgz", "integrity": "sha1-ZuXOH3btJ7QwPYxlEujRIW6BBrw=" }, + "logform": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.3.0.tgz", + "integrity": "sha512-graeoWUH2knKbGthMtuG1EfaSPMZFZBIrhuJHhkS5ZseFBrc7DupCzihOQAzsK/qIKPQaPJ/lFQFctILUY5ARQ==", + "requires": { + "colors": "^1.2.1", + "fecha": "^4.2.0", + "ms": "^2.1.1", + "safe-stable-stringify": "^1.1.0", + "triple-beam": "^1.3.0" + } + }, "lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -5983,11 +2306,11 @@ } }, "makeerror": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.11.tgz", - "integrity": "sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw=", + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", "requires": { - "tmpl": "1.0.x" + "tmpl": "1.0.5" } }, "markdown-include": { @@ -6013,16 +2336,16 @@ } }, "mime-db": { - "version": "1.49.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.49.0.tgz", - "integrity": "sha512-CIc8j9URtOVApSFCQIF+VBkX1RwXp/oMMOrqdyXSBXq5RWNEsRfyj1kiRnQgmNXmHxPoFIxOroKA3zcU9P+nAA==" + "version": "1.51.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", + "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==" }, "mime-types": { - "version": "2.1.32", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.32.tgz", - "integrity": "sha512-hJGaVS4G4c9TSMYh2n6SQAGrC4RnfU+daP8G7cSCmaqNjiOoUY0VHCMS42pxnQmVF1GWwFhbHWn3RIxCqTmZ9A==", + "version": "2.1.34", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", + "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", "requires": { - "mime-db": "1.49.0" + "mime-db": "1.51.0" } }, "mimic-fn": { @@ -6048,30 +2371,38 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "requires": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=" }, - "natural-orderby": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/natural-orderby/-/natural-orderby-2.0.3.tgz", - "integrity": "sha512-p7KTHxU0CUrcOXe62Zfrb5Z13nLvPhSWR/so3kFulUQU0sgUll2Z0LwpsLN351eOOD+hRGu/F1g+6xDfPeD++Q==" + "nedb-promises": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/nedb-promises/-/nedb-promises-5.0.2.tgz", + "integrity": "sha512-087g8JdsStXRWDxC9qqE4qMLqZGJrUnYF54pvOCDDfcLoptJUCqGb7j2WvWlaleeqft9rUjiJ9egvMJlUnJTmA==", + "requires": { + "@seald-io/nedb": "^2.2.0" + } }, "node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=" }, - "node-modules-regexp": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz", - "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=" - }, "node-releases": { - "version": "1.1.73", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.73.tgz", - "integrity": "sha512-uW7fodD6pyW2FZNZnp/Z3hvWKeEW1Y8R1+1CnErE8cXFXzl5blBOoVB41CvMer6P6Q0S5FXDwcHgFd1Wj0U9zg==" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.1.tgz", + "integrity": "sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA==" }, "normalize-path": { "version": "3.0.0", @@ -6096,6 +2427,11 @@ "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==" }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -6104,6 +2440,14 @@ "wrappy": "1" } }, + "one-time": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", + "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", + "requires": { + "fn.name": "1.x.x" + } + }, "onetime": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", @@ -6125,11 +2469,6 @@ "word-wrap": "~1.2.3" } }, - "p-each-series": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-2.2.0.tgz", - "integrity": "sha512-ycIL2+1V32th+8scbpTvyHNaHe02z0sjgh91XXjAk+ZeXoPN4Z46DVUnzdso0aX4KckKw0FNNFHdjZ2UsZvxiA==" - }, "p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", @@ -6176,18 +2515,20 @@ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + }, "picomatch": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==" }, "pirates": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.1.tgz", - "integrity": "sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA==", - "requires": { - "node-modules-regexp": "^1.0.0" - } + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.4.tgz", + "integrity": "sha512-ZIrVPH+A52Dw84R0L3/VS9Op04PuQ2SEoJL6bkshmiTic/HldyW9Tf7oH5mhJZBK7NmDx27vSMrYEXPXclpDKw==" }, "pkg-dir": { "version": "4.2.0", @@ -6197,30 +2538,27 @@ "find-up": "^4.0.0" } }, - "pre-push": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pre-push/-/pre-push-0.1.1.tgz", - "integrity": "sha1-Kip5gn0kOnbJEImJescH9F5xaqw=", - "requires": { - "shelljs": "0.3.x" - } - }, "prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=" }, "pretty-format": { - "version": "27.0.6", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.0.6.tgz", - "integrity": "sha512-8tGD7gBIENgzqA+UBzObyWqQ5B778VIFZA/S66cclyd5YkFLYs2Js7gxDKf0MXtTc9zcS7t1xhdfcElJ3YIvkQ==", + "version": "27.4.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.4.2.tgz", + "integrity": "sha512-p0wNtJ9oLuvgOQDEIZ9zQjZffK7KtyR6Si0jnXULIDwrlNF8Cuir3AZP0hHv0jmKuNN/edOnbMjnzd4uTcmWiw==", "requires": { - "@jest/types": "^27.0.6", - "ansi-regex": "^5.0.0", + "@jest/types": "^27.4.2", + "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", "react-is": "^17.0.1" }, "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, "ansi-styles": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", @@ -6228,15 +2566,20 @@ } } }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, "progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==" }, "prompts": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.1.tgz", - "integrity": "sha512-EQyfIuO2hPDsX1L/blblV+H7I0knhgAd82cVneCwcdND9B8AuCDuRcBH6yIcG4dFzlOUqbazQqwGjx5xmsNLuQ==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", "requires": { "kleur": "^3.0.3", "sisteransi": "^1.0.5" @@ -6262,6 +2605,16 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -6289,6 +2642,11 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==" }, + "resolve.exports": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-1.1.0.tgz", + "integrity": "sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ==" + }, "rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -6302,6 +2660,11 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, + "safe-stable-stringify": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-1.1.1.tgz", + "integrity": "sha512-ERq4hUjKDbJfE4+XtZLFPCDi8Vb1JqaxAPTxWFLBx8XcAlf9Bda/ZJdVezs/NAfsMQScyIlUMx+Yeu7P7rx5jw==" + }, "safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -6333,15 +2696,18 @@ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" }, - "shelljs": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.3.0.tgz", - "integrity": "sha1-NZbmMHp4FUT1kfN9phg2DzHbV7E=" - }, "signal-exit": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz", + "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==" + }, + "simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", + "requires": { + "is-arrayish": "^0.3.1" + } }, "sisteransi": { "version": "1.0.5", @@ -6359,9 +2725,9 @@ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, "source-map-support": { - "version": "0.5.19", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", - "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "requires": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -6372,12 +2738,24 @@ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, + "stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" + }, "stack-utils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.3.tgz", - "integrity": "sha512-gL//fkxfWUsIlFL2Tl42Cl6+HFALEaB1FU76I/Fy+oZjRreP7OPMXFlGbxM7NQsI0ZpUfw76sHnv0WNYuTb7Iw==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.5.tgz", + "integrity": "sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==", "requires": { "escape-string-regexp": "^2.0.0" + }, + "dependencies": { + "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==" + } } }, "string-length": { @@ -6399,6 +2777,21 @@ "strip-ansi": "^6.0.0" } }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "requires": { + "safe-buffer": "~5.2.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" + } + } + }, "strip-ansi": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", @@ -6458,15 +2851,36 @@ "minimatch": "^3.0.4" } }, + "text-hex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", + "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==" + }, + "thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "requires": { + "any-promise": "^1.0.0" + } + }, + "thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=", + "requires": { + "thenify": ">= 3.1.0 < 4" + } + }, "throat": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.1.tgz", "integrity": "sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==" }, "tmpl": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.4.tgz", - "integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=" + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==" }, "to-fast-properties": { "version": "2.0.0", @@ -6507,6 +2921,11 @@ "yargs": "^16.1.0" } }, + "triple-beam": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", + "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==" + }, "type-check": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", @@ -6538,10 +2957,15 @@ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, "v8-to-istanbul": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.0.0.tgz", - "integrity": "sha512-LkmXi8UUNxnCC+JlH7/fsfsKr5AU110l+SYGJimWNkWhxbN5EyeOtm1MJ0hhvqMMOhGwBj1Fp70Yv9i+hX0QAg==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-8.1.0.tgz", + "integrity": "sha512-/PRhfd8aTNp9Ggr62HPzXg2XasNFGy5PBt0Rp04du7/8GNNSgxFL6WBTkgMKSL9bFjH+8kKEG3f37FmxiTqUUA==", "requires": { "@types/istanbul-lib-coverage": "^2.0.1", "convert-source-map": "^1.6.0", @@ -6577,11 +3001,11 @@ } }, "walker": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.7.tgz", - "integrity": "sha1-L3+bj9ENZ3JisYqITijRlhjgKPs=", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", "requires": { - "makeerror": "1.0.x" + "makeerror": "1.0.12" } }, "webidl-conversions": { @@ -6620,6 +3044,62 @@ "isexe": "^2.0.0" } }, + "winston": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.3.3.tgz", + "integrity": "sha512-oEXTISQnC8VlSAKf1KYSSd7J6IWuRPQqDdo8eoRNaYKLvwSb5+79Z3Yi1lrl6KDpU6/VWaxpakDAtb1oQ4n9aw==", + "requires": { + "@dabh/diagnostics": "^2.0.2", + "async": "^3.1.0", + "is-stream": "^2.0.0", + "logform": "^2.2.0", + "one-time": "^1.0.0", + "readable-stream": "^3.4.0", + "stack-trace": "0.0.x", + "triple-beam": "^1.3.0", + "winston-transport": "^4.4.0" + }, + "dependencies": { + "async": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.2.tgz", + "integrity": "sha512-H0E+qZaDEfx/FY4t7iLRv1W2fFI6+pyCeTw1uN20AQPiwqwM6ojPxHxdLv4z8hi2DtnW9BOckSspLucW7pIE5g==" + } + } + }, + "winston-transport": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.4.0.tgz", + "integrity": "sha512-Lc7/p3GtqtqPBYYtS6KCN3c77/2QCev51DvcJKbkFPQNoj1sinkGwLGFDxkXY9J6p9+EPnYs+D90uwbnaiURTw==", + "requires": { + "readable-stream": "^2.3.7", + "triple-beam": "^1.2.0" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", @@ -6652,10 +3132,9 @@ } }, "ws": { - "version": "7.5.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.3.tgz", - "integrity": "sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg==", - "requires": {} + "version": "7.5.6", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.6.tgz", + "integrity": "sha512-6GLgCqo2cy2A2rjCNFlxQS6ZljG/coZfZXclldI8FB/1G3CCI36Zd8xy2HrFVACi8tfk5XrgLQEk+P0Tnz9UcA==" }, "xml-name-validator": { "version": "3.0.0", From b775228d1e533b2917ac30b3f07645453dddb252 Mon Sep 17 00:00:00 2001 From: Aleksandr Statciuk Date: Sun, 12 Dec 2021 07:09:40 +0300 Subject: [PATCH 12/34] Create .gitignore --- scripts/.gitignore | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 scripts/.gitignore diff --git a/scripts/.gitignore b/scripts/.gitignore new file mode 100644 index 0000000000..001a2070d1 --- /dev/null +++ b/scripts/.gitignore @@ -0,0 +1,2 @@ +logs/ +channels.db \ No newline at end of file From 213da67762c121e43e871fbdf0cc6f6ed8eccfbf Mon Sep 17 00:00:00 2001 From: Aleksandr Statciuk Date: Sun, 12 Dec 2021 07:10:03 +0300 Subject: [PATCH 13/34] Create scripts/commands --- scripts/commands/check-streams.js | 50 ++++ scripts/commands/cleanup-database.js | 14 ++ scripts/commands/create-database.js | 104 ++++++++ scripts/commands/create-matrix.js | 15 ++ scripts/commands/generate-playlists.js | 321 +++++++++++++++++++++++++ scripts/commands/update-database.js | 221 +++++++++++++++++ scripts/commands/update-playlists.js | 17 ++ scripts/commands/update-readme.js | 142 +++++++++++ scripts/commands/validate.js | 55 +++++ 9 files changed, 939 insertions(+) create mode 100644 scripts/commands/check-streams.js create mode 100644 scripts/commands/cleanup-database.js create mode 100644 scripts/commands/create-database.js create mode 100644 scripts/commands/create-matrix.js create mode 100644 scripts/commands/generate-playlists.js create mode 100644 scripts/commands/update-database.js create mode 100644 scripts/commands/update-playlists.js create mode 100644 scripts/commands/update-readme.js create mode 100644 scripts/commands/validate.js diff --git a/scripts/commands/check-streams.js b/scripts/commands/check-streams.js new file mode 100644 index 0000000000..9a74e7776f --- /dev/null +++ b/scripts/commands/check-streams.js @@ -0,0 +1,50 @@ +const { program } = require('commander') +const { db, logger, timer, checker, store, file, parser } = require('../core') + +const options = program + .requiredOption('-c, --cluster-id ', 'The ID of cluster to load', parser.parseNumber) + .option('-t, --timeout ', 'Set timeout for each request', parser.parseNumber, 60000) + .option('-d, --delay ', 'Set delay for each request', parser.parseNumber, 0) + .option('--debug', 'Enable debug mode') + .parse(process.argv) + .opts() + +const config = { + timeout: options.timeout, + delay: options.delay, + debug: options.debug +} + +const LOGS_PATH = process.env.LOGS_PATH || 'scripts/logs' + +async function main() { + logger.info('Starting...') + logger.info(`Timeout: ${options.timeout}ms`) + logger.info(`Delay: ${options.delay}ms`) + timer.start() + + const clusterLog = `${LOGS_PATH}/check-streams/cluster_${options.clusterId}.log` + logger.info(`Loading cluster: ${options.clusterId}`) + logger.info(`Creating '${clusterLog}'...`) + await file.create(clusterLog) + const items = await db.find({ cluster_id: options.clusterId }) + const total = items.length + logger.info(`Found ${total} links`) + + logger.info('Checking...') + const results = {} + for (const [i, item] of items.entries()) { + const message = `[${i + 1}/${total}] ${item.filepath}: ${item.url}` + const result = await checker.check(item, config) + if (!result.error) { + logger.info(message) + } else { + logger.info(`${message} (${result.error})`) + } + await file.append(clusterLog, JSON.stringify(result) + '\n') + } + + logger.info(`Done in ${timer.format('HH[h] mm[m] ss[s]')}`) +} + +main() diff --git a/scripts/commands/cleanup-database.js b/scripts/commands/cleanup-database.js new file mode 100644 index 0000000000..11f9e9e6b3 --- /dev/null +++ b/scripts/commands/cleanup-database.js @@ -0,0 +1,14 @@ +const { db, logger } = require('../core') + +async function main() { + const removed = await db.remove( + { 'status.code': { $in: ['timeout', 'offline'] } }, + { multi: true } + ) + + db.compact() + + logger.info(`Removed ${removed} links`) +} + +main() diff --git a/scripts/commands/create-database.js b/scripts/commands/create-database.js new file mode 100644 index 0000000000..ecbbc05973 --- /dev/null +++ b/scripts/commands/create-database.js @@ -0,0 +1,104 @@ +const { db, file, parser, store, logger } = require('../core') +const transliteration = require('transliteration') +const { program } = require('commander') +const _ = require('lodash') + +const options = program + .option( + '--max-clusters ', + 'Set maximum number of clusters', + parser.parseNumber, + 200 + ) + .option('--input-dir ', 'Set path to input directory', 'channels') + .parse(process.argv) + .opts() + +const links = [] + +async function main() { + logger.info('Starting...') + logger.info(`Number of clusters: ${options.maxClusters}`) + + await loadChannels() + await saveToDatabase() + + logger.info('Done') +} + +main() + +async function loadChannels() { + logger.info(`Loading links...`) + + const files = await file.list(`${options.inputDir}/**/*.m3u`) + for (const filepath of files) { + const items = await parser.parsePlaylist(filepath) + for (const item of items) { + item.filepath = filepath + links.push(item) + } + } + logger.info(`Found ${links.length} links`) +} + +async function saveToDatabase() { + logger.info('Saving to the database...') + + await db.reset() + const chunks = split(_.shuffle(links), options.maxClusters) + for (const [i, chunk] of chunks.entries()) { + for (const item of chunk) { + const stream = store.create() + stream.set('name', { title: item.name }) + stream.set('id', { id: item.tvg.id }) + stream.set('filepath', { filepath: item.filepath }) + stream.set('src_country', { filepath: item.filepath }) + stream.set('tvg_country', { tvg_country: item.tvg.country }) + stream.set('countries', { tvg_country: item.tvg.country }) + stream.set('regions', { countries: stream.get('countries') }) + stream.set('languages', { tvg_language: item.tvg.language }) + stream.set('categories', { group_title: item.group.title }) + stream.set('tvg_url', { tvg_url: item.tvg.url }) + stream.set('guides', { tvg_url: item.tvg.url }) + stream.set('logo', { logo: item.tvg.logo }) + stream.set('resolution', { title: item.name }) + stream.set('status', { title: item.name }) + stream.set('url', { url: item.url }) + stream.set('http', { http: item.http }) + stream.set('is_nsfw', { categories: stream.get('categories') }) + stream.set('is_broken', { status: stream.get('status') }) + stream.set('updated', { updated: false }) + stream.set('cluster_id', { cluster_id: i + 1 }) + + if (!stream.get('id')) { + const id = generateChannelId(stream.get('name'), stream.get('src_country')) + stream.set('id', { id }) + } + + await db.insert(stream.data()) + } + } +} + +function split(arr, n) { + let result = [] + for (let i = n; i > 0; i--) { + result.push(arr.splice(0, Math.ceil(arr.length / i))) + } + return result +} + +function generateChannelId(name, src_country) { + if (name && src_country) { + const slug = transliteration + .transliterate(name) + .replace(/\+/gi, 'Plus') + .replace(/[^a-z\d]+/gi, '') + const code = src_country.code.toLowerCase() + + return `${slug}.${code}` + } + + return null +} diff --git a/scripts/commands/create-matrix.js b/scripts/commands/create-matrix.js new file mode 100644 index 0000000000..be639b0287 --- /dev/null +++ b/scripts/commands/create-matrix.js @@ -0,0 +1,15 @@ +const { logger, db } = require('../core') + +async function main() { + const docs = await db.find({}).sort({ cluster_id: 1 }) + const cluster_id = docs.reduce((acc, curr) => { + if (!acc.includes(curr.cluster_id)) acc.push(curr.cluster_id) + return acc + }, []) + + const matrix = { cluster_id } + const output = `::set-output name=matrix::${JSON.stringify(matrix)}` + logger.info(output) +} + +main() diff --git a/scripts/commands/generate-playlists.js b/scripts/commands/generate-playlists.js new file mode 100644 index 0000000000..d8005a1ea2 --- /dev/null +++ b/scripts/commands/generate-playlists.js @@ -0,0 +1,321 @@ +const { db, logger, generator, file } = require('../core') +const _ = require('lodash') + +let languages = [] +let countries = [] +let categories = [] +let regions = [] + +const LOGS_PATH = process.env.LOGS_PATH || 'scripts/logs' +const PUBLIC_PATH = process.env.PUBLIC_PATH || '.gh-pages' + +async function main() { + await setUp() + + await generateCategories() + await generateCountries() + await generateLanguages() + await generateRegions() + await generateIndex() + await generateIndexNSFW() + await generateIndexCategory() + await generateIndexCountry() + await generateIndexLanguage() + await generateIndexRegion() + + await generateChannelsJson() +} + +main() + +async function generateCategories() { + logger.info(`Generating categories/...`) + + for (const category of categories) { + const { count } = await generator.generate( + `${PUBLIC_PATH}/categories/${category.slug}.m3u`, + { categories: { $elemMatch: category } }, + { saveEmpty: true, includeNSFW: true } + ) + + await log('categories', { + name: category.name, + slug: category.slug, + count + }) + } + + const { count: otherCount } = await generator.generate( + `${PUBLIC_PATH}/categories/other.m3u`, + { categories: { $size: 0 } }, + { saveEmpty: true } + ) + + await log('categories', { + name: 'Other', + slug: 'other', + count: otherCount + }) +} + +async function generateCountries() { + logger.info(`Generating countries/...`) + + for (const country of countries) { + const { count } = await generator.generate( + `${PUBLIC_PATH}/countries/${country.code.toLowerCase()}.m3u`, + { + countries: { $elemMatch: country } + } + ) + + await log('countries', { + name: country.name, + code: country.code, + count + }) + } + + const { count: intCount } = await generator.generate(`${PUBLIC_PATH}/countries/int.m3u`, { + tvg_country: 'INT' + }) + + await log('countries', { + name: 'International', + code: 'INT', + count: intCount + }) + + const { count: undefinedCount } = await generator.generate( + `${PUBLIC_PATH}/countries/undefined.m3u`, + { + countries: { $size: 0 } + } + ) + + await log('countries', { + name: 'Undefined', + code: 'UNDEFINED', + count: undefinedCount + }) +} + +async function generateLanguages() { + logger.info(`Generating languages/...`) + + for (const language of _.uniqBy(languages, 'code')) { + const { count } = await generator.generate(`${PUBLIC_PATH}/languages/${language.code}.m3u`, { + languages: { $elemMatch: language } + }) + + await log('languages', { + name: language.name, + code: language.code, + count + }) + } + + const { count: undefinedCount } = await generator.generate( + `${PUBLIC_PATH}/languages/undefined.m3u`, + { + languages: { $size: 0 } + } + ) + + await log('languages', { + name: 'Undefined', + code: 'undefined', + count: undefinedCount + }) +} + +async function generateRegions() { + logger.info(`Generating regions/...`) + + for (const region of regions) { + const { count } = await generator.generate( + `${PUBLIC_PATH}/regions/${region.code.toLowerCase()}.m3u`, + { + regions: { $elemMatch: region } + } + ) + + await log('regions', { + name: region.name, + code: region.code, + count + }) + } + + const { count: undefinedCount } = await generator.generate( + `${PUBLIC_PATH}/regions/undefined.m3u`, + { regions: { $size: 0 } }, + { saveEmpty: true } + ) + + await log('regions', { + name: 'Undefined', + code: 'UNDEFINED', + count: undefinedCount + }) +} + +async function generateIndexNSFW() { + logger.info(`Generating index.nsfw.m3u...`) + + await generator.generate(`${PUBLIC_PATH}/index.nsfw.m3u`, {}, { includeNSFW: true }) +} + +async function generateIndex() { + logger.info(`Generating index.m3u...`) + + await generator.generate(`${PUBLIC_PATH}/index.m3u`, {}) +} + +async function generateIndexCategory() { + logger.info(`Generating index.category.m3u...`) + + await generator.generate( + `${PUBLIC_PATH}/index.category.m3u`, + {}, + { sortBy: item => item.group_title } + ) +} + +async function generateIndexCountry() { + logger.info(`Generating index.country.m3u...`) + + await generator.generate( + `${PUBLIC_PATH}/index.country.m3u`, + {}, + { + onLoad: function (items) { + let results = items + .filter(item => !item.countries.length) + .map(item => { + const newItem = _.cloneDeep(item) + newItem.group_title = '' + return newItem + }) + for (const country of _.sortBy(Object.values(countries), ['name'])) { + let filtered = items + .filter(item => { + return item.countries.map(c => c.code).includes(country.code) + }) + .map(item => { + const newItem = _.cloneDeep(item) + newItem.group_title = country.name + return newItem + }) + results = results.concat(filtered) + } + + return results + }, + sortBy: item => item.group_title + } + ) +} + +async function generateIndexLanguage() { + logger.info(`Generating index.language.m3u...`) + + await generator.generate( + `${PUBLIC_PATH}/index.language.m3u`, + {}, + { + onLoad: function (items) { + let results = items + .filter(item => !item.languages.length) + .map(item => { + const newItem = _.cloneDeep(item) + newItem.group_title = '' + return newItem + }) + for (const language of languages) { + let filtered = items + .filter(item => { + return item.languages.map(c => c.code).includes(language.code) + }) + .map(item => { + const newItem = _.cloneDeep(item) + newItem.group_title = language.name + return newItem + }) + results = results.concat(filtered) + } + + return results + }, + sortBy: item => item.group_title + } + ) +} + +async function generateIndexRegion() { + logger.info(`Generating index.region.m3u...`) + + await generator.generate( + `${PUBLIC_PATH}/index.region.m3u`, + {}, + { + onLoad: function (items) { + let results = items + .filter(item => !item.regions.length) + .map(item => { + const newItem = _.cloneDeep(item) + newItem.group_title = '' + return newItem + }) + for (const region of regions) { + let filtered = items + .filter(item => { + return item.regions.map(c => c.code).includes(region.code) + }) + .map(item => { + const newItem = _.cloneDeep(item) + newItem.group_title = region.name + return newItem + }) + results = results.concat(filtered) + } + + return results + }, + sortBy: item => item.group_title + } + ) +} + +async function generateChannelsJson() { + logger.info('Generating channels.json...') + + await generator.generate(`${PUBLIC_PATH}/channels.json`, {}, { format: 'json' }) +} + +async function setUp() { + logger.info(`Loading database...`) + const items = await db.find({}) + categories = _.sortBy(_.uniqBy(_.flatten(items.map(i => i.categories)), 'slug'), ['name']) + countries = _.sortBy(_.uniqBy(_.flatten(items.map(i => i.countries)), 'code'), ['name']) + languages = _.sortBy(_.uniqBy(_.flatten(items.map(i => i.languages)), 'code'), ['name']) + regions = _.sortBy(_.uniqBy(_.flatten(items.map(i => i.regions)), 'code'), ['name']) + + const categoriesLog = `${LOGS_PATH}/generate-playlists/categories.log` + const countriesLog = `${LOGS_PATH}/generate-playlists/countries.log` + const languagesLog = `${LOGS_PATH}/generate-playlists/languages.log` + const regionsLog = `${LOGS_PATH}/generate-playlists/regions.log` + + logger.info(`Creating '${categoriesLog}'...`) + await file.create(categoriesLog) + logger.info(`Creating '${countriesLog}'...`) + await file.create(countriesLog) + logger.info(`Creating '${languagesLog}'...`) + await file.create(languagesLog) + logger.info(`Creating '${regionsLog}'...`) + await file.create(regionsLog) +} + +async function log(type, data) { + await file.append(`${LOGS_PATH}/generate-playlists/${type}.log`, JSON.stringify(data) + '\n') +} diff --git a/scripts/commands/update-database.js b/scripts/commands/update-database.js new file mode 100644 index 0000000000..4dad7658f3 --- /dev/null +++ b/scripts/commands/update-database.js @@ -0,0 +1,221 @@ +const _ = require('lodash') +const statuses = require('../data/statuses') +const languages = require('../data/languages') +const { db, store, parser, file, logger } = require('../core') + +let epgCodes = [] +let streams = [] +let checkResults = {} +const origins = {} +const items = [] + +const LOGS_PATH = process.env.LOGS_PATH || 'scripts/logs' +const EPG_CODES_FILEPATH = process.env.EPG_CODES_FILEPATH || 'scripts/data/codes.json' + +async function main() { + await setUp() + await loadDatabase() + await loadCheckResults() + await findStreamOrigins() + await updateStreams() + await updateDatabase() +} + +main() + +async function loadDatabase() { + logger.info('Loading database...') + + streams = await db.find({}) + + logger.info(`Found ${streams.length} streams`) +} + +async function loadCheckResults() { + logger.info('Loading check results from logs/...') + + const files = await file.list(`${LOGS_PATH}/check-streams/cluster_*.log`) + for (const filepath of files) { + const results = await parser.parseLogs(filepath) + for (const result of results) { + checkResults[result._id] = result + } + } + + logger.info(`Found ${Object.values(checkResults).length} results`) +} + +async function findStreamOrigins() { + logger.info('Searching for stream origins...') + + for (const { error, requests } of Object.values(checkResults)) { + if (error || !Array.isArray(requests) || !requests.length) continue + + let origin = requests.shift() + origin = new URL(origin.url) + for (const request of requests) { + const curr = new URL(request.url) + const key = curr.href.replace(/(^\w+:|^)/, '') + if (!origins[key] && curr.host === origin.host) { + origins[key] = origin.href + } + } + } + + logger.info(`Found ${_.uniq(Object.values(origins)).length} origins`) +} + +async function updateStreams() { + logger.info('Updating streams...') + + let updated = 0 + for (const item of streams) { + const stream = store.create(item) + const result = checkResults[item._id] + + if (result) { + const { error, streams, requests } = result + const status = parseStatus(error) + const resolution = parseResolution(streams) + const origin = findOrigin(requests) + + if (status) { + stream.set('status', { status }) + stream.set('is_broken', { status: stream.get('status') }) + } + + if (resolution) { + stream.set('resolution', { resolution }) + } + + if (origin) { + stream.set('url', { url: origin }) + } + } + + if (!stream.has('logo')) { + const logo = findLogo(stream.get('id')) + stream.set('logo', { logo }) + } + + if (!stream.has('guides')) { + const guides = findGuides(stream.get('id')) + stream.set('guides', { guides }) + } + + if (!stream.has('countries') && stream.get('src_country')) { + const countries = [stream.get('src_country')] + stream.set('countries', { countries }) + } + + if (!stream.has('languages')) { + const languages = findLanguages(stream.get('countries'), stream.get('src_country')) + stream.set('languages', { languages }) + } + + if (stream.changed) { + stream.set('updated', true) + items.push(stream.data()) + updated++ + } + } + + logger.info(`Updated ${updated} items`) +} + +async function updateDatabase() { + logger.info('Updating database...') + + for (const item of items) { + await db.update({ _id: item._id }, item) + } + db.compact() + + logger.info('Done') +} + +async function setUp() { + try { + const codes = await file.read(EPG_CODES_FILEPATH) + epgCodes = JSON.parse(codes) + } catch (err) { + logger.error(err.message) + } +} + +function findLanguages(countries, src_country) { + if (countries && Array.isArray(countries)) { + let codes = countries.map(country => country.lang) + codes = _.uniq(codes) + + return codes.map(code => languages.find(l => l.code === code)).filter(l => l) + } + + if (src_country) { + const code = src_country.lang + const lang = languages.find(l => l.code === code) + + return lang ? [lang] : [] + } + + return [] +} + +function findOrigin(requests) { + if (origins && Array.isArray(requests)) { + requests = requests.map(r => r.url.replace(/(^\w+:|^)/, '')) + for (const url of requests) { + if (origins[url]) { + return origins[url] + } + } + } + + return null +} + +function parseResolution(streams) { + const resolution = streams + .filter(s => s.codec_type === 'video') + .reduce( + (acc, curr) => { + if (curr.height > acc.height) return { width: curr.width, height: curr.height } + return acc + }, + { width: 0, height: 0 } + ) + + if (resolution.width > 0 && resolution.height > 0) return resolution + return null +} + +function parseStatus(error) { + if (error) { + if (error.includes('timed out')) { + return statuses['timeout'] + } else if (error.includes('403')) { + return statuses['geo_blocked'] + } + return statuses['offline'] + } + + return null +} + +function findLogo(id) { + const item = epgCodes.find(i => i.tvg_id === id) + if (item && item.logo) { + return item.logo + } + + return null +} + +function findGuides(id) { + const item = epgCodes.find(i => i.tvg_id === id) + if (item && Array.isArray(item.guides)) { + return item.guides + } + + return [] +} diff --git a/scripts/commands/update-playlists.js b/scripts/commands/update-playlists.js new file mode 100644 index 0000000000..acaf5998a1 --- /dev/null +++ b/scripts/commands/update-playlists.js @@ -0,0 +1,17 @@ +const _ = require('lodash') +const { generator, db, logger } = require('../core') + +async function main() { + let items = await db + .find({}) + .sort({ name: 1, 'status.level': 1, 'resolution.height': -1, url: 1 }) + items = _.uniqBy(items, 'url') + const files = _.groupBy(items, 'filepath') + + for (const filepath in files) { + const items = files[filepath] + await generator.saveAsM3U(filepath, items, { includeGuides: false }) + } +} + +main() diff --git a/scripts/commands/update-readme.js b/scripts/commands/update-readme.js new file mode 100644 index 0000000000..2cef7ac239 --- /dev/null +++ b/scripts/commands/update-readme.js @@ -0,0 +1,142 @@ +const { file, markdown, parser, logger } = require('../core') +const { program } = require('commander') + +let categories = [] +let countries = [] +let languages = [] +let regions = [] + +const LOGS_PATH = process.env.LOGS_PATH || 'scripts/logs' + +const options = program + .option('-c, --config ', 'Set path to config file', '.readme/config.json') + .parse(process.argv) + .opts() + +async function main() { + await setUp() + + await generateCategoryTable() + await generateLanguageTable() + await generateRegionTable() + await generateCountryTable() + + await updateReadme() +} + +main() + +async function generateCategoryTable() { + logger.info('Generating category table...') + + const rows = [] + for (const category of categories) { + rows.push({ + category: category.name, + channels: category.count, + playlist: `https://iptv-org.github.io/iptv/categories/${category.slug}.m3u` + }) + } + + const table = markdown.createTable(rows, [ + { name: 'Category', align: 'left' }, + { name: 'Channels', align: 'right' }, + { name: 'Playlist', align: 'left' } + ]) + + await file.create('./.readme/_categories.md', table) +} + +async function generateCountryTable() { + logger.info('Generating country table...') + + const rows = [] + for (const country of countries) { + const flag = getCountryFlag(country.code) + const prefix = flag ? `${flag} ` : '' + + rows.push({ + country: prefix + country.name, + channels: country.count, + playlist: `https://iptv-org.github.io/iptv/countries/${country.code.toLowerCase()}.m3u` + }) + } + + const table = markdown.createTable(rows, [ + { name: 'Country', align: 'left' }, + { name: 'Channels', align: 'right' }, + { name: 'Playlist', align: 'left' } + ]) + + await file.create('./.readme/_countries.md', table) +} + +async function generateRegionTable() { + logger.info('Generating region table...') + + const rows = [] + for (const region of regions) { + rows.push({ + region: region.name, + channels: region.count, + playlist: `https://iptv-org.github.io/iptv/regions/${region.code.toLowerCase()}.m3u` + }) + } + + const table = markdown.createTable(rows, [ + { name: 'Region', align: 'left' }, + { name: 'Channels', align: 'right' }, + { name: 'Playlist', align: 'left' } + ]) + + await file.create('./.readme/_regions.md', table) +} + +async function generateLanguageTable() { + logger.info('Generating language table...') + + const rows = [] + for (const language of languages) { + rows.push({ + language: language.name, + channels: language.count, + playlist: `https://iptv-org.github.io/iptv/languages/${language.code}.m3u` + }) + } + + const table = markdown.createTable(rows, [ + { name: 'Language', align: 'left' }, + { name: 'Channels', align: 'right' }, + { name: 'Playlist', align: 'left' } + ]) + + await file.create('./.readme/_languages.md', table) +} + +async function updateReadme() { + logger.info('Updating README.md...') + + const config = require(file.resolve(options.config)) + await file.createDir(file.dirname(config.build)) + await markdown.compile(options.config) +} + +async function setUp() { + categories = await parser.parseLogs(`${LOGS_PATH}/generate-playlists/categories.log`) + countries = await parser.parseLogs(`${LOGS_PATH}/generate-playlists/countries.log`) + languages = await parser.parseLogs(`${LOGS_PATH}/generate-playlists/languages.log`) + regions = await parser.parseLogs(`${LOGS_PATH}/generate-playlists/regions.log`) +} + +function getCountryFlag(code) { + switch (code) { + case 'UK': + return '🇬🇧' + case 'INT': + return '🌍' + case 'UNDEFINED': + return '' + default: + return code.replace(/./g, char => String.fromCodePoint(char.charCodeAt(0) + 127397)) + } +} diff --git a/scripts/commands/validate.js b/scripts/commands/validate.js new file mode 100644 index 0000000000..0d2b716558 --- /dev/null +++ b/scripts/commands/validate.js @@ -0,0 +1,55 @@ +const blocklist = require('../data/blocklist') +const parser = require('iptv-playlist-parser') +const { file, logger } = require('../core') +const { program } = require('commander') + +const options = program + .option('--input-dir ', 'Set path to input directory', 'channels') + .parse(process.argv) + .opts() + +async function main() { + const files = await file.list(`${options.inputDir}/**/*.m3u`) + const errors = [] + for (const filepath of files) { + const content = await file.read(filepath) + const playlist = parser.parse(content) + const basename = file.basename(filepath) + const [_, country] = basename.match(/([a-z]{2})(|_.*)\.m3u/i) || [null, null] + + const items = playlist.items + .map(item => { + const details = check(item, country) + + return details ? { ...item, details } : null + }) + .filter(i => i) + + items.forEach(item => { + errors.push( + `${filepath}:${item.line} '${item.details.name}' is on the blocklist due to claims of copyright holders (${item.details.reference})` + ) + }) + } + + errors.forEach(error => { + logger.error(error) + }) + + if (errors.length) { + logger.info('') + process.exit(1) + } +} + +function check(channel, country) { + return blocklist.find(item => { + const regexp = new RegExp(item.regex, 'i') + const hasSameName = regexp.test(channel.name) + const fromSameCountry = country === item.country.toLowerCase() + + return hasSameName && fromSameCountry + }) +} + +main() From c6c31545228ab9011992af456fe11424c97a5a0d Mon Sep 17 00:00:00 2001 From: Aleksandr Statciuk Date: Sun, 12 Dec 2021 07:10:18 +0300 Subject: [PATCH 14/34] Create scripts/core --- scripts/core/checker.js | 19 +++++++ scripts/core/db.js | 61 ++++++++++++++++++++ scripts/core/file.js | 67 ++++++++++++++++++++++ scripts/core/generator.js | 114 ++++++++++++++++++++++++++++++++++++++ scripts/core/index.js | 10 ++++ scripts/core/logger.js | 42 ++++++++++++++ scripts/core/markdown.js | 39 +++++++++++++ scripts/core/parser.js | 31 +++++++++++ scripts/core/playlist.js | 49 ++++++++++++++++ scripts/core/store.js | 56 +++++++++++++++++++ scripts/core/timer.js | 29 ++++++++++ 11 files changed, 517 insertions(+) create mode 100644 scripts/core/checker.js create mode 100644 scripts/core/db.js create mode 100644 scripts/core/file.js create mode 100644 scripts/core/generator.js create mode 100644 scripts/core/index.js create mode 100644 scripts/core/logger.js create mode 100644 scripts/core/markdown.js create mode 100644 scripts/core/parser.js create mode 100644 scripts/core/playlist.js create mode 100644 scripts/core/store.js create mode 100644 scripts/core/timer.js diff --git a/scripts/core/checker.js b/scripts/core/checker.js new file mode 100644 index 0000000000..552110072a --- /dev/null +++ b/scripts/core/checker.js @@ -0,0 +1,19 @@ +const IPTVChecker = require('iptv-checker') + +const checker = {} + +checker.check = async function (item, config) { + const ic = new IPTVChecker(config) + const result = await ic.checkStream({ url: item.url, http: item.http }) + + return { + _id: item._id, + url: item.url, + http: item.http, + error: !result.status.ok ? result.status.reason : null, + streams: result.status.ok ? result.status.metadata.streams : [], + requests: result.status.ok ? result.status.metadata.requests : [] + } +} + +module.exports = checker diff --git a/scripts/core/db.js b/scripts/core/db.js new file mode 100644 index 0000000000..27360a839f --- /dev/null +++ b/scripts/core/db.js @@ -0,0 +1,61 @@ +const Database = require('nedb-promises') +const file = require('./file') + +const DB_FILEPATH = process.env.DB_FILEPATH || './scripts/channels.db' + +const nedb = Database.create({ + filename: file.resolve(DB_FILEPATH), + autoload: true, + onload(err) { + if (err) console.error(err) + }, + compareStrings: (a, b) => { + a = a.replace(/\s/g, '_') + b = b.replace(/\s/g, '_') + + return a.localeCompare(b, undefined, { + sensitivity: 'accent', + numeric: true + }) + } +}) + +const db = {} + +db.removeIndex = function (field) { + return nedb.removeIndex(field) +} + +db.addIndex = function (options) { + return nedb.ensureIndex(options) +} + +db.compact = function () { + return nedb.persistence.compactDatafile() +} + +db.reset = function () { + return file.clear(DB_FILEPATH) +} + +db.count = function (query) { + return nedb.count(query) +} + +db.insert = function (doc) { + return nedb.insert(doc) +} + +db.update = function (query, update) { + return nedb.update(query, update) +} + +db.find = function (query) { + return nedb.find(query) +} + +db.remove = function (query, options) { + return nedb.remove(query, options) +} + +module.exports = db diff --git a/scripts/core/file.js b/scripts/core/file.js new file mode 100644 index 0000000000..56da4db967 --- /dev/null +++ b/scripts/core/file.js @@ -0,0 +1,67 @@ +const path = require('path') +const glob = require('glob') +const fs = require('mz/fs') + +const file = {} + +file.list = function (pattern) { + return new Promise(resolve => { + glob(pattern, function (err, files) { + resolve(files) + }) + }) +} + +file.getFilename = function (filepath) { + return path.parse(filepath).name +} + +file.createDir = async function (dir) { + if (await file.exists(dir)) return + + return fs.mkdir(dir, { recursive: true }).catch(console.error) +} + +file.exists = function (filepath) { + return fs.exists(path.resolve(filepath)) +} + +file.read = function (filepath) { + return fs.readFile(path.resolve(filepath), { encoding: 'utf8' }).catch(console.error) +} + +file.append = function (filepath, data) { + return fs.appendFile(path.resolve(filepath), data).catch(console.error) +} + +file.create = function (filepath, data = '') { + filepath = path.resolve(filepath) + const dir = path.dirname(filepath) + + return file + .createDir(dir) + .then(() => fs.writeFile(filepath, data, { encoding: 'utf8', flag: 'w' })) + .catch(console.error) +} + +file.write = function (filepath, data = '') { + return fs.writeFile(path.resolve(filepath), data).catch(console.error) +} + +file.clear = function (filepath) { + return file.write(filepath, '') +} + +file.resolve = function (filepath) { + return path.resolve(filepath) +} + +file.dirname = function (filepath) { + return path.dirname(filepath) +} + +file.basename = function (filepath) { + return path.basename(filepath) +} + +module.exports = file diff --git a/scripts/core/generator.js b/scripts/core/generator.js new file mode 100644 index 0000000000..046ac15fdb --- /dev/null +++ b/scripts/core/generator.js @@ -0,0 +1,114 @@ +const { create: createPlaylist } = require('./playlist') +const store = require('./store') +const file = require('./file') +const logger = require('./logger') +const db = require('./db') +const _ = require('lodash') + +const generator = {} + +generator.generate = async function (filepath, query = {}, options = {}) { + options = { + ...{ + format: 'm3u', + saveEmpty: false, + includeNSFW: false, + includeGuides: true, + includeBroken: false, + onLoad: r => r, + uniqBy: item => item.id || _.uniqueId(), + sortBy: null + }, + ...options + } + + query['is_nsfw'] = options.includeNSFW ? { $in: [true, false] } : false + query['is_broken'] = options.includeBroken ? { $in: [true, false] } : false + + let items = await db + .find(query) + .sort({ name: 1, 'status.level': 1, 'resolution.height': -1, url: 1 }) + + items = _.uniqBy(items, 'url') + if (!options.saveEmpty && !items.length) return { filepath, query, options, count: 0 } + if (options.uniqBy) items = _.uniqBy(items, options.uniqBy) + + items = options.onLoad(items) + + if (options.sortBy) items = _.sortBy(items, options.sortBy) + + switch (options.format) { + case 'json': + await saveAsJSON(filepath, items, options) + break + case 'm3u': + default: + await saveAsM3U(filepath, items, options) + break + } + + return { filepath, query, options, count: items.length } +} + +async function saveAsM3U(filepath, items, options) { + const playlist = await createPlaylist(filepath) + + const header = {} + if (options.includeGuides) { + let guides = items.map(item => item.guides) + guides = _.uniq(_.flatten(guides)).sort().join(',') + + header['x-tvg-url'] = guides + } + + await playlist.header(header) + for (const item of items) { + const stream = store.create(item) + await playlist.link( + stream.get('url'), + stream.get('title'), + { + 'tvg-id': stream.get('tvg_id'), + 'tvg-country': stream.get('tvg_country'), + 'tvg-language': stream.get('tvg_language'), + 'tvg-logo': stream.get('tvg_logo'), + // 'tvg-url': stream.get('tvg_url') || undefined, + 'user-agent': stream.get('http.user-agent') || undefined, + 'group-title': stream.get('group_title') + }, + { + 'http-referrer': stream.get('http.referrer') || undefined, + 'http-user-agent': stream.get('http.user-agent') || undefined + } + ) + } +} + +async function saveAsJSON(filepath, items, options) { + const output = items.map(item => { + const stream = store.create(item) + const categories = stream.get('categories').map(c => ({ name: c.name, slug: c.slug })) + const countries = stream.get('countries').map(c => ({ name: c.name, code: c.code })) + + return { + name: stream.get('name'), + logo: stream.get('logo'), + url: stream.get('url'), + categories, + countries, + languages: stream.get('languages'), + tvg: { + id: stream.get('tvg_id'), + name: stream.get('name'), + url: stream.get('tvg_url') + } + } + }) + + await file.create(filepath, JSON.stringify(output)) +} + +generator.saveAsM3U = saveAsM3U +generator.saveAsJSON = saveAsJSON + +module.exports = generator diff --git a/scripts/core/index.js b/scripts/core/index.js new file mode 100644 index 0000000000..948ff6c6d0 --- /dev/null +++ b/scripts/core/index.js @@ -0,0 +1,10 @@ +exports.db = require('./db') +exports.logger = require('./logger') +exports.file = require('./file') +exports.timer = require('./timer') +exports.parser = require('./parser') +exports.checker = require('./checker') +exports.generator = require('./generator') +exports.playlist = require('./playlist') +exports.store = require('./store') +exports.markdown = require('./markdown') diff --git a/scripts/core/logger.js b/scripts/core/logger.js new file mode 100644 index 0000000000..a109a050ba --- /dev/null +++ b/scripts/core/logger.js @@ -0,0 +1,42 @@ +const { createLogger, format, transports, addColors } = require('winston') +const { combine, timestamp, printf } = format + +const consoleFormat = ({ level, message, timestamp }) => { + if (typeof message === 'object') return JSON.stringify(message) + return message +} + +const config = { + levels: { + error: 0, + warn: 1, + info: 2, + failed: 3, + success: 4, + http: 5, + verbose: 6, + debug: 7, + silly: 8 + }, + colors: { + info: 'white', + success: 'green', + failed: 'red' + } +} + +const t = [ + new transports.Console({ + format: format.combine(format.printf(consoleFormat)) + }) +] + +const logger = createLogger({ + transports: t, + levels: config.levels, + level: 'verbose' +}) + +addColors(config.colors) + +module.exports = logger diff --git a/scripts/core/markdown.js b/scripts/core/markdown.js new file mode 100644 index 0000000000..32dc1110ec --- /dev/null +++ b/scripts/core/markdown.js @@ -0,0 +1,39 @@ +const markdownInclude = require('markdown-include') +const file = require('./file') + +const markdown = {} + +markdown.createTable = function (data, cols) { + let output = '\n' + + output += ' \n ' + for (let column of cols) { + output += `` + } + output += '\n \n' + + output += ' \n' + for (let item of data) { + output += ' ' + let i = 0 + for (let prop in item) { + const column = cols[i] + let nowrap = column.nowrap + let align = column.align + output += `` + i++ + } + output += '\n' + } + output += ' \n' + + output += '
${column.name}
${item[prop]}
' + + return output +} + +markdown.compile = function (filepath) { + markdownInclude.compileFiles(file.resolve(filepath)) +} + +module.exports = markdown diff --git a/scripts/core/parser.js b/scripts/core/parser.js new file mode 100644 index 0000000000..009d274eb2 --- /dev/null +++ b/scripts/core/parser.js @@ -0,0 +1,31 @@ +const ipp = require('iptv-playlist-parser') +const logger = require('./logger') +const file = require('./file') + +const parser = {} + +parser.parsePlaylist = async function (filepath) { + const content = await file.read(filepath) + const playlist = ipp.parse(content) + + return playlist.items +} + +parser.parseLogs = async function (filepath) { + const content = await file.read(filepath) + if (!content) return [] + const lines = content.split('\n') + + return lines.map(line => (line ? JSON.parse(line) : null)).filter(l => l) +} + +parser.parseNumber = function (string) { + const parsed = parseInt(string) + if (isNaN(parsed)) { + logger.error('Not a number') + } + + return parsed +} + +module.exports = parser diff --git a/scripts/core/playlist.js b/scripts/core/playlist.js new file mode 100644 index 0000000000..fb8077b27d --- /dev/null +++ b/scripts/core/playlist.js @@ -0,0 +1,49 @@ +const file = require('./file') + +const playlist = {} + +playlist.create = async function (filepath) { + playlist.filepath = filepath + const dir = file.dirname(filepath) + file.createDir(dir) + await file.create(filepath, '') + + return playlist +} + +playlist.header = async function (attrs) { + let header = `#EXTM3U` + for (const name in attrs) { + const value = attrs[name] + header += ` ${name}="${value}"` + } + header += `\n` + + await file.append(playlist.filepath, header) + + return playlist +} + +playlist.link = async function (url, title, attrs, vlcOpts) { + let link = `#EXTINF:-1` + for (const name in attrs) { + const value = attrs[name] + if (value !== undefined) { + link += ` ${name}="${value}"` + } + } + link += `,${title}\n` + for (const name in vlcOpts) { + const value = vlcOpts[name] + if (value !== undefined) { + link += `#EXTVLCOPT:${name}=${value}\n` + } + } + link += `${url}\n` + + await file.append(playlist.filepath, link) + + return playlist +} + +module.exports = playlist diff --git a/scripts/core/store.js b/scripts/core/store.js new file mode 100644 index 0000000000..c415944039 --- /dev/null +++ b/scripts/core/store.js @@ -0,0 +1,56 @@ +const _ = require('lodash') +const logger = require('./logger') +const setters = require('../store/setters') +const getters = require('../store/getters') + +module.exports = { + create(state = {}) { + return { + state, + changed: false, + set: function (prop, value) { + const prevState = JSON.stringify(this.state) + + const setter = setters[prop] + if (typeof setter === 'function') { + try { + this.state[prop] = setter.bind()(value) + } catch (error) { + logger.error(`store/setters/${prop}.js: ${error.message}`) + } + } else if (typeof value === 'object') { + this.state[prop] = value[prop] + } else { + this.state[prop] = value + } + + const newState = JSON.stringify(this.state) + if (prevState !== newState) { + this.changed = true + } + + return this + }, + get: function (prop) { + const getter = getters[prop] + if (typeof getter === 'function') { + try { + return getter.bind(this.state)() + } catch (error) { + logger.error(`store/getters/${prop}.js: ${error.message}`) + } + } else { + return prop.split('.').reduce((o, i) => (o ? o[i] : undefined), this.state) + } + }, + has: function (prop) { + const value = this.get(prop) + + return !_.isEmpty(value) + }, + data: function () { + return this.state + } + } + } +} diff --git a/scripts/core/timer.js b/scripts/core/timer.js new file mode 100644 index 0000000000..6e5f381d92 --- /dev/null +++ b/scripts/core/timer.js @@ -0,0 +1,29 @@ +const { performance } = require('perf_hooks') +const dayjs = require('dayjs') +const duration = require('dayjs/plugin/duration') +const relativeTime = require('dayjs/plugin/relativeTime') + +dayjs.extend(relativeTime) +dayjs.extend(duration) + +const timer = {} + +let t0 = 0 + +timer.start = function () { + t0 = performance.now() +} + +timer.format = function (f) { + let t1 = performance.now() + + return dayjs.duration(t1 - t0).format(f) +} + +timer.humanize = function (suffix = true) { + let t1 = performance.now() + + return dayjs.duration(t1 - t0).humanize(suffix) +} + +module.exports = timer From 958703d6d60d456b59251a783a72cb97dc0820de Mon Sep 17 00:00:00 2001 From: Aleksandr Statciuk Date: Sun, 12 Dec 2021 07:10:52 +0300 Subject: [PATCH 15/34] Remove old scripts --- scripts/create-matrix.js | 9 - scripts/filter.js | 43 ----- scripts/format.js | 307 --------------------------------- scripts/generate.js | 232 ------------------------- scripts/helpers/Channel.js | 162 ----------------- scripts/helpers/Playlist.js | 41 ----- scripts/helpers/db.js | 237 ------------------------- scripts/helpers/epg.js | 12 -- scripts/helpers/file.js | 53 ------ scripts/helpers/log.js | 17 -- scripts/helpers/parser.js | 20 --- scripts/helpers/utils.js | 86 --------- scripts/remove-broken-links.js | 42 ----- scripts/remove-duplicates.js | 81 --------- scripts/sort.js | 41 ----- scripts/update-readme.js | 142 --------------- 16 files changed, 1525 deletions(-) delete mode 100644 scripts/create-matrix.js delete mode 100644 scripts/filter.js delete mode 100644 scripts/format.js delete mode 100644 scripts/generate.js delete mode 100644 scripts/helpers/Channel.js delete mode 100644 scripts/helpers/Playlist.js delete mode 100644 scripts/helpers/db.js delete mode 100644 scripts/helpers/epg.js delete mode 100644 scripts/helpers/file.js delete mode 100644 scripts/helpers/log.js delete mode 100644 scripts/helpers/parser.js delete mode 100644 scripts/helpers/utils.js delete mode 100644 scripts/remove-broken-links.js delete mode 100644 scripts/remove-duplicates.js delete mode 100644 scripts/sort.js delete mode 100644 scripts/update-readme.js diff --git a/scripts/create-matrix.js b/scripts/create-matrix.js deleted file mode 100644 index 6e306d42b3..0000000000 --- a/scripts/create-matrix.js +++ /dev/null @@ -1,9 +0,0 @@ -const file = require('./helpers/file') - -file.list().then(files => { - files = files.filter(file => file !== 'channels/unsorted.m3u') - const country = files.map(file => file.replace(/channels\/|\.m3u/gi, '')) - const matrix = { country } - const output = `::set-output name=matrix::${JSON.stringify(matrix)}` - console.log(output) -}) diff --git a/scripts/filter.js b/scripts/filter.js deleted file mode 100644 index f6676c9370..0000000000 --- a/scripts/filter.js +++ /dev/null @@ -1,43 +0,0 @@ -const blacklist = require('./data/blacklist.json') -const parser = require('./helpers/parser') -const file = require('./helpers/file') -const log = require('./helpers/log') - -async function main() { - log.start() - - const files = await file.list() - if (!files.length) log.print(`No files is selected\n`) - for (const file of files) { - log.print(`\nProcessing '${file}'...`) - await parser - .parsePlaylist(file) - .then(removeBlacklisted) - .then(p => p.save()) - } - - log.print('\n') - log.finish() -} - -function removeBlacklisted(playlist) { - const channels = playlist.channels.filter(channel => { - return !blacklist.find(item => { - const regexp = new RegExp(item.regex, 'i') - const hasSameName = regexp.test(channel.name) - const fromSameCountry = playlist.country.code === item.country - - return hasSameName && fromSameCountry - }) - }) - - if (playlist.channels.length !== channels.length) { - log.print(`updated`) - playlist.channels = channels - playlist.updated = true - } - - return playlist -} - -main() diff --git a/scripts/format.js b/scripts/format.js deleted file mode 100644 index 74bf3e276f..0000000000 --- a/scripts/format.js +++ /dev/null @@ -1,307 +0,0 @@ -const axios = require('axios') -const { program } = require('commander') -const normalize = require('normalize-url') -const IPTVChecker = require('iptv-checker') -const parser = require('./helpers/parser') -const utils = require('./helpers/utils') -const file = require('./helpers/file') -const log = require('./helpers/log') -const epg = require('./helpers/epg') - -const ignoreStatus = ['Geo-blocked'] - -program - .usage('[OPTIONS]...') - .option('--debug', 'Enable debug mode') - .option('--offline', 'Enable offline mode') - .option('-d, --delay ', 'Set delay for each request', parseNumber, 0) - .option('-t, --timeout ', 'Set timeout for each request', parseNumber, 5000) - .option('-c, --country ', 'Comma-separated list of country codes', '') - .option('-e, --exclude ', 'Comma-separated list of country codes to be excluded', '') - .parse(process.argv) - -const config = program.opts() -const checker = new IPTVChecker({ - timeout: config.timeout -}) - -let buffer, origins -async function main() { - log.start() - - const include = config.country.split(',').filter(i => i) - const exclude = config.exclude.split(',').filter(i => i) - let files = await file.list(include, exclude) - if (!files.length) log.print(`No files is selected\n`) - for (const file of files) { - await parser.parsePlaylist(file).then(updatePlaylist).then(savePlaylist) - } - - log.finish() -} - -function savePlaylist(playlist) { - if (file.read(playlist.url) !== playlist.toString()) { - log.print(`File '${playlist.url}' has been updated\n`) - playlist.updated = true - } - - playlist.save() -} - -async function updatePlaylist(playlist) { - const total = playlist.channels.length - log.print(`Processing '${playlist.url}'...\n`) - - let channels = {} - let codes = {} - if (!config.offline) { - channels = await loadChannelsJson() - codes = await loadCodes() - } - - buffer = {} - origins = {} - for (const [i, channel] of playlist.channels.entries()) { - const curr = i + 1 - updateTvgName(channel) - updateTvgId(channel, playlist) - updateTvgCountry(channel) - normalizeUrl(channel) - - const data = channels[channel.tvg.id] - const epgData = codes[channel.tvg.id] - updateLogo(channel, data, epgData) - updateGroupTitle(channel, data) - updateTvgLanguage(channel, data) - - if (config.offline || ignoreStatus.includes(channel.status)) { - continue - } - - await checker - .checkStream(channel.data) - .then(parseResult) - .then(result => { - updateStatus(channel, result.status) - if (result.status === 'online') { - buffer[i] = result - updateOrigins(channel, result.requests) - updateResolution(channel, result.resolution) - } else { - buffer[i] = null - if (config.debug) { - log.print(` INFO: ${channel.url} (${result.error})\n`) - } - } - }) - .catch(err => { - buffer[i] = null - if (config.debug) { - log.print(` ERR: ${channel.data.url} (${err.message})\n`) - } - }) - } - - for (const [i, channel] of playlist.channels.entries()) { - if (!buffer[i]) continue - const { requests } = buffer[i] - updateUrl(channel, requests) - } - - return playlist -} - -function updateOrigins(channel, requests) { - if (!requests) return - const origin = new URL(channel.url) - const target = new URL(requests[0]) - const type = origin.host === target.host ? 'origin' : 'redirect' - requests.forEach(url => { - const key = utils.removeProtocol(url) - if (!origins[key] && type === 'origin') { - origins[key] = channel.url - } - }) -} - -function updateStatus(channel, status) { - switch (status) { - case 'online': - if (channel.status !== 'Not 24/7') - channel.status = channel.status === 'Offline' ? 'Not 24/7' : null - break - case 'error_403': - if (!channel.status) channel.status = 'Geo-blocked' - break - case 'offline': - if (channel.status !== 'Not 24/7') channel.status = 'Offline' - break - } -} - -function updateResolution(channel, resolution) { - if (!channel.resolution.height && resolution) { - channel.resolution = resolution - } -} - -function updateUrl(channel, requests) { - for (const request of requests) { - let key = utils.removeProtocol(channel.url) - if (origins[key]) { - channel.updateUrl(origins[key]) - break - } - - key = utils.removeProtocol(request) - if (origins[key]) { - channel.updateUrl(origins[key]) - break - } - } -} - -function parseResult(result) { - return { - status: parseStatus(result.status), - resolution: result.status.ok ? parseResolution(result.status.metadata.streams) : null, - requests: result.status.ok ? parseRequests(result.status.metadata.requests) : [], - error: !result.status.ok ? result.status.reason : null - } -} - -function parseStatus(status) { - if (status.ok) { - return 'online' - } else if (status.reason.includes('timed out')) { - return 'timeout' - } else if (status.reason.includes('403')) { - return 'error_403' - } else if (status.reason.includes('not one of 40{0,1,3,4}')) { - return 'error_40x' // 402, 451 - } else { - return 'offline' - } -} - -function parseResolution(streams) { - const resolution = streams - .filter(stream => stream.codec_type === 'video') - .reduce( - (acc, curr) => { - if (curr.height > acc.height) return { width: curr.width, height: curr.height } - return acc - }, - { width: 0, height: 0 } - ) - - return resolution.width > 0 && resolution.height > 0 ? resolution : null -} - -function parseRequests(requests) { - requests = requests.map(r => r.url) - requests.shift() - - return requests -} - -function updateTvgName(channel) { - if (!channel.tvg.name) { - channel.tvg.name = channel.name.replace(/\"/gi, '') - } -} - -function updateTvgId(channel, playlist) { - const code = playlist.country.code - if (!channel.tvg.id && channel.tvg.name) { - const id = utils.name2id(channel.tvg.name) - channel.tvg.id = id ? `${id}.${code}` : '' - } -} - -function updateTvgCountry(channel) { - if (!channel.countries.length && channel.tvg.id) { - const code = channel.tvg.id.split('.')[1] || null - const name = utils.code2name(code) - channel.countries = name ? [{ code, name }] : [] - channel.tvg.country = channel.countries.map(c => c.code.toUpperCase()).join(';') - } -} - -function updateLogo(channel, data, epgData) { - if (!channel.logo) { - if (data && data.logo) { - channel.logo = data.logo - } else if (epgData && epgData.logo) { - channel.logo = epgData.logo - } - } -} - -function updateTvgLanguage(channel, data) { - if (!channel.tvg.language) { - if (data && data.languages.length) { - channel.tvg.language = data.languages.map(l => l.name).join(';') - } else if (channel.countries.length) { - const countryCode = channel.countries[0].code - channel.tvg.language = utils.country2language(countryCode) - } - } -} - -function updateGroupTitle(channel, data) { - if (!channel.group.title) { - if (channel.category) { - channel.group.title = channel.category - } else if (data && data.category) { - channel.group.title = data.category - } - } -} - -function normalizeUrl(channel) { - const normalized = normalize(channel.url, { stripWWW: false }) - const decoded = decodeURIComponent(normalized).replace(/\s/g, '+') - channel.updateUrl(decoded) -} - -function parseNumber(str) { - return parseInt(str) -} - -function loadCodes() { - return epg.codes - .load() - .then(codes => { - let output = {} - codes.forEach(item => { - output[item['tvg_id']] = item - }) - return output - }) - .catch(console.log) -} - -function loadChannelsJson() { - return axios - .get('https://iptv-org.github.io/iptv/channels.json') - .then(r => r.data) - .then(channels => { - let output = {} - channels.forEach(channel => { - const item = output[channel.tvg.id] - if (!item) { - output[channel.tvg.id] = channel - } else { - item.logo = item.logo || channel.logo - item.languages = item.languages.length ? item.languages : channel.languages - item.category = item.category || channel.category - } - }) - return output - }) - .catch(console.log) -} - -main() diff --git a/scripts/generate.js b/scripts/generate.js deleted file mode 100644 index 07aaf7e1af..0000000000 --- a/scripts/generate.js +++ /dev/null @@ -1,232 +0,0 @@ -const file = require('./helpers/file') -const log = require('./helpers/log') -const db = require('./helpers/db') - -const ROOT_DIR = './.gh-pages' - -async function main() { - await loadDatabase() - createRootDirectory() - createNoJekyllFile() - generateIndex() - generateCategoryIndex() - generateCountryIndex() - generateLanguageIndex() - generateCategories() - generateCountries() - generateLanguages() - generateChannelsJson() - showResults() -} - -async function loadDatabase() { - log.print('Loading database...\n') - await db.load() -} - -function createRootDirectory() { - log.print('Creating .gh-pages folder...\n') - file.createDir(ROOT_DIR) -} - -function createNoJekyllFile() { - log.print('Creating .nojekyll...\n') - file.create(`${ROOT_DIR}/.nojekyll`) -} - -function generateIndex() { - log.print('Generating index.m3u...\n') - const channels = db.channels - .sortBy(['name', 'status', 'resolution.height', 'url'], ['asc', 'asc', 'desc', 'asc']) - .removeDuplicates() - .removeOffline() - .get() - const guides = channels.map(channel => channel.tvg.url) - - const filename = `${ROOT_DIR}/index.m3u` - const urlTvg = generateUrlTvg(guides) - file.create(filename, `#EXTM3U url-tvg="${urlTvg}"\n`) - - const nsfwFilename = `${ROOT_DIR}/index.nsfw.m3u` - file.create(nsfwFilename, `#EXTM3U url-tvg="${urlTvg}"\n`) - - for (const channel of channels) { - if (!channel.isNSFW()) { - file.append(filename, channel.toString()) - } - file.append(nsfwFilename, channel.toString()) - } -} - -function generateCategoryIndex() { - log.print('Generating index.category.m3u...\n') - const channels = db.channels - .sortBy( - ['category', 'name', 'status', 'resolution.height', 'url'], - ['asc', 'asc', 'asc', 'desc', 'asc'] - ) - .removeDuplicates() - .removeOffline() - .get() - const guides = channels.map(channel => channel.tvg.url) - - const filename = `${ROOT_DIR}/index.category.m3u` - const urlTvg = generateUrlTvg(guides) - file.create(filename, `#EXTM3U url-tvg="${urlTvg}"\n`) - - for (const channel of channels) { - file.append(filename, channel.toString()) - } -} - -function generateCountryIndex() { - log.print('Generating index.country.m3u...\n') - - const guides = [] - const lines = [] - for (const country of [{ code: 'undefined' }, ...db.countries.sortBy(['name']).all()]) { - const channels = db.channels - .sortBy(['name', 'status', 'resolution.height', 'url'], ['asc', 'asc', 'desc', 'asc']) - .forCountry(country) - .removeDuplicates() - .removeNSFW() - .removeOffline() - .get() - for (const channel of channels) { - const groupTitle = channel.group.title - channel.group.title = country.name || '' - lines.push(channel.toString()) - channel.group.title = groupTitle - guides.push(channel.tvg.url) - } - } - - const filename = `${ROOT_DIR}/index.country.m3u` - const urlTvg = generateUrlTvg(guides) - file.create(filename, `#EXTM3U url-tvg="${urlTvg}"\n${lines.join('')}`) -} - -function generateLanguageIndex() { - log.print('Generating index.language.m3u...\n') - - const guides = [] - const lines = [] - for (const language of [{ code: 'undefined' }, ...db.languages.sortBy(['name']).all()]) { - const channels = db.channels - .sortBy(['name', 'status', 'resolution.height', 'url'], ['asc', 'asc', 'desc', 'asc']) - .forLanguage(language) - .removeDuplicates() - .removeNSFW() - .removeOffline() - .get() - for (const channel of channels) { - const groupTitle = channel.group.title - channel.group.title = language.name || '' - lines.push(channel.toString()) - channel.group.title = groupTitle - guides.push(channel.tvg.url) - } - } - - const filename = `${ROOT_DIR}/index.language.m3u` - const urlTvg = generateUrlTvg(guides) - file.create(filename, `#EXTM3U url-tvg="${urlTvg}"\n${lines.join('')}`) -} - -function generateCategories() { - log.print(`Generating /categories...\n`) - const outputDir = `${ROOT_DIR}/categories` - file.createDir(outputDir) - - for (const category of [...db.categories.all(), { id: 'other' }]) { - const channels = db.channels - .sortBy(['name', 'status', 'resolution.height', 'url'], ['asc', 'asc', 'desc', 'asc']) - .forCategory(category) - .removeDuplicates() - .removeOffline() - .get() - const guides = channels.map(channel => channel.tvg.url) - - const filename = `${outputDir}/${category.id}.m3u` - const urlTvg = generateUrlTvg(guides) - file.create(filename, `#EXTM3U url-tvg="${urlTvg}"\n`) - for (const channel of channels) { - file.append(filename, channel.toString()) - } - } -} - -function generateCountries() { - log.print(`Generating /countries...\n`) - const outputDir = `${ROOT_DIR}/countries` - file.createDir(outputDir) - - for (const country of [...db.countries.all(), { code: 'undefined' }]) { - const channels = db.channels - .sortBy(['name', 'status', 'resolution.height', 'url'], ['asc', 'asc', 'desc', 'asc']) - .forCountry(country) - .removeDuplicates() - .removeOffline() - .removeNSFW() - .get() - const guides = channels.map(channel => channel.tvg.url) - - const filename = `${outputDir}/${country.code}.m3u` - const urlTvg = generateUrlTvg(guides) - file.create(filename, `#EXTM3U url-tvg="${urlTvg}"\n`) - for (const channel of channels) { - file.append(filename, channel.toString()) - } - } -} - -function generateLanguages() { - log.print(`Generating /languages...\n`) - const outputDir = `${ROOT_DIR}/languages` - file.createDir(outputDir) - - for (const language of [...db.languages.all(), { code: 'undefined' }]) { - const channels = db.channels - .sortBy(['name', 'status', 'resolution.height', 'url'], ['asc', 'asc', 'desc', 'asc']) - .forLanguage(language) - .removeDuplicates() - .removeOffline() - .removeNSFW() - .get() - const guides = channels.map(channel => channel.tvg.url) - - const filename = `${outputDir}/${language.code}.m3u` - const urlTvg = generateUrlTvg(guides) - file.create(filename, `#EXTM3U url-tvg="${urlTvg}"\n`) - for (const channel of channels) { - file.append(filename, channel.toString()) - } - } -} - -function generateChannelsJson() { - log.print('Generating channels.json...\n') - const filename = `${ROOT_DIR}/channels.json` - const channels = db.channels - .sortBy(['name', 'status', 'resolution.height', 'url'], ['asc', 'asc', 'desc', 'asc']) - .get() - .map(c => c.toObject()) - file.create(filename, JSON.stringify(channels)) -} - -function showResults() { - log.print( - `Total: ${db.channels.count()} channels, ${db.countries.count()} countries, ${db.languages.count()} languages, ${db.categories.count()} categories.\n` - ) -} - -function generateUrlTvg(guides) { - const output = guides.reduce((acc, curr) => { - if (curr && !acc.includes(curr)) acc.push(curr) - return acc - }, []) - - return output.sort().join(',') -} - -main() diff --git a/scripts/helpers/Channel.js b/scripts/helpers/Channel.js deleted file mode 100644 index 3d177ad14b..0000000000 --- a/scripts/helpers/Channel.js +++ /dev/null @@ -1,162 +0,0 @@ -const categories = require('../data/categories') -const utils = require('./utils') -const file = require('./file') - -const sfwCategories = categories.filter(c => !c.nsfw).map(c => c.name) -const nsfwCategories = categories.filter(c => c.nsfw).map(c => c.name) - -module.exports = class Channel { - constructor(data) { - this.data = data - this.raw = data.raw - this.tvg = data.tvg - this.http = data.http - this.url = data.url - this.logo = data.tvg.logo - this.group = data.group - this.name = this.parseName(data.name) - this.status = this.parseStatus(data.name) - this.resolution = this.parseResolution(data.name) - this.category = this.parseCategory(data.group.title) - this.countries = this.parseCountries(data.tvg.country) - this.languages = this.parseLanguages(data.tvg.language) - this.hash = this.generateHash() - } - - generateHash() { - return `${this.tvg.id}:${this.tvg.country}:${this.tvg.language}:${this.logo}:${this.group.title}:${this.name}`.toLowerCase() - } - - updateUrl(url) { - this.url = url - this.data.url = url - } - - parseName(title) { - return title - .trim() - .split(' ') - .map(s => s.trim()) - .filter(s => { - return !/\[|\]/i.test(s) && !/\((\d+)P\)/i.test(s) - }) - .join(' ') - } - - parseStatus(title) { - const match = title.match(/\[(.*)\]/i) - return match ? match[1] : null - } - - parseResolution(title) { - const match = title.match(/\((\d+)P\)/i) - const height = match ? parseInt(match[1]) : null - - return { width: null, height } - } - - parseCategory(string) { - const category = categories.find(c => c.id === string.toLowerCase()) - if (!category) return '' - - return category.name - } - - parseCountries(string) { - const list = string.split(';') - return list - .reduce((acc, curr) => { - const codes = utils.region2codes(curr) - if (codes.length) { - for (let code of codes) { - if (!acc.includes(code)) { - acc.push(code) - } - } - } else { - acc.push(curr) - } - - return acc - }, []) - .map(code => { - const name = code ? utils.code2name(code) : null - if (!name) return null - - return { code: code.toLowerCase(), name } - }) - .filter(c => c) - } - - parseLanguages(string) { - const list = string.split(';') - return list - .map(name => { - const code = name ? utils.language2code(name) : null - if (!code) return null - - return { code, name } - }) - .filter(l => l) - } - - isSFW() { - return sfwCategories.includes(this.category) - } - - isNSFW() { - return nsfwCategories.includes(this.category) - } - - getInfo() { - let info = `-1 tvg-id="${this.tvg.id}" tvg-country="${this.tvg.country || ''}" tvg-language="${ - this.tvg.language || '' - }" tvg-logo="${this.logo || ''}"` - - if (this.http['user-agent']) { - info += ` user-agent="${this.http['user-agent']}"` - } - - info += ` group-title="${this.group.title || ''}",${this.name}` - - if (this.resolution.height) { - info += ` (${this.resolution.height}p)` - } - - if (this.status) { - info += ` [${this.status}]` - } - - if (this.http['referrer']) { - info += `\n#EXTVLCOPT:http-referrer=${this.http['referrer']}` - } - - if (this.http['user-agent']) { - info += `\n#EXTVLCOPT:http-user-agent=${this.http['user-agent']}` - } - - return info - } - - toString(raw = false) { - if (raw) return this.raw + '\n' - - return '#EXTINF:' + this.getInfo() + '\n' + this.url + '\n' - } - - toObject() { - return { - name: this.name, - logo: this.logo || null, - url: this.url, - category: this.category || null, - languages: this.languages, - countries: this.countries, - tvg: { - id: this.tvg.id || null, - name: this.tvg.name || this.name.replace(/\"/gi, ''), - url: this.tvg.url || null - } - } - } -} diff --git a/scripts/helpers/Playlist.js b/scripts/helpers/Playlist.js deleted file mode 100644 index 0df181a2da..0000000000 --- a/scripts/helpers/Playlist.js +++ /dev/null @@ -1,41 +0,0 @@ -const Channel = require('./Channel') -const file = require('./file') - -module.exports = class Playlist { - constructor({ header, items, url, name, country }) { - this.url = url - this.name = name - this.country = country - this.header = header - this.channels = items.map(item => new Channel(item)).filter(channel => channel.url) - this.updated = false - } - - getHeader() { - let header = ['#EXTM3U'] - for (let key in this.header.attrs) { - let value = this.header.attrs[key] - if (value) { - header.push(`${key}="${value}"`) - } - } - - return header.join(' ') - } - - toString(options = {}) { - const config = { raw: false, ...options } - let output = `${this.getHeader()}\n` - for (let channel of this.channels) { - output += channel.toString(config.raw) - } - - return output - } - - save() { - if (this.updated) { - file.create(this.url, this.toString()) - } - } -} diff --git a/scripts/helpers/db.js b/scripts/helpers/db.js deleted file mode 100644 index 52587ce387..0000000000 --- a/scripts/helpers/db.js +++ /dev/null @@ -1,237 +0,0 @@ -const categories = require('../data/categories') -const parser = require('./parser') -const utils = require('./utils') -const file = require('./file') -const epg = require('./epg') - -const db = {} - -db.load = async function () { - const files = await file.list() - const codes = await epg.codes.load() - for (const file of files) { - const playlist = await parser.parsePlaylist(file) - for (const channel of playlist.channels) { - const code = codes.find(ch => ch['tvg_id'] === channel.tvg.id) - if (code && Array.isArray(code.guides) && code.guides.length) { - channel.tvg.url = code.guides[0] - } - - db.channels.add(channel) - - for (const country of channel.countries) { - if (!db.countries.has(country)) { - db.countries.add(country) - } - } - - for (const language of channel.languages) { - if (!db.languages.has(language)) { - db.languages.add(language) - } - } - } - - db.playlists.add(playlist) - } -} - -db.channels = { - list: [], - filter: null, - duplicates: true, - offline: true, - nsfw: true, - add(channel) { - this.list.push(channel) - }, - get() { - let output - if (this.filter) { - switch (this.filter.field) { - case 'countries': - if (this.filter.value === 'undefined') { - output = this.list.filter(channel => !channel.countries.length) - } else { - output = this.list.filter(channel => - channel.countries.map(c => c.code).includes(this.filter.value) - ) - } - break - case 'languages': - if (this.filter.value === 'undefined') { - output = this.list.filter(channel => !channel.languages.length) - } else { - output = this.list.filter(channel => - channel.languages.map(c => c.code).includes(this.filter.value) - ) - } - break - case 'category': - if (this.filter.value === 'other') { - output = this.list.filter(channel => !channel.category) - } else { - output = this.list.filter( - channel => channel.category.toLowerCase() === this.filter.value - ) - } - break - } - } else { - output = this.list - } - - if (!this.duplicates) { - const buffer = [] - output = output.filter(channel => { - if (buffer.includes(channel.hash)) return false - buffer.push(channel.hash) - - return true - }) - } - - if (!this.nsfw) { - output = output.filter(channel => !channel.isNSFW()) - } - - if (!this.offline) { - output = output.filter(channel => channel.status !== 'Offline') - } - - this.nsfw = true - this.duplicates = true - this.offline = true - this.filter = null - - return output - }, - removeDuplicates() { - this.duplicates = false - - return this - }, - removeNSFW() { - this.nsfw = false - - return this - }, - removeOffline() { - this.offline = false - - return this - }, - all() { - return this.list - }, - forCountry(country) { - this.filter = { - field: 'countries', - value: country.code - } - - return this - }, - forLanguage(language) { - this.filter = { - field: 'languages', - value: language.code - } - - return this - }, - forCategory(category) { - this.filter = { - field: 'category', - value: category.id - } - - return this - }, - count() { - return this.get().length - }, - sortBy(fields, order) { - this.list = utils.sortBy(this.list, fields, order) - - return this - } -} - -db.countries = { - list: [], - has(country) { - return this.list.map(c => c.code).includes(country.code) - }, - add(country) { - this.list.push(country) - }, - all() { - return this.list - }, - count() { - return this.list.length - }, - sortBy(fields, order) { - this.list = utils.sortBy(this.list, fields, order) - - return this - } -} - -db.languages = { - list: [], - has(language) { - return this.list.map(c => c.code).includes(language.code) - }, - add(language) { - this.list.push(language) - }, - all() { - return this.list - }, - count() { - return this.list.length - }, - sortBy(fields, order) { - this.list = utils.sortBy(this.list, fields, order) - - return this - } -} - -db.categories = { - list: categories, - all() { - return this.list - }, - count() { - return this.list.length - } -} - -db.playlists = { - list: [], - add(playlist) { - this.list.push(playlist) - }, - all() { - return this.list - }, - only(list = []) { - return this.list.filter(playlist => list.includes(playlist.filename)) - }, - except(list = []) { - return this.list.filter(playlist => !list.includes(playlist.filename)) - }, - sortBy(fields, order) { - this.list = utils.sortBy(this.list, fields, order) - - return this - }, - count() { - return this.list.length - } -} - -module.exports = db diff --git a/scripts/helpers/epg.js b/scripts/helpers/epg.js deleted file mode 100644 index 202a89e894..0000000000 --- a/scripts/helpers/epg.js +++ /dev/null @@ -1,12 +0,0 @@ -const axios = require('axios') - -module.exports = { - codes: { - async load() { - return await axios - .get('https://iptv-org.github.io/epg/codes.json') - .then(r => r.data) - .catch(console.log) - } - } -} diff --git a/scripts/helpers/file.js b/scripts/helpers/file.js deleted file mode 100644 index 44ff351357..0000000000 --- a/scripts/helpers/file.js +++ /dev/null @@ -1,53 +0,0 @@ -const markdownInclude = require('markdown-include') -const path = require('path') -const glob = require('glob') -const fs = require('fs') - -const rootPath = path.resolve(__dirname) + '/../../' -const file = {} - -file.list = function (include = [], exclude = []) { - return new Promise(resolve => { - glob('channels/**/*.m3u', function (err, files) { - if (include.length) { - include = include.map(filename => `channels/${filename}.m3u`) - files = files.filter(filename => include.includes(filename)) - } - - if (exclude.length) { - exclude = exclude.map(filename => `channels/${filename}.m3u`) - files = files.filter(filename => !exclude.includes(filename)) - } - - resolve(files) - }) - }) -} - -file.getFilename = function (filename) { - return path.parse(filename).name -} - -file.createDir = function (dir) { - if (!fs.existsSync(dir)) { - fs.mkdirSync(dir) - } -} - -file.read = function (filename) { - return fs.readFileSync(rootPath + filename, { encoding: 'utf8' }) -} - -file.append = function (filename, data) { - fs.appendFileSync(rootPath + filename, data) -} - -file.create = function (filename, data = '') { - fs.writeFileSync(rootPath + filename, data) -} - -file.compileMarkdown = function (filename) { - markdownInclude.compileFiles(rootPath + filename) -} - -module.exports = file diff --git a/scripts/helpers/log.js b/scripts/helpers/log.js deleted file mode 100644 index 3120110b80..0000000000 --- a/scripts/helpers/log.js +++ /dev/null @@ -1,17 +0,0 @@ -const log = {} - -log.print = function (message) { - if (typeof message === 'object') message = JSON.stringify(message, null, 2) - process.stdout.write(message) -} - -log.start = function () { - this.print('Starting...\n') - console.time('Done in') -} - -log.finish = function () { - console.timeEnd('Done in') -} - -module.exports = log diff --git a/scripts/helpers/parser.js b/scripts/helpers/parser.js deleted file mode 100644 index 138af59073..0000000000 --- a/scripts/helpers/parser.js +++ /dev/null @@ -1,20 +0,0 @@ -const playlistParser = require('iptv-playlist-parser') -const Playlist = require('./Playlist') -const utils = require('./utils') -const file = require('./file') - -const parser = {} - -parser.parsePlaylist = async function (url) { - const content = file.read(url) - const result = playlistParser.parse(content) - const filename = file.getFilename(url) - const country = { - code: filename, - name: utils.code2name(filename) - } - - return new Playlist({ header: result.header, items: result.items, url, filename, country }) -} - -module.exports = parser diff --git a/scripts/helpers/utils.js b/scripts/helpers/utils.js deleted file mode 100644 index 0a140ff673..0000000000 --- a/scripts/helpers/utils.js +++ /dev/null @@ -1,86 +0,0 @@ -const { orderBy } = require('natural-orderby') -const transliteration = require('transliteration') -const countries = require('../data/countries') -const categories = require('../data/categories') -const languages = require('../data/languages') -const regions = require('../data/regions') - -const utils = {} -const intlDisplayNames = new Intl.DisplayNames(['en'], { - style: 'narrow', - type: 'region' -}) - -utils.name2id = function (name) { - return transliteration - .transliterate(name) - .replace(/\+/gi, 'Plus') - .replace(/[^a-z\d]+/gi, '') -} - -utils.code2flag = function (code) { - code = code.toUpperCase() - switch (code) { - case 'UK': - return '🇬🇧' - case 'INT': - return '🌍' - case 'UNDEFINED': - return '' - default: - return code.replace(/./g, char => String.fromCodePoint(char.charCodeAt(0) + 127397)) - } -} - -utils.region2codes = function (region) { - region = region.toUpperCase() - - return regions[region] ? regions[region].codes : [] -} - -utils.code2name = function (code) { - try { - code = code.toUpperCase() - if (regions[code]) return regions[code].name - if (code === 'US') return 'United States' - if (code === 'INT') return 'International' - return intlDisplayNames.of(code) - } catch (e) { - return null - } -} - -utils.language2code = function (name) { - const lang = languages.find(l => l.name === name) - - return lang && lang.code ? lang.code : null -} - -utils.country2language = function (code) { - const country = countries[code.toUpperCase()] - if (!country.languages.length) return '' - const language = languages.find(l => l.code === country.languages[0]) - - return language ? language.name : '' -} - -utils.sortBy = function (arr, fields, order = null) { - fields = fields.map(field => { - if (field === 'resolution.height') return channel => channel.resolution.height || 0 - if (field === 'status') return channel => channel.status || '' - return channel => channel[field] - }) - return orderBy(arr, fields, order) -} - -utils.removeProtocol = function (string) { - return string.replace(/(^\w+:|^)\/\//, '') -} - -utils.sleep = function (ms) { - return function (x) { - return new Promise(resolve => setTimeout(() => resolve(x), ms)) - } -} - -module.exports = utils diff --git a/scripts/remove-broken-links.js b/scripts/remove-broken-links.js deleted file mode 100644 index a6fff7a85c..0000000000 --- a/scripts/remove-broken-links.js +++ /dev/null @@ -1,42 +0,0 @@ -const parser = require('./helpers/parser') -const file = require('./helpers/file') -const log = require('./helpers/log') - -async function main() { - log.start() - - let files = await file.list() - if (!files.length) log.print(`No files is selected\n`) - files = files.filter(file => file !== 'channels/unsorted.m3u') - for (const file of files) { - log.print(`\nProcessing '${file}'...`) - await parser - .parsePlaylist(file) - .then(removeBrokenLinks) - .then(p => p.save()) - } - - log.print('\n') - log.finish() -} - -async function removeBrokenLinks(playlist) { - const buffer = [] - const channels = playlist.channels.filter(channel => { - const sameHash = buffer.find(item => item.hash === channel.hash) - if (sameHash && channel.status === 'Offline') return false - - buffer.push(channel) - return true - }) - - if (playlist.channels.length !== channels.length) { - log.print('updated') - playlist.channels = channels - playlist.updated = true - } - - return playlist -} - -main() diff --git a/scripts/remove-duplicates.js b/scripts/remove-duplicates.js deleted file mode 100644 index c75882f70c..0000000000 --- a/scripts/remove-duplicates.js +++ /dev/null @@ -1,81 +0,0 @@ -const parser = require('./helpers/parser') -const utils = require('./helpers/utils') -const file = require('./helpers/file') -const log = require('./helpers/log') - -let globalBuffer = [] - -async function main() { - log.start() - - let files = await file.list() - if (!files.length) log.print(`No files is selected\n`) - files = files.filter(file => file !== 'channels/unsorted.m3u') - for (const file of files) { - log.print(`\nProcessing '${file}'...`) - await parser - .parsePlaylist(file) - .then(addToGlobalBuffer) - .then(removeDuplicates) - .then(p => p.save()) - } - - if (files.length) { - log.print(`\nProcessing 'channels/unsorted.m3u'...`) - await parser - .parsePlaylist('channels/unsorted.m3u') - .then(removeDuplicates) - .then(removeGlobalDuplicates) - .then(p => p.save()) - } - - log.print('\n') - log.finish() -} - -async function addToGlobalBuffer(playlist) { - playlist.channels.forEach(channel => { - const url = utils.removeProtocol(channel.url) - globalBuffer.push(url) - }) - - return playlist -} - -async function removeDuplicates(playlist) { - const buffer = [] - const channels = playlist.channels.filter(channel => { - const sameUrl = buffer.find(item => { - return utils.removeProtocol(item.url) === utils.removeProtocol(channel.url) - }) - if (sameUrl) return false - - buffer.push(channel) - return true - }) - - if (playlist.channels.length !== channels.length) { - log.print('updated') - playlist.channels = channels - playlist.updated = true - } - - return playlist -} - -async function removeGlobalDuplicates(playlist) { - const channels = playlist.channels.filter(channel => { - const url = utils.removeProtocol(channel.url) - return !globalBuffer.includes(url) - }) - - if (channels.length !== playlist.channels.length) { - log.print('updated') - playlist.channels = channels - playlist.updated = true - } - - return playlist -} - -main() diff --git a/scripts/sort.js b/scripts/sort.js deleted file mode 100644 index c199bd5d18..0000000000 --- a/scripts/sort.js +++ /dev/null @@ -1,41 +0,0 @@ -const parser = require('./helpers/parser') -const utils = require('./helpers/utils') -const file = require('./helpers/file') -const log = require('./helpers/log') - -async function main() { - log.start() - - let files = await file.list() - if (!files.length) log.print(`No files is selected\n`) - files = files.filter(file => file !== 'channels/unsorted.m3u') - for (const file of files) { - log.print(`\nProcessing '${file}'...`) - await parser - .parsePlaylist(file) - .then(sortChannels) - .then(p => p.save()) - } - - log.print('\n') - log.finish() -} - -async function sortChannels(playlist) { - let channels = [...playlist.channels] - channels = utils.sortBy( - channels, - ['name', 'status', 'resolution.height', 'url'], - ['asc', 'asc', 'desc', 'asc'] - ) - - if (JSON.stringify(channels) !== JSON.stringify(playlist.channels)) { - log.print('updated') - playlist.channels = channels - playlist.updated = true - } - - return playlist -} - -main() diff --git a/scripts/update-readme.js b/scripts/update-readme.js deleted file mode 100644 index 5fa324039a..0000000000 --- a/scripts/update-readme.js +++ /dev/null @@ -1,142 +0,0 @@ -const utils = require('./helpers/utils') -const file = require('./helpers/file') -const log = require('./helpers/log') -const db = require('./helpers/db') - -async function main() { - log.start() - await loadDatabase() - generateCategoriesTable() - generateCountriesTable() - generateLanguagesTable() - generateReadme() - log.finish() -} - -async function loadDatabase() { - log.print('Loading database...\n') - await db.load() -} - -function generateCategoriesTable() { - log.print('Generating categories table...\n') - - const categories = [] - for (const category of [...db.categories.all(), { name: 'Other', id: 'other' }]) { - categories.push({ - category: category.name, - channels: db.channels.forCategory(category).removeOffline().removeDuplicates().count(), - playlist: `https://iptv-org.github.io/iptv/categories/${category.id}.m3u` - }) - } - - const table = generateTable(categories, { - columns: [ - { name: 'Category', align: 'left' }, - { name: 'Channels', align: 'right' }, - { name: 'Playlist', align: 'left' } - ] - }) - - file.create('./.readme/_categories.md', table) -} - -function generateCountriesTable() { - log.print('Generating countries table...\n') - - const countries = [] - for (const country of [ - ...db.countries.sortBy(['name']).all(), - { name: 'Undefined', code: 'undefined' } - ]) { - let flag = utils.code2flag(country.code) - const prefix = flag ? `${flag} ` : '' - countries.push({ - country: prefix + country.name, - channels: db.channels - .forCountry(country) - .removeOffline() - .removeDuplicates() - .removeNSFW() - .count(), - playlist: `https://iptv-org.github.io/iptv/countries/${country.code}.m3u` - }) - } - - const table = generateTable(countries, { - columns: [ - { name: 'Country', align: 'left' }, - { name: 'Channels', align: 'right' }, - { name: 'Playlist', align: 'left', nowrap: true } - ] - }) - - file.create('./.readme/_countries.md', table) -} - -function generateLanguagesTable() { - log.print('Generating languages table...\n') - const languages = [] - - for (const language of [ - ...db.languages.sortBy(['name']).all(), - { name: 'Undefined', code: 'undefined' } - ]) { - languages.push({ - language: language.name, - channels: db.channels - .forLanguage(language) - .removeOffline() - .removeDuplicates() - .removeNSFW() - .count(), - playlist: `https://iptv-org.github.io/iptv/languages/${language.code}.m3u` - }) - } - - const table = generateTable(languages, { - columns: [ - { name: 'Language', align: 'left' }, - { name: 'Channels', align: 'right' }, - { name: 'Playlist', align: 'left' } - ] - }) - - file.create('./.readme/_languages.md', table) -} - -function generateTable(data, options) { - let output = '\n' - - output += '\t\n\t\t' - for (let column of options.columns) { - output += `` - } - output += '\n\t\n' - - output += '\t\n' - for (let item of data) { - output += '\t\t' - let i = 0 - for (let prop in item) { - const column = options.columns[i] - let nowrap = column.nowrap - let align = column.align - output += `` - i++ - } - output += '\n' - } - output += '\t\n' - - output += '
${column.name}
${item[prop]}
' - - return output -} - -function generateReadme() { - log.print('Generating README.md...\n') - file.compileMarkdown('.readme/config.json') -} - -main() From a2ed544550a5f1574b3d2a1e586a46142f4b6461 Mon Sep 17 00:00:00 2001 From: Aleksandr Statciuk Date: Sun, 12 Dec 2021 07:11:11 +0300 Subject: [PATCH 16/34] Rename to blocklist.json --- scripts/data/blacklist.json | 632 ------------------------------------ scripts/data/blocklist.json | 632 ++++++++++++++++++++++++++++++++++++ 2 files changed, 632 insertions(+), 632 deletions(-) delete mode 100644 scripts/data/blacklist.json create mode 100644 scripts/data/blocklist.json diff --git a/scripts/data/blacklist.json b/scripts/data/blacklist.json deleted file mode 100644 index f5c735d0e6..0000000000 --- a/scripts/data/blacklist.json +++ /dev/null @@ -1,632 +0,0 @@ -[ - { - "name": "Animal Planet", - "country": "us", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^Animal Planet$" - }, - { - "name": "Arena 4", - "country": "hu", - "dmca_notice": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", - "regex": "^Arena( |)4$" - }, - { - "name": "Asian Food Network", - "country": "sg", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^Asian Food Network$" - }, - { - "name": "Astro SuperSport", - "country": "my", - "dmca_notice": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", - "regex": "^Astro SuperSport$" - }, - { - "name": "Azteca 7", - "country": "mx", - "dmca_notice": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", - "regex": "^Azteca 7$" - }, - { - "name": "beIN Sports", - "country": "qa", - "dmca_notice": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", - "regex": "^beIN Sports" - }, - { - "name": "Canal+ Sport", - "country": "fr", - "dmca_notice": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", - "regex": "^Canal( |)+ Sport" - }, - { - "name": "Cooking Channel", - "country": "us", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^Cooking Channel$" - }, - { - "name": "DAZN", - "country": "uk", - "dmca_notice": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", - "regex": "^DAZN($| [1-4] .*)$" - }, - { - "name": "Diema Sport", - "country": "bg", - "dmca_notice": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", - "regex": "^Diema Sport($| [1-3])$" - }, - { - "name": "Digi Sport", - "country": "ro", - "dmca_notice": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", - "regex": "^Digi Sport($| [1-4].*)" - }, - { - "name": "Discovery Asia", - "country": "us", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^Discovery Asia$" - }, - { - "name": "Discovery Channel", - "country": "us", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^Discovery Channel$" - }, - { - "name": "Discovery Civiliztion", - "country": "us", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^Discovery Civiliztion$" - }, - { - "name": "Discovery en Espanol", - "country": "us", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^Discovery en Espanol$" - }, - { - "name": "Discovery Family", - "country": "us", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^Discovery Family$" - }, - { - "name": "Discovery Historia", - "country": "us", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^Discovery Historia$" - }, - { - "name": "Discovery History", - "country": "us", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^Discovery History$" - }, - { - "name": "Discovery Home and Health", - "country": "us", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^Discovery Home and Health$" - }, - { - "name": "Discovery Life", - "country": "us", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^Discovery Life$" - }, - { - "name": "Discovery Science", - "country": "us", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^Discovery Science$" - }, - { - "name": "Discovery Shed", - "country": "us", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^Discovery Shed$" - }, - { - "name": "Discovery Theater", - "country": "us", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^Discovery Theater$" - }, - { - "name": "Discovery Travel and Living", - "country": "us", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^Discovery Travel and Living$" - }, - { - "name": "Discovery Turbo Xtra", - "country": "us", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^Discovery Turbo Xtra$" - }, - { - "name": "Discovery World", - "country": "us", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^Discovery World$" - }, - { - "name": "Discovery", - "country": "us", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^Discovery$" - }, - { - "name": "DIY Network", - "country": "us", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^DIY Network$" - }, - { - "name": "DKiss", - "country": "es", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^DKiss$" - }, - { - "name": "DMax", - "country": "us", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^DMax$" - }, - { - "name": "Eleven Sports", - "country": "uk", - "dmca_notice": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", - "regex": "^Eleven Sports($| [1-6] .*)$" - }, - { - "name": "ESPN", - "country": "us", - "dmca_notice": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", - "regex": "^ESPN($|[1-3]| .*)$" - }, - { - "name": "Eurosport", - "country": "fr", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^Eurosport($| [1-2])$" - }, - { - "name": "eve", - "country": "us", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^eve$" - }, - { - "name": "Familia Discovery", - "country": "us", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^Familia Discovery$" - }, - { - "name": "Fatafeat", - "country": "eg", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^Fatafeat$" - }, - { - "name": "FEM", - "country": "no", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^FEM$" - }, - { - "name": "Fine Living", - "country": "us", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^Fine Living$" - }, - { - "name": "Flow Sports", - "country": "uk", - "dmca_notice": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", - "regex": "^Flow Sports$" - }, - { - "name": "Food Network", - "country": "us", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^Food Network$" - }, - { - "name": "food tv", - "country": "us", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^food( |)tv$" - }, - { - "name": "Fox Sports", - "country": "us", - "dmca_notice": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", - "regex": "^Fox Sports$" - }, - { - "name": "Frisbee", - "country": "it", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^Frisbee$" - }, - { - "name": "Futbol", - "country": "tj", - "dmca_notice": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", - "regex": "^(Futbol|Football TV|ТВ Футбол|Футбол)$" - }, - { - "name": "GTV Sports", - "country": "gh", - "dmca_notice": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", - "regex": "^GTV Sports" - }, - { - "name": "Giallo", - "country": "it", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^Giallo$" - }, - { - "name": "GolfTV", - "country": "us", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^Golf( |)TV$" - }, - { - "name": "HGTV", - "country": "us", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^HGTV$" - }, - { - "name": "Investigation Discovery", - "country": "us", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^(Investigation Discovery|ID Investigation Discovery|ID Investigation|ID)$" - }, - { - "name": "K2", - "country": "it", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^K2$" - }, - { - "name": "Living Channel", - "country": "nz", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^Living Channel$" - }, - { - "name": "LookSport", - "country": "ro", - "dmca_notice": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", - "regex": "^Look( |)Sport" - }, - { - "name": "Mango", - "country": "us", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^Mango$" - }, - { - "name": "Match!", - "country": "ru", - "dmca_notice": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", - "regex": "^(Match|Матч)" - }, - { - "name": "Motortrend", - "country": "us", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^Motortrend$" - }, - { - "name": "Mola TV", - "country": "id", - "dmca_notice": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", - "regex": "^Mola TV($| .*)$" - }, - { - "name": "Movistar Liga de Campeones", - "country": "es", - "dmca_notice": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", - "regex": "^Movistar Liga de Campeones [1-8]$" - }, - { - "name": "Nova Sport", - "country": "cz", - "dmca_notice": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", - "regex": "^Nova Sport [1-3]$" - }, - { - "name": "Nova Sports", - "country": "gr", - "dmca_notice": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", - "regex": "^Nova Sports [1-6]$" - }, - { - "name": "Nove", - "country": "it", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^Nove($| .*)$" - }, - { - "name": "PPTV HD 36", - "country": "th", - "dmca_notice": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", - "regex": "^PPTV($| HD)$" - }, - { - "name": "One", - "country": "il", - "dmca_notice": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", - "regex": "^One$" - }, - { - "name": "OWN", - "country": "us", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^(OWN|Oprah)$" - }, - { - "name": "Quest Red", - "country": "us", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^Quest Red$" - }, - { - "name": "Quest", - "country": "us", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^Quest$" - }, - { - "name": "Real Time", - "country": "us", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^Real Time$" - }, - { - "name": "SABC Sport ", - "country": "za", - "dmca_notice": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", - "regex": "^SABC Sport" - }, - { - "name": "Setanta Sports", - "country": "ie", - "dmca_notice": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", - "regex": "^Setanta Sports($| .*)$" - }, - { - "name": "Sky Sports", - "country": "uk", - "dmca_notice": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", - "regex": "^Sky Sports$" - }, - { - "name": "Sky Sport Bundesliga", - "country": "de", - "dmca_notice": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", - "regex": "^Sky Sport Bundesliga [0-9]+$" - }, - { - "name": "Sky TG24", - "country": "it", - "dmca_notice": "https://github.com/iptv-org/iptv/pull/2294", - "regex": "^Sky TG24$" - }, - { - "name": "Sony Ten", - "country": "in", - "dmca_notice": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", - "regex": "^Sony Ten [1-4]$" - }, - { - "name": "Spíler TV", - "country": "hu", - "dmca_notice": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", - "regex": "^Spíler( |[1-2] )TV$" - }, - { - "name": "Šport TV", - "country": "si", - "dmca_notice": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", - "regex": "^(Šport|Sport) TV" - }, - { - "name": "Sport Klub", - "country": "hu", - "dmca_notice": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", - "regex": "^(Sport Klub|SK[1-9])" - }, - { - "name": "SportsNet", - "country": "ca", - "dmca_notice": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", - "regex": "^SportsNet$" - }, - { - "name": "StarHub TV", - "country": "sg", - "dmca_notice": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", - "regex": "^StarHub TV$" - }, - { - "name": "StarSat", - "country": "za", - "dmca_notice": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", - "regex": "^StarSat$" - }, - { - "name": "StarTimes TV", - "country": "mz", - "dmca_notice": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", - "regex": "^StarTimes TV" - }, - { - "name": "SuperSport", - "country": "al", - "dmca_notice": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", - "regex": "^SuperSport [1-7]$" - }, - { - "name": "Tivibu Spor", - "country": "tr", - "dmca_notice": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", - "regex": "^Tivibu Spor" - }, - { - "name": "TLC", - "country": "us", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^TLC$" - }, - { - "name": "Trvl Channel", - "country": "us", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^Trvl Channel$" - }, - { - "name": "TSN", - "country": "mt", - "dmca_notice": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", - "regex": "^TSN$" - }, - { - "name": "TTV", - "country": "pl", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^TTV$" - }, - { - "name": "TV Norge", - "country": "no", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^TV Norge$" - }, - { - "name": "TV Varzish", - "country": "tj", - "dmca_notice": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", - "regex": "^(TV Varzish|Varzish TV|Варзиш ТВ)$" - }, - { - "name": "TV3 Sport", - "country": "dk", - "dmca_notice": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", - "regex": "^TV( |)3 Sport$" - }, - { - "name": "tvN Asia", - "country": "kr", - "dmca_notice": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", - "regex": "^tvN($| Asia)$" - }, - { - "name": "Tvn 24 Bis", - "country": "pl", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^Tvn 24 Bis$" - }, - { - "name": "TVN 24", - "country": "pl", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^TVN 24$" - }, - { - "name": "Tvn 7", - "country": "pl", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^Tvn 7$" - }, - { - "name": "TVN Extra", - "country": "pl", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^TVN Extra$" - }, - { - "name": "TVN Fabula", - "country": "pl", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^TVN Fabula$" - }, - { - "name": "TVN Meteo", - "country": "pl", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^TVN Meteo$" - }, - { - "name": "TVN Style", - "country": "pl", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^TVN Style$" - }, - { - "name": "TVN Turbo", - "country": "pl", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^TVN Turbo$" - }, - { - "name": "TVN Warszawa", - "country": "pl", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^TVN Warszawa$" - }, - { - "name": "TVN", - "country": "pl", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^TVN$" - }, - { - "name": "V Sport", - "country": "no", - "dmca_notice": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", - "regex": "^V Sport" - }, - { - "name": "Vox", - "country": "no", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^Vox$" - }, - { - "name": "VTV Cab", - "country": "kr", - "dmca_notice": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", - "regex": "^VTV( |)Cab$" - }, - { - "name": "World Discovery", - "country": "us", - "dmca_notice": "https://github.com/iptv-org/iptv/issues/1831", - "regex": "^World Discovery$" - }, - { - "name": "Xee", - "country": "dk", - "dmca_notice": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", - "regex": "^Xee$" - }, - { - "name": "XtvN", - "country": "kr", - "dmca_notice": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", - "regex": "^X( |)tvN$" - } -] diff --git a/scripts/data/blocklist.json b/scripts/data/blocklist.json new file mode 100644 index 0000000000..c1c91775d8 --- /dev/null +++ b/scripts/data/blocklist.json @@ -0,0 +1,632 @@ +[ + { + "name": "Animal Planet", + "country": "US", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^Animal Planet\\b" + }, + { + "name": "Arena 4", + "country": "HU", + "reference": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", + "regex": "^Arena( |)4\\b" + }, + { + "name": "Asian Food Network", + "country": "SG", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^Asian Food Network\\b" + }, + { + "name": "Astro SuperSport", + "country": "MY", + "reference": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", + "regex": "^Astro SuperSport\\b" + }, + { + "name": "Azteca 7", + "country": "MX", + "reference": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", + "regex": "^Azteca 7\\b" + }, + { + "name": "beIN Sports", + "country": "QA", + "reference": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", + "regex": "^beIN Sports\\b" + }, + { + "name": "Canal+ Sport", + "country": "FR", + "reference": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", + "regex": "^Canal( |)+ Sport\\b" + }, + { + "name": "Cooking Channel", + "country": "US", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^Cooking Channel\\b" + }, + { + "name": "DAZN", + "country": "UK", + "reference": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", + "regex": "^DAZN($| [1-4] .*)\\b" + }, + { + "name": "Diema Sport", + "country": "BG", + "reference": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", + "regex": "^Diema Sport\\b" + }, + { + "name": "Digi Sport", + "country": "RO", + "reference": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", + "regex": "^Digi Sport\\b" + }, + { + "name": "Discovery Asia", + "country": "US", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^Discovery Asia\\b" + }, + { + "name": "Discovery Channel", + "country": "US", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^Discovery Channel\\b" + }, + { + "name": "Discovery Civiliztion", + "country": "US", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^Discovery Civiliztion\\b" + }, + { + "name": "Discovery en Espanol", + "country": "US", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^Discovery en Espanol\\b" + }, + { + "name": "Discovery Family", + "country": "US", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^Discovery Family\\b" + }, + { + "name": "Discovery Historia", + "country": "US", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^Discovery Historia\\b" + }, + { + "name": "Discovery History", + "country": "US", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^Discovery History\\b" + }, + { + "name": "Discovery Home and Health", + "country": "US", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^Discovery Home and Health\\b" + }, + { + "name": "Discovery Life", + "country": "US", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^Discovery Life\\b" + }, + { + "name": "Discovery Science", + "country": "US", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^Discovery Science\\b" + }, + { + "name": "Discovery Shed", + "country": "US", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^Discovery Shed\\b" + }, + { + "name": "Discovery Theater", + "country": "US", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^Discovery Theater\\b" + }, + { + "name": "Discovery Travel and Living", + "country": "US", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^Discovery Travel and Living\\b" + }, + { + "name": "Discovery Turbo Xtra", + "country": "US", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^Discovery Turbo Xtra\\b" + }, + { + "name": "Discovery World", + "country": "US", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^Discovery World\\b" + }, + { + "name": "Discovery", + "country": "US", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^Discovery\\b" + }, + { + "name": "DIY Network", + "country": "US", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^DIY Network\\b" + }, + { + "name": "DKiss", + "country": "ES", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^DKiss\\b" + }, + { + "name": "DMax", + "country": "US", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^DMax\\b" + }, + { + "name": "Eleven Sports", + "country": "UK", + "reference": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", + "regex": "^Eleven Sports($| [1-6] .*)\\b" + }, + { + "name": "ESPN", + "country": "US", + "reference": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", + "regex": "^ESPN($|[1-3]| .*)\\b" + }, + { + "name": "Eurosport", + "country": "FR", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^Eurosport($| [1-2])\\b" + }, + { + "name": "eve", + "country": "US", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^eve\\b" + }, + { + "name": "Familia Discovery", + "country": "US", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^Familia Discovery\\b" + }, + { + "name": "Fatafeat", + "country": "EG", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^Fatafeat\\b" + }, + { + "name": "FEM", + "country": "NO", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^FEM\\b" + }, + { + "name": "Fine Living", + "country": "US", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^Fine Living\\b" + }, + { + "name": "Flow Sports", + "country": "UK", + "reference": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", + "regex": "^Flow Sports\\b" + }, + { + "name": "Food Network", + "country": "US", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^Food Network\\b" + }, + { + "name": "food tv", + "country": "US", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^food( |)tv\\b" + }, + { + "name": "Fox Sports", + "country": "US", + "reference": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", + "regex": "^Fox Sports\\b" + }, + { + "name": "Frisbee", + "country": "IT", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^Frisbee\\b" + }, + { + "name": "Futbol", + "country": "TJ", + "reference": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", + "regex": "^(Futbol|Football TV|ТВ Футбол|Футбол)\\b" + }, + { + "name": "GTV Sports", + "country": "GH", + "reference": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", + "regex": "^GTV Sports\\b" + }, + { + "name": "Giallo", + "country": "IT", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^Giallo\\b" + }, + { + "name": "GolfTV", + "country": "US", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^Golf( |)TV\\b" + }, + { + "name": "HGTV", + "country": "US", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^HGTV\\b" + }, + { + "name": "Investigation Discovery", + "country": "US", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^(Investigation Discovery|ID Investigation Discovery|ID Investigation|ID)\\b" + }, + { + "name": "K2", + "country": "IT", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^K2\\b" + }, + { + "name": "Living Channel", + "country": "NZ", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^Living Channel\\b" + }, + { + "name": "LookSport", + "country": "RO", + "reference": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", + "regex": "^Look( |)Sport\\b" + }, + { + "name": "Mango", + "country": "US", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^Mango\\b" + }, + { + "name": "Match!", + "country": "RU", + "reference": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", + "regex": "^(Match|Матч)\\b" + }, + { + "name": "Motortrend", + "country": "US", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^Motortrend\\b" + }, + { + "name": "Mola TV", + "country": "ID", + "reference": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", + "regex": "^Mola TV($| .*)\\b" + }, + { + "name": "Movistar Liga de Campeones", + "country": "ES", + "reference": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", + "regex": "^Movistar Liga de Campeones [1-8]\\b" + }, + { + "name": "Nova Sport", + "country": "CZ", + "reference": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", + "regex": "^Nova Sport [1-3]\\b" + }, + { + "name": "Nova Sports", + "country": "GR", + "reference": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", + "regex": "^Nova Sports [1-6]\\b" + }, + { + "name": "Nove", + "country": "IT", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^Nove($| .*)\\b" + }, + { + "name": "PPTV HD 36", + "country": "TH", + "reference": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", + "regex": "^PPTV($| HD)\\b" + }, + { + "name": "One", + "country": "IL", + "reference": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", + "regex": "^One\\b" + }, + { + "name": "OWN", + "country": "US", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^(OWN|Oprah)\\b" + }, + { + "name": "Quest Red", + "country": "US", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^Quest Red\\b" + }, + { + "name": "Quest", + "country": "US", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^Quest\\b" + }, + { + "name": "Real Time", + "country": "US", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^Real Time\\b" + }, + { + "name": "SABC Sport ", + "country": "ZA", + "reference": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", + "regex": "^SABC Sport\\b" + }, + { + "name": "Setanta Sports", + "country": "IE", + "reference": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", + "regex": "^Setanta Sports($| .*)\\b" + }, + { + "name": "Sky Sports", + "country": "UK", + "reference": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", + "regex": "^Sky Sports\\b" + }, + { + "name": "Sky Sport Bundesliga", + "country": "DE", + "reference": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", + "regex": "^Sky Sport Bundesliga [0-9]+\\b" + }, + { + "name": "Sky TG24", + "country": "IT", + "reference": "https://github.com/iptv-org/iptv/pull/2294", + "regex": "^Sky TG24\\b" + }, + { + "name": "Sony Ten", + "country": "IN", + "reference": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", + "regex": "^Sony Ten [1-4]\\b" + }, + { + "name": "Spíler TV", + "country": "HU", + "reference": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", + "regex": "^Spíler( |[1-2] )TV\\b" + }, + { + "name": "Šport TV", + "country": "SI", + "reference": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", + "regex": "^(Šport|Sport) TV\\b" + }, + { + "name": "Sport Klub", + "country": "HU", + "reference": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", + "regex": "^(Sport Klub|SK[1-9])\\b" + }, + { + "name": "SportsNet", + "country": "CA", + "reference": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", + "regex": "^SportsNet\\b" + }, + { + "name": "StarHub TV", + "country": "SG", + "reference": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", + "regex": "^StarHub TV\\b" + }, + { + "name": "StarSat", + "country": "ZA", + "reference": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", + "regex": "^StarSat\\b" + }, + { + "name": "StarTimes TV", + "country": "MZ", + "reference": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", + "regex": "^StarTimes TV\\b" + }, + { + "name": "SuperSport", + "country": "AL", + "reference": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", + "regex": "^SuperSport [1-7]\\b" + }, + { + "name": "Tivibu Spor", + "country": "TR", + "reference": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", + "regex": "^Tivibu Spor\\b" + }, + { + "name": "TLC", + "country": "US", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^TLC\\b" + }, + { + "name": "Trvl Channel", + "country": "US", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^Trvl Channel\\b" + }, + { + "name": "TSN", + "country": "MT", + "reference": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", + "regex": "^TSN\\b" + }, + { + "name": "TTV", + "country": "PL", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^TTV\\b" + }, + { + "name": "TV Norge", + "country": "NO", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^TV Norge\\b" + }, + { + "name": "TV Varzish", + "country": "TJ", + "reference": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", + "regex": "^(TV Varzish|Varzish TV|Варзиш ТВ)\\b" + }, + { + "name": "TV3 Sport", + "country": "DK", + "reference": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", + "regex": "^TV( |)3 Sport\\b" + }, + { + "name": "tvN Asia", + "country": "KR", + "reference": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", + "regex": "^tvN($| Asia)\\b" + }, + { + "name": "Tvn 24 Bis", + "country": "PL", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^Tvn(| )24 Bis\\b" + }, + { + "name": "TVN 24", + "country": "PL", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^TVN 24\\b" + }, + { + "name": "Tvn 7", + "country": "PL", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^Tvn 7\\b" + }, + { + "name": "TVN Extra", + "country": "PL", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^TVN Extra\\b" + }, + { + "name": "TVN Fabula", + "country": "PL", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^TVN Fabula\\b" + }, + { + "name": "TVN Meteo", + "country": "PL", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^TVN Meteo\\b" + }, + { + "name": "TVN Style", + "country": "PL", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^TVN Style\\b" + }, + { + "name": "TVN Turbo", + "country": "PL", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^TVN Turbo\\b" + }, + { + "name": "TVN Warszawa", + "country": "PL", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^TVN Warszawa\\b" + }, + { + "name": "TVN", + "country": "PL", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^TVN\\b" + }, + { + "name": "V Sport", + "country": "NO", + "reference": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", + "regex": "^V Sport\\b" + }, + { + "name": "Vox", + "country": "NO", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^Vox\\b" + }, + { + "name": "VTV Cab", + "country": "KR", + "reference": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", + "regex": "^VTV( |)Cab\\b" + }, + { + "name": "World Discovery", + "country": "US", + "reference": "https://github.com/iptv-org/iptv/issues/1831", + "regex": "^World Discovery\\b" + }, + { + "name": "Xee", + "country": "DK", + "reference": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", + "regex": "^Xee\\b" + }, + { + "name": "XtvN", + "country": "KR", + "reference": "https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md", + "regex": "^X( |)tvN\\b" + } +] From a3a6340c1b5db7cf3acaffa379049464d6c9b211 Mon Sep 17 00:00:00 2001 From: Aleksandr Statciuk Date: Sun, 12 Dec 2021 07:11:16 +0300 Subject: [PATCH 17/34] Create .gitignore --- scripts/data/.gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 scripts/data/.gitignore diff --git a/scripts/data/.gitignore b/scripts/data/.gitignore new file mode 100644 index 0000000000..3063886eab --- /dev/null +++ b/scripts/data/.gitignore @@ -0,0 +1 @@ +codes.json \ No newline at end of file From 5b68f73cc56a7bf71aa081282368f9b86ee82295 Mon Sep 17 00:00:00 2001 From: Aleksandr Statciuk Date: Sun, 12 Dec 2021 07:11:19 +0300 Subject: [PATCH 18/34] Update categories.json --- scripts/data/categories.json | 120 +++++++++++++++++------------------ 1 file changed, 60 insertions(+), 60 deletions(-) diff --git a/scripts/data/categories.json b/scripts/data/categories.json index f15b795c5c..41a23b1b44 100644 --- a/scripts/data/categories.json +++ b/scripts/data/categories.json @@ -1,147 +1,147 @@ -[ - { +{ + "auto": { "name": "Auto", - "id": "auto", + "slug": "auto", "nsfw": false }, - { + "animation": { "name": "Animation", - "id": "animation", + "slug": "animation", "nsfw": false }, - { + "business": { "name": "Business", - "id": "business", + "slug": "business", "nsfw": false }, - { + "classic": { "name": "Classic", - "id": "classic", + "slug": "classic", "nsfw": false }, - { + "comedy": { "name": "Comedy", - "id": "comedy", + "slug": "comedy", "nsfw": false }, - { + "cooking": { "name": "Cooking", - "id": "cooking", + "slug": "cooking", "nsfw": false }, - { + "culture": { "name": "Culture", - "id": "culture", + "slug": "culture", "nsfw": false }, - { + "documentary": { "name": "Documentary", - "id": "documentary", + "slug": "documentary", "nsfw": false }, - { + "education": { "name": "Education", - "id": "education", + "slug": "education", "nsfw": false }, - { + "entertainment": { "name": "Entertainment", - "id": "entertainment", + "slug": "entertainment", "nsfw": false }, - { + "family": { "name": "Family", - "id": "family", + "slug": "family", "nsfw": false }, - { + "general": { "name": "General", - "id": "general", + "slug": "general", "nsfw": false }, - { + "kids": { "name": "Kids", - "id": "kids", + "slug": "kids", "nsfw": false }, - { + "legislative": { "name": "Legislative", - "id": "legislative", + "slug": "legislative", "nsfw": false }, - { + "lifestyle": { "name": "Lifestyle", - "id": "lifestyle", + "slug": "lifestyle", "nsfw": false }, - { + "local": { "name": "Local", - "id": "local", + "slug": "local", "nsfw": false }, - { + "movies": { "name": "Movies", - "id": "movies", + "slug": "movies", "nsfw": false }, - { + "music": { "name": "Music", - "id": "music", + "slug": "music", "nsfw": false }, - { + "news": { "name": "News", - "id": "news", + "slug": "news", "nsfw": false }, - { + "outdoor": { "name": "Outdoor", - "id": "outdoor", + "slug": "outdoor", "nsfw": false }, - { + "relax": { "name": "Relax", - "id": "relax", + "slug": "relax", "nsfw": false }, - { + "religious": { "name": "Religious", - "id": "religious", + "slug": "religious", "nsfw": false }, - { + "series": { "name": "Series", - "id": "series", + "slug": "series", "nsfw": false }, - { + "science": { "name": "Science", - "id": "science", + "slug": "science", "nsfw": false }, - { + "shop": { "name": "Shop", - "id": "shop", + "slug": "shop", "nsfw": false }, - { + "sports": { "name": "Sports", - "id": "sports", + "slug": "sports", "nsfw": false }, - { + "travel": { "name": "Travel", - "id": "travel", + "slug": "travel", "nsfw": false }, - { + "weather": { "name": "Weather", - "id": "weather", + "slug": "weather", "nsfw": false }, - { + "xxx": { "name": "XXX", - "id": "xxx", + "slug": "xxx", "nsfw": true } -] +} From 666e40a9bdd972c736e23cf0cf6537d3238f6b0a Mon Sep 17 00:00:00 2001 From: Aleksandr Statciuk Date: Sun, 12 Dec 2021 07:11:21 +0300 Subject: [PATCH 19/34] Update countries.json --- scripts/data/countries.json | 1246 +++++++---------------------------- 1 file changed, 254 insertions(+), 992 deletions(-) diff --git a/scripts/data/countries.json b/scripts/data/countries.json index 2e4f2b85f4..53286657c5 100644 --- a/scripts/data/countries.json +++ b/scripts/data/countries.json @@ -1,1002 +1,264 @@ { - "AD": { - "name": "Andorra", - "languages": ["cat"] - }, - "AE": { - "name": "United Arab Emirates", - "languages": ["ara"] - }, - "AF": { - "name": "Afghanistan", - "languages": ["pus", "uzb", "tuk"] - }, - "AG": { - "name": "Antigua and Barbuda", - "languages": ["eng"] - }, - "AI": { - "name": "Anguilla", - "languages": ["eng"] - }, - "AL": { - "name": "Albania", - "languages": ["sqi"] - }, - "AM": { - "name": "Armenia", - "languages": ["hye", "rus"] - }, - "AO": { - "name": "Angola", - "languages": ["por"] - }, - "AQ": { - "name": "Antarctica", - "languages": [] - }, - "AR": { - "name": "Argentina", - "languages": ["spa", "grn"] - }, - "AS": { - "name": "American Samoa", - "languages": ["eng", "smo"] - }, - "AT": { - "name": "Austria", - "languages": ["deu"] - }, - "AU": { - "name": "Australia", - "languages": ["eng"] - }, - "AW": { - "name": "Aruba", - "languages": ["nld", "pan"] - }, - "AX": { - "name": "Åland", - "languages": ["swe"] - }, - "AZ": { - "name": "Azerbaijan", - "languages": ["aze"] - }, - "BA": { - "name": "Bosnia and Herzegovina", - "languages": ["bos", "hrv", "srp"] - }, - "BB": { - "name": "Barbados", - "languages": ["eng"] - }, - "BD": { - "name": "Bangladesh", - "languages": ["ben"] - }, - "BE": { - "name": "Belgium", - "languages": ["nld", "fra", "deu"] - }, - "BF": { - "name": "Burkina Faso", - "languages": ["fra", "ful"] - }, - "BG": { - "name": "Bulgaria", - "languages": ["bul"] - }, - "BH": { - "name": "Bahrain", - "languages": ["ara"] - }, - "BI": { - "name": "Burundi", - "languages": ["fra", "run"] - }, - "BJ": { - "name": "Benin", - "languages": ["fra"] - }, - "BL": { - "name": "Saint Barthélemy", - "languages": ["fra"] - }, - "BM": { - "name": "Bermuda", - "languages": ["eng"] - }, - "BN": { - "name": "Brunei", - "languages": ["msa"] - }, - "BO": { - "name": "Bolivia", - "languages": ["spa", "aym", "que"] - }, - "BQ": { - "name": "Bonaire", - "languages": ["nld"] - }, - "BR": { - "name": "Brazil", - "languages": ["por"] - }, - "BS": { - "name": "Bahamas", - "languages": ["eng"] - }, - "BT": { - "name": "Bhutan", - "languages": ["dzo"] - }, - "BV": { - "name": "Bouvet Island", - "languages": ["nor", "nob", "nno"] - }, - "BW": { - "name": "Botswana", - "languages": ["eng", "tsn"] - }, - "BY": { - "name": "Belarus", - "languages": ["bel", "rus"] - }, - "BZ": { - "name": "Belize", - "languages": ["eng", "spa"] - }, - "CA": { - "name": "Canada", - "languages": ["eng", "fra"] - }, - "CC": { - "name": "Cocos [Keeling] Islands", - "languages": ["eng"] - }, + "AD": { "name": "Andorra", "code": "AD", "lang": "cat" }, + "AE": { "name": "United Arab Emirates", "code": "AE", "lang": "ara" }, + "AF": { "name": "Afghanistan", "code": "AF", "lang": "pus" }, + "AG": { "name": "Antigua and Barbuda", "code": "AG", "lang": "eng" }, + "AI": { "name": "Anguilla", "code": "AI", "lang": "eng" }, + "AL": { "name": "Albania", "code": "AL", "lang": "sqi" }, + "AM": { "name": "Armenia", "code": "AM", "lang": "hye" }, + "AO": { "name": "Angola", "code": "AO", "lang": "por" }, + "AQ": { "name": "Antarctica", "code": "AQ", "lang": null }, + "AR": { "name": "Argentina", "code": "AR", "lang": "spa" }, + "AS": { "name": "American Samoa", "code": "AS", "lang": "eng" }, + "AT": { "name": "Austria", "code": "AT", "lang": "deu" }, + "AU": { "name": "Australia", "code": "AU", "lang": "eng" }, + "AW": { "name": "Aruba", "code": "AW", "lang": "nld" }, + "AX": { "name": "Åland", "code": "AX", "lang": "swe" }, + "AZ": { "name": "Azerbaijan", "code": "AZ", "lang": "aze" }, + "BA": { "name": "Bosnia and Herzegovina", "code": "BA", "lang": "bos" }, + "BB": { "name": "Barbados", "code": "BB", "lang": "eng" }, + "BD": { "name": "Bangladesh", "code": "BD", "lang": "ben" }, + "BE": { "name": "Belgium", "code": "BE", "lang": "nld" }, + "BF": { "name": "Burkina Faso", "code": "BF", "lang": "fra" }, + "BG": { "name": "Bulgaria", "code": "BG", "lang": "bul" }, + "BH": { "name": "Bahrain", "code": "BH", "lang": "ara" }, + "BI": { "name": "Burundi", "code": "BI", "lang": "fra" }, + "BJ": { "name": "Benin", "code": "BJ", "lang": "fra" }, + "BL": { "name": "Saint Barthélemy", "code": "BL", "lang": "fra" }, + "BM": { "name": "Bermuda", "code": "BM", "lang": "eng" }, + "BN": { "name": "Brunei", "code": "BN", "lang": "msa" }, + "BO": { "name": "Bolivia", "code": "BO", "lang": "spa" }, + "BQ": { "name": "Bonaire", "code": "BQ", "lang": "nld" }, + "BR": { "name": "Brazil", "code": "BR", "lang": "por" }, + "BS": { "name": "Bahamas", "code": "BS", "lang": "eng" }, + "BT": { "name": "Bhutan", "code": "BT", "lang": "dzo" }, + "BV": { "name": "Bouvet Island", "code": "BV", "lang": "nor" }, + "BW": { "name": "Botswana", "code": "BW", "lang": "eng" }, + "BY": { "name": "Belarus", "code": "BY", "lang": "bel" }, + "BZ": { "name": "Belize", "code": "BZ", "lang": "eng" }, + "CA": { "name": "Canada", "code": "CA", "lang": "eng" }, + "CC": { "name": "Cocos [Keeling] Islands", "code": "CC", "lang": "eng" }, "CD": { "name": "Democratic Republic of the Congo", - "languages": ["fra", "lin", "kon", "swa", "lub"] - }, - "CF": { - "name": "Central African Republic", - "languages": ["fra", "sag"] - }, - "CG": { - "name": "Republic of the Congo", - "languages": ["fra", "lin"] - }, - "CH": { - "name": "Switzerland", - "languages": ["deu", "fra", "ita"] - }, - "CI": { - "name": "Ivory Coast", - "languages": ["fra"] - }, - "CK": { - "name": "Cook Islands", - "languages": ["eng"] - }, - "CL": { - "name": "Chile", - "languages": ["spa"] - }, - "CM": { - "name": "Cameroon", - "languages": ["eng", "fra"] - }, - "CN": { - "name": "China", - "languages": ["zho"] - }, - "CO": { - "name": "Colombia", - "languages": ["spa"] - }, - "CR": { - "name": "Costa Rica", - "languages": ["spa"] - }, - "CU": { - "name": "Cuba", - "languages": ["spa"] - }, - "CV": { - "name": "Cape Verde", - "languages": ["por"] - }, - "CW": { - "name": "Curacao", - "languages": ["nld", "pan", "eng"] - }, - "CX": { - "name": "Christmas Island", - "languages": ["eng"] - }, - "CY": { - "name": "Cyprus", - "languages": ["ell", "tur", "hye"] - }, - "CZ": { - "name": "Czech Republic", - "languages": ["ces", "slk"] - }, - "DE": { - "name": "Germany", - "languages": ["deu"] - }, - "DJ": { - "name": "Djibouti", - "languages": ["fra", "ara"] - }, - "DK": { - "name": "Denmark", - "languages": ["dan"] - }, - "DM": { - "name": "Dominica", - "languages": ["eng"] - }, - "DO": { - "name": "Dominican Republic", - "languages": ["spa"] - }, - "DZ": { - "name": "Algeria", - "languages": ["ara"] - }, - "EC": { - "name": "Ecuador", - "languages": ["spa"] - }, - "EE": { - "name": "Estonia", - "languages": ["est"] - }, - "EG": { - "name": "Egypt", - "languages": ["ara"] - }, - "EH": { - "name": "Western Sahara", - "languages": ["spa"] - }, - "ER": { - "name": "Eritrea", - "languages": ["tir", "ara", "eng"] - }, - "ES": { - "name": "Spain", - "languages": ["spa", "eus", "cat", "glg", "oci"] - }, - "ET": { - "name": "Ethiopia", - "languages": ["amh"] - }, - "FI": { - "name": "Finland", - "languages": ["fin", "swe"] - }, - "FJ": { - "name": "Fiji", - "languages": ["eng", "fij", "hin", "urd"] - }, - "FK": { - "name": "Falkland Islands", - "languages": ["eng"] - }, - "FM": { - "name": "Micronesia", - "languages": ["eng"] - }, - "FO": { - "name": "Faroe Islands", - "languages": ["fao"] - }, - "FR": { - "name": "France", - "languages": ["fra"] - }, - "GA": { - "name": "Gabon", - "languages": ["fra"] - }, - "UK": { - "name": "United Kingdom", - "languages": ["eng"] - }, - "GD": { - "name": "Grenada", - "languages": ["eng"] - }, - "GE": { - "name": "Georgia", - "languages": ["kat"] - }, - "GF": { - "name": "French Guiana", - "languages": ["fra"] - }, - "GG": { - "name": "Guernsey", - "languages": ["eng", "fra"] - }, - "GH": { - "name": "Ghana", - "languages": ["eng"] - }, - "GI": { - "name": "Gibraltar", - "languages": ["eng"] - }, - "GL": { - "name": "Greenland", - "languages": ["kal"] - }, - "GM": { - "name": "Gambia", - "languages": ["eng"] - }, - "GN": { - "name": "Guinea", - "languages": ["fra", "ful"] - }, - "GP": { - "name": "Guadeloupe", - "languages": ["fra"] - }, - "GQ": { - "name": "Equatorial Guinea", - "languages": ["spa", "fra"] - }, - "GR": { - "name": "Greece", - "languages": ["ell"] + "code": "CD", + "lang": "fra" }, + "CF": { "name": "Central African Republic", "code": "CF", "lang": "fra" }, + "CG": { "name": "Republic of the Congo", "code": "CG", "lang": "fra" }, + "CH": { "name": "Switzerland", "code": "CH", "lang": "deu" }, + "CI": { "name": "Ivory Coast", "code": "CI", "lang": "fra" }, + "CK": { "name": "Cook Islands", "code": "CK", "lang": "eng" }, + "CL": { "name": "Chile", "code": "CL", "lang": "spa" }, + "CM": { "name": "Cameroon", "code": "CM", "lang": "eng" }, + "CN": { "name": "China", "code": "CN", "lang": "zho" }, + "CO": { "name": "Colombia", "code": "CO", "lang": "spa" }, + "CR": { "name": "Costa Rica", "code": "CR", "lang": "spa" }, + "CU": { "name": "Cuba", "code": "CU", "lang": "spa" }, + "CV": { "name": "Cape Verde", "code": "CV", "lang": "por" }, + "CW": { "name": "Curacao", "code": "CW", "lang": "nld" }, + "CX": { "name": "Christmas Island", "code": "CX", "lang": "eng" }, + "CY": { "name": "Cyprus", "code": "CY", "lang": "ell" }, + "CZ": { "name": "Czech Republic", "code": "CZ", "lang": "ces" }, + "DE": { "name": "Germany", "code": "DE", "lang": "deu" }, + "DJ": { "name": "Djibouti", "code": "DJ", "lang": "fra" }, + "DK": { "name": "Denmark", "code": "DK", "lang": "dan" }, + "DM": { "name": "Dominica", "code": "DM", "lang": "eng" }, + "DO": { "name": "Dominican Republic", "code": "DO", "lang": "spa" }, + "DZ": { "name": "Algeria", "code": "DZ", "lang": "ara" }, + "EC": { "name": "Ecuador", "code": "EC", "lang": "spa" }, + "EE": { "name": "Estonia", "code": "EE", "lang": "est" }, + "EG": { "name": "Egypt", "code": "EG", "lang": "ara" }, + "EH": { "name": "Western Sahara", "code": "EH", "lang": "spa" }, + "ER": { "name": "Eritrea", "code": "ER", "lang": "tir" }, + "ES": { "name": "Spain", "code": "ES", "lang": "spa" }, + "ET": { "name": "Ethiopia", "code": "ET", "lang": "amh" }, + "FI": { "name": "Finland", "code": "FI", "lang": "fin" }, + "FJ": { "name": "Fiji", "code": "FJ", "lang": "eng" }, + "FK": { "name": "Falkland Islands", "code": "FK", "lang": "eng" }, + "FM": { "name": "Micronesia", "code": "FM", "lang": "eng" }, + "FO": { "name": "Faroe Islands", "code": "FO", "lang": "fao" }, + "FR": { "name": "France", "code": "FR", "lang": "fra" }, + "GA": { "name": "Gabon", "code": "GA", "lang": "fra" }, + "UK": { "name": "United Kingdom", "code": "UK", "lang": "eng" }, + "GD": { "name": "Grenada", "code": "GD", "lang": "eng" }, + "GE": { "name": "Georgia", "code": "GE", "lang": "kat" }, + "GF": { "name": "French Guiana", "code": "GF", "lang": "fra" }, + "GG": { "name": "Guernsey", "code": "GG", "lang": "eng" }, + "GH": { "name": "Ghana", "code": "GH", "lang": "eng" }, + "GI": { "name": "Gibraltar", "code": "GI", "lang": "eng" }, + "GL": { "name": "Greenland", "code": "GL", "lang": "kal" }, + "GM": { "name": "Gambia", "code": "GM", "lang": "eng" }, + "GN": { "name": "Guinea", "code": "GN", "lang": "fra" }, + "GP": { "name": "Guadeloupe", "code": "GP", "lang": "fra" }, + "GQ": { "name": "Equatorial Guinea", "code": "GQ", "lang": "spa" }, + "GR": { "name": "Greece", "code": "GR", "lang": "ell" }, "GS": { "name": "South Georgia and the South Sandwich Islands", - "languages": ["eng"] - }, - "GT": { - "name": "Guatemala", - "languages": ["spa"] - }, - "GU": { - "name": "Guam", - "languages": ["eng", "cha", "spa"] - }, - "GW": { - "name": "Guinea-Bissau", - "languages": ["por"] - }, - "GY": { - "name": "Guyana", - "languages": ["eng"] - }, - "HK": { - "name": "Hong Kong", - "languages": ["zho", "eng"] - }, - "HM": { - "name": "Heard Island and McDonald Islands", - "languages": ["eng"] - }, - "HN": { - "name": "Honduras", - "languages": ["spa"] - }, - "HR": { - "name": "Croatia", - "languages": ["hrv"] - }, - "HT": { - "name": "Haiti", - "languages": ["fra", "hat"] - }, - "HU": { - "name": "Hungary", - "languages": ["hun"] - }, - "ID": { - "name": "Indonesia", - "languages": ["ind"] - }, - "IE": { - "name": "Ireland", - "languages": ["gle", "eng"] - }, - "IL": { - "name": "Israel", - "languages": ["heb", "ara"] - }, - "IM": { - "name": "Isle of Man", - "languages": ["eng", "glv"] - }, - "IN": { - "name": "India", - "languages": ["hin", "eng"] - }, - "IO": { - "name": "British Indian Ocean Territory", - "languages": ["eng"] - }, - "IQ": { - "name": "Iraq", - "languages": ["ara", "kur"] - }, - "IR": { - "name": "Iran", - "languages": ["fas"] - }, - "IS": { - "name": "Iceland", - "languages": ["isl"] - }, - "IT": { - "name": "Italy", - "languages": ["ita"] - }, - "JE": { - "name": "Jersey", - "languages": ["eng", "fra"] - }, - "JM": { - "name": "Jamaica", - "languages": ["eng"] - }, - "JO": { - "name": "Jordan", - "languages": ["ara"] - }, - "JP": { - "name": "Japan", - "languages": ["jpn"] - }, - "KE": { - "name": "Kenya", - "languages": ["eng", "swa"] - }, - "KG": { - "name": "Kyrgyzstan", - "languages": ["kir", "rus"] - }, - "KH": { - "name": "Cambodia", - "languages": ["khm"] - }, - "KI": { - "name": "Kiribati", - "languages": ["eng"] - }, - "KM": { - "name": "Comoros", - "languages": ["ara", "fra"] - }, - "KN": { - "name": "Saint Kitts and Nevis", - "languages": ["eng"] - }, - "KP": { - "name": "North Korea", - "languages": ["kor"] - }, - "KR": { - "name": "South Korea", - "languages": ["kor"] - }, - "KW": { - "name": "Kuwait", - "languages": ["ara"] - }, - "KY": { - "name": "Cayman Islands", - "languages": ["eng"] - }, - "KZ": { - "name": "Kazakhstan", - "languages": ["kaz", "rus"] - }, - "LA": { - "name": "Laos", - "languages": ["lao"] - }, - "LB": { - "name": "Lebanon", - "languages": ["ara", "fra"] - }, - "LC": { - "name": "Saint Lucia", - "languages": ["eng"] - }, - "LI": { - "name": "Liechtenstein", - "languages": ["deu"] - }, - "LK": { - "name": "Sri Lanka", - "languages": ["sin", "tam"] - }, - "LR": { - "name": "Liberia", - "languages": ["eng"] - }, - "LS": { - "name": "Lesotho", - "languages": ["eng", "sot"] - }, - "LT": { - "name": "Lithuania", - "languages": ["lit"] - }, - "LU": { - "name": "Luxembourg", - "languages": ["fra", "deu", "ltz"] - }, - "LV": { - "name": "Latvia", - "languages": ["lav"] - }, - "LY": { - "name": "Libya", - "languages": ["ara"] - }, - "MA": { - "name": "Morocco", - "languages": ["ara"] - }, - "MC": { - "name": "Monaco", - "languages": ["fra"] - }, - "MD": { - "name": "Moldova", - "languages": ["ron"] - }, - "ME": { - "name": "Montenegro", - "languages": ["srp", "bos", "sqi", "hrv"] - }, - "MF": { - "name": "Saint Martin", - "languages": ["eng", "fra", "nld"] - }, - "MG": { - "name": "Madagascar", - "languages": ["fra", "mlg"] - }, - "MH": { - "name": "Marshall Islands", - "languages": ["eng", "mah"] - }, - "MK": { - "name": "North Macedonia", - "languages": ["mkd"] - }, - "ML": { - "name": "Mali", - "languages": ["fra"] - }, - "MM": { - "name": "Myanmar [Burma]", - "languages": ["mya"] - }, - "MN": { - "name": "Mongolia", - "languages": ["mon"] - }, - "MO": { - "name": "Macao", - "languages": ["zho", "por"] - }, - "MP": { - "name": "Northern Mariana Islands", - "languages": ["eng", "cha"] - }, - "MQ": { - "name": "Martinique", - "languages": ["fra"] - }, - "MR": { - "name": "Mauritania", - "languages": ["ara"] - }, - "MS": { - "name": "Montserrat", - "languages": ["eng"] - }, - "MT": { - "name": "Malta", - "languages": ["mlt", "eng"] - }, - "MU": { - "name": "Mauritius", - "languages": ["eng"] - }, - "MV": { - "name": "Maldives", - "languages": ["div"] - }, - "MW": { - "name": "Malawi", - "languages": ["eng", "nya"] - }, - "MX": { - "name": "Mexico", - "languages": ["spa"] - }, - "MY": { - "name": "Malaysia", - "languages": ["msa"] - }, - "MZ": { - "name": "Mozambique", - "languages": ["por"] - }, - "NA": { - "name": "Namibia", - "languages": ["eng", "afr"] - }, - "NC": { - "name": "New Caledonia", - "languages": ["fra"] - }, - "NE": { - "name": "Niger", - "languages": ["fra"] - }, - "NF": { - "name": "Norfolk Island", - "languages": ["eng"] - }, - "NG": { - "name": "Nigeria", - "languages": ["eng"] - }, - "NI": { - "name": "Nicaragua", - "languages": ["spa"] - }, - "NL": { - "name": "Netherlands", - "languages": ["nld"] - }, - "NO": { - "name": "Norway", - "languages": ["nor", "nob", "nno"] - }, - "NP": { - "name": "Nepal", - "languages": ["nep"] - }, - "NR": { - "name": "Nauru", - "languages": ["eng", "nau"] - }, - "NU": { - "name": "Niue", - "languages": ["eng"] - }, - "NZ": { - "name": "New Zealand", - "languages": ["eng", "mri"] - }, - "OM": { - "name": "Oman", - "languages": ["ara"] - }, - "PA": { - "name": "Panama", - "languages": ["spa"] - }, - "PE": { - "name": "Peru", - "languages": ["spa"] - }, - "PF": { - "name": "French Polynesia", - "languages": ["fra"] - }, - "PG": { - "name": "Papua New Guinea", - "languages": ["eng"] - }, - "PH": { - "name": "Philippines", - "languages": ["eng"] - }, - "PK": { - "name": "Pakistan", - "languages": ["eng", "urd"] - }, - "PL": { - "name": "Poland", - "languages": ["pol"] - }, - "PM": { - "name": "Saint Pierre and Miquelon", - "languages": ["fra"] - }, - "PN": { - "name": "Pitcairn Islands", - "languages": ["eng"] - }, - "PR": { - "name": "Puerto Rico", - "languages": ["spa", "eng"] - }, - "PS": { - "name": "Palestine", - "languages": ["ara"] - }, - "PT": { - "name": "Portugal", - "languages": ["por"] - }, - "PW": { - "name": "Palau", - "languages": ["eng"] - }, - "PY": { - "name": "Paraguay", - "languages": ["spa", "grn"] - }, - "QA": { - "name": "Qatar", - "languages": ["ara"] - }, - "RE": { - "name": "Réunion", - "languages": ["fra"] - }, - "RO": { - "name": "Romania", - "languages": ["ron"] - }, - "RS": { - "name": "Serbia", - "languages": ["srp"] - }, - "RU": { - "name": "Russia", - "languages": ["rus"] - }, - "RW": { - "name": "Rwanda", - "languages": ["kin", "eng", "fra"] - }, - "SA": { - "name": "Saudi Arabia", - "languages": ["ara"] - }, - "SB": { - "name": "Solomon Islands", - "languages": ["eng"] - }, - "SC": { - "name": "Seychelles", - "languages": ["fra", "eng"] - }, - "SD": { - "name": "Sudan", - "languages": ["ara", "eng"] - }, - "SE": { - "name": "Sweden", - "languages": ["swe"] - }, - "SG": { - "name": "Singapore", - "languages": ["eng", "msa", "tam", "zho"] - }, - "SH": { - "name": "Saint Helena", - "languages": ["eng"] - }, - "SI": { - "name": "Slovenia", - "languages": ["slv"] - }, - "SJ": { - "name": "Svalbard and Jan Mayen", - "languages": ["nor"] - }, - "SK": { - "name": "Slovakia", - "languages": ["slk"] - }, - "SL": { - "name": "Sierra Leone", - "languages": ["eng"] - }, - "SM": { - "name": "San Marino", - "languages": ["ita"] - }, - "SN": { - "name": "Senegal", - "languages": ["fra"] - }, - "SO": { - "name": "Somalia", - "languages": ["som", "ara"] - }, - "SR": { - "name": "Suriname", - "languages": ["nld"] - }, - "SS": { - "name": "South Sudan", - "languages": ["eng"] - }, - "ST": { - "name": "São Tomé and Príncipe", - "languages": ["por"] - }, - "SV": { - "name": "El Salvador", - "languages": ["spa"] - }, - "SX": { - "name": "Sint Maarten", - "languages": ["nld", "eng"] - }, - "SY": { - "name": "Syria", - "languages": ["ara"] - }, - "SZ": { - "name": "Swaziland", - "languages": ["eng", "ssw"] - }, - "TC": { - "name": "Turks and Caicos Islands", - "languages": ["eng"] - }, - "TD": { - "name": "Chad", - "languages": ["fra", "ara"] - }, - "TF": { - "name": "French Southern Territories", - "languages": ["fra"] - }, - "TG": { - "name": "Togo", - "languages": ["fra"] - }, - "TH": { - "name": "Thailand", - "languages": ["tha"] - }, - "TJ": { - "name": "Tajikistan", - "languages": ["tgk", "rus"] - }, - "TK": { - "name": "Tokelau", - "languages": ["eng"] - }, - "TL": { - "name": "East Timor", - "languages": ["por"] - }, - "TM": { - "name": "Turkmenistan", - "languages": ["tuk", "rus"] - }, - "TN": { - "name": "Tunisia", - "languages": ["ara"] - }, - "TO": { - "name": "Tonga", - "languages": ["eng", "ton"] - }, - "TR": { - "name": "Turkey", - "languages": ["tur"] - }, - "TT": { - "name": "Trinidad and Tobago", - "languages": ["eng"] - }, - "TV": { - "name": "Tuvalu", - "languages": ["eng"] - }, - "TW": { - "name": "Taiwan", - "languages": ["zho"] - }, - "TZ": { - "name": "Tanzania", - "languages": ["swa", "eng"] - }, - "UA": { - "name": "Ukraine", - "languages": ["ukr"] - }, - "UG": { - "name": "Uganda", - "languages": ["eng", "swa"] - }, - "UM": { - "name": "U.S. Minor Outlying Islands", - "languages": ["eng"] - }, - "US": { - "name": "United States", - "languages": ["eng"] - }, - "UY": { - "name": "Uruguay", - "languages": ["spa"] - }, - "UZ": { - "name": "Uzbekistan", - "languages": ["uzb", "rus"] - }, - "VA": { - "name": "Vatican City", - "languages": ["ita", "lat"] - }, - "VC": { - "name": "Saint Vincent and the Grenadines", - "languages": ["eng"] - }, - "VE": { - "name": "Venezuela", - "languages": ["spa"] - }, - "VG": { - "name": "British Virgin Islands", - "languages": ["eng"] - }, - "VI": { - "name": "U.S. Virgin Islands", - "languages": ["eng"] - }, - "VN": { - "name": "Vietnam", - "languages": ["vie"] - }, - "VU": { - "name": "Vanuatu", - "languages": ["bis", "eng", "fra"] - }, - "WF": { - "name": "Wallis and Futuna", - "languages": ["fra"] - }, - "WS": { - "name": "Samoa", - "languages": ["smo", "eng"] - }, - "XK": { - "name": "Kosovo", - "languages": ["sqi", "srp"] - }, - "YE": { - "name": "Yemen", - "languages": ["ara"] - }, - "YT": { - "name": "Mayotte", - "languages": ["fra"] - }, + "code": "GS", + "lang": "eng" + }, + "GT": { "name": "Guatemala", "code": "GT", "lang": "spa" }, + "GU": { "name": "Guam", "code": "GU", "lang": "eng" }, + "GW": { "name": "Guinea-Bissau", "code": "GW", "lang": "por" }, + "GY": { "name": "Guyana", "code": "GY", "lang": "eng" }, + "HK": { "name": "Hong Kong", "code": "HK", "lang": "zho" }, + "HM": { "name": "Heard Island and McDonald Islands", "code": "HM", "lang": "eng" }, + "HN": { "name": "Honduras", "code": "HN", "lang": "spa" }, + "HR": { "name": "Croatia", "code": "HR", "lang": "hrv" }, + "HT": { "name": "Haiti", "code": "HT", "lang": "fra" }, + "HU": { "name": "Hungary", "code": "HU", "lang": "hun" }, + "ID": { "name": "Indonesia", "code": "ID", "lang": "ind" }, + "IE": { "name": "Ireland", "code": "IE", "lang": "gle" }, + "IL": { "name": "Israel", "code": "IL", "lang": "heb" }, + "IM": { "name": "Isle of Man", "code": "IM", "lang": "eng" }, + "IN": { "name": "India", "code": "IN", "lang": "hin" }, + "IO": { "name": "British Indian Ocean Territory", "code": "IO", "lang": "eng" }, + "IQ": { "name": "Iraq", "code": "IQ", "lang": "ara" }, + "IR": { "name": "Iran", "code": "IR", "lang": "fas" }, + "IS": { "name": "Iceland", "code": "IS", "lang": "isl" }, + "IT": { "name": "Italy", "code": "IT", "lang": "ita" }, + "JE": { "name": "Jersey", "code": "JE", "lang": "eng" }, + "JM": { "name": "Jamaica", "code": "JM", "lang": "eng" }, + "JO": { "name": "Jordan", "code": "JO", "lang": "ara" }, + "JP": { "name": "Japan", "code": "JP", "lang": "jpn" }, + "KE": { "name": "Kenya", "code": "KE", "lang": "eng" }, + "KG": { "name": "Kyrgyzstan", "code": "KG", "lang": "kir" }, + "KH": { "name": "Cambodia", "code": "KH", "lang": "khm" }, + "KI": { "name": "Kiribati", "code": "KI", "lang": "eng" }, + "KM": { "name": "Comoros", "code": "KM", "lang": "ara" }, + "KN": { "name": "Saint Kitts and Nevis", "code": "KN", "lang": "eng" }, + "KP": { "name": "North Korea", "code": "KP", "lang": "kor" }, + "KR": { "name": "South Korea", "code": "KR", "lang": "kor" }, + "KW": { "name": "Kuwait", "code": "KW", "lang": "ara" }, + "KY": { "name": "Cayman Islands", "code": "KY", "lang": "eng" }, + "KZ": { "name": "Kazakhstan", "code": "KZ", "lang": "kaz" }, + "LA": { "name": "Laos", "code": "LA", "lang": "lao" }, + "LB": { "name": "Lebanon", "code": "LB", "lang": "ara" }, + "LC": { "name": "Saint Lucia", "code": "LC", "lang": "eng" }, + "LI": { "name": "Liechtenstein", "code": "LI", "lang": "deu" }, + "LK": { "name": "Sri Lanka", "code": "LK", "lang": "sin" }, + "LR": { "name": "Liberia", "code": "LR", "lang": "eng" }, + "LS": { "name": "Lesotho", "code": "LS", "lang": "eng" }, + "LT": { "name": "Lithuania", "code": "LT", "lang": "lit" }, + "LU": { "name": "Luxembourg", "code": "LU", "lang": "fra" }, + "LV": { "name": "Latvia", "code": "LV", "lang": "lav" }, + "LY": { "name": "Libya", "code": "LY", "lang": "ara" }, + "MA": { "name": "Morocco", "code": "MA", "lang": "ara" }, + "MC": { "name": "Monaco", "code": "MC", "lang": "fra" }, + "MD": { "name": "Moldova", "code": "MD", "lang": "ron" }, + "ME": { "name": "Montenegro", "code": "ME", "lang": "srp" }, + "MF": { "name": "Saint Martin", "code": "MF", "lang": "eng" }, + "MG": { "name": "Madagascar", "code": "MG", "lang": "fra" }, + "MH": { "name": "Marshall Islands", "code": "MH", "lang": "eng" }, + "MK": { "name": "North Macedonia", "code": "MK", "lang": "mkd" }, + "ML": { "name": "Mali", "code": "ML", "lang": "fra" }, + "MM": { "name": "Myanmar [Burma]", "code": "MM", "lang": "mya" }, + "MN": { "name": "Mongolia", "code": "MN", "lang": "mon" }, + "MO": { "name": "Macao", "code": "MO", "lang": "zho" }, + "MP": { "name": "Northern Mariana Islands", "code": "MP", "lang": "eng" }, + "MQ": { "name": "Martinique", "code": "MQ", "lang": "fra" }, + "MR": { "name": "Mauritania", "code": "MR", "lang": "ara" }, + "MS": { "name": "Montserrat", "code": "MS", "lang": "eng" }, + "MT": { "name": "Malta", "code": "MT", "lang": "mlt" }, + "MU": { "name": "Mauritius", "code": "MU", "lang": "eng" }, + "MV": { "name": "Maldives", "code": "MV", "lang": "div" }, + "MW": { "name": "Malawi", "code": "MW", "lang": "eng" }, + "MX": { "name": "Mexico", "code": "MX", "lang": "spa" }, + "MY": { "name": "Malaysia", "code": "MY", "lang": "msa" }, + "MZ": { "name": "Mozambique", "code": "MZ", "lang": "por" }, + "NA": { "name": "Namibia", "code": "NA", "lang": "eng" }, + "NC": { "name": "New Caledonia", "code": "NC", "lang": "fra" }, + "NE": { "name": "Niger", "code": "NE", "lang": "fra" }, + "NF": { "name": "Norfolk Island", "code": "NF", "lang": "eng" }, + "NG": { "name": "Nigeria", "code": "NG", "lang": "eng" }, + "NI": { "name": "Nicaragua", "code": "NI", "lang": "spa" }, + "NL": { "name": "Netherlands", "code": "NL", "lang": "nld" }, + "NO": { "name": "Norway", "code": "NO", "lang": "nor" }, + "NP": { "name": "Nepal", "code": "NP", "lang": "nep" }, + "NR": { "name": "Nauru", "code": "NR", "lang": "eng" }, + "NU": { "name": "Niue", "code": "NU", "lang": "eng" }, + "NZ": { "name": "New Zealand", "code": "NZ", "lang": "eng" }, + "OM": { "name": "Oman", "code": "OM", "lang": "ara" }, + "PA": { "name": "Panama", "code": "PA", "lang": "spa" }, + "PE": { "name": "Peru", "code": "PE", "lang": "spa" }, + "PF": { "name": "French Polynesia", "code": "PF", "lang": "fra" }, + "PG": { "name": "Papua New Guinea", "code": "PG", "lang": "eng" }, + "PH": { "name": "Philippines", "code": "PH", "lang": "eng" }, + "PK": { "name": "Pakistan", "code": "PK", "lang": "eng" }, + "PL": { "name": "Poland", "code": "PL", "lang": "pol" }, + "PM": { "name": "Saint Pierre and Miquelon", "code": "PM", "lang": "fra" }, + "PN": { "name": "Pitcairn Islands", "code": "PN", "lang": "eng" }, + "PR": { "name": "Puerto Rico", "code": "PR", "lang": "spa" }, + "PS": { "name": "Palestine", "code": "PS", "lang": "ara" }, + "PT": { "name": "Portugal", "code": "PT", "lang": "por" }, + "PW": { "name": "Palau", "code": "PW", "lang": "eng" }, + "PY": { "name": "Paraguay", "code": "PY", "lang": "spa" }, + "QA": { "name": "Qatar", "code": "QA", "lang": "ara" }, + "RE": { "name": "Réunion", "code": "RE", "lang": "fra" }, + "RO": { "name": "Romania", "code": "RO", "lang": "ron" }, + "RS": { "name": "Serbia", "code": "RS", "lang": "srp" }, + "RU": { "name": "Russia", "code": "RU", "lang": "rus" }, + "RW": { "name": "Rwanda", "code": "RW", "lang": "kin" }, + "SA": { "name": "Saudi Arabia", "code": "SA", "lang": "ara" }, + "SB": { "name": "Solomon Islands", "code": "SB", "lang": "eng" }, + "SC": { "name": "Seychelles", "code": "SC", "lang": "fra" }, + "SD": { "name": "Sudan", "code": "SD", "lang": "ara" }, + "SE": { "name": "Sweden", "code": "SE", "lang": "swe" }, + "SG": { "name": "Singapore", "code": "SG", "lang": "eng" }, + "SH": { "name": "Saint Helena", "code": "SH", "lang": "eng" }, + "SI": { "name": "Slovenia", "code": "SI", "lang": "slv" }, + "SJ": { "name": "Svalbard and Jan Mayen", "code": "SJ", "lang": "nor" }, + "SK": { "name": "Slovakia", "code": "SK", "lang": "slk" }, + "SL": { "name": "Sierra Leone", "code": "SL", "lang": "eng" }, + "SM": { "name": "San Marino", "code": "SM", "lang": "ita" }, + "SN": { "name": "Senegal", "code": "SN", "lang": "fra" }, + "SO": { "name": "Somalia", "code": "SO", "lang": "som" }, + "SR": { "name": "Suriname", "code": "SR", "lang": "nld" }, + "SS": { "name": "South Sudan", "code": "SS", "lang": "eng" }, + "ST": { "name": "São Tomé and Príncipe", "code": "ST", "lang": "por" }, + "SV": { "name": "El Salvador", "code": "SV", "lang": "spa" }, + "SX": { "name": "Sint Maarten", "code": "SX", "lang": "nld" }, + "SY": { "name": "Syria", "code": "SY", "lang": "ara" }, + "SZ": { "name": "Swaziland", "code": "SZ", "lang": "eng" }, + "TC": { "name": "Turks and Caicos Islands", "code": "TC", "lang": "eng" }, + "TD": { "name": "Chad", "code": "TD", "lang": "fra" }, + "TF": { "name": "French Southern Territories", "code": "TF", "lang": "fra" }, + "TG": { "name": "Togo", "code": "TG", "lang": "fra" }, + "TH": { "name": "Thailand", "code": "TH", "lang": "tha" }, + "TJ": { "name": "Tajikistan", "code": "TJ", "lang": "tgk" }, + "TK": { "name": "Tokelau", "code": "TK", "lang": "eng" }, + "TL": { "name": "East Timor", "code": "TL", "lang": "por" }, + "TM": { "name": "Turkmenistan", "code": "TM", "lang": "tuk" }, + "TN": { "name": "Tunisia", "code": "TN", "lang": "ara" }, + "TO": { "name": "Tonga", "code": "TO", "lang": "eng" }, + "TR": { "name": "Turkey", "code": "TR", "lang": "tur" }, + "TT": { "name": "Trinidad and Tobago", "code": "TT", "lang": "eng" }, + "TV": { "name": "Tuvalu", "code": "TV", "lang": "eng" }, + "TW": { "name": "Taiwan", "code": "TW", "lang": "zho" }, + "TZ": { "name": "Tanzania", "code": "TZ", "lang": "swa" }, + "UA": { "name": "Ukraine", "code": "UA", "lang": "ukr" }, + "UG": { "name": "Uganda", "code": "UG", "lang": "eng" }, + "UM": { "name": "U.S. Minor Outlying Islands", "code": "UM", "lang": "eng" }, + "US": { "name": "United States", "code": "US", "lang": "eng" }, + "UY": { "name": "Uruguay", "code": "UY", "lang": "spa" }, + "UZ": { "name": "Uzbekistan", "code": "UZ", "lang": "uzb" }, + "VA": { "name": "Vatican City", "code": "VA", "lang": "ita" }, + "VC": { "name": "Saint Vincent and the Grenadines", "code": "VC", "lang": "eng" }, + "VE": { "name": "Venezuela", "code": "VE", "lang": "spa" }, + "VG": { "name": "British Virgin Islands", "code": "VG", "lang": "eng" }, + "VI": { "name": "U.S. Virgin Islands", "code": "VI", "lang": "eng" }, + "VN": { "name": "Vietnam", "code": "VN", "lang": "vie" }, + "VU": { "name": "Vanuatu", "code": "VU", "lang": "bis" }, + "WF": { "name": "Wallis and Futuna", "code": "WF", "lang": "fra" }, + "WS": { "name": "Samoa", "code": "WS", "lang": "smo" }, + "XK": { "name": "Kosovo", "code": "XK", "lang": "sqi" }, + "YE": { "name": "Yemen", "code": "YE", "lang": "ara" }, + "YT": { "name": "Mayotte", "code": "YT", "lang": "fra" }, "ZA": { "name": "South Africa", - "languages": ["afr", "eng", "nbl", "sot", "ssw", "tsn", "tso", "ven", "xho", "zul"] + "code": "ZA", + "lang": "afr" }, - "ZM": { - "name": "Zambia", - "languages": ["eng"] - }, - "ZW": { - "name": "Zimbabwe", - "languages": ["eng", "sna", "nde"] - } + "ZM": { "name": "Zambia", "code": "ZM", "lang": "eng" }, + "ZW": { "name": "Zimbabwe", "code": "ZW", "lang": "eng" } } From 198d7ef4c2818db515f3b3c690bc51c39182414d Mon Sep 17 00:00:00 2001 From: Aleksandr Statciuk Date: Sun, 12 Dec 2021 07:11:24 +0300 Subject: [PATCH 20/34] Update regions.json --- scripts/data/regions.json | 210 ++++++++++++++------------------------ 1 file changed, 77 insertions(+), 133 deletions(-) diff --git a/scripts/data/regions.json b/scripts/data/regions.json index eccab1abf3..101fdd70f0 100644 --- a/scripts/data/regions.json +++ b/scripts/data/regions.json @@ -1,7 +1,8 @@ { "AFR": { "name": "Africa", - "codes": [ + "code": "AFR", + "country_codes": [ "AO", "BF", "BI", @@ -65,7 +66,8 @@ }, "AMER": { "name": "Americas", - "codes": [ + "code": "AMER", + "country_codes": [ "AG", "AI", "AR", @@ -126,7 +128,8 @@ }, "APAC": { "name": "Asia-Pacific", - "codes": [ + "code": "APAC", + "country_codes": [ "AF", "AS", "AU", @@ -181,7 +184,8 @@ }, "ARAB": { "name": "Arab world", - "codes": [ + "code": "ARAB", + "country_codes": [ "AE", "BH", "DJ", @@ -208,7 +212,8 @@ }, "ASIA": { "name": "Asia", - "codes": [ + "code": "ASIA", + "country_codes": [ "AE", "AF", "AM", @@ -263,7 +268,8 @@ }, "CARIB": { "name": "Caribbean", - "codes": [ + "code": "CARIB", + "country_codes": [ "AG", "AI", "AW", @@ -295,15 +301,18 @@ }, "CAS": { "name": "Central Asia", - "codes": ["KG", "KZ", "TJ", "TM", "UZ"] + "code": "CAS", + "country_codes": ["KG", "KZ", "TJ", "TM", "UZ"] }, "CIS": { "name": "Commonwealth of Independent States", - "codes": ["AM", "AZ", "BY", "KG", "KZ", "MD", "RU", "TJ", "UZ"] + "code": "CIS", + "country_codes": ["AM", "AZ", "BY", "KG", "KZ", "MD", "RU", "TJ", "UZ"] }, "EMEA": { - "name": "Europe, Middle East and Africa", - "codes": [ + "name": "Europe, the Middle East and Africa", + "code": "EMEA", + "country_codes": [ "AD", "AE", "AL", @@ -430,7 +439,8 @@ }, "EUR": { "name": "Europe", - "codes": [ + "code": "EUR", + "country_codes": [ "AD", "AL", "AM", @@ -485,7 +495,8 @@ }, "HISPAM": { "name": "Hispanic America", - "codes": [ + "code": "HISPAM", + "country_codes": [ "AR", "BO", "CL", @@ -509,7 +520,8 @@ }, "LATAM": { "name": "Latin America", - "codes": [ + "code": "LATAM", + "country_codes": [ "AR", "BL", "BO", @@ -538,90 +550,15 @@ "VE" ] }, - "MAGHRIB": { - "name": "Maghrib", - "codes": ["DZ", "LY", "MA", "MR", "TN"] - }, - "MEA": { - "name": "Middle East and Africa", - "codes": [ - "AE", - "AO", - "BF", - "BH", - "BI", - "BJ", - "BW", - "CD", - "CF", - "CG", - "CI", - "CM", - "CV", - "DJ", - "DZ", - "EG", - "EH", - "ER", - "ET", - "GA", - "GH", - "GM", - "GN", - "GQ", - "GW", - "IQ", - "IR", - "JO", - "KE", - "KM", - "KW", - "LB", - "LR", - "LS", - "LY", - "MA", - "MG", - "ML", - "MR", - "MU", - "MW", - "MZ", - "NA", - "NE", - "NG", - "OM", - "PS", - "QA", - "RE", - "RW", - "SA", - "SC", - "SD", - "SH", - "SL", - "SN", - "SO", - "SS", - "ST", - "SY", - "SZ", - "TD", - "TF", - "TG", - "TN", - "TZ", - "UG", - "YE", - "YT", - "ZA", - "ZM", - "ZW" - ] + "MAGHREB": { + "name": "Maghreb", + "code": "MAGHREB", + "country_codes": ["DZ", "LY", "MA", "MR", "TN"] }, "MENA": { "name": "Middle East and North Africa", - "codes": [ + "code": "MENA", + "country_codes": [ "AE", "BH", "DJ", @@ -645,43 +582,10 @@ "YE" ] }, - "NORD": { - "name": "Nordics", - "codes": ["AX", "DK", "FO", "FI", "IS", "NO", "SE"] - }, - "OCE": { - "name": "Oceania", - "codes": [ - "AS", - "AU", - "CK", - "FJ", - "FM", - "GU", - "KI", - "MH", - "MP", - "NC", - "NF", - "NR", - "NU", - "NZ", - "PF", - "PG", - "PN", - "PW", - "SB", - "TK", - "TO", - "TV", - "VU", - "WF", - "WS" - ] - }, "MIDEAST": { "name": "Middle East", - "codes": [ + "code": "MIDEAST", + "country_codes": [ "AE", "BH", "CY", @@ -703,7 +607,8 @@ }, "NORAM": { "name": "North America", - "codes": [ + "code": "NORAM", + "country_codes": [ "AG", "AI", "AW", @@ -746,13 +651,51 @@ "VI" ] }, + "NORD": { + "name": "Nordics", + "code": "NORD", + "country_codes": ["AX", "DK", "FO", "FI", "IS", "NO", "SE"] + }, + "OCE": { + "name": "Oceania", + "code": "OCE", + "country_codes": [ + "AS", + "AU", + "CK", + "FJ", + "FM", + "GU", + "KI", + "MH", + "MP", + "NC", + "NF", + "NR", + "NU", + "NZ", + "PF", + "PG", + "PN", + "PW", + "SB", + "TK", + "TO", + "TV", + "VU", + "WF", + "WS" + ] + }, "SAS": { "name": "South Asia", - "codes": ["AF", "BD", "BT", "IN", "LK", "MV", "NP", "PK"] + "code": "SAS", + "country_codes": ["AF", "BD", "BT", "IN", "LK", "MV", "NP", "PK"] }, "SSA": { "name": "Sub-Saharan Africa", - "codes": [ + "code": "SSA", + "country_codes": [ "AO", "BF", "BI", @@ -806,7 +749,8 @@ }, "WAFR": { "name": "West Africa", - "codes": [ + "code": "WAFR", + "country_codes": [ "BF", "BJ", "CI", From 0e21288935dc0d24e1f873b3c58d8c3f49459532 Mon Sep 17 00:00:00 2001 From: Aleksandr Statciuk Date: Sun, 12 Dec 2021 07:11:26 +0300 Subject: [PATCH 21/34] Create statuses.json --- scripts/data/statuses.json | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 scripts/data/statuses.json diff --git a/scripts/data/statuses.json b/scripts/data/statuses.json new file mode 100644 index 0000000000..8e96c1409b --- /dev/null +++ b/scripts/data/statuses.json @@ -0,0 +1,27 @@ +{ + "online": { + "label": "", + "code": "online", + "level": 1 + }, + "geo_blocked": { + "label": "Geo-blocked", + "code": "geo_blocked", + "level": 2 + }, + "not_247": { + "label": "Not 24/7", + "code": "not_247", + "level": 3 + }, + "timeout": { + "label": "Timeout", + "code": "timeout", + "level": 4 + }, + "offline": { + "label": "Offline", + "code": "offline", + "level": 5 + } +} From 21b8ce87318e929bcfe2a9f01ed2b865e63fc6f2 Mon Sep 17 00:00:00 2001 From: Aleksandr Statciuk Date: Sun, 12 Dec 2021 07:11:50 +0300 Subject: [PATCH 22/34] Create scripts/store/getters --- scripts/store/getters/group_title.js | 12 ++++++++++++ scripts/store/getters/index.js | 7 +++++++ scripts/store/getters/title.js | 13 +++++++++++++ scripts/store/getters/tvg_country.js | 5 +++++ scripts/store/getters/tvg_id.js | 3 +++ scripts/store/getters/tvg_language.js | 3 +++ scripts/store/getters/tvg_logo.js | 3 +++ scripts/store/getters/tvg_url.js | 3 +++ 8 files changed, 49 insertions(+) create mode 100644 scripts/store/getters/group_title.js create mode 100644 scripts/store/getters/index.js create mode 100644 scripts/store/getters/title.js create mode 100644 scripts/store/getters/tvg_country.js create mode 100644 scripts/store/getters/tvg_id.js create mode 100644 scripts/store/getters/tvg_language.js create mode 100644 scripts/store/getters/tvg_logo.js create mode 100644 scripts/store/getters/tvg_url.js diff --git a/scripts/store/getters/group_title.js b/scripts/store/getters/group_title.js new file mode 100644 index 0000000000..ddae6ef2b6 --- /dev/null +++ b/scripts/store/getters/group_title.js @@ -0,0 +1,12 @@ +module.exports = function () { + if (this.group_title) return this.group_title + + if (Array.isArray(this.categories)) { + return this.categories + .map(i => i.name) + .sort() + .join(';') + } + + return '' +} diff --git a/scripts/store/getters/index.js b/scripts/store/getters/index.js new file mode 100644 index 0000000000..df20631e05 --- /dev/null +++ b/scripts/store/getters/index.js @@ -0,0 +1,7 @@ +exports.group_title = require('./group_title') +exports.title = require('./title') +exports.tvg_country = require('./tvg_country') +exports.tvg_id = require('./tvg_id') +exports.tvg_language = require('./tvg_language') +exports.tvg_logo = require('./tvg_logo') +exports.tvg_url = require('./tvg_url') diff --git a/scripts/store/getters/title.js b/scripts/store/getters/title.js new file mode 100644 index 0000000000..7dc8304a67 --- /dev/null +++ b/scripts/store/getters/title.js @@ -0,0 +1,13 @@ +module.exports = function () { + let title = this.name + + if (this.resolution.height) { + title += ` (${this.resolution.height}p)` + } + + if (this.status.label) { + title += ` [${this.status.label}]` + } + + return title +} diff --git a/scripts/store/getters/tvg_country.js b/scripts/store/getters/tvg_country.js new file mode 100644 index 0000000000..7865e26b38 --- /dev/null +++ b/scripts/store/getters/tvg_country.js @@ -0,0 +1,5 @@ +module.exports = function () { + if (this.tvg_country) return this.tvg_country + + return Array.isArray(this.countries) ? this.countries.map(i => i.code).join(';') : '' +} diff --git a/scripts/store/getters/tvg_id.js b/scripts/store/getters/tvg_id.js new file mode 100644 index 0000000000..6b362cefe4 --- /dev/null +++ b/scripts/store/getters/tvg_id.js @@ -0,0 +1,3 @@ +module.exports = function () { + return this.id || '' +} diff --git a/scripts/store/getters/tvg_language.js b/scripts/store/getters/tvg_language.js new file mode 100644 index 0000000000..2ad39c7fec --- /dev/null +++ b/scripts/store/getters/tvg_language.js @@ -0,0 +1,3 @@ +module.exports = function () { + return Array.isArray(this.languages) ? this.languages.map(i => i.name).join(';') : '' +} diff --git a/scripts/store/getters/tvg_logo.js b/scripts/store/getters/tvg_logo.js new file mode 100644 index 0000000000..e5d62bc9df --- /dev/null +++ b/scripts/store/getters/tvg_logo.js @@ -0,0 +1,3 @@ +module.exports = function () { + return this.logo || '' +} diff --git a/scripts/store/getters/tvg_url.js b/scripts/store/getters/tvg_url.js new file mode 100644 index 0000000000..9bd084c789 --- /dev/null +++ b/scripts/store/getters/tvg_url.js @@ -0,0 +1,3 @@ +module.exports = function () { + return this.guides.length ? this.guides[0] : '' +} From 42d8a670d2c6445f0270640d4ff8c0388f77e8f4 Mon Sep 17 00:00:00 2001 From: Aleksandr Statciuk Date: Sun, 12 Dec 2021 07:12:06 +0300 Subject: [PATCH 23/34] Create scripts/store/setters --- scripts/store/setters/categories.js | 8 ++++++++ scripts/store/setters/countries.js | 25 +++++++++++++++++++++++++ scripts/store/setters/guides.js | 3 +++ scripts/store/setters/index.js | 12 ++++++++++++ scripts/store/setters/is_broken.js | 7 +++++++ scripts/store/setters/is_nsfw.js | 3 +++ scripts/store/setters/languages.js | 12 ++++++++++++ scripts/store/setters/name.js | 10 ++++++++++ scripts/store/setters/regions.js | 22 ++++++++++++++++++++++ scripts/store/setters/resolution.js | 9 +++++++++ scripts/store/setters/src_country.js | 13 +++++++++++++ scripts/store/setters/status.js | 25 +++++++++++++++++++++++++ scripts/store/setters/url.js | 7 +++++++ 13 files changed, 156 insertions(+) create mode 100644 scripts/store/setters/categories.js create mode 100644 scripts/store/setters/countries.js create mode 100644 scripts/store/setters/guides.js create mode 100644 scripts/store/setters/index.js create mode 100644 scripts/store/setters/is_broken.js create mode 100644 scripts/store/setters/is_nsfw.js create mode 100644 scripts/store/setters/languages.js create mode 100644 scripts/store/setters/name.js create mode 100644 scripts/store/setters/regions.js create mode 100644 scripts/store/setters/resolution.js create mode 100644 scripts/store/setters/src_country.js create mode 100644 scripts/store/setters/status.js create mode 100644 scripts/store/setters/url.js diff --git a/scripts/store/setters/categories.js b/scripts/store/setters/categories.js new file mode 100644 index 0000000000..8dc50974bb --- /dev/null +++ b/scripts/store/setters/categories.js @@ -0,0 +1,8 @@ +const categories = require('../../data/categories') + +module.exports = function ({ group_title }) { + return group_title + .split(';') + .map(i => categories[i.toLowerCase()]) + .filter(i => i) +} diff --git a/scripts/store/setters/countries.js b/scripts/store/setters/countries.js new file mode 100644 index 0000000000..b193911b8a --- /dev/null +++ b/scripts/store/setters/countries.js @@ -0,0 +1,25 @@ +const dataRegions = require('../../data/regions') +const dataCountries = require('../../data/countries') + +module.exports = function ({ tvg_country, countries = [] }) { + if (tvg_country) { + return tvg_country + .split(';') + .reduce((acc, curr) => { + const region = dataRegions[curr] + if (region) { + for (let code of region.country_codes) { + if (!acc.includes(code)) acc.push(code) + } + } else { + acc.push(curr) + } + + return acc + }, []) + .map(item => dataCountries[item]) + .filter(i => i) + } + + return countries +} diff --git a/scripts/store/setters/guides.js b/scripts/store/setters/guides.js new file mode 100644 index 0000000000..0c0ff7296c --- /dev/null +++ b/scripts/store/setters/guides.js @@ -0,0 +1,3 @@ +module.exports = function ({ tvg_url, guides = [] }) { + return tvg_url ? [tvg_url] : guides +} diff --git a/scripts/store/setters/index.js b/scripts/store/setters/index.js new file mode 100644 index 0000000000..436bea49a6 --- /dev/null +++ b/scripts/store/setters/index.js @@ -0,0 +1,12 @@ +exports.categories = require('./categories') +exports.countries = require('./countries') +exports.guides = require('./guides') +exports.is_broken = require('./is_broken') +exports.is_nsfw = require('./is_nsfw') +exports.languages = require('./languages') +exports.name = require('./name') +exports.regions = require('./regions') +exports.resolution = require('./resolution') +exports.src_country = require('./src_country') +exports.status = require('./status') +exports.url = require('./url') diff --git a/scripts/store/setters/is_broken.js b/scripts/store/setters/is_broken.js new file mode 100644 index 0000000000..cf4cea231b --- /dev/null +++ b/scripts/store/setters/is_broken.js @@ -0,0 +1,7 @@ +module.exports = function ({ is_broken = false, status }) { + if (status) { + return status.level > 3 ? true : false + } + + return is_broken +} diff --git a/scripts/store/setters/is_nsfw.js b/scripts/store/setters/is_nsfw.js new file mode 100644 index 0000000000..886b850a69 --- /dev/null +++ b/scripts/store/setters/is_nsfw.js @@ -0,0 +1,3 @@ +module.exports = function ({ categories }) { + return Array.isArray(categories) ? categories.filter(c => c.nsfw).length > 0 : false +} diff --git a/scripts/store/setters/languages.js b/scripts/store/setters/languages.js new file mode 100644 index 0000000000..a5ee56dcc3 --- /dev/null +++ b/scripts/store/setters/languages.js @@ -0,0 +1,12 @@ +const langs = require('../../data/languages') + +module.exports = function ({ tvg_language, languages = [] }) { + if (tvg_language) { + return tvg_language + .split(';') + .map(name => langs.find(l => l.name === name)) + .filter(i => i) + } + + return languages +} diff --git a/scripts/store/setters/name.js b/scripts/store/setters/name.js new file mode 100644 index 0000000000..d566053371 --- /dev/null +++ b/scripts/store/setters/name.js @@ -0,0 +1,10 @@ +module.exports = function ({ title }) { + return title + .trim() + .split(' ') + .map(s => s.trim()) + .filter(s => { + return !/\[|\]/i.test(s) && !/\((\d+)P\)/i.test(s) + }) + .join(' ') +} diff --git a/scripts/store/setters/regions.js b/scripts/store/setters/regions.js new file mode 100644 index 0000000000..7016eecd1b --- /dev/null +++ b/scripts/store/setters/regions.js @@ -0,0 +1,22 @@ +const _ = require('lodash') + +let regions = require('../../data/regions') + +module.exports = function ({ countries }) { + if (!countries.length) return [] + + const output = [] + regions = Object.values(regions) + countries.forEach(country => { + regions + .filter(region => region.country_codes.includes(country.code)) + .forEach(found => { + output.push({ + name: found.name, + code: found.code + }) + }) + }) + + return _.uniqBy(output, 'code') +} diff --git a/scripts/store/setters/resolution.js b/scripts/store/setters/resolution.js new file mode 100644 index 0000000000..1722e6aa2e --- /dev/null +++ b/scripts/store/setters/resolution.js @@ -0,0 +1,9 @@ +module.exports = function ({ title, resolution = {} }) { + if (title) { + const [_, h] = title.match(/\((\d+)P\)/i) || [null, null] + + return h ? { height: parseInt(h), width: null } : resolution + } + + return resolution +} diff --git a/scripts/store/setters/src_country.js b/scripts/store/setters/src_country.js new file mode 100644 index 0000000000..6eaa9d4d30 --- /dev/null +++ b/scripts/store/setters/src_country.js @@ -0,0 +1,13 @@ +const { file } = require('../../core') +const countries = require('../../data/countries') + +module.exports = function ({ filepath }) { + if (filepath) { + const basename = file.basename(filepath) + const [_, code] = basename.match(/([a-z]{2})(|_.*)\.m3u/i) || [null, null] + + return code ? countries[code.toUpperCase()] : null + } + + return null +} diff --git a/scripts/store/setters/status.js b/scripts/store/setters/status.js new file mode 100644 index 0000000000..463ac0d05b --- /dev/null +++ b/scripts/store/setters/status.js @@ -0,0 +1,25 @@ +const statuses = require('../../data/statuses') + +module.exports = function ({ title, status = {} }) { + if (title) { + const [_, label] = title.match(/\[(.*)\]/i) || [null, null] + + return Object.values(statuses).find(s => s.label === label) || statuses['online'] + } + + if (status) { + switch (status.code) { + case 'not_247': + case 'geo_blocked': + return status + case 'offline': + return statuses['not_247'] + case 'timeout': + return statuses['timeout'] + default: + return statuses['online'] + } + } + + return status +} diff --git a/scripts/store/setters/url.js b/scripts/store/setters/url.js new file mode 100644 index 0000000000..9951593992 --- /dev/null +++ b/scripts/store/setters/url.js @@ -0,0 +1,7 @@ +const normalize = require('normalize-url') + +module.exports = function ({ url }) { + const normalized = normalize(url, { stripWWW: false }) + + return decodeURIComponent(normalized).replace(/\s/g, '+') +} From 9bd944c2fff8d8a159ba364b854b058ce2fc8132 Mon Sep 17 00:00:00 2001 From: Aleksandr Statciuk Date: Sun, 12 Dec 2021 07:13:02 +0300 Subject: [PATCH 24/34] Create tests --- tests/__data__/.gitignore | 2 + tests/__data__/input/channels/ad_example.m3u | 3 + tests/__data__/input/channels/us_blocked.m3u | 3 + tests/__data__/input/codes.json | 1 + .../input/logs/check-streams/cluster_1.log | 3 + .../logs/generate-playlists/categories.log | 3 + .../logs/generate-playlists/countries.log | 5 + .../logs/generate-playlists/languages.log | 4 + .../input/logs/generate-playlists/regions.log | 5 + tests/__data__/input/readme.json | 4 + tests/__data__/input/readme.md | 182 ++++++++++++++++ tests/__data__/input/test.db | 3 + tests/commands/check-streams.test.js | 44 ++++ tests/commands/cleanup-database.test.js | 25 +++ tests/commands/create-database.test.js | 45 ++++ tests/commands/create-matrix.test.js | 20 ++ tests/commands/generate-playlists.test.js | 204 ++++++++++++++++++ tests/commands/update-database.test.js | 100 +++++++++ tests/commands/update-playlists.test.js | 37 ++++ tests/commands/update-readme.test.js | 23 ++ tests/commands/validate.test.js | 16 ++ 21 files changed, 732 insertions(+) create mode 100644 tests/__data__/.gitignore create mode 100644 tests/__data__/input/channels/ad_example.m3u create mode 100644 tests/__data__/input/channels/us_blocked.m3u create mode 100644 tests/__data__/input/codes.json create mode 100644 tests/__data__/input/logs/check-streams/cluster_1.log create mode 100644 tests/__data__/input/logs/generate-playlists/categories.log create mode 100644 tests/__data__/input/logs/generate-playlists/countries.log create mode 100644 tests/__data__/input/logs/generate-playlists/languages.log create mode 100644 tests/__data__/input/logs/generate-playlists/regions.log create mode 100644 tests/__data__/input/readme.json create mode 100644 tests/__data__/input/readme.md create mode 100644 tests/__data__/input/test.db create mode 100644 tests/commands/check-streams.test.js create mode 100644 tests/commands/cleanup-database.test.js create mode 100644 tests/commands/create-database.test.js create mode 100644 tests/commands/create-matrix.test.js create mode 100644 tests/commands/generate-playlists.test.js create mode 100644 tests/commands/update-database.test.js create mode 100644 tests/commands/update-playlists.test.js create mode 100644 tests/commands/update-readme.test.js create mode 100644 tests/commands/validate.test.js diff --git a/tests/__data__/.gitignore b/tests/__data__/.gitignore new file mode 100644 index 0000000000..d0dea4f002 --- /dev/null +++ b/tests/__data__/.gitignore @@ -0,0 +1,2 @@ +output/ +temp/ \ No newline at end of file diff --git a/tests/__data__/input/channels/ad_example.m3u b/tests/__data__/input/channels/ad_example.m3u new file mode 100644 index 0000000000..52612ebde6 --- /dev/null +++ b/tests/__data__/input/channels/ad_example.m3u @@ -0,0 +1,3 @@ +#EXTM3U +#EXTINF:-1 tvg-id="ATV.ad" tvg-country="AD" tvg-language="Catalan" tvg-logo="https://i.imgur.com/kJCjeQ4.png" group-title="General",ATV (720p) [Offline] +https://iptv-all.lanesh4d0w.repl.co/andorra/atv \ No newline at end of file diff --git a/tests/__data__/input/channels/us_blocked.m3u b/tests/__data__/input/channels/us_blocked.m3u new file mode 100644 index 0000000000..f08f25184e --- /dev/null +++ b/tests/__data__/input/channels/us_blocked.m3u @@ -0,0 +1,3 @@ +#EXTM3U +#EXTINF:-1 tvg-id="FoxSports2Asia.us" tvg-country="TH" tvg-language="Thai" tvg-logo="" group-title="Sports",Fox Sports 2 Asia (Thai) (720p) +https://example.com/playlist.m3u8 diff --git a/tests/__data__/input/codes.json b/tests/__data__/input/codes.json new file mode 100644 index 0000000000..3f8989427b --- /dev/null +++ b/tests/__data__/input/codes.json @@ -0,0 +1 @@ +[{"tvg_id":"AndorraTV.ad","display_name":"Andorra TV","country":"ad","guides":["https://iptv-org.github.io/epg/guides/ad/andorradifusio.ad.epg.xml"],"logo":"https://www.andorradifusio.ad/images/logo/andorradifusio_logo_22122020091723.png"}] \ No newline at end of file diff --git a/tests/__data__/input/logs/check-streams/cluster_1.log b/tests/__data__/input/logs/check-streams/cluster_1.log new file mode 100644 index 0000000000..a152151d3a --- /dev/null +++ b/tests/__data__/input/logs/check-streams/cluster_1.log @@ -0,0 +1,3 @@ +{"_id":"I6cjG2xCBRFFP4sz","url":"https://iptv-all.lanesh4d0w.repl.co/andorra/atv","http":{"referrer":"","user-agent":""},"error":"Operation timed out","streams":[],"requests":[]} +{"_id":"3TbieV1ptnZVCIdn","url":"http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8","http":{"referrer":"","user-agent":""},"error":"Server returned 404 Not Found","streams":[],"requests":[]} + {"_id":"2ST8btby3mmsgPF0","url":"http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8","http":{"referrer":"","user-agent":""},"error":null,"streams":[{"index":0,"codec_name":"timed_id3","codec_long_name":"timed ID3 metadata","codec_type":"data","codec_tag_string":"ID3 ","codec_tag":"0x20334449","r_frame_rate":"0/0","avg_frame_rate":"0/0","time_base":"1/90000","disposition":{"default":0,"dub":0,"original":0,"comment":0,"lyrics":0,"karaoke":0,"forced":0,"hearing_impaired":0,"visual_impaired":0,"clean_effects":0,"attached_pic":0,"timed_thumbnails":0},"tags":{"variant_bitrate":"6527203"}},{"index":1,"codec_name":"h264","codec_long_name":"H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10","profile":"Main","codec_type":"video","codec_tag_string":"[27][0][0][0]","codec_tag":"0x001b","width":1920,"height":1080,"coded_width":1920,"coded_height":1080,"closed_captions":0,"has_b_frames":0,"sample_aspect_ratio":"1:1","display_aspect_ratio":"16:9","pix_fmt":"yuv420p","level":40,"chroma_location":"left","refs":1,"is_avc":"false","nal_length_size":"0","r_frame_rate":"50/1","avg_frame_rate":"50/1","time_base":"1/90000","start_pts":8171218184,"start_time":"90791.313156","bits_per_raw_sample":"8","disposition":{"default":0,"dub":0,"original":0,"comment":0,"lyrics":0,"karaoke":0,"forced":0,"hearing_impaired":0,"visual_impaired":0,"clean_effects":0,"attached_pic":0,"timed_thumbnails":0},"tags":{"variant_bitrate":"6527203"}},{"index":2,"codec_name":"aac","codec_long_name":"AAC (Advanced Audio Coding)","profile":"LC","codec_type":"audio","codec_tag_string":"[15][0][0][0]","codec_tag":"0x000f","sample_fmt":"fltp","sample_rate":"48000","channels":2,"channel_layout":"stereo","bits_per_sample":0,"r_frame_rate":"0/0","avg_frame_rate":"0/0","time_base":"1/90000","start_pts":8171229134,"start_time":"90791.434822","disposition":{"default":0,"dub":0,"original":0,"comment":0,"lyrics":0,"karaoke":0,"forced":0,"hearing_impaired":0,"visual_impaired":0,"clean_effects":0,"attached_pic":0,"timed_thumbnails":0},"tags":{"variant_bitrate":"6527203"}}],"requests":[{"method":"GET","url":"http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8","headers":{"User-Agent":"Lavf/58.76.100","Accept":"*/*","Range":"bytes=0-","Connection":"close","Host":"46.46.143.222:1935","Icy-MetaData":"1"}},{"method":"GET","url":"http://46.46.143.222:1935/live/mp4:ldpr.stream/chunklist_w1629502765.m3u8","headers":{"User-Agent":"Lavf/58.76.100","Accept":"*/*","Range":"bytes=0-","Connection":"keep-alive","Host":"46.46.143.222:1935","Icy-MetaData":"1"}},{"method":"GET","url":"http://46.46.143.222:1935/live/mp4:ldpr.stream/media_w1629502765_1085323.ts","headers":{"User-Agent":"Lavf/58.76.100","Accept":"*/*","Range":"bytes=0-","Connection":"keep-alive","Host":"46.46.143.222:1935","Icy-MetaData":"1"}},{"method":"GET","url":"http://46.46.143.222:1935/live/mp4:ldpr.stream/media_w1629502765_1085324.ts","headers":{"User-Agent":"Lavf/58.76.100","Accept":"*/*","Range":"bytes=0-","Connection":"keep-alive","Host":"46.46.143.222:1935","Icy-MetaData":"1"}}]} \ No newline at end of file diff --git a/tests/__data__/input/logs/generate-playlists/categories.log b/tests/__data__/input/logs/generate-playlists/categories.log new file mode 100644 index 0000000000..5f4d99cf2b --- /dev/null +++ b/tests/__data__/input/logs/generate-playlists/categories.log @@ -0,0 +1,3 @@ +{"name":"General","slug":"general","count":1} +{"name":"News","slug":"news","count":1} +{"name":"Other","slug":"other","count":0} diff --git a/tests/__data__/input/logs/generate-playlists/countries.log b/tests/__data__/input/logs/generate-playlists/countries.log new file mode 100644 index 0000000000..e8e3f180d1 --- /dev/null +++ b/tests/__data__/input/logs/generate-playlists/countries.log @@ -0,0 +1,5 @@ +{"name":"Andorra","code":"AD","count":0} +{"name":"Russia","code":"RU","count":1} +{"name":"United Kingdom","code":"UK","count":1} +{"name":"International","code":"INT","count":0} +{"name":"Undefined","code":"UNDEFINED","count":0} diff --git a/tests/__data__/input/logs/generate-playlists/languages.log b/tests/__data__/input/logs/generate-playlists/languages.log new file mode 100644 index 0000000000..4a5a060f85 --- /dev/null +++ b/tests/__data__/input/logs/generate-playlists/languages.log @@ -0,0 +1,4 @@ +{"name":"Catalan","code":"cat","count":0} +{"name":"English","code":"eng","count":1} +{"name":"Russian","code":"rus","count":1} +{"name":"Undefined","code":"undefined","count":0} diff --git a/tests/__data__/input/logs/generate-playlists/regions.log b/tests/__data__/input/logs/generate-playlists/regions.log new file mode 100644 index 0000000000..8d78fde4fe --- /dev/null +++ b/tests/__data__/input/logs/generate-playlists/regions.log @@ -0,0 +1,5 @@ +{"name":"Asia","code":"ASIA","count":1} +{"name":"Commonwealth of Independent States","code":"CIS","count":1} +{"name":"Europe","code":"EUR","count":2} +{"name":"Europe, the Middle East and Africa","code":"EMEA","count":2} +{"name":"Undefined","code":"UNDEFINED","count":0} diff --git a/tests/__data__/input/readme.json b/tests/__data__/input/readme.json new file mode 100644 index 0000000000..d226f0e660 --- /dev/null +++ b/tests/__data__/input/readme.json @@ -0,0 +1,4 @@ +{ + "build" : "tests/__data__/output/readme.md", + "files" : ["./.readme/template.md"] +} \ No newline at end of file diff --git a/tests/__data__/input/readme.md b/tests/__data__/input/readme.md new file mode 100644 index 0000000000..9ba2befb9a --- /dev/null +++ b/tests/__data__/input/readme.md @@ -0,0 +1,182 @@ +# IPTV + +[![auto-update](https://github.com/iptv-org/iptv/actions/workflows/auto-update.yml/badge.svg)](https://github.com/iptv-org/iptv/actions/workflows/auto-update.yml) + +Collection of publicly available IPTV channels from all over the world. + +Internet Protocol television (IPTV) is the delivery of television content over Internet Protocol (IP) networks. + +## Usage + +To watch IPTV you just need to paste this link `https://iptv-org.github.io/iptv/index.m3u` to any player which supports M3U-playlists. + +![VLC Network Panel](.readme/preview.png) + +Also you can instead use one of these playlists: + +- `https://iptv-org.github.io/iptv/index.category.m3u` (grouped by category) +- `https://iptv-org.github.io/iptv/index.language.m3u` (grouped by language) +- `https://iptv-org.github.io/iptv/index.country.m3u` (grouped by country) +- `https://iptv-org.github.io/iptv/index.region.m3u` (grouped by region) +- `https://iptv-org.github.io/iptv/index.nsfw.m3u` (includes adult channels) + +Or select one of the playlists from the list below. + +### Playlists by category + +
+Expand +
+ + + + + + + + + + + +
CategoryChannelsPlaylist
General1https://iptv-org.github.io/iptv/categories/general.m3u
News1https://iptv-org.github.io/iptv/categories/news.m3u
Other0https://iptv-org.github.io/iptv/categories/other.m3u
+ +
+ +### Playlists by language + +
+Expand +
+ + + + + + + + + + + + +
LanguageChannelsPlaylist
Catalan0https://iptv-org.github.io/iptv/languages/cat.m3u
English1https://iptv-org.github.io/iptv/languages/eng.m3u
Russian1https://iptv-org.github.io/iptv/languages/rus.m3u
Undefined0https://iptv-org.github.io/iptv/languages/undefined.m3u
+ +
+ +### Playlists by region + +
+Expand +
+ + + + + + + + + + + + + +
RegionChannelsPlaylist
Asia1https://iptv-org.github.io/iptv/regions/asia.m3u
Commonwealth of Independent States1https://iptv-org.github.io/iptv/regions/cis.m3u
Europe2https://iptv-org.github.io/iptv/regions/eur.m3u
Europe, the Middle East and Africa2https://iptv-org.github.io/iptv/regions/emea.m3u
Undefined0https://iptv-org.github.io/iptv/regions/undefined.m3u
+ +
+ +### Playlists by country + +
+Expand +
+ + + + + + + + + + + + + +
CountryChannelsPlaylist
🇦🇩 Andorra0https://iptv-org.github.io/iptv/countries/ad.m3u
🇷🇺 Russia1https://iptv-org.github.io/iptv/countries/ru.m3u
🇬🇧 United Kingdom1https://iptv-org.github.io/iptv/countries/uk.m3u
🌍 International0https://iptv-org.github.io/iptv/countries/int.m3u
Undefined0https://iptv-org.github.io/iptv/countries/undefined.m3u
+ +
+ +## For Developers + +In addition to the above methods, you can also get a list of all available channels in JSON format. + +To do this, you just have to make a GET request to: + +``` +https://iptv-org.github.io/iptv/channels.json +``` + +If successful, you should get the following response: + +
+Expand +
+ +``` +[ + ... + { + "name": "CNN", + "logo": "https://i.imgur.com/ilZJT5s.png", + "url": "http://ott-cdn.ucom.am/s27/index.m3u8", + "categories": [ + { + "name": "News", + "slug": "news" + } + ], + "countries": [ + { + "code": "us", + "name": "United States" + }, + { + "code": "ca", + "name": "Canada" + } + ], + "languages": [ + { + "code": "eng", + "name": "English" + } + ], + "tvg": { + "id": "cnn.us", + "name": "CNN", + "url": "http://epg.streamstv.me/epg/guide-usa.xml.gz" + } + }, + ... +] +``` +
+ +## EPG + +Playlists already have a built-in list of EPG, so players that support the `url-tvg` tag should load it automatically. If not, you can find a list of available programs here: + +https://github.com/iptv-org/epg + +## Resources + +You can find links to various IPTV related resources in this repository [iptv-org/awesome-iptv](https://github.com/iptv-org/awesome-iptv). + +## Contribution + +Please make sure to read the [Contributing Guide](CONTRIBUTING.md) before sending an issue or making a pull request. + +## 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 or opening an issue. 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). diff --git a/tests/__data__/input/test.db b/tests/__data__/input/test.db new file mode 100644 index 0000000000..bb5733aae0 --- /dev/null +++ b/tests/__data__/input/test.db @@ -0,0 +1,3 @@ +{"name":"ЛДПР ТВ","id":"LDPRTV.ru","filepath":"tests/__data__/output/channels/ru.m3u","src_country":{"name":"Russia","code":"RU","lang":"rus"},"tvg_country":"RU","countries":[{"name":"Russia","code":"RU","lang":"rus"}],"regions":[{"name":"Asia","code":"ASIA"},{"name":"Commonwealth of Independent States","code":"CIS"},{"name":"Europe, the Middle East and Africa","code":"EMEA"},{"name":"Europe","code":"EUR"}],"languages":[{"name":"Russian","code":"rus"}],"categories":[{"name":"General","slug":"general","nsfw":false}],"tvg_url":"","guides":["https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml"],"logo":"https://iptvx.one/icn/ldpr-tv.png","resolution":{"height":1080,"width":null},"status":{"label":"","code":"online","level":1},"url":"http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8","http":{"referrer":"","user-agent":""},"is_nsfw":false,"is_broken":false,"updated":false,"cluster_id":1,"_id":"2ST8btby3mmsgPF0"} +{"name":"BBC News HD","id":"BBCNews.uk","filepath":"tests/__data__/output/channels/uk.m3u","src_country":{"name":"United Kingdom","code":"UK","lang":"eng"},"tvg_country":"UK","countries":[{"name":"United Kingdom","code":"UK","lang":"eng"}],"regions":[{"name":"Europe, the Middle East and Africa","code":"EMEA"},{"name":"Europe","code":"EUR"}],"languages":[{"name":"English","code":"eng"}],"categories":[{"name":"News","slug":"news","nsfw":false}],"tvg_url":"","guides":[],"logo":"https://i.imgur.com/eNPIQ9f.png","resolution":{"height":720,"width":null},"status":{"label":"Not 24/7","code":"not_247","level":3},"url":"http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8","http":{"referrer":"","user-agent":""},"is_nsfw":false,"is_broken":false,"updated":false,"cluster_id":3,"_id":"3TbieV1ptnZVCIdn"} +{"name":"ATV","id":"AndorraTV.ad","filepath":"tests/__data__/output/channels/ad.m3u","src_country":{"name":"Andorra","code":"AD","lang":"cat"},"tvg_country":"AD","countries":[{"name":"Andorra","code":"AD","lang":"cat"}],"regions":[{"name":"Europe, the Middle East and Africa","code":"EMEA"},{"name":"Europe","code":"EUR"}],"languages":[{"name":"Catalan","code":"cat"}],"categories":[{"name":"General","slug":"general","nsfw":false}],"tvg_url":"","guides":[],"logo":"https://i.imgur.com/kJCjeQ4.png","resolution":{"height":720,"width":null},"status":{"label":"Offline","code":"offline","level":5},"url":"https://iptv-all.lanesh4d0w.repl.co/andorra/atv","http":{"referrer":"","user-agent":""},"is_nsfw":false,"is_broken":true,"updated":false,"cluster_id":1,"_id":"I6cjG2xCBRFFP4sz"} diff --git a/tests/commands/check-streams.test.js b/tests/commands/check-streams.test.js new file mode 100644 index 0000000000..250a2dc49b --- /dev/null +++ b/tests/commands/check-streams.test.js @@ -0,0 +1,44 @@ +const fs = require('fs') +const path = require('path') +const { execSync } = require('child_process') + +beforeEach(() => { + fs.rmdirSync('tests/__data__/output', { recursive: true }) + fs.mkdirSync('tests/__data__/output') + fs.copyFileSync('tests/__data__/input/test.db', 'tests/__data__/temp/test.db') +}) + +afterEach(() => { + fs.rmdirSync('tests/__data__/temp', { recursive: true }) + fs.mkdirSync('tests/__data__/temp') +}) + +it('return results if stream with error', () => { + const result = execSync( + 'DB_FILEPATH=tests/__data__/temp/test.db LOGS_PATH=tests/__data__/output/logs node scripts/commands/check-streams.js --cluster-id=1 --timeout=1', + { encoding: 'utf8' } + ) + const logs = fs.readFileSync( + path.resolve('tests/__data__/output/logs/check-streams/cluster_1.log'), + { + encoding: 'utf8' + } + ) + const lines = logs.split('\n') + expect(JSON.parse(lines[0])).toMatchObject({ + _id: '2ST8btby3mmsgPF0', + url: 'http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8', + http: { referrer: '', 'user-agent': '' }, + error: 'Operation timed out', + streams: [], + requests: [] + }) + expect(JSON.parse(lines[1])).toMatchObject({ + _id: 'I6cjG2xCBRFFP4sz', + url: 'https://iptv-all.lanesh4d0w.repl.co/andorra/atv', + http: { referrer: '', 'user-agent': '' }, + error: 'Operation timed out', + streams: [], + requests: [] + }) +}) diff --git a/tests/commands/cleanup-database.test.js b/tests/commands/cleanup-database.test.js new file mode 100644 index 0000000000..bd541e8e7d --- /dev/null +++ b/tests/commands/cleanup-database.test.js @@ -0,0 +1,25 @@ +const fs = require('fs') +const path = require('path') +const { execSync } = require('child_process') + +beforeEach(() => { + fs.copyFileSync('tests/__data__/input/test.db', 'tests/__data__/temp/test.db') +}) + +afterEach(() => { + fs.rmdirSync('tests/__data__/temp', { recursive: true }) + fs.mkdirSync('tests/__data__/temp') +}) + +it('can remove broken links from database', () => { + const result = execSync( + 'DB_FILEPATH=tests/__data__/temp/test.db node scripts/commands/cleanup-database.js', + { encoding: 'utf8' } + ) + + const database = fs.readFileSync('tests/__data__/temp/test.db', { encoding: 'utf8' }) + const lines = database.split('\n') + expect(lines[0]).toBe( + `{"name":"ЛДПР ТВ","id":"LDPRTV.ru","filepath":"tests/__data__/output/channels/ru.m3u","src_country":{"name":"Russia","code":"RU","lang":"rus"},"tvg_country":"RU","countries":[{"name":"Russia","code":"RU","lang":"rus"}],"regions":[{"name":"Asia","code":"ASIA"},{"name":"Commonwealth of Independent States","code":"CIS"},{"name":"Europe, the Middle East and Africa","code":"EMEA"},{"name":"Europe","code":"EUR"}],"languages":[{"name":"Russian","code":"rus"}],"categories":[{"name":"General","slug":"general","nsfw":false}],"tvg_url":"","guides":["https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml"],"logo":"https://iptvx.one/icn/ldpr-tv.png","resolution":{"height":1080,"width":null},"status":{"label":"","code":"online","level":1},"url":"http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8","http":{"referrer":"","user-agent":""},"is_nsfw":false,"is_broken":false,"updated":false,"cluster_id":1,"_id":"2ST8btby3mmsgPF0"}` + ) +}) diff --git a/tests/commands/create-database.test.js b/tests/commands/create-database.test.js new file mode 100644 index 0000000000..4a1a9c494c --- /dev/null +++ b/tests/commands/create-database.test.js @@ -0,0 +1,45 @@ +const fs = require('fs') +const path = require('path') +const { execSync } = require('child_process') + +beforeEach(() => { + fs.rmdirSync('tests/__data__/output', { recursive: true }) + fs.mkdirSync('tests/__data__/output') +}) + +it('can create database', () => { + execSync( + 'DB_FILEPATH=tests/__data__/output/test.db node scripts/commands/create-database.js --input-dir=tests/__data__/input/channels --max-clusters=1', + { encoding: 'utf8' } + ) + + const database = fs.readFileSync(path.resolve('tests/__data__/output/test.db'), { + encoding: 'utf8' + }) + const item = database.split('\n').find(i => i.includes('ATV.ad')) + expect(JSON.parse(item)).toMatchObject({ + name: 'ATV', + id: 'ATV.ad', + filepath: 'tests/__data__/input/channels/ad_example.m3u', + src_country: { name: 'Andorra', code: 'AD', lang: 'cat' }, + tvg_country: 'AD', + countries: [{ name: 'Andorra', code: 'AD', lang: 'cat' }], + regions: [ + { name: 'Europe, the Middle East and Africa', code: 'EMEA' }, + { name: 'Europe', code: 'EUR' } + ], + languages: [{ name: 'Catalan', code: 'cat' }], + categories: [{ name: 'General', slug: 'general', nsfw: false }], + tvg_url: '', + guides: [], + logo: 'https://i.imgur.com/kJCjeQ4.png', + resolution: { height: 720, width: null }, + status: { label: 'Offline', code: 'offline', level: 5 }, + url: 'https://iptv-all.lanesh4d0w.repl.co/andorra/atv', + http: { referrer: '', 'user-agent': '' }, + is_nsfw: false, + is_broken: true, + updated: false, + cluster_id: 1 + }) +}) diff --git a/tests/commands/create-matrix.test.js b/tests/commands/create-matrix.test.js new file mode 100644 index 0000000000..5310cd1df5 --- /dev/null +++ b/tests/commands/create-matrix.test.js @@ -0,0 +1,20 @@ +const fs = require('fs') +const path = require('path') +const { execSync } = require('child_process') + +beforeEach(() => { + fs.copyFileSync('tests/__data__/input/test.db', 'tests/__data__/temp/test.db') +}) + +afterEach(() => { + fs.rmdirSync('tests/__data__/temp', { recursive: true }) + fs.mkdirSync('tests/__data__/temp') +}) + +it('can create valid matrix', () => { + const result = execSync( + 'DB_FILEPATH=tests/__data__/temp/test.db node scripts/commands/create-matrix.js', + { encoding: 'utf8' } + ) + expect(result).toBe('::set-output name=matrix::{"cluster_id":[1,3]}\n') +}) diff --git a/tests/commands/generate-playlists.test.js b/tests/commands/generate-playlists.test.js new file mode 100644 index 0000000000..f68cf0f6bd --- /dev/null +++ b/tests/commands/generate-playlists.test.js @@ -0,0 +1,204 @@ +const fs = require('fs') +const path = require('path') +const { execSync } = require('child_process') + +function content(filepath) { + return fs.readFileSync(`tests/__data__/output/${filepath}`, { + encoding: 'utf8' + }) +} + +beforeEach(() => { + fs.rmdirSync('tests/__data__/output', { recursive: true }) + fs.copyFileSync('tests/__data__/input/test.db', 'tests/__data__/temp/test.db') + + execSync( + 'DB_FILEPATH=tests/__data__/temp/test.db PUBLIC_PATH=tests/__data__/output/.gh-pages LOGS_PATH=tests/__data__/output/logs node scripts/commands/generate-playlists.js', + { encoding: 'utf8' } + ) +}) + +afterEach(() => { + fs.rmdirSync('tests/__data__/temp', { recursive: true }) + fs.mkdirSync('tests/__data__/temp') +}) + +it('can generate categories', () => { + expect(content('.gh-pages/categories/general.m3u')) + .toBe(`#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml" +#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-country="RU" tvg-language="Russian" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8 +`) + + expect(content('.gh-pages/categories/news.m3u')).toBe(`#EXTM3U x-tvg-url="" +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-country="UK" tvg-language="English" tvg-logo="https://i.imgur.com/eNPIQ9f.png" group-title="News",BBC News HD (720p) [Not 24/7] +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +`) +}) + +it('can generate countries', () => { + expect(content('.gh-pages/countries/ru.m3u')) + .toBe(`#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml" +#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-country="RU" tvg-language="Russian" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8 +`) + + expect(content('.gh-pages/countries/uk.m3u')).toBe(`#EXTM3U x-tvg-url="" +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-country="UK" tvg-language="English" tvg-logo="https://i.imgur.com/eNPIQ9f.png" group-title="News",BBC News HD (720p) [Not 24/7] +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +`) +}) + +it('can generate languages', () => { + expect(content('.gh-pages/languages/rus.m3u')) + .toBe(`#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml" +#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-country="RU" tvg-language="Russian" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8 +`) + + expect(content('.gh-pages/languages/eng.m3u')).toBe(`#EXTM3U x-tvg-url="" +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-country="UK" tvg-language="English" tvg-logo="https://i.imgur.com/eNPIQ9f.png" group-title="News",BBC News HD (720p) [Not 24/7] +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +`) +}) + +it('can generate regions', () => { + expect(content('.gh-pages/regions/asia.m3u')) + .toBe(`#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml" +#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-country="RU" tvg-language="Russian" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8 +`) + + expect(content('.gh-pages/regions/cis.m3u')) + .toBe(`#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml" +#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-country="RU" tvg-language="Russian" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8 +`) + + expect(content('.gh-pages/regions/emea.m3u')) + .toBe(`#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml" +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-country="UK" tvg-language="English" tvg-logo="https://i.imgur.com/eNPIQ9f.png" group-title="News",BBC News HD (720p) [Not 24/7] +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-country="RU" tvg-language="Russian" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8 +`) + + expect(content('.gh-pages/regions/eur.m3u')) + .toBe(`#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml" +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-country="UK" tvg-language="English" tvg-logo="https://i.imgur.com/eNPIQ9f.png" group-title="News",BBC News HD (720p) [Not 24/7] +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-country="RU" tvg-language="Russian" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8 +`) +}) + +it('can generate channels.json', () => { + expect(content('.gh-pages/channels.json')).toBe( + `[{"name":"BBC News HD","logo":"https://i.imgur.com/eNPIQ9f.png","url":"http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8","categories":[{"name":"News","slug":"news"}],"countries":[{"name":"United Kingdom","code":"UK"}],"languages":[{"name":"English","code":"eng"}],"tvg":{"id":"BBCNews.uk","name":"BBC News HD","url":""}},{"name":"ЛДПР ТВ","logo":"https://iptvx.one/icn/ldpr-tv.png","url":"http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8","categories":[{"name":"General","slug":"general"}],"countries":[{"name":"Russia","code":"RU"}],"languages":[{"name":"Russian","code":"rus"}],"tvg":{"id":"LDPRTV.ru","name":"ЛДПР ТВ","url":"https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml"}}]` + ) +}) + +it('can generate index.category.m3u', () => { + expect(content('.gh-pages/index.category.m3u')) + .toBe(`#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml" +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-country="UK" tvg-language="English" tvg-logo="https://i.imgur.com/eNPIQ9f.png" group-title="News",BBC News HD (720p) [Not 24/7] +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-country="RU" tvg-language="Russian" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8 +`) +}) + +it('can generate index.country.m3u', () => { + expect(content('.gh-pages/index.country.m3u')) + .toBe(`#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml" +#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-country="RU" tvg-language="Russian" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="Russia",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8 +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-country="UK" tvg-language="English" tvg-logo="https://i.imgur.com/eNPIQ9f.png" group-title="United Kingdom",BBC News HD (720p) [Not 24/7] +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +`) +}) + +it('can generate index.language.m3u', () => { + expect(content('.gh-pages/index.language.m3u')) + .toBe(`#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml" +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-country="UK" tvg-language="English" tvg-logo="https://i.imgur.com/eNPIQ9f.png" group-title="English",BBC News HD (720p) [Not 24/7] +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-country="RU" tvg-language="Russian" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="Russian",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8 +`) +}) + +it('can generate index.region.m3u', () => { + expect(content('.gh-pages/index.region.m3u')) + .toBe(`#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml" +#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-country="RU" tvg-language="Russian" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="Asia",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8 +#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-country="RU" tvg-language="Russian" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="Commonwealth of Independent States",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8 +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-country="UK" tvg-language="English" tvg-logo="https://i.imgur.com/eNPIQ9f.png" group-title="Europe",BBC News HD (720p) [Not 24/7] +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-country="RU" tvg-language="Russian" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="Europe",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8 +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-country="UK" tvg-language="English" tvg-logo="https://i.imgur.com/eNPIQ9f.png" group-title="Europe, the Middle East and Africa",BBC News HD (720p) [Not 24/7] +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-country="RU" tvg-language="Russian" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="Europe, the Middle East and Africa",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8 +`) +}) + +it('can generate index.m3u', () => { + expect(content('.gh-pages/index.m3u')) + .toBe(`#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml" +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-country="UK" tvg-language="English" tvg-logo="https://i.imgur.com/eNPIQ9f.png" group-title="News",BBC News HD (720p) [Not 24/7] +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-country="RU" tvg-language="Russian" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8 +`) +}) + +it('can generate index.nsfw.m3u', () => { + expect(content('.gh-pages/index.nsfw.m3u')) + .toBe(`#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml" +#EXTINF:-1 tvg-id="BBCNews.uk" tvg-country="UK" tvg-language="English" tvg-logo="https://i.imgur.com/eNPIQ9f.png" group-title="News",BBC News HD (720p) [Not 24/7] +http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8 +#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-country="RU" tvg-language="Russian" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8 +`) +}) + +it('can generate logs categories', () => { + expect(content('logs/generate-playlists/categories.log')) + .toBe(`{"name":"General","slug":"general","count":1} +{"name":"News","slug":"news","count":1} +{"name":"Other","slug":"other","count":0} +`) +}) + +it('can generate logs countries', () => { + expect(content('logs/generate-playlists/countries.log')) + .toBe(`{"name":"Andorra","code":"AD","count":0} +{"name":"Russia","code":"RU","count":1} +{"name":"United Kingdom","code":"UK","count":1} +{"name":"International","code":"INT","count":0} +{"name":"Undefined","code":"UNDEFINED","count":0} +`) +}) + +it('can generate logs languages', () => { + expect(content('logs/generate-playlists/languages.log')) + .toBe(`{"name":"Catalan","code":"cat","count":0} +{"name":"English","code":"eng","count":1} +{"name":"Russian","code":"rus","count":1} +{"name":"Undefined","code":"undefined","count":0} +`) +}) + +it('can generate logs regions', () => { + expect(content('logs/generate-playlists/regions.log')) + .toBe(`{"name":"Asia","code":"ASIA","count":1} +{"name":"Commonwealth of Independent States","code":"CIS","count":1} +{"name":"Europe","code":"EUR","count":2} +{"name":"Europe, the Middle East and Africa","code":"EMEA","count":2} +{"name":"Undefined","code":"UNDEFINED","count":0} +`) +}) diff --git a/tests/commands/update-database.test.js b/tests/commands/update-database.test.js new file mode 100644 index 0000000000..d235e9a29d --- /dev/null +++ b/tests/commands/update-database.test.js @@ -0,0 +1,100 @@ +const fs = require('fs') +const path = require('path') +const { execSync } = require('child_process') + +beforeEach(() => { + fs.copyFileSync('tests/__data__/input/test.db', 'tests/__data__/temp/test.db') +}) + +afterEach(() => { + fs.rmdirSync('tests/__data__/temp', { recursive: true }) + fs.mkdirSync('tests/__data__/temp') +}) + +it('can update database', () => { + const result = execSync( + 'DB_FILEPATH=tests/__data__/temp/test.db LOGS_PATH=tests/__data__/input/logs EPG_CODES_FILEPATH=tests/__data__/input/codes.json node scripts/commands/update-database.js', + { encoding: 'utf8' } + ) + const database = fs.readFileSync('tests/__data__/temp/test.db', { encoding: 'utf8' }) + const lines = database.split('\n') + expect(JSON.parse(lines[0])).toMatchObject({ + name: 'ЛДПР ТВ', + id: 'LDPRTV.ru', + filepath: 'tests/__data__/output/channels/ru.m3u', + src_country: { name: 'Russia', code: 'RU', lang: 'rus' }, + tvg_country: 'RU', + countries: [{ name: 'Russia', code: 'RU', lang: 'rus' }], + regions: [ + { name: 'Asia', code: 'ASIA' }, + { name: 'Commonwealth of Independent States', code: 'CIS' }, + { name: 'Europe, the Middle East and Africa', code: 'EMEA' }, + { name: 'Europe', code: 'EUR' } + ], + languages: [{ name: 'Russian', code: 'rus' }], + categories: [{ name: 'General', slug: 'general', nsfw: false }], + tvg_url: '', + guides: ['https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml'], + logo: 'https://iptvx.one/icn/ldpr-tv.png', + resolution: { height: 1080, width: 1920 }, + status: { label: '', code: 'online', level: 1 }, + url: 'http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8', + http: { referrer: '', 'user-agent': '' }, + is_nsfw: false, + is_broken: false, + updated: true, + cluster_id: 1, + _id: '2ST8btby3mmsgPF0' + }) + expect(JSON.parse(lines[1])).toMatchObject({ + name: 'BBC News HD', + id: 'BBCNews.uk', + filepath: 'tests/__data__/output/channels/uk.m3u', + src_country: { name: 'United Kingdom', code: 'UK', lang: 'eng' }, + tvg_country: 'UK', + countries: [{ name: 'United Kingdom', code: 'UK', lang: 'eng' }], + regions: [ + { name: 'Europe, the Middle East and Africa', code: 'EMEA' }, + { name: 'Europe', code: 'EUR' } + ], + languages: [{ name: 'English', code: 'eng' }], + categories: [{ name: 'News', slug: 'news', nsfw: false }], + tvg_url: '', + guides: [], + logo: 'https://i.imgur.com/eNPIQ9f.png', + resolution: { height: 720, width: null }, + status: { label: 'Not 24/7', code: 'not_247', level: 3 }, + url: 'http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8', + http: { referrer: '', 'user-agent': '' }, + is_nsfw: false, + is_broken: false, + updated: false, + cluster_id: 3, + _id: '3TbieV1ptnZVCIdn' + }) + expect(JSON.parse(lines[2])).toMatchObject({ + name: 'ATV', + id: 'AndorraTV.ad', + filepath: 'tests/__data__/output/channels/ad.m3u', + src_country: { name: 'Andorra', code: 'AD', lang: 'cat' }, + tvg_country: 'AD', + countries: [{ name: 'Andorra', code: 'AD', lang: 'cat' }], + regions: [ + { name: 'Europe, the Middle East and Africa', code: 'EMEA' }, + { name: 'Europe', code: 'EUR' } + ], + languages: [{ name: 'Catalan', code: 'cat' }], + categories: [{ name: 'General', slug: 'general', nsfw: false }], + tvg_url: '', + guides: ['https://iptv-org.github.io/epg/guides/ad/andorradifusio.ad.epg.xml'], + logo: 'https://i.imgur.com/kJCjeQ4.png', + resolution: { height: 720, width: null }, + status: { label: 'Timeout', code: 'timeout', level: 4 }, + url: 'https://iptv-all.lanesh4d0w.repl.co/andorra/atv', + http: { referrer: '', 'user-agent': '' }, + is_nsfw: false, + is_broken: true, + updated: true, + cluster_id: 1 + }) +}) diff --git a/tests/commands/update-playlists.test.js b/tests/commands/update-playlists.test.js new file mode 100644 index 0000000000..1656f051d7 --- /dev/null +++ b/tests/commands/update-playlists.test.js @@ -0,0 +1,37 @@ +const fs = require('fs') +const path = require('path') +const { execSync } = require('child_process') + +beforeEach(() => { + fs.copyFileSync('tests/__data__/input/test.db', 'tests/__data__/temp/test.db') +}) + +afterEach(() => { + fs.rmdirSync('tests/__data__/temp', { recursive: true }) + fs.mkdirSync('tests/__data__/temp') +}) + +it('can update playlist', () => { + const result = execSync( + 'DB_FILEPATH=tests/__data__/temp/test.db node scripts/commands/update-playlists.js', + { encoding: 'utf8' } + ) + + const adPlaylist = fs.readFileSync('tests/__data__/output/channels/ad.m3u', { + encoding: 'utf8' + }) + + expect(adPlaylist).toBe(`#EXTM3U +#EXTINF:-1 tvg-id="AndorraTV.ad" tvg-country="AD" tvg-language="Catalan" tvg-logo="https://i.imgur.com/kJCjeQ4.png" group-title="General",ATV (720p) [Offline] +https://iptv-all.lanesh4d0w.repl.co/andorra/atv +`) + + const ruPlaylist = fs.readFileSync('tests/__data__/output/channels/ru.m3u', { + encoding: 'utf8' + }) + + expect(ruPlaylist).toBe(`#EXTM3U +#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-country="RU" tvg-language="Russian" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="General",ЛДПР ТВ (1080p) +http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8 +`) +}) diff --git a/tests/commands/update-readme.test.js b/tests/commands/update-readme.test.js new file mode 100644 index 0000000000..716215473e --- /dev/null +++ b/tests/commands/update-readme.test.js @@ -0,0 +1,23 @@ +const fs = require('fs') +const path = require('path') +const { execSync } = require('child_process') + +beforeEach(() => { + fs.rmdirSync(path.resolve('tests/__data__/output'), { recursive: true }) +}) + +it('can update readme.md', () => { + const result = execSync( + 'LOGS_PATH=tests/__data__/input/logs node scripts/commands/update-readme.js --config=tests/__data__/input/readme.json', + { encoding: 'utf8' } + ) + + const readme = fs.readFileSync(path.resolve('tests/__data__/output/readme.md'), { + encoding: 'utf8' + }) + const expected = fs.readFileSync(path.resolve('tests/__data__/input/readme.md'), { + encoding: 'utf8' + }) + + expect(readme).toBe(expected) +}) diff --git a/tests/commands/validate.test.js b/tests/commands/validate.test.js new file mode 100644 index 0000000000..7460b01589 --- /dev/null +++ b/tests/commands/validate.test.js @@ -0,0 +1,16 @@ +const fs = require('fs') +const path = require('path') +const { execSync } = require('child_process') + +it('can validate channels name', () => { + try { + execSync('node scripts/commands/validate.js --input-dir=tests/__data__/input/channels', { + encoding: 'utf8' + }) + } catch (err) { + expect(err.status).toBe(1) + expect(err.stdout).toBe( + `tests/__data__/input/channels/us_blocked.m3u:2 'Fox Sports' is on the blocklist due to claims of copyright holders (https://github.com/github/dmca/blob/master/2020/09/2020-09-16-dfl.md)\n\n` + ) + } +}) From 27fd83af15a6136d629e23b8bac1d76f21aa70e2 Mon Sep 17 00:00:00 2001 From: Aleksandr Statciuk Date: Sun, 12 Dec 2021 07:37:39 +0300 Subject: [PATCH 25/34] Update auto-update.yml --- .github/workflows/auto-update.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/auto-update.yml b/.github/workflows/auto-update.yml index 5fc625e2bf..97f4f161f9 100644 --- a/.github/workflows/auto-update.yml +++ b/.github/workflows/auto-update.yml @@ -94,7 +94,7 @@ jobs: git-config-email: 84861620+iptv-bot[bot]@users.noreply.github.com commit-message: '[Bot] Generate playlists' - uses: repo-sync/pull-request@v2 - if: ${{ !env.ACT }} + if: ${{ github.ref == 'refs/heads/master' }} id: pull-request with: github_token: ${{ steps.create-app-token.outputs.token }} From 6b5bfd52917de46daf59df103d2fb0ce95443838 Mon Sep 17 00:00:00 2001 From: Aleksandr Statciuk Date: Sun, 12 Dec 2021 07:39:44 +0300 Subject: [PATCH 26/34] Update cleanup.yml --- .github/workflows/cleanup.yml | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/.github/workflows/cleanup.yml b/.github/workflows/cleanup.yml index fb7a67d447..ff86dc62ad 100644 --- a/.github/workflows/cleanup.yml +++ b/.github/workflows/cleanup.yml @@ -6,28 +6,34 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 + - run: echo "::set-output name=branch_name::$(date +'bot/cleanup-%s')" + id: create-branch-name + - run: | + git config user.name 'iptv-bot[bot]' + git config user.email '84861620+iptv-bot[bot]@users.noreply.github.com' + - run: git checkout -b ${{ steps.create-branch-name.outputs.branch_name }} - run: npm install - run: node scripts/commands/create-database.js - run: node scripts/commands/cleanup-database.js - run: node scripts/commands/update-playlists.js + - run: | + git add channels/* + git commit -m "[Bot] Update playlists" - uses: tibdex/github-app-token@v1 if: ${{ !env.ACT }} id: create-app-token with: app_id: ${{ secrets.APP_ID }} private_key: ${{ secrets.APP_PRIVATE_KEY }} - - uses: peter-evans/create-pull-request@v3 + - uses: repo-sync/pull-request@v2 if: ${{ github.ref == 'refs/heads/master' }} - token: ${{ steps.create-app-token.outputs.token }} - commit-message: '[Bot] Update playlists' - committer: 'iptv-bot[bot] <84861620+iptv-bot[bot]@users.noreply.github.com>' - author: 'iptv-bot[bot] <84861620+iptv-bot[bot]@users.noreply.github.com>' - branch: bot/cleanup - branch-suffix: timestamp - delete-branch: true - base: master - title: '[Bot] Remove broken links' - body: | - This pull request is created by [cleanup][1] workflow. + id: pull-request + with: + github_token: ${{ steps.create-app-token.outputs.token }} + source_branch: ${{ steps.create-branch-name.outputs.branch_name }} + destination_branch: 'master' + pr_title: '[Bot] Remove broken links' + pr_body: | + This pull request is created by [cleanup][1] workflow. - [1]: https://github.com/iptv-org/iptv/actions/runs/${{ github.run_id }} + [1]: https://github.com/iptv-org/iptv/actions/runs/${{ github.run_id }} From 964538ceadd1a36b6068a1cf269407e3b4ff96d8 Mon Sep 17 00:00:00 2001 From: Aleksandr Statciuk Date: Sun, 12 Dec 2021 07:45:35 +0300 Subject: [PATCH 27/34] Update update-playlists.js --- scripts/commands/update-playlists.js | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/commands/update-playlists.js b/scripts/commands/update-playlists.js index acaf5998a1..648c27ee94 100644 --- a/scripts/commands/update-playlists.js +++ b/scripts/commands/update-playlists.js @@ -5,7 +5,6 @@ async function main() { let items = await db .find({}) .sort({ name: 1, 'status.level': 1, 'resolution.height': -1, url: 1 }) - items = _.uniqBy(items, 'url') const files = _.groupBy(items, 'filepath') for (const filepath in files) { From 6f6b1896d83f7b72b1886af29fd1d565df8a34a3 Mon Sep 17 00:00:00 2001 From: Aleksandr Statciuk Date: Sun, 12 Dec 2021 08:08:37 +0300 Subject: [PATCH 28/34] Update test.db --- tests/__data__/input/test.db | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/__data__/input/test.db b/tests/__data__/input/test.db index bb5733aae0..331b770816 100644 --- a/tests/__data__/input/test.db +++ b/tests/__data__/input/test.db @@ -1,3 +1,4 @@ {"name":"ЛДПР ТВ","id":"LDPRTV.ru","filepath":"tests/__data__/output/channels/ru.m3u","src_country":{"name":"Russia","code":"RU","lang":"rus"},"tvg_country":"RU","countries":[{"name":"Russia","code":"RU","lang":"rus"}],"regions":[{"name":"Asia","code":"ASIA"},{"name":"Commonwealth of Independent States","code":"CIS"},{"name":"Europe, the Middle East and Africa","code":"EMEA"},{"name":"Europe","code":"EUR"}],"languages":[{"name":"Russian","code":"rus"}],"categories":[{"name":"General","slug":"general","nsfw":false}],"tvg_url":"","guides":["https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml"],"logo":"https://iptvx.one/icn/ldpr-tv.png","resolution":{"height":1080,"width":null},"status":{"label":"","code":"online","level":1},"url":"http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8","http":{"referrer":"","user-agent":""},"is_nsfw":false,"is_broken":false,"updated":false,"cluster_id":1,"_id":"2ST8btby3mmsgPF0"} {"name":"BBC News HD","id":"BBCNews.uk","filepath":"tests/__data__/output/channels/uk.m3u","src_country":{"name":"United Kingdom","code":"UK","lang":"eng"},"tvg_country":"UK","countries":[{"name":"United Kingdom","code":"UK","lang":"eng"}],"regions":[{"name":"Europe, the Middle East and Africa","code":"EMEA"},{"name":"Europe","code":"EUR"}],"languages":[{"name":"English","code":"eng"}],"categories":[{"name":"News","slug":"news","nsfw":false}],"tvg_url":"","guides":[],"logo":"https://i.imgur.com/eNPIQ9f.png","resolution":{"height":720,"width":null},"status":{"label":"Not 24/7","code":"not_247","level":3},"url":"http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8","http":{"referrer":"","user-agent":""},"is_nsfw":false,"is_broken":false,"updated":false,"cluster_id":3,"_id":"3TbieV1ptnZVCIdn"} {"name":"ATV","id":"AndorraTV.ad","filepath":"tests/__data__/output/channels/ad.m3u","src_country":{"name":"Andorra","code":"AD","lang":"cat"},"tvg_country":"AD","countries":[{"name":"Andorra","code":"AD","lang":"cat"}],"regions":[{"name":"Europe, the Middle East and Africa","code":"EMEA"},{"name":"Europe","code":"EUR"}],"languages":[{"name":"Catalan","code":"cat"}],"categories":[{"name":"General","slug":"general","nsfw":false}],"tvg_url":"","guides":[],"logo":"https://i.imgur.com/kJCjeQ4.png","resolution":{"height":720,"width":null},"status":{"label":"Offline","code":"offline","level":5},"url":"https://iptv-all.lanesh4d0w.repl.co/andorra/atv","http":{"referrer":"","user-agent":""},"is_nsfw":false,"is_broken":true,"updated":false,"cluster_id":1,"_id":"I6cjG2xCBRFFP4sz"} +{"name":"BBC News HD","id":"AndorraTV.ad","filepath":"tests/__data__/output/channels/uk.m3u","src_country":{"name":"United Kingdom","code":"UK","lang":"eng"},"tvg_country":"UK","countries":[{"name":"United Kingdom","code":"UK","lang":"eng"}],"regions":[{"name":"Europe, the Middle East and Africa","code":"EMEA"},{"name":"Europe","code":"EUR"}],"languages":[{"name":"English","code":"eng"}],"categories":[{"name":"News","slug":"news","nsfw":false}],"tvg_url":"","guides":[],"logo":"https://i.imgur.com/eNPIQ9f.png","resolution":{"height":720,"width":null},"status":{"label":"Not 24/7","code":"not_247","level":3},"url":"http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8","http":{"referrer":"","user-agent":""},"is_nsfw":false,"is_broken":false,"updated":false,"cluster_id":3,"_id":"WTbieV1ptnZVCIdn"} From e93d677927756806769e86619d89a1a7ec6cc8d7 Mon Sep 17 00:00:00 2001 From: Aleksandr Statciuk Date: Sun, 12 Dec 2021 08:08:55 +0300 Subject: [PATCH 29/34] Update update-database.test.js --- tests/commands/update-database.test.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tests/commands/update-database.test.js b/tests/commands/update-database.test.js index d235e9a29d..f70f6fabc0 100644 --- a/tests/commands/update-database.test.js +++ b/tests/commands/update-database.test.js @@ -3,12 +3,9 @@ const path = require('path') const { execSync } = require('child_process') beforeEach(() => { - fs.copyFileSync('tests/__data__/input/test.db', 'tests/__data__/temp/test.db') -}) - -afterEach(() => { fs.rmdirSync('tests/__data__/temp', { recursive: true }) fs.mkdirSync('tests/__data__/temp') + fs.copyFileSync('tests/__data__/input/test.db', 'tests/__data__/temp/test.db') }) it('can update database', () => { From 712650e65c5897cbad0e2ceab224b2bfc446d296 Mon Sep 17 00:00:00 2001 From: Aleksandr Statciuk Date: Sun, 12 Dec 2021 08:09:01 +0300 Subject: [PATCH 30/34] Update update-database.js --- scripts/commands/update-database.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/scripts/commands/update-database.js b/scripts/commands/update-database.js index 4dad7658f3..459ab9ac22 100644 --- a/scripts/commands/update-database.js +++ b/scripts/commands/update-database.js @@ -15,6 +15,7 @@ const EPG_CODES_FILEPATH = process.env.EPG_CODES_FILEPATH || 'scripts/data/codes async function main() { await setUp() await loadDatabase() + await removeDuplicates() await loadCheckResults() await findStreamOrigins() await updateStreams() @@ -31,6 +32,16 @@ async function loadDatabase() { logger.info(`Found ${streams.length} streams`) } +async function removeDuplicates() { + logger.info('Removing duplicates...') + + const before = streams.length + streams = _.uniqBy(streams, 'id') + const after = streams.length + + logger.info(`Removed ${before - after} links`) +} + async function loadCheckResults() { logger.info('Loading check results from logs/...') From b016b8416007023b2370825fa5f3146f5587896c Mon Sep 17 00:00:00 2001 From: Aleksandr Statciuk Date: Sun, 12 Dec 2021 08:43:43 +0300 Subject: [PATCH 31/34] Update cleanup-database.js --- scripts/commands/cleanup-database.js | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/scripts/commands/cleanup-database.js b/scripts/commands/cleanup-database.js index 11f9e9e6b3..d005c48078 100644 --- a/scripts/commands/cleanup-database.js +++ b/scripts/commands/cleanup-database.js @@ -1,11 +1,21 @@ const { db, logger } = require('../core') async function main() { - const removed = await db.remove( - { 'status.code': { $in: ['timeout', 'offline'] } }, - { multi: true } - ) + logger.info(`Loading database...`) + let streams = await db.find({}) + logger.info(`Removing broken links...`) + let removed = 0 + const buffer = [] + for (const stream of streams) { + const duplicate = buffer.find(i => i.id === stream.id) + if (duplicate && ['offline', 'timeout'].includes(stream.status.code)) { + await db.remove({ _id: stream._id }) + removed++ + } else { + buffer.push(stream) + } + } db.compact() logger.info(`Removed ${removed} links`) From 325c7362ff693dea3af591fe04fbda31688c173f Mon Sep 17 00:00:00 2001 From: Aleksandr Statciuk Date: Sun, 12 Dec 2021 09:05:55 +0300 Subject: [PATCH 32/34] Update parser.js --- scripts/core/parser.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/core/parser.js b/scripts/core/parser.js index 009d274eb2..b54fd8f5a0 100644 --- a/scripts/core/parser.js +++ b/scripts/core/parser.js @@ -22,7 +22,7 @@ parser.parseLogs = async function (filepath) { parser.parseNumber = function (string) { const parsed = parseInt(string) if (isNaN(parsed)) { - logger.error('Not a number') + throw new Error('scripts/core/parser.js:parseNumber() Input value is not a number') } return parsed From 605733b365980e88330cedd7891ebd315b3f9725 Mon Sep 17 00:00:00 2001 From: Aleksandr Statciuk Date: Mon, 13 Dec 2021 01:17:46 +0300 Subject: [PATCH 33/34] Update auto-update.yml --- .github/workflows/auto-update.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/auto-update.yml b/.github/workflows/auto-update.yml index 97f4f161f9..d50866cc18 100644 --- a/.github/workflows/auto-update.yml +++ b/.github/workflows/auto-update.yml @@ -69,11 +69,19 @@ jobs: path: scripts/logs - run: npm install - run: node scripts/commands/update-database.js + - uses: actions/upload-artifact@v2 + with: + name: database + path: scripts/channels.db - run: node scripts/commands/update-playlists.js - run: | git add channels/* git commit -m "[Bot] Update playlists" - run: node scripts/commands/generate-playlists.js + - uses: actions/upload-artifact@v2 + with: + name: logs + path: scripts/logs - run: node scripts/commands/update-readme.js - run: | git add README.md From 79f1c95a49ea9519838e849c31bdb819816a9122 Mon Sep 17 00:00:00 2001 From: Aleksandr Statciuk Date: Mon, 13 Dec 2021 06:55:52 +0300 Subject: [PATCH 34/34] Update CONTRIBUTING.md --- CONTRIBUTING.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0fb17cabf1..6a330d4eaa 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -11,15 +11,15 @@ Before submitting your contribution, please make sure to take a moment and read ### Request a Channel -To request a channel, create an [issue](https://github.com/iptv-org/iptv/issues/new?assignees=&labels=channel+request&template=------channel-request.md) and complete all details requested. Understand that our community of volunteers will try to help you, but if a public link cannot be found, there is little we can do. (**IMPORTANT:** the issue should contain a request for only one channel, otherwise it will be closed immediately) +To request a channel, create an [issue](https://github.com/iptv-org/iptv/issues/new?assignees=&labels=channel+request&template=------channel-request.yml&title=Add%3A+) and complete all details requested. Understand that our community of volunteers will try to help you, but if a public link cannot be found, there is little we can do. (**IMPORTANT:** the issue should contain a request for only one channel, otherwise it will be closed immediately) ### Report a Broken Stream -To report a broadcast that is not working, create an [issue](https://github.com/iptv-org/iptv/issues/new?assignees=&labels=broken+stream&template=----broken-stream.md) with a description of the channel. (**IMPORTANT:** an issue should contain a report for only one channel, otherwise it will be closed immediately) +To report a broadcast that is not working, create an [issue](https://github.com/iptv-org/iptv/issues/new?assignees=&labels=broken+stream&template=-----broken-stream.yml&title=Replace%3A+) with a description of the channel. (**IMPORTANT:** an issue should contain a report for only one channel, otherwise it will be closed immediately) ### Request Channel Removal -Publish your DMCA notice somewhere and send us a link to it through this [form](https://github.com/iptv-org/iptv/issues/new?assignees=&labels=DMCA&template=--remove-channel.md). +Publish your DMCA notice somewhere and send us a link to it through this [form](https://github.com/iptv-org/iptv/issues/new?assignees=&labels=DMCA&template=--remove-channel.yml&title=Remove%3A+). ## Pull Request Guidelines