diff --git a/.github/workflows/auto-update.yml b/.github/workflows/auto-update.yml index dec1f3be64..d50866cc18 100644 --- a/.github/workflows/auto-update.yml +++ b/.github/workflows/auto-update.yml @@ -4,279 +4,118 @@ 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 + name: logs + path: scripts/logs + - run: npm install + - run: node scripts/commands/update-database.js + - uses: actions/upload-artifact@v2 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 + 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: - 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: 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: ${{ github.ref == 'refs/heads/master' }} + 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 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 diff --git a/.github/workflows/cleanup.yml b/.github/workflows/cleanup.yml index a030d6bc67..ff86dc62ad 100644 --- a/.github/workflows/cleanup.yml +++ b/.github/workflows/cleanup.yml @@ -2,65 +2,38 @@ 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: 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 }} - - name: Create Pull Request - id: pr - uses: repo-sync/pull-request@v2 + - uses: repo-sync/pull-request@v2 + if: ${{ github.ref == 'refs/heads/master' }} + id: pull-request with: - source_branch: 'bot/cleanup' + github_token: ${{ steps.create-app-token.outputs.token }} + source_branch: ${{ steps.create-branch-name.outputs.branch_name }} destination_branch: 'master' - pr_title: '[Bot] Cleaning playlists' + 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 }} - pr_draft: true - github_token: ${{ steps.generate-token.outputs.token }} 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 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 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 | 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. | 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", diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2d835b3e83..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&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.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&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.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&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.yml&title=Remove%3A+). ## 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. 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", 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" } } 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 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..d005c48078 --- /dev/null +++ b/scripts/commands/cleanup-database.js @@ -0,0 +1,24 @@ +const { db, logger } = require('../core') + +async function main() { + 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`) +} + +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..459ab9ac22 --- /dev/null +++ b/scripts/commands/update-database.js @@ -0,0 +1,232 @@ +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 removeDuplicates() + 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 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/...') + + 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..648c27ee94 --- /dev/null +++ b/scripts/commands/update-playlists.js @@ -0,0 +1,16 @@ +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 }) + 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() 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..b54fd8f5a0 --- /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)) { + throw new Error('scripts/core/parser.js:parseNumber() Input value is 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 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/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 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" + } +] 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 } -] +} 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" } } 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", 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 + } +} 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/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] : '' +} 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, '+') +} 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() 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..331b770816 --- /dev/null +++ b/tests/__data__/input/test.db @@ -0,0 +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"} 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..f70f6fabc0 --- /dev/null +++ b/tests/commands/update-database.test.js @@ -0,0 +1,97 @@ +const fs = require('fs') +const path = require('path') +const { execSync } = require('child_process') + +beforeEach(() => { + 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', () => { + 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` + ) + } +})