diff --git a/.dockerignore b/.dockerignore deleted file mode 100644 index 600e365..0000000 --- a/.dockerignore +++ /dev/null @@ -1 +0,0 @@ -**/node_modules \ No newline at end of file diff --git a/.eslintrc.yml b/.eslintrc.yml new file mode 100644 index 0000000..eec2e96 --- /dev/null +++ b/.eslintrc.yml @@ -0,0 +1,27 @@ +env: + commonjs: true + es6: true + node: true +extends: 'eslint:recommended' +globals: + Atomics: readonly + SharedArrayBuffer: readonly +parserOptions: + ecmaVersion: 2018 +rules: + no-empty: + - error + - { "allowEmptyCatch": true } + indent: + - error + - 4 + - { "SwitchCase": 1 } + linebreak-style: + - error + - windows + quotes: + - error + - single + semi: + - error + - always diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml deleted file mode 100644 index b4b1904..0000000 --- a/.github/ISSUE_TEMPLATE/bug.yml +++ /dev/null @@ -1,93 +0,0 @@ -name: Bug -description: File a bug report -assignees: - - AnimeDL - - AnidlSupport -labels: - - bug -title: "[BUG]: " -body: - - type: markdown - attributes: - value: | - Thank you for reporting the issues you found and have with this program. - This template will guide you through all the information we need. - - type: input - id: version - attributes: - label: Program version - description: "Which version of the program do you use?" - placeholder: "1.0.0" - validations: - required: true - - type: dropdown - id: opsystem - attributes: - label: Operating System - description: "Please tell us what OS you are using." - options: - - Windows - - Linux - - MacOS - validations: - required: true - - type: dropdown - id: gui - attributes: - label: Type - description: "Please tell us if you are using the gui or the cli version." - options: - - CLI - - GUI - validations: - required: true - - type: dropdown - id: service - attributes: - label: Service - description: "Please tell us what service the bug occured in." - options: - - Crunchyroll - - Hidive - - AnimationDigitalNetwork - - AnimeOnegai - - All - - Irrelevant - validations: - required: true - - type: input - id: command - attributes: - label: Command used - description: "Please tell us what command you used." - validations: - required: true - - type: input - id: ShowID - attributes: - label: Show ID - description: "Please provide the ID of an example show." - placeholder: "1234" - validations: - required: true - - type: input - id: Episode - attributes: - label: Episode - description: "Please provide the episode ID you used as an example." - placeholder: "1" - validations: - required: true - - type: textarea - id: output - attributes: - label: Console Output - description: "Please paste the console output from the beginning till termination here. If you are using the gui open the log folder under 'Debug > Open Log Folder' in the Menu. Please copy the content of latest.log here." - render: Shell - validations: - required: true - - type: textarea - id: additionalInfos - attributes: - label: Additional Information - description: "Do you have any additional information you can provide?" diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..0fcac98 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,18 @@ +--- +name: Bug report +about: Create a report to help us improve +title: "[BUG] " +labels: bug +assignees: '' + +--- + + + +** Main info: ** + +Script version: +Show ID: +Episode ID: + +** Additional Info: ** diff --git a/.github/ISSUE_TEMPLATE/feature.yml b/.github/ISSUE_TEMPLATE/feature.yml deleted file mode 100644 index 829c37c..0000000 --- a/.github/ISSUE_TEMPLATE/feature.yml +++ /dev/null @@ -1,29 +0,0 @@ -name: Enhancement -description: Suggest a enhancement or feature -labels: - - enhancement -title: "[Feedback]: " -body: - - type: markdown - attributes: - value: | - Thank you for giving feedback with this program. - This template will guide you through all the information we need. - - type: dropdown - id: programversion - attributes: - label: Type - description: "Is this suggestion for the CLI, GUI, or Both?" - options: - - CLI - - GUI - - Both - validations: - required: true - - type: textarea - id: suggestion - attributes: - label: Suggestion - description: "What is your suggestion?" - validations: - required: true diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index 47167bb..0000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,6 +0,0 @@ -version: 2 -updates: - - package-ecosystem: "npm" - directory: "/" - schedule: - interval: "daily" diff --git a/.github/workflows/auto-documentation.yml b/.github/workflows/auto-documentation.yml deleted file mode 100644 index 7f35044..0000000 --- a/.github/workflows/auto-documentation.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: auto-documentation - -on: - push: - branches: [ master ] - -jobs: - documentation: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - with: - ref: ${{ github.head_ref }} - - uses: pnpm/action-setup@v2 - with: - version: 8.6.6 - - name: Use Node.js - uses: actions/setup-node@v3 - with: - node-version: 20 - - run: pnpm i - - run: pnpm run docs - - uses: stefanzweifel/git-auto-commit-action@v4 - with: - commit_message: ${{ github.event.head_commit.message }} + Documentation \ No newline at end of file diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml deleted file mode 100644 index f653aca..0000000 --- a/.github/workflows/docker.yml +++ /dev/null @@ -1,32 +0,0 @@ -# This workflow will build a Node project with Docker - -name: build and push docker image - -on: - push: - branches: [ master ] - -jobs: - build-node: - - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Set up Docker Buildx - id: buildx - uses: docker/setup-buildx-action@v1 - - name: Login to DockerHub - if: ${{ github.ref == 'refs/heads/master' }} - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - name: Build and push Docker images - uses: docker/build-push-action@v2.9.0 - with: - github-token: ${{ github.token }} - push: ${{ github.ref == 'refs/heads/master' }} - tags: | - "multidl/multi-downloader-nx:latest" - - name: Image digest - run: echo ${{ steps.docker_build.outputs.digest }} diff --git a/.github/workflows/release-matrix.yml b/.github/workflows/release-matrix.yml index 28e9401..860011c 100644 --- a/.github/workflows/release-matrix.yml +++ b/.github/workflows/release-matrix.yml @@ -2,30 +2,30 @@ name: Release Builds on: release: - types: [ published ] + types: [ created ] jobs: build: + runs-on: ubuntu-latest strategy: matrix: - build_type: [ linux, macos, windows ] - build_arch: [ x64 ] - gui: [ gui, cli ] - runs-on: ubuntu-latest + build_type: [ linux64, macos64, win64 ] steps: + - name: Set build type + run: | + echo BUILD_TYPE=${{ matrix.build_type }} >> $GITHUB_ENV - name: Checkout uses: actions/checkout@v2 - - uses: pnpm/action-setup@v2 - with: - version: 8.6.6 + - name: Set up Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v2 with: - node-version: 20 + node-version: 14 check-latest: true + - name: Install Node modules - run: | - pnpm install + run: npm install + - name: Get name and version from package.json run: | test -n $(node -p -e "require('./package.json').name") && @@ -33,34 +33,14 @@ jobs: echo PACKAGE_NAME=$(node -p -e "require('./package.json').name") >> $GITHUB_ENV && echo PACKAGE_VERSION=$(node -p -e "require('./package.json').version") >> $GITHUB_ENV || exit 1 - name: Make build - run: pnpm run build-${{ matrix.build_type }}-${{ matrix.gui }} + run: npm run build-${{ env.BUILD_TYPE }} + - name: Upload release uses: actions/upload-release-asset@v1 with: upload_url: ${{ github.event.release.upload_url }} - asset_name: multi-downloader-nx-${{ matrix.build_type }}-${{ matrix.gui }}.7z - asset_path: ./lib/_builds/multi-downloader-nx-${{ matrix.build_type }}-${{ matrix.build_arch }}-${{ matrix.gui }}.7z + asset_name: ${{ env.PACKAGE_NAME }}-${{ env.PACKAGE_VERSION }}-${{ env.BUILD_TYPE }}.7z + asset_path: ./_builds/${{ env.PACKAGE_NAME }}-${{ env.PACKAGE_VERSION }}-${{ env.BUILD_TYPE }}.7z asset_content_type: application/x-7z-compressed env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - build-docker: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Set up Docker Buildx - id: buildx - uses: docker/setup-buildx-action@v1 - - name: Login to DockerHub - uses: docker/login-action@v1 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - name: Build and push Docker images - uses: docker/build-push-action@v2.9.0 - with: - github-token: ${{ github.token }} - push: true - tags: | - "multidl/multi-downloader-nx:${{ github.event.release.tag_name }}" - - name: Image digest - run: echo ${{ steps.docker_build.outputs.digest }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml deleted file mode 100644 index 63a789e..0000000 --- a/.github/workflows/test.yml +++ /dev/null @@ -1,39 +0,0 @@ -name: Style and build test - -on: - push: - branches: [ master ] - pull_request: - branches: [ master ] - -jobs: - eslint: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: pnpm/action-setup@v2 - with: - version: 8.6.6 - - name: Set up Node.js - uses: actions/setup-node@v3 - with: - node-version: 20 - check-latest: true - - run: pnpm i - - run: npx eslint . - test: - needs: eslint - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: pnpm/action-setup@v2 - with: - version: 8.6.6 - - name: Set up Node.js - uses: actions/setup-node@v3 - with: - node-version: 20 - check-latest: true - - run: pnpm i - - run: pnpm run test - diff --git a/.gitignore b/.gitignore index 30031ee..62e0b9d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,45 +1,19 @@ /bin/ff* /bin/mkv* /_builds/* -**/node_modules/ +/node_modules/ /videos/*.json -/videos/*.ts -/videos/*.m4s -/videos/*.txt .DS_Store ffmpeg mkvmerge token.yml +package-lock.json *.exe *.dll +*.ts *.mkv *.mp4 *.ass *.srt *.resume *.user.yml -lib -test.* -updates.json -*_token.yml -*_profile.yml -*_sess.yml -archive.json -guistate.json -fonts -.webpack/ -out/ -dist/ -gui/react/build/ -docker-compose.yml -crunchyendpoints -.vscode -.idea -/logs -/tmp/*/ -!videos/.gitkeep -/videos/* -/tmp/*.* -bin -widevine/* -!widevine/.gitkeep \ No newline at end of file diff --git a/@types/adnPlayerConfig.d.ts b/@types/adnPlayerConfig.d.ts deleted file mode 100644 index 82a81ec..0000000 --- a/@types/adnPlayerConfig.d.ts +++ /dev/null @@ -1,50 +0,0 @@ -export interface ADNPlayerConfig { - player: Player; -} - -export interface Player { - image: string; - options: Options; -} - -export interface Options { - user: User; - chromecast: Chromecast; - ios: Ios; - video: Video; - dock: any[]; - preference: Preference; -} - -export interface Chromecast { - appId: string; - refreshTokenUrl: string; -} - -export interface Ios { - videoUrl: string; - appUrl: string; - title: string; -} - -export interface Preference { - quality: string; - autoplay: boolean; - language: string; - green: boolean; -} - -export interface User { - hasAccess: boolean; - profileId: number; - refreshToken: string; - refreshTokenUrl: string; -} - -export interface Video { - startDate: null; - currentDate: Date; - available: boolean; - free: boolean; - url: string; -} diff --git a/@types/adnSearch.d.ts b/@types/adnSearch.d.ts deleted file mode 100644 index a8f47b7..0000000 --- a/@types/adnSearch.d.ts +++ /dev/null @@ -1,46 +0,0 @@ -export interface ADNSearch { - shows: ADNSearchShow[]; - total: number; -} - -export interface ADNSearchShow { - id: number; - title: string; - type: string; - originalTitle: string; - shortTitle: string; - reference: string; - age: string; - languages: string[]; - summary: string; - image: string; - image2x: string; - imageHorizontal: string; - imageHorizontal2x: string; - url: string; - urlPath: string; - episodeCount: number; - genres: string[]; - copyright: string; - rating: number; - ratingsCount: number; - commentsCount: number; - qualities: string[]; - simulcast: boolean; - free: boolean; - available: boolean; - download: boolean; - basedOn: string; - tagline: null; - firstReleaseYear: string; - productionStudio: string; - countryOfOrigin: string; - productionTeam: ProductionTeam[]; - nextVideoReleaseDate: null; - indexable: boolean; -} - -export interface ProductionTeam { - role: string; - name: string; -} diff --git a/@types/adnStreams.d.ts b/@types/adnStreams.d.ts deleted file mode 100644 index 8942942..0000000 --- a/@types/adnStreams.d.ts +++ /dev/null @@ -1,51 +0,0 @@ -export interface ADNStreams { - links: Links; - video: Video; - metadata: Metadata; -} - -export interface Links { - streaming: Streaming; - subtitles: Subtitles; - history: string; - nextVideoUrl: string; - previousVideoUrl: string; -} - -export interface Streaming { - [streams: string]: Streams; -} - -export interface Streams { - mobile: string; - sd: string; - hd: string; - fhd: string; - auto: string; -} - -export interface Subtitles { - all: string; -} - -export interface Metadata { - title: string; - subtitle: string; - summary: null; - rating: number; -} - -export interface Video { - guid: string; - id: number; - currentTime: number; - duration: number; - url: string; - image: string; - tcEpisodeStart?:string; - tcEpisodeEnd?: string; - tcIntroStart?: string; - tcIntroEnd?: string; - tcEndingStart?: string; - tcEndingEnd?: string; -} diff --git a/@types/adnSubtitles.d.ts b/@types/adnSubtitles.d.ts deleted file mode 100644 index ec45718..0000000 --- a/@types/adnSubtitles.d.ts +++ /dev/null @@ -1,11 +0,0 @@ -export interface ADNSubtitles { - [subtitleLang: string]: Subtitle[]; -} - -export interface Subtitle { - startTime: number; - endTime: number; - positionAlign: string; - lineAlign: string; - text: string; -} diff --git a/@types/adnVideos.d.ts b/@types/adnVideos.d.ts deleted file mode 100644 index ccf3d0b..0000000 --- a/@types/adnVideos.d.ts +++ /dev/null @@ -1,77 +0,0 @@ -export interface ADNVideos { - videos: ADNVideo[]; -} - -export interface ADNVideo { - id: number; - title: string; - name: string; - number: string; - shortNumber: string; - season: string; - reference: string; - type: string; - order: number; - image: string; - image2x: string; - summary: string; - releaseDate: Date; - duration: number; - url: string; - urlPath: string; - embeddedUrl: string; - languages: string[]; - qualities: string[]; - rating: number; - ratingsCount: number; - commentsCount: number; - available: boolean; - download: boolean; - free: boolean; - freeWithAds: boolean; - show: Show; - indexable: boolean; - isSelected?: boolean; -} - -export interface Show { - id: number; - title: string; - type: string; - originalTitle: string; - shortTitle: string; - reference: string; - age: string; - languages: string[]; - summary: string; - image: string; - image2x: string; - imageHorizontal: string; - imageHorizontal2x: string; - url: string; - urlPath: string; - episodeCount: number; - genres: string[]; - copyright: string; - rating: number; - ratingsCount: number; - commentsCount: number; - qualities: string[]; - simulcast: boolean; - free: boolean; - available: boolean; - download: boolean; - basedOn: string; - tagline: string; - firstReleaseYear: string; - productionStudio: string; - countryOfOrigin: string; - productionTeam: ProductionTeam[]; - nextVideoReleaseDate: Date; - indexable: boolean; -} - -export interface ProductionTeam { - role: string; - name: string; -} diff --git a/@types/animeOnegaiSearch.d.ts b/@types/animeOnegaiSearch.d.ts deleted file mode 100644 index 74bdfc1..0000000 --- a/@types/animeOnegaiSearch.d.ts +++ /dev/null @@ -1,88 +0,0 @@ -export interface AnimeOnegaiSearch { - text: string; - list: AOSearchResult[]; -} - -export interface AOSearchResult { - /** - * Asset ID - */ - ID: number; - CreatedAt: Date; - UpdatedAt: Date; - DeletedAt: null; - title: string; - active: boolean; - excerpt: string; - description: string; - bg: string; - poster: string; - entry: string; - code_name: string; - /** - * The Video ID required to get the streams - */ - video_entry: string; - trailer: string; - year: number; - /** - * Asset Type, Known Possibilities - * * 1 - Video - * * 2 - Series - */ - asset_type: 1 | 2; - status: number; - permalink: string; - duration: string; - subtitles: boolean; - price: number; - rent_price: number; - rating: number; - color: number | null; - classification: number; - brazil_classification: null | string; - likes: number; - views: number; - button: string; - stream_url: string; - stream_url_backup: string; - copyright: null | string; - skip_intro: null | string; - ending: null | string; - bumper_intro: string; - ads: string; - age_restriction: boolean | null; - epg: null; - allow_languages: string[] | null; - allow_countries: string[] | null; - classification_text: string; - locked: boolean; - resign: boolean; - favorite: boolean; - actors_list: null; - voiceactors_list: null; - artdirectors_list: null; - audios_list: null; - awards_list: null; - companies_list: null; - countries_list: null; - directors_list: null; - edition_list: null; - genres_list: null; - music_list: null; - photograpy_list: null; - producer_list: null; - screenwriter_list: null; - season_list: null; - tags_list: null; - chapter_id: number; - chapter_entry: string; - chapter_poster: string; - progress_time: number; - progress_percent: number; - included_subscription: number; - paid_content: number; - rent_content: number; - objectID: string; - lang: string; -} \ No newline at end of file diff --git a/@types/animeOnegaiSeasons.d.ts b/@types/animeOnegaiSeasons.d.ts deleted file mode 100644 index 3ffe879..0000000 --- a/@types/animeOnegaiSeasons.d.ts +++ /dev/null @@ -1,36 +0,0 @@ -export interface AnimeOnegaiSeasons { - ID: number; - CreatedAt: Date; - UpdatedAt: Date; - DeletedAt: null; - name: string; - number: number; - asset_id: number; - entry: string; - description: string; - active: boolean; - allow_languages: string[]; - allow_countries: string[]; - list: Episode[]; -} - -export interface Episode { - ID: number; - CreatedAt: Date; - UpdatedAt: Date; - DeletedAt: null; - name: string; - number: number; - description: string; - thumbnail: string; - entry: string; - video_entry: string; - active: boolean; - season_id: number; - stream_url: string; - skip_intro: null; - ending: null; - open_free: boolean; - asset_id: number; - age_restriction: boolean; -} diff --git a/@types/animeOnegaiSeries.d.ts b/@types/animeOnegaiSeries.d.ts deleted file mode 100644 index 52662ff..0000000 --- a/@types/animeOnegaiSeries.d.ts +++ /dev/null @@ -1,111 +0,0 @@ -export interface AnimeOnegaiSeries { - ID: number; - CreatedAt: Date; - UpdatedAt: Date; - DeletedAt: null; - title: string; - active: boolean; - excerpt: string; - description: string; - bg: string; - poster: string; - entry: string; - code_name: string; - /** - * The Video ID required to get the streams - */ - video_entry: string; - trailer: string; - year: number; - asset_type: number; - status: number; - permalink: string; - duration: string; - subtitles: boolean; - price: number; - rent_price: number; - rating: number; - color: number; - classification: number; - brazil_classification: string; - likes: number; - views: number; - button: string; - stream_url: string; - stream_url_backup: string; - copyright: string; - skip_intro: null; - ending: null; - bumper_intro: string; - ads: string; - age_restriction: boolean; - epg: null; - allow_languages: string[]; - allow_countries: string[]; - classification_text: string; - locked: boolean; - resign: boolean; - favorite: boolean; - actors_list: CtorsList[]; - voiceactors_list: CtorsList[]; - artdirectors_list: any[]; - audios_list: SList[]; - awards_list: any[]; - companies_list: any[]; - countries_list: any[]; - directors_list: CtorsList[]; - edition_list: any[]; - genres_list: SList[]; - music_list: any[]; - photograpy_list: any[]; - producer_list: any[]; - screenwriter_list: any[]; - season_list: any[]; - tags_list: TagsList[]; - chapter_id: number; - chapter_entry: string; - chapter_poster: string; - progress_time: number; - progress_percent: number; - included_subscription: number; - paid_content: number; - rent_content: number; - objectID: string; - lang: string; -} - -export interface CtorsList { - ID: number; - CreatedAt: Date; - UpdatedAt: Date; - DeletedAt: null; - name: string; - Permalink?: string; - country: number | null; - year: number | null; - death: number | null; - image: string; - genre: null; - description: string; - permalink?: string; - background?: string; -} - -export interface SList { - ID: number; - CreatedAt: Date; - UpdatedAt: Date; - DeletedAt: null; - name: string; - age_restriction?: number; -} - -export interface TagsList { - ID: number; - CreatedAt: Date; - UpdatedAt: Date; - DeletedAt: null; - name: string; - position: number; - status: boolean; -} diff --git a/@types/animeOnegaiStream.d.ts b/@types/animeOnegaiStream.d.ts deleted file mode 100644 index 7199316..0000000 --- a/@types/animeOnegaiStream.d.ts +++ /dev/null @@ -1,41 +0,0 @@ -export interface AnimeOnegaiStream { - ID: number; - CreatedAt: Date; - UpdatedAt: Date; - DeletedAt: null; - name: string; - source_url: string; - backup_url: string; - live: boolean; - token_handler: number; - entry: string; - job: string; - drm: boolean; - transcoding_content_id: string; - transcoding_asset_id: string; - status: number; - thumbnail: string; - hls: string; - dash: string; - widevine_proxy: string; - playready_proxy: string; - apple_licence: string; - apple_certificate: string; - dpath: string; - dbin: string; - subtitles: Subtitle[]; - origin: number; - offline_entry: string; - offline_status: boolean; -} - -export interface Subtitle { - ID: number; - CreatedAt: Date; - UpdatedAt: Date; - DeletedAt: null; - name: string; - lang: string; - entry_id: string; - url: string; -} diff --git a/@types/crunchyAndroidEpisodes.d.ts b/@types/crunchyAndroidEpisodes.d.ts deleted file mode 100644 index c5488c0..0000000 --- a/@types/crunchyAndroidEpisodes.d.ts +++ /dev/null @@ -1,139 +0,0 @@ -import { Images } from './crunchyEpisodeList'; - -export interface CrunchyAndroidEpisodes { - __class__: string; - __href__: string; - __resource_key__: string; - __links__: Actions; - __actions__: Actions; - total: number; - items: CrunchyAndroidEpisode[]; -} - -export interface Actions { -} - -export interface CrunchyAndroidEpisode { - __class__: string; - __href__: string; - __resource_key__: string; - __links__: Links; - __actions__: Actions; - playback: string; - id: string; - channel_id: ChannelID; - series_id: string; - series_title: string; - series_slug_title: string; - season_id: string; - season_title: string; - season_slug_title: string; - season_number: number; - episode: string; - episode_number: number; - sequence_number: number; - production_episode_id: string; - title: string; - slug_title: string; - description: string; - next_episode_id: string; - next_episode_title: string; - hd_flag: boolean; - maturity_ratings: MaturityRating[]; - extended_maturity_rating: Actions; - is_mature: boolean; - mature_blocked: boolean; - episode_air_date: Date; - upload_date: Date; - availability_starts: Date; - availability_ends: Date; - eligible_region: string; - available_date: Date; - free_available_date: Date; - premium_date: Date; - premium_available_date: Date; - is_subbed: boolean; - is_dubbed: boolean; - is_clip: boolean; - seo_title: string; - seo_description: string; - season_tags: string[]; - available_offline: boolean; - subtitle_locales: Locale[]; - availability_notes: string; - audio_locale: Locale; - versions: Version[]; - closed_captions_available: boolean; - identifier: string; - media_type: MediaType; - slug: string; - images: Images; - duration_ms: number; - is_premium_only: boolean; - listing_id: string; - hide_season_title?: boolean; - hide_season_number?: boolean; - isSelected?: boolean; - seq_id: string; -} - -export interface Links { - 'episode/channel': Link; - 'episode/next_episode': Link; - 'episode/season': Link; - 'episode/series': Link; - streams: Link; -} - -export interface Link { - href: string; -} - -export interface Thumbnail { - width: number; - height: number; - type: string; - source: string; -} - -export enum Locale { - enUS = 'en-US', - esLA = 'es-LA', - es419 = 'es-419', - esES = 'es-ES', - ptBR = 'pt-BR', - frFR = 'fr-FR', - deDE = 'de-DE', - arME = 'ar-ME', - arSA = 'ar-SA', - itIT = 'it-IT', - ruRU = 'ru-RU', - trTR = 'tr-TR', - hiIN = 'hi-IN', - zhCN = 'zh-CN', - koKR = 'ko-KR', - jaJP = 'ja-JP', -} - -export enum MediaType { - Episode = 'episode', -} - -export enum ChannelID { - Crunchyroll = 'crunchyroll', -} - -export enum MaturityRating { - Tv14 = 'TV-14', -} - -export interface Version { - audio_locale: Locale; - guid: string; - original: boolean; - variant: string; - season_guid: string; - media_guid: string; - is_premium_only: boolean; -} - diff --git a/@types/crunchyAndroidObject.d.ts b/@types/crunchyAndroidObject.d.ts deleted file mode 100644 index b4d46fa..0000000 --- a/@types/crunchyAndroidObject.d.ts +++ /dev/null @@ -1,189 +0,0 @@ -import { ImageType, Images, Image } from './objectInfo'; - -export interface CrunchyAndroidObject { - __class__: string; - __href__: string; - __resource_key__: string; - __links__: Actions; - __actions__: Actions; - total: number; - items: AndroidObject[]; -} - -export interface Actions { -} - -export interface AndroidObject { - __class__: string; - __href__: string; - __links__: Links; - __actions__: Actions; - id: string; - external_id: string; - channel_id: string; - title: string; - description: string; - promo_title: string; - promo_description: string; - type: string; - slug: string; - slug_title: string; - images: Images; - movie_listing_metadata?: MovieListingMetadata; - movie_metadata?: MovieMetadata; - playback?: string; - episode_metadata?: EpisodeMetadata; - streams_link?: string; - season_metadata?: SeasonMetadata; - linked_resource_key: string; - isSelected?: boolean; - f_num: string; - s_num: string; -} - -export interface Links { - 'episode/season': LinkData; - 'episode/series': LinkData; - resource: LinkData; - 'resource/channel': LinkData; - streams: LinkData; -} - -export interface LinkData { - href: string; -} - -export interface EpisodeMetadata { - audio_locale: Locale; - availability_ends: Date; - availability_notes: string; - availability_starts: Date; - available_date: null; - available_offline: boolean; - closed_captions_available: boolean; - duration_ms: number; - eligible_region: string; - episode: string; - episode_air_date: Date; - episode_number: number; - extended_maturity_rating: Record; - free_available_date: Date; - identifier: string; - is_clip: boolean; - is_dubbed: boolean; - is_mature: boolean; - is_premium_only: boolean; - is_subbed: boolean; - mature_blocked: boolean; - maturity_ratings: string[]; - premium_available_date: Date; - premium_date: null; - season_id: string; - season_number: number; - season_slug_title: string; - season_title: string; - sequence_number: number; - series_id: string; - series_slug_title: string; - series_title: string; - subtitle_locales: Locale[]; - tenant_categories?: string[]; - upload_date: Date; - versions: EpisodeMetadataVersion[]; -} - -export interface MovieListingMetadata { - availability_notes: string; - available_date: null; - available_offline: boolean; - duration_ms: number; - extended_description: string; - extended_maturity_rating: Record; - first_movie_id: string; - free_available_date: Date; - is_dubbed: boolean; - is_mature: boolean; - is_premium_only: boolean; - is_subbed: boolean; - mature_blocked: boolean; - maturity_ratings: string[]; - movie_release_year: number; - premium_available_date: Date; - premium_date: null; - subtitle_locales: Locale[]; - tenant_categories: string[]; -} - -export interface MovieMetadata { - availability_notes: string; - available_offline: boolean; - closed_captions_available: boolean; - duration_ms: number; - extended_maturity_rating: Record; - is_dubbed: boolean; - is_mature: boolean; - is_premium_only: boolean; - is_subbed: boolean; - mature_blocked: boolean; - maturity_ratings: string[]; - movie_listing_id: string; - movie_listing_slug_title: string; - movie_listing_title: string; -} - -export interface SeasonMetadata { - audio_locale: Locale; - audio_locales: Locale[]; - extended_maturity_rating: Record; - identifier: string; - is_mature: boolean; - mature_blocked: boolean; - maturity_ratings: string[]; - season_display_number: string; - season_sequence_number: number; - subtitle_locales: Locale[]; - versions: SeasonMetadataVersion[]; -} - -export interface SeasonMetadataVersion { - audio_locale: Locale; - guid: string; - original: boolean; - variant: string; -} -export interface SeriesMetadata { - audio_locales: Locale[]; - availability_notes: string; - episode_count: number; - extended_description: string; - extended_maturity_rating: Record; - is_dubbed: boolean; - is_mature: boolean; - is_simulcast: boolean; - is_subbed: boolean; - mature_blocked: boolean; - maturity_ratings: string[]; - season_count: number; - series_launch_year: number; - subtitle_locales: Locale[]; - tenant_categories?: string[]; -} - -export enum Locale { - enUS = 'en-US', - esLA = 'es-LA', - es419 = 'es-419', - esES = 'es-ES', - ptBR = 'pt-BR', - frFR = 'fr-FR', - deDE = 'de-DE', - arME = 'ar-ME', - arSA = 'ar-SA', - itIT = 'it-IT', - ruRU = 'ru-RU', - trTR = 'tr-TR', - hiIN = 'hi-IN', - zhCN = 'zh-CN', - koKR = 'ko-KR', - jaJP = 'ja-JP', -} \ No newline at end of file diff --git a/@types/crunchyAndroidStreams.d.ts b/@types/crunchyAndroidStreams.d.ts deleted file mode 100644 index c5e9889..0000000 --- a/@types/crunchyAndroidStreams.d.ts +++ /dev/null @@ -1,93 +0,0 @@ -export interface CrunchyAndroidStreams { - __class__: string; - __href__: string; - __resource_key__: string; - __links__: Links; - __actions__: Record; - media_id: string; - audio_locale: Locale; - subtitles: Subtitles; - closed_captions: Subtitles; - streams: Streams; - bifs: string[]; - versions: Version[]; - captions: Record; -} - -export interface Subtitles { - '': Subtitle; - 'en-US'?: Subtitle; - 'es-LA'?: Subtitle; - 'es-419'?: Subtitle; - 'es-ES'?: Subtitle; - 'pt-BR'?: Subtitle; - 'fr-FR'?: Subtitle; - 'de-DE'?: Subtitle; - 'ar-ME'?: Subtitle; - 'ar-SA'?: Subtitle; - 'it-IT'?: Subtitle; - 'ru-RU'?: Subtitle; - 'tr-TR'?: Subtitle; - 'hi-IN'?: Subtitle; - 'zh-CN'?: Subtitle; - 'ko-KR'?: Subtitle; - 'ja-JP'?: Subtitle; -} - -export interface Links { - resource: Resource; -} - -export interface Resource { - href: string; -} - -export interface Streams { - [key: string]: { [key: string]: Download }; -} - -export interface Download { - hardsub_locale: Locale; - hardsub_lang?: string; - url: string; -} - -export interface Urls { - '': Download; -} - -export interface Subtitle { - locale: Locale; - url: string; - format: string; -} - -export interface Version { - audio_locale: Locale; - guid: string; - original: boolean; - variant: string; - season_guid: string; - media_guid: string; - is_premium_only: boolean; -} - -export enum Locale { - default = '', - enUS = 'en-US', - esLA = 'es-LA', - es419 = 'es-419', - esES = 'es-ES', - ptBR = 'pt-BR', - frFR = 'fr-FR', - deDE = 'de-DE', - arME = 'ar-ME', - arSA = 'ar-SA', - itIT = 'it-IT', - ruRU = 'ru-RU', - trTR = 'tr-TR', - hiIN = 'hi-IN', - zhCN = 'zh-CN', - koKR = 'ko-KR', - jaJP = 'ja-JP', -} \ No newline at end of file diff --git a/@types/crunchyChapters.d.ts b/@types/crunchyChapters.d.ts deleted file mode 100644 index 5aafdb3..0000000 --- a/@types/crunchyChapters.d.ts +++ /dev/null @@ -1,26 +0,0 @@ -export interface CrunchyChapters { - [key: string]: CrunchyChapter; - lastUpdate: Date; - mediaId: string; -} - -export interface CrunchyChapter { - approverId: string; - distributionNumber: string; - end: number; - start: number; - title: string; - seriesId: string; - new: boolean; - type: string; -} - -export interface CrunchyOldChapter { - media_id: string; - startTime: number; - endTime: number; - duration: number; - comparedWith: string; - ordering: string; - last_updated: Date; -} \ No newline at end of file diff --git a/@types/crunchyEpisodeList.d.ts b/@types/crunchyEpisodeList.d.ts deleted file mode 100644 index 2f57ca4..0000000 --- a/@types/crunchyEpisodeList.d.ts +++ /dev/null @@ -1,134 +0,0 @@ -import { Links } from './crunchyAndroidEpisodes'; - -export interface CrunchyEpisodeList { - total: number; - data: CrunchyEpisode[]; - meta: Meta; -} - -export interface CrunchyEpisode { - next_episode_id: string; - series_id: string; - season_number: number; - next_episode_title: string; - availability_notes: string; - duration_ms: number; - series_slug_title: string; - series_title: string; - is_dubbed: boolean; - versions: Version[] | null; - identifier: string; - sequence_number: number; - eligible_region: Record; - availability_starts: Date; - images: Images; - season_id: string; - seo_title: string; - is_premium_only: boolean; - extended_maturity_rating: Record; - title: string; - production_episode_id: string; - premium_available_date: Date; - season_title: string; - seo_description: string; - audio_locale: Locale; - id: string; - media_type: MediaType; - availability_ends: Date; - free_available_date: Date; - playback: string; - channel_id: ChannelID; - episode: string; - is_mature: boolean; - listing_id: string; - episode_air_date: Date; - slug: string; - available_date: Date; - subtitle_locales: Locale[]; - slug_title: string; - available_offline: boolean; - description: string; - is_subbed: boolean; - premium_date: Date; - upload_date: Date; - season_slug_title: string; - closed_captions_available: boolean; - episode_number: number; - season_tags: any[]; - maturity_ratings: MaturityRating[]; - streams_link?: string; - mature_blocked: boolean; - is_clip: boolean; - hd_flag: boolean; - hide_season_title?: boolean; - hide_season_number?: boolean; - isSelected?: boolean; - seq_id: string; - __links__?: Links; -} - -export enum Locale { - enUS = 'en-US', - esLA = 'es-LA', - es419 = 'es-419', - esES = 'es-ES', - ptBR = 'pt-BR', - frFR = 'fr-FR', - deDE = 'de-DE', - arME = 'ar-ME', - arSA = 'ar-SA', - itIT = 'it-IT', - ruRU = 'ru-RU', - trTR = 'tr-TR', - hiIN = 'hi-IN', - zhCN = 'zh-CN', - koKR = 'ko-KR', - jaJP = 'ja-JP', -} - -export enum ChannelID { - Crunchyroll = 'crunchyroll', -} - -export interface Images { - poster_tall?: Array; - poster_wide?: Array; - promo_image?: Array; - thumbnail?: Array; -} - -export interface Image { - height: number; - source: string; - type: ImageType; - width: number; -} - -export enum ImageType { - PosterTall = 'poster_tall', - PosterWide = 'poster_wide', - PromoImage = 'promo_image', - Thumbnail = 'thumbnail', -} - -export enum MaturityRating { - Tv14 = 'TV-14', -} - -export enum MediaType { - Episode = 'episode', -} - -export interface Version { - audio_locale: Locale; - guid: string; - is_premium_only: boolean; - media_guid: string; - original: boolean; - season_guid: string; - variant: string; -} - -export interface Meta { - versions_considered?: boolean; -} \ No newline at end of file diff --git a/@types/crunchyPlayStreams.d.ts b/@types/crunchyPlayStreams.d.ts deleted file mode 100644 index 88abd2f..0000000 --- a/@types/crunchyPlayStreams.d.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { Locale } from './playbackData'; - -export interface CrunchyPlayStream { - assetId: string; - audioLocale: Locale; - bifs: string; - burnedInLocale: string; - captions: { [key: string]: Caption }; - hardSubs: { [key: string]: HardSub }; - playbackType: string; - session: Session; - subtitles: { [key: string]: Subtitle }; - token: string; - url: string; - versions: any[]; -} - -export interface Caption { - format: string; - language: string; - url: string; -} - -export interface HardSub { - hlang: string; - url: string; - quality: string; -} - -export interface Session { - renewSeconds: number; - noNetworkRetryIntervalSeconds: number; - noNetworkTimeoutSeconds: number; - maximumPauseSeconds: number; - endOfVideoUnloadSeconds: number; - sessionExpirationSeconds: number; - usesStreamLimits: boolean; -} - -export interface Subtitle { - format: string; - language: string; - url: string; -} diff --git a/@types/crunchySearch.d.ts b/@types/crunchySearch.d.ts deleted file mode 100644 index 09ade69..0000000 --- a/@types/crunchySearch.d.ts +++ /dev/null @@ -1,183 +0,0 @@ -// Generated by https://quicktype.io - -export interface CrunchySearch { - total: number; - data: CrunchySearchData[]; - meta: Record; -} - -export interface CrunchySearchData { - type: string; - count: number; - items: CrunchySearchItem[]; -} - -export interface CrunchySearchItem { - title: string; - images: Images; - series_metadata?: SeriesMetadata; - promo_description: string; - external_id: string; - slug: string; - new: boolean; - slug_title: string; - channel_id: ChannelID; - description: string; - linked_resource_key: string; - type: ItemType; - id: string; - promo_title: string; - search_metadata: SearchMetadata; - movie_listing_metadata?: MovieListingMetadata; - playback?: string; - streams_link?: string; - episode_metadata?: EpisodeMetadata; -} - -export enum ChannelID { - Crunchyroll = 'crunchyroll', -} - -export interface EpisodeMetadata { - audio_locale: Locale; - availability_ends: Date; - availability_notes: string; - availability_starts: Date; - available_date: null; - available_offline: boolean; - closed_captions_available: boolean; - duration_ms: number; - eligible_region: string[]; - episode: string; - episode_air_date: Date; - episode_number: number; - extended_maturity_rating: Record; - free_available_date: Date; - identifier: string; - is_clip: boolean; - is_dubbed: boolean; - is_mature: boolean; - is_premium_only: boolean; - is_subbed: boolean; - mature_blocked: boolean; - maturity_ratings: MaturityRating[]; - premium_available_date: Date; - premium_date: null; - season_id: string; - season_number: number; - season_slug_title: string; - season_title: string; - sequence_number: number; - series_id: string; - series_slug_title: string; - series_title: string; - subtitle_locales: Locale[]; - upload_date: Date; - versions: Version[] | null; - tenant_categories?: string[]; -} - -export enum Locale { - enUS = 'en-US', - esLA = 'es-LA', - es419 = 'es-419', - esES = 'es-ES', - ptBR = 'pt-BR', - frFR = 'fr-FR', - deDE = 'de-DE', - arME = 'ar-ME', - arSA = 'ar-SA', - itIT = 'it-IT', - ruRU = 'ru-RU', - trTR = 'tr-TR', - hiIN = 'hi-IN', - zhCN = 'zh-CN', - koKR = 'ko-KR', - jaJP = 'ja-JP', -} - -export enum MaturityRating { - Tv14 = 'TV-14', - TvMa = 'TV-MA', -} - -export interface Version { - audio_locale: Locale; - guid: string; - is_premium_only: boolean; - media_guid: string; - original: boolean; - season_guid: string; - variant: string; -} - -export interface Images { - poster_tall?: Array; - poster_wide?: Array; - promo_image?: Array; - thumbnail?: Array; -} - -export interface Image { - height: number; - source: string; - type: ImageType; - width: number; -} - -export enum ImageType { - PosterTall = 'poster_tall', - PosterWide = 'poster_wide', - PromoImage = 'promo_image', - Thumbnail = 'thumbnail', -} - -export interface MovieListingMetadata { - availability_notes: string; - available_date: null; - available_offline: boolean; - duration_ms: number; - extended_description: string; - extended_maturity_rating: Record; - first_movie_id: string; - free_available_date: Date; - is_dubbed: boolean; - is_mature: boolean; - is_premium_only: boolean; - is_subbed: boolean; - mature_blocked: boolean; - maturity_ratings: string[]; - movie_release_year: number; - premium_available_date: Date; - premium_date: null; - subtitle_locales: any[]; - tenant_categories: string[]; -} - -export interface SearchMetadata { - score: number; -} - -export interface SeriesMetadata { - audio_locales: Locale[]; - availability_notes: string; - episode_count: number; - extended_description: string; - extended_maturity_rating: Record; - is_dubbed: boolean; - is_mature: boolean; - is_simulcast: boolean; - is_subbed: boolean; - mature_blocked: boolean; - maturity_ratings: MaturityRating[]; - season_count: number; - series_launch_year: number; - subtitle_locales: Locale[]; - tenant_categories?: string[]; -} - -export enum ItemType { - Episode = 'episode', - MovieListing = 'movie_listing', - Series = 'series', -} \ No newline at end of file diff --git a/@types/crunchyTypes.d.ts b/@types/crunchyTypes.d.ts deleted file mode 100644 index 2795a50..0000000 --- a/@types/crunchyTypes.d.ts +++ /dev/null @@ -1,211 +0,0 @@ -import { HLSCallback } from 'hls-download'; -import { sxItem } from '../crunchy'; -import { LanguageItem } from '../modules/module.langsData'; -import { DownloadInfo } from './messageHandler'; -import { CrunchyPlayStreams } from './enums'; - -export type CrunchyDownloadOptions = { - hslang: string, - kstream: number, - cstream: keyof typeof CrunchyPlayStreams | 'none', - novids?: boolean, - noaudio?: boolean, - x: number, - q: number, - fileName: string, - numbers: number, - partsize: number, - callbackMaker?: (data: DownloadInfo) => HLSCallback, - timeout: number, - waittime: number, - fsRetryTime: number, - dlsubs: string[], - skipsubs: boolean, - nosubs?: boolean, - mp4: boolean, - override: string[], - videoTitle: string, - force: 'Y'|'y'|'N'|'n'|'C'|'c', - ffmpegOptions: string[], - mkvmergeOptions: string[], - defaultSub: LanguageItem, - defaultAudio: LanguageItem, - ccTag: string, - dlVideoOnce: boolean, - skipmux?: boolean, - syncTiming: boolean, - nocleanup: boolean, - chapters: boolean, - fontName: string | undefined, - originalFontSize: boolean, - fontSize: number, - dubLang: string[], -} - -export type CrunchyMultiDownload = { - dubLang: string[], - all?: boolean, - but?: boolean, - e?: string, - s?: string -} - -export type CrunchyMuxOptions = { - output: string, - skipSubMux?: boolean - keepAllVideos?: bolean - novids?: boolean, - mp4: boolean, - forceMuxer?: 'ffmpeg'|'mkvmerge', - nocleanup?: boolean, - videoTitle: string, - ffmpegOptions: string[], - mkvmergeOptions: string[], - defaultSub: LanguageItem, - defaultAudio: LanguageItem, - ccTag: string, - syncTiming: boolean, -} - -export type CrunchyEpMeta = { - data: { - mediaId: string, - lang?: LanguageItem, - playback?: string, - versions?: EpisodeVersion[] | null, - isSubbed: boolean, - isDubbed: boolean, - }[], - seriesTitle: string, - seasonTitle: string, - episodeNumber: string, - episodeTitle: string, - seasonID: string, - season: number, - showID: string, - e: string, - image: string, -} - -export type DownloadedMedia = { - type: 'Video', - lang: LanguageItem, - path: string, - isPrimary?: boolean -} | { - type: 'Audio', - lang: LanguageItem, - path: string, - isPrimary?: boolean -} | { - type: 'Chapters', - lang: LanguageItem, - path: string -} | ({ - type: 'Subtitle', - signs: boolean, - cc: boolean -} & sxItem ) - -export type ParseItem = { - __class__?: string; - isSelected?: boolean, - type?: string, - id: string, - title: string, - playback?: string, - season_number?: number|string, - episode_number?: number|string, - season_count?: number|string, - is_premium_only?: boolean, - hide_metadata?: boolean, - seq_id?: string, - f_num?: string, - s_num?: string - external_id?: string, - ep_num?: string - last_public?: string, - subtitle_locales?: string[], - availability_notes?: string, - identifier?: string, - versions?: Version[] | null, - media_type?: string | null, - movie_release_year?: number | null, -} - -export interface SeriesSearch { - total: number; - data: SeriesSearchItem[]; - meta: Meta; -} - -export interface SeriesSearchItem { - description: string; - seo_description: string; - number_of_episodes: number; - is_dubbed: boolean; - identifier: string; - channel_id: string; - slug_title: string; - season_sequence_number: number; - season_tags: string[]; - extended_maturity_rating: Record; - is_mature: boolean; - audio_locale: string; - season_number: number; - images: Record; - mature_blocked: boolean; - versions: Version[]; - title: string; - is_subbed: boolean; - id: string; - audio_locales: string[]; - subtitle_locales: string[]; - availability_notes: string; - series_id: string; - season_display_number: string; - is_complete: boolean; - keywords: any[]; - maturity_ratings: string[]; - is_simulcast: boolean; - seo_title: string; -} -export interface Version { - audio_locale: Locale; - guid: string; - original: boolean; - variant: string; -} - -export interface EpisodeVersion { - audio_locale: Locale; - guid: string; - is_premium_only: boolean; - media_guid: string; - original: boolean; - season_guid: string; - variant: string; -} - -export enum Locale { - enUS = 'en-US', - esLA = 'es-LA', - es419 = 'es-419', - esES = 'es-ES', - ptBR = 'pt-BR', - frFR = 'fr-FR', - deDE = 'de-DE', - arME = 'ar-ME', - arSA = 'ar-SA', - itIT = 'it-IT', - ruRU = 'ru-RU', - trTR = 'tr-TR', - hiIN = 'hi-IN', - zhCN = 'zh-CN', - koKR = 'ko-KR', - jaJP = 'ja-JP', -} - -export interface Meta { - versions_considered: boolean; -} diff --git a/@types/downloadedFile.d.ts b/@types/downloadedFile.d.ts deleted file mode 100644 index 9627b0c..0000000 --- a/@types/downloadedFile.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { LanguageItem } from '../modules/module.langsData'; - -export type DownloadedFile = { - path: string, - lang: LanguageItem -} \ No newline at end of file diff --git a/@types/enums.ts b/@types/enums.ts deleted file mode 100644 index 13c08cc..0000000 --- a/@types/enums.ts +++ /dev/null @@ -1,16 +0,0 @@ -export enum CrunchyPlayStreams { - 'chrome' = 'web/chrome', - 'firefox' = 'web/firefox', - 'safari' = 'web/safari', - 'edge' = 'web/edge', - 'fallback' = 'web/fallback', - 'ps4' = 'console/ps4', - 'ps5' = 'console/ps5', - 'switch' = 'console/switch', - 'samsungtv' = 'tv/samsung', - 'lgtv' = 'tv/lg', - 'rokutv' = 'tv/roku', - 'android' = 'android/phone', - 'iphone' = 'ios/iphone', - 'ipad' = 'ios/ipad', -} \ No newline at end of file diff --git a/@types/episode.d.ts b/@types/episode.d.ts deleted file mode 100644 index 291cf6d..0000000 --- a/@types/episode.d.ts +++ /dev/null @@ -1,391 +0,0 @@ -// Generated by https://quicktype.io - -export interface EpisodeData { - id: number; - title: string; - mediaDict: { [key: string]: string }; - episodeSlug: string; - starRating: number; - parent: EpisodeDataParent; - number: string; - description: string; - filename: string; - seriesBanner: string; - media: Media[]; - externalItemId: string; - contentId: string; - metaItems: MetaItems; - thumb: string; - type: Type; - default: { [key: string]: Default }; - published: boolean; - versions: VersionClass[]; - mediaCategory: string; - order: number; - seriesVersions: any[]; - source: Source; - ids: EpisodeDataIDS; - runtime: string; - siblings: PreviousSeasonEpisode[]; - seriesTitle: string; - seriesSlug: string; - next: Next; - previousSeasonEpisode: PreviousSeasonEpisode; - seasonTitle: string; - quality: Quality; - ratings: Array; - languages: TitleElement[]; - releaseDate: string; - historicalSelections: HistoricalSelections; - userRating: UserRating; -} - -export interface Default { - items: DefaultItem[]; -} - -export interface DefaultItem { - languages: string[]; - territories: string[]; - version: null; - value: Value[]; - devices: any[]; -} - -export interface Value { - name: MetaType; - value: string; - label: Label; -} - -export enum Label { - Rating = 'Rating', - RatingSystem = 'Rating System', - ReleaseDate = 'Release Date', - Synopsis = 'Synopsis', - SynopsisType = 'Synopsis Type', -} - -export enum MetaType { - Rating = 'rating', - RatingSystemType = 'RatingSystemType', - ReleaseDate = 'release-date', - Synopsis = 'synopsis', - Synopsistype = 'synopsistype', - VideoRatingType = 'VideoRatingType', -} - -export interface HistoricalSelections { - version: string; - language: string; -} - -export interface EpisodeDataIDS { - externalShowId: string; - externalSeasonId: string; - externalEpisodeId: string; -} - -export enum TitleElement { - Empty = '', - English = 'English', -} - -export interface Media { - id: number; - title: string; - experienceType: string; - created: string; - createdBy: string; - itemFieldData: Next; - keyPath: string; - filename: string; - complianceStatus: null; - events: any[]; - clients: string[]; - qcStatus: null; - qcStatusDate: null; - image: string; - thumb: string; - ext: string; - avails: Avail[]; - version: string; - startTimecode: null; - endTimecode: null; - versionId: string; - mediaType: string; - status: string; - languages: LanguageClass[]; - territories: any[]; - devices: any[]; - keyType: string; - purpose: null; - externalItemId: null | string; - proxyId: null; - externalDbId: null; - mediaChildren: MediaChild[]; - isDefault: boolean; - parent: MediaChildParent; - filePath: null | string; - mediaInfo: Next; - type: string; - approved: boolean; - mediaKey: string; - itemFields: any[]; - source: Source; - fieldData: Next; - sourceId: null | string; - timecodeOverride: null; - seriesTitle: string; - episodeTitle: string; - genre: any[]; - txDate: string; - description: string; - synopsis: string; - resolution: null; - restrictedAccess: boolean; - createdById: string; - userIdsWithAccess: any[]; - runtime?: number; - language?: TitleElement; - purchased: boolean; -} - -export interface Avail { - id: number; - description: string; - endDate: string; - startDate: string; - ids: AvailIDS; - originalAirDate: null; - physicalReleaseDate: null; - preorderDate: null; - language: TitleElement; - territory: string; - territoryCode: string; - license: string; - parentAvail: null; - item: number; - version: string; - applyToLevel: null; - availLevel: string; - availDisplayCode: string; - availStatus: string; - bundleOnly: boolean; - contentOwnerOrganization: string; - currency: null; - price: null; - purchase: string; - priceValue: string; - resolutionFormat: null; - runtimeMilliseconds: null; - seasonOrEpisodeNumber: null; - tmsid: null; - deviceList: string; - tvodSku: null; -} - -export interface AvailIDS { - externalSeasonId: string; - externalAsianId: null; - externalShowId: string; - externalEpisodeId: string; - externalEnglishId: string; - externalAlphaId: string; -} - -export type Next = Record - -export interface LanguageClass { - code: string; - id: number; - title: TitleElement; -} - -export interface MediaChild { - id: number; - title: string; - experienceType: string; - created: string; - createdBy: string; - itemFieldData: Next; - keyPath: null; - filename: string; - complianceStatus: null; - events: any[]; - clients: string[]; - qcStatus: null; - qcStatusDate: null; - image: string; - ext: string; - avails: any[]; - version: string; - startTimecode: null; - endTimecode: null; - versionId: string; - mediaType: string; - status: string; - languages: LanguageClass[]; - territories: any[]; - devices: any[]; - keyType: string; - purpose: null; - externalItemId: string; - proxyId: null; - externalDbId: null; - mediaChildren: any[]; - isDefault: boolean; - parent: MediaChildParent; - filePath: string; - mediaInfo: MediaInfo; - type: string; - approved: boolean; - mediaKey: null; - itemFields: any[]; - source: Source; - fieldData: Next; - sourceId: null; - timecodeOverride: null; - seriesTitle: string; - episodeTitle: string; - genre: any[]; - txDate: string; - description: string; - synopsis: string; - resolution: null | string; - restrictedAccess: boolean; - createdById: string; - userIdsWithAccess: any[]; - language: TitleElement; -} - -export interface MediaInfo { - imageAspectRatio: null | string; - format: string; - scanMode: null | string; - burnedInSubtitleLanguage: string; - screenAspectRatio: null | string; - subtitleFormat: null | string; - subtitleContent: null | string; - frameHeight: number | null; - frameWidth: number | null; - video: Video; -} - -export interface Video { - codecId: null | string; - container: null | string; - encodingRate: number | null; - frameRate: null | string; - height: number | null; - width: number | null; - duration: number | null; - bitRate: number | null; -} - -export interface MediaChildParent { - title: string; - type: string; - catalogParent: CatalogParent; - slug: string; - grandparentId: number; - id: number; -} - -export interface CatalogParent { - id: number; - title: string; -} - -export enum Source { - Dbb = 'dbb', -} - -export interface MetaItems { - items: Items; - filters: Filters; -} - -export interface Filters { - territory: any[]; - language: any[]; -} - -export interface Items { - 'release-date': AnimationProductionStudio; - rating: AnimationProductionStudio; - synopsis: AnimationProductionStudio; - 'animation-production-studio': AnimationProductionStudio; -} - -export interface AnimationProductionStudio { - items: AnimationProductionStudioItem[]; - label: string; - id: number; - slug: string; -} - -export interface AnimationProductionStudioItem { - id: number; - metaType: MetaType; - metaTypeId: string; - client: null; - languages: TitleElement; - territories: string; - devices: string; - isDefault: boolean; - value: Value[]; - approved: boolean; - version: null; - source: Source; -} - -export interface EpisodeDataParent { - seasonId: number; - seasonNumber: string; - title: string; - titleSlug: string; - titleType: string; - titleId: number; -} - -export interface PreviousSeasonEpisode { - seasonTitle?: string; - mediaCategory: Type; - thumb: string; - title: string; - image: string; - number: string; - id: number; - version: string[]; - order: number; - slug: string; - season?: number; - languages?: TitleElement[]; -} - -export enum Type { - Episode = 'episode', - Ova = 'ova', -} - -export interface Quality { - quality: string; - height: number; -} - -export interface UserRating { - overall: number; - ja: number; - eng: number; -} - -export interface VersionClass { - compliance_approved: boolean; - title: string; - version_id: string; - is_default: boolean; - runtime: string; - external_id: string; - id: number; -} diff --git a/@types/github.d.ts b/@types/github.d.ts deleted file mode 100644 index b597cef..0000000 --- a/@types/github.d.ts +++ /dev/null @@ -1,106 +0,0 @@ -export type GithubTag = { - name: string, - zipball_url: string, - tarball_url: string, - commit: { - sha: string, - url: string - }, - node_id: string -} - -export interface TagCompare { - url: string; - html_url: string; - permalink_url: string; - diff_url: string; - patch_url: string; - base_commit: BaseCommitClass; - merge_base_commit: BaseCommitClass; - status: string; - ahead_by: number; - behind_by: number; - total_commits: number; - commits: BaseCommitClass[]; - files: File[]; -} - -export interface BaseCommitClass { - sha: string; - node_id: string; - commit: BaseCommitCommit; - url: string; - html_url: string; - comments_url: string; - author: BaseCommitAuthor; - committer: BaseCommitAuthor; - parents: Parent[]; -} - -export interface BaseCommitAuthor { - login: string; - id: number; - node_id: string; - avatar_url: string; - gravatar_id: string; - url: string; - html_url: string; - followers_url: string; - following_url: string; - gists_url: string; - starred_url: string; - subscriptions_url: string; - organizations_url: string; - repos_url: string; - events_url: string; - received_events_url: string; - type: string; - site_admin: boolean; -} - -export interface BaseCommitCommit { - author: PurpleAuthor; - committer: PurpleAuthor; - message: string; - tree: Tree; - url: string; - comment_count: number; - verification: Verification; -} - -export interface PurpleAuthor { - name: string; - email: string; - date: string; -} - -export interface Tree { - sha: string; - url: string; -} - -export interface Verification { - verified: boolean; - reason: string; - signature: string; - payload: string; -} - -export interface Parent { - sha: string; - url: string; - html_url: string; -} - -export interface File { - sha: string; - filename: string; - status: string; - additions: number; - deletions: number; - changes: number; - blob_url: string; - raw_url: string; - contents_url: string; - patch: string; -} diff --git a/@types/hidiveDashboard.d.ts b/@types/hidiveDashboard.d.ts deleted file mode 100644 index e8ad27d..0000000 --- a/@types/hidiveDashboard.d.ts +++ /dev/null @@ -1,73 +0,0 @@ -export interface HidiveDashboard { - Code: number; - Status: string; - Message: null; - Messages: Messages; - Data: Data; - Timestamp: string; - IPAddress: string; -} - -export interface Data { - TitleRows: TitleRow[]; - LoadTime: number; -} - -export interface TitleRow { - Name: string; - Titles: Title[]; - LoadTime: number; -} - -export interface Title { - Id: number; - Name: string; - ShortSynopsis: string; - MediumSynopsis: string; - LongSynopsis: string; - KeyArtUrl: string; - MasterArtUrl: string; - Rating: null | string; - OverallRating: number; - RatingCount: number; - MALScore: null; - UserRating: number; - RunTime: number | null; - ShowInfoTitle: string; - FirstPremiereDate: Date; - EpisodeCount: number; - SeasonName: string; - RokuHDArtUrl: string; - RokuSDArtUrl: string; - IsRateable: boolean; - InQueue: boolean; - IsFavorite: boolean; - IsContinueWatching: boolean; - ContinueWatching: ContinueWatching; - Episodes: any[]; - LoadTime: number; -} - -export interface ContinueWatching { - Id: string; - ProfileId: number; - EpisodeId: number; - Status: Status | null; - CurrentTime: number; - UserId: number; - TitleId: number; - SeasonId: number; - VideoId: number; - TotalSeconds: number; - CreatedDT: Date; - ModifiedDT: Date | null; -} - -export enum Status { - Paused = 'Paused', - Playing = 'Playing', - Watching = 'Watching', -} - -export interface Messages { -} diff --git a/@types/hidiveEpisodeList.d.ts b/@types/hidiveEpisodeList.d.ts deleted file mode 100644 index ce35e8e..0000000 --- a/@types/hidiveEpisodeList.d.ts +++ /dev/null @@ -1,84 +0,0 @@ -export interface HidiveEpisodeList { - Code: number; - Status: string; - Message: null; - Messages: Record; - Data: Data; - Timestamp: string; - IPAddress: string; -} - -export interface Data { - Title: HidiveTitle; -} - -export interface HidiveTitle { - Id: number; - Name: string; - ShortSynopsis: string; - MediumSynopsis: string; - LongSynopsis: string; - KeyArtUrl: string; - MasterArtUrl: string; - Rating: string; - OverallRating: number; - RatingCount: number; - MALScore: null; - UserRating: number; - RunTime: number; - ShowInfoTitle: string; - FirstPremiereDate: Date; - EpisodeCount: number; - SeasonName: string; - RokuHDArtUrl: string; - RokuSDArtUrl: string; - IsRateable: boolean; - InQueue: boolean; - IsFavorite: boolean; - IsContinueWatching: boolean; - ContinueWatching: ContinueWatching; - Episodes: HidiveEpisode[]; - LoadTime: number; -} - -export interface ContinueWatching { - Id: string; - ProfileId: number; - EpisodeId: number; - Status: string; - CurrentTime: number; - UserId: number; - TitleId: number; - SeasonId: number; - VideoId: number; - TotalSeconds: number; - CreatedDT: Date; - ModifiedDT: Date; -} - -export interface HidiveEpisode { - Id: number; - Number: number; - Name: string; - Summary: string; - HIDIVEPremiereDate: Date; - ScreenShotSmallUrl: string; - ScreenShotCompressedUrl: string; - SeasonNumber: number; - TitleId: number; - SeasonNumberValue: number; - EpisodeNumberValue: number; - VideoKey: string; - DisplayNameLong: string; - PercentProgress: number; - LoadTime: number; -} - -export interface HidiveEpisodeExtra extends HidiveEpisode { - titleId: number; - epKey: string; - nameLong: string; - seriesTitle: string; - seriesId?: number; - isSelected: boolean; -} \ No newline at end of file diff --git a/@types/hidiveSearch.d.ts b/@types/hidiveSearch.d.ts deleted file mode 100644 index 2a6af57..0000000 --- a/@types/hidiveSearch.d.ts +++ /dev/null @@ -1,47 +0,0 @@ -export interface HidiveSearch { - Code: number; - Status: string; - Message: null; - Messages: Record; - Data: HidiveSearchData; - Timestamp: string; - IPAddress: string; -} - -export interface HidiveSearchData { - Query: string; - Slug: string; - TitleResults: HidiveSearchItem[]; - SearchId: number; - IsSearchPinned: boolean; - IsPinnedSearchAvailable: boolean; -} - -export interface HidiveSearchItem { - Id: number; - Name: string; - ShortSynopsis: string; - MediumSynopsis: string; - LongSynopsis: string; - KeyArtUrl: string; - MasterArtUrl: string; - Rating: string; - OverallRating: number; - RatingCount: number; - MALScore: null; - UserRating: number; - RunTime: number | null; - ShowInfoTitle: string; - FirstPremiereDate: Date; - EpisodeCount: number; - SeasonName: string; - RokuHDArtUrl: string; - RokuSDArtUrl: string; - IsRateable: boolean; - InQueue: boolean; - IsFavorite: boolean; - IsContinueWatching: boolean; - ContinueWatching: null; - Episodes: any[]; - LoadTime: number; -} \ No newline at end of file diff --git a/@types/hidiveTypes.d.ts b/@types/hidiveTypes.d.ts deleted file mode 100644 index 858c40d..0000000 --- a/@types/hidiveTypes.d.ts +++ /dev/null @@ -1,61 +0,0 @@ -export interface HidiveVideoList { - Code: number; - Status: string; - Message: null; - Messages: Record; - Data: HidiveVideo; - Timestamp: string; - IPAddress: string; -} - -export interface HidiveVideo { - ShowAds: boolean; - CaptionCssUrl: string; - FontSize: number; - FontScale: number; - CaptionLanguages: string[]; - CaptionLanguage: string; - CaptionVttUrls: Record; - VideoLanguages: string[]; - VideoLanguage: string; - VideoUrls: Record; - FontColorName: string; - AutoPlayNextEpisode: boolean; - MaxStreams: number; - CurrentTime: number; - FontColorCode: string; - RunTime: number; - AdUrl: null; -} - -export interface HidiveStreamList { - hls: string[]; - drm: string[]; - drmEnabled: boolean; -} - -export interface HidiveStreamInfo extends HidiveStreamList { - language?: string; - episodeTitle?: string; - seriesTitle?: string; - season?: number; - episodeNumber?: number; - uncut?: boolean; - image?: string; -} - -export interface HidiveSubtitleInfo { - language: string; - cc: boolean; - url: string; -} - -export type DownloadedMedia = { - type: 'Video', - lang: LanguageItem, - path: string, - uncut: boolean -} | ({ - type: 'Subtitle', - cc: boolean -} & sxItem ) \ No newline at end of file diff --git a/@types/iso639.d.ts b/@types/iso639.d.ts deleted file mode 100644 index 57f0f24..0000000 --- a/@types/iso639.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -declare module 'iso-639' { - export type iso639Type = { - [key: string]: { - '639-1'?: string, - '639-2'?: string - } - } - export const iso_639_2: iso639Type; -} \ No newline at end of file diff --git a/@types/items.d.ts b/@types/items.d.ts deleted file mode 100644 index cc3ae6e..0000000 --- a/@types/items.d.ts +++ /dev/null @@ -1,169 +0,0 @@ -export interface Item { - // Added later - id: string, - id_split: (number|string)[] - // Added from the start - mostRecentSvodJpnUs: MostRecentSvodJpnUs; - synopsis: string; - mediaCategory: ContentType; - mostRecentSvodUsEndTimestamp: number; - quality: QualityClass; - genres: Genre[]; - titleImages: TitleImages; - engAllTerritoryAvail: EngAllTerritoryAvail; - thumb: string; - mostRecentSvodJpnAllTerrStartTimestamp: number; - title: string; - starRating: number; - primaryAvail: PrimaryAvail; - access: Access[]; - version: Version[]; - mostRecentSvodJpnAllTerrEndTimestamp: number; - itemId: number; - versionAudio: VersionAudio; - contentType: ContentType; - mostRecentSvodUsStartTimestamp: number; - poster: string; - mostRecentSvodEngAllTerrEndTimestamp: number; - mostRecentSvodJpnUsStartTimestamp: number; - mostRecentSvodJpnUsEndTimestamp: number; - mostRecentSvodStartTimestamp: number; - mostRecentSvod: MostRecent; - altAvail: AltAvail; - ids: IDs; - mostRecentSvodUs: MostRecent; - item: Item; - mostRecentSvodEngAllTerrStartTimestamp: number; - audio: string[]; - mostRecentAvod: MostRecent; -} - -export enum ContentType { - Episode = 'episode', - Ova = 'ova', -} - -export interface IDs { - externalShowId: ID; - externalSeasonId: ExternalSeasonID; - externalEpisodeId: string; - externalAsianId?: string -} - -export interface Item { - seasonTitle: string; - seasonId: number; - episodeOrder: number; - episodeSlug: string; - created: Date; - titleSlug: string; - episodeNum: string; - episodeId: number; - titleId: number; - seasonNum: string; - ratings: Array; - showImage: string; - titleName: string; - runtime: string; - episodeName: string; - seasonOrder: number; - titleExternalId: string; -} - - -export interface MostRecent { - image?: string; - siblingStartTimestamp?: string; - devices?: Device[]; - availId?: number; - distributor?: Distributor; - quality?: MostRecentAvodQuality; - endTimestamp?: string; - mediaCategory?: ContentType; - isPromo?: boolean; - siblingType?: Purchase; - version?: Version; - territory?: Territory; - startDate?: Date; - endDate?: Date; - versionId?: number; - tier?: Device | null; - purchase?: Purchase; - startTimestamp?: string; - language?: Audio; - itemTitle?: string; - ids?: MostRecentAvodIDS; - experience?: number; - siblingEndTimestamp?: string; - item?: Item; - subscriptionRequired?: boolean; - purchased?: boolean; -} - -export interface MostRecentAvodIDS { - externalSeasonId: ExternalSeasonID; - externalAsianId: null; - externalShowId: ID; - externalEpisodeId: string; - externalEnglishId: string; - externalAlphaId: string; -} - -export enum Purchase { - AVOD = 'A-VOD', - Dfov = 'DFOV', - Est = 'EST', - Svod = 'SVOD', -} - -export enum Version { - Simulcast = 'Simulcast', - Uncut = 'Uncut', -} - -export type MostRecentSvodJpnUs = Record - -export interface QualityClass { - quality: QualityQuality; - height: number; -} - -export enum QualityQuality { - HD = 'HD', - SD = 'SD', -} - -export interface TitleImages { - showThumbnail: string; - showBackgroundSite: string; - showDetailHeaderDesktop: string; - continueWatchingDesktop: string; - showDetailHeroSite: string; - appleHorizontalBannerShow: string; - backgroundImageXbox_360: string; - applePosterCover: string; - showDetailBoxArtTablet: string; - featuredShowBackgroundTablet: string; - backgroundImageAppletvfiretv: string; - newShowDetailHero: string; - showDetailHeroDesktop: string; - showKeyart: string; - continueWatchingMobile: string; - featuredSpotlightShowPhone: string; - appleHorizontalBannerMovie: string; - featuredSpotlightShowTablet: string; - showDetailBoxArtPhone: string; - featuredShowBackgroundPhone: string; - appleSquareCover: string; - backgroundVideo: string; - showMasterKeyArt: string; - newShowDetailHeroPhone: string; - showDetailBoxArtXbox_360: string; - showDetailHeaderMobile: string; - showLogo: string; -} - -export interface VersionAudio { - Uncut?: Audio[]; - Simulcast: Audio[]; -} \ No newline at end of file diff --git a/@types/m3u8-parsed.d.ts b/@types/m3u8-parsed.d.ts deleted file mode 100644 index 7505adf..0000000 --- a/@types/m3u8-parsed.d.ts +++ /dev/null @@ -1,49 +0,0 @@ -declare module 'm3u8-parsed' { - export type M3U8 = { - allowCache: boolean, - discontinuityStarts: [], - segments: { - duration: number, - byterange?: { - length: number, - offset: number - }, - uri: string, - key: { - method: string, - uri: string, - }, - timeline: number - }[], - version: number, - mediaGroups: { - [type: string]: { - [index: string]: { - [language: string]: { - default: boolean, - autoselect: boolean, - language: string, - uri: string - } - } - } - }, - playlists: { - uri: string, - timeline: number, - attributes: { - 'CLOSED-CAPTIONS': string, - 'AUDIO': string, - 'FRAME-RATE': number, - 'RESOLUTION': { - width: number, - height: number - }, - 'CODECS': string, - 'AVERAGE-BANDWIDTH': string, - 'BANDWIDTH': number - } - }[], - } - export default function (data: string): M3U8; -} \ No newline at end of file diff --git a/@types/messageHandler.d.ts b/@types/messageHandler.d.ts deleted file mode 100644 index 7e63da4..0000000 --- a/@types/messageHandler.d.ts +++ /dev/null @@ -1,161 +0,0 @@ -import { HLSCallback } from 'hls-download'; -import type { FunimationSearch } from './funiSearch'; -import type { AvailableMuxer } from '../modules/module.args'; -import { LanguageItem } from '../modules/module.langsData'; - -export interface MessageHandler { - name: string - auth: (data: AuthData) => Promise; - version: () => Promise; - checkToken: () => Promise; - search: (data: SearchData) => Promise, - availableDubCodes: () => Promise, - availableSubCodes: () => Promise, - handleDefault: (name: string) => Promise, - resolveItems: (data: ResolveItemsData) => Promise, - listEpisodes: (id: string) => Promise, - downloadItem: (data: QueueItem) => void, - isDownloading: () => Promise, - openFolder: (path: FolderTypes) => void, - openFile: (data: [FolderTypes, string]) => void, - openURL: (data: string) => void; - getQueue: () => Promise, - removeFromQueue: (index: number) => void, - clearQueue: () => void, - setDownloadQueue: (data: boolean) => void, - getDownloadQueue: () => Promise -} - -export type FolderTypes = 'content' | 'config'; - -export type QueueItem = { - title: string, - episode: string, - fileName: string, - dlsubs: string[], - parent: { - title: string, - season: string - }, - q: number, - dlVideoOnce: boolean, - dubLang: string[], - image: string, -} & ResolveItemsData - -export type ResolveItemsData = { - id: string, - dubLang: string[], - all: boolean, - but: boolean, - novids: boolean, - noaudio: boolean - dlVideoOnce: boolean, - e: string, - fileName: string, - q: number, - dlsubs: string[] -} - -export type SearchResponseItem = { - image: string, - name: string, - desc?: string, - id: string, - lang?: string[], - rating: number -}; - -export type Episode = { - e: string, - lang: string[], - name: string, - season: string, - seasonTitle: string, - episode: string, - id: string, - img: string, - description: string, - time: string -} - -export type SearchResponse = ResponseBase -export type EpisodeListResponse = ResponseBase - -export type FuniEpisodeData = { - title: string, - episode: string, - epsiodeNumber: string, - episodeID: string, - seasonTitle: string, - seasonNumber: string, - ids: { - episode: string, - show: string, - season: string - }, - image: string -}; - -export type AuthData = { username: string, password: string }; -export type SearchData = { search: string, page?: number, 'search-type'?: string, 'search-locale'?: string }; -export type FuniGetShowData = { id: number, e?: string, but: boolean, all: boolean }; -export type FuniGetEpisodeData = { subs: FuniSubsData, fnSlug: FuniEpisodeData, simul?: boolean; dubLang: string[], s: string } -export type FuniStreamData = { force?: 'Y'|'y'|'N'|'n'|'C'|'c', callbackMaker?: (data: DownloadInfo) => HLSCallback, q: number, x: number, fileName: string, numbers: number, novids?: boolean, - timeout: number, partsize: number, fsRetryTime: number, noaudio?: boolean, mp4: boolean, ass: boolean, fontSize: number, fontName?: string, skipmux?: boolean, - forceMuxer: AvailableMuxer | undefined, simul: boolean, skipSubMux: boolean, nocleanup: boolean, override: string[], videoTitle: string, - ffmpegOptions: string[], mkvmergeOptions: string[], defaultAudio: LanguageItem, defaultSub: LanguageItem, ccTag: string } -export type FuniSubsData = { nosubs?: boolean, sub: boolean, dlsubs: string[], ccTag: string } -export type DownloadData = { - hslang?: string; id: string, e: string, dubLang: string[], dlsubs: string[], fileName: string, q: number, novids: boolean, noaudio: boolean, dlVideoOnce: boolean -} - -export type AuthResponse = ResponseBase; -export type FuniSearchReponse = ResponseBase; -export type FuniShowResponse = ResponseBase; -export type FuniGetEpisodeResponse = ResponseBase; -export type CheckTokenResponse = ResponseBase; - - -export type ResponseBase = ({ - isOk: true, - value: T -} | { - isOk: false, - reason: Error -}); - -export type ProgressData = { - total: number, - cur: number, - percent: number|string, - time: number, - downloadSpeed: number, - bytes: number -}; - -export type PossibleMessages = keyof ServiceHandler; - -export type DownloadInfo = { - image: string, - parent: { - title: string - }, - title: string, - language: LanguageItem, - fileName: string -} - -export type ExtendedProgress = { - progress: ProgressData, - downloadInfo: DownloadInfo -} - -export type GuiState = { - setup: boolean, - services: Record -} - -export type GuiStateService = { - queue: QueueItem[] -} \ No newline at end of file diff --git a/@types/mpd-parser.d.ts b/@types/mpd-parser.d.ts deleted file mode 100644 index a45968f..0000000 --- a/@types/mpd-parser.d.ts +++ /dev/null @@ -1,101 +0,0 @@ -declare module 'mpd-parser' { - export type Segment = { - uri: string, - timeline: number, - duration: number, - resolvedUri: string, - map: { - uri: string, - resolvedUri: string, - byterange?: { - length: number, - offset: number - } - }, - byterange?: { - length: number, - offset: number - }, - number: number, - presentationTime: number - } - - export type Sidx = { - uri: string, - resolvedUri: string, - byterange: { - length: number, - offset: number - }, - map: { - uri: string, - resolvedUri: string, - byterange: { - length: number, - offset: number - } - }, - duration: number, - timeline: number, - presentationTime: number, - number: number - } - - export type Playlist = { - attributes: { - NAME: string, - BANDWIDTH: number, - CODECS: string, - 'PROGRAM-ID': number, - // Following for video only - 'FRAME-RATE'?: number, - AUDIO?: string, // audio stream name - SUBTITLES?: string, - RESOLUTION?: { - width: number, - height: number - } - }, - uri: string, - endList: boolean, - timeline: number, - resolvedUri: string, - targetDuration: number, - discontinuitySequence: number, - discontinuityStarts: [], - timelineStarts: { - start: number, - timeline: number - }[], - mediaSequence: number, - contentProtection?: { - [type: string]: { - pssh?: Uint8Array - } - } - segments: Segment[] - sidx?: Sidx - } - - export type Manifest = { - allowCache: boolean, - discontinuityStarts: [], - segments: [], - endList: true, - duration: number, - playlists: Playlist[], - mediaGroups: { - AUDIO: { - audio: { - [name: string]: { - language: string, - autoselect: boolean, - default: boolean, - playlists: Playlist[] - } - } - } - } - } - export function parse(manifest: string): Manifest -} diff --git a/@types/newHidiveEpisode.d.ts b/@types/newHidiveEpisode.d.ts deleted file mode 100644 index 90fe2c7..0000000 --- a/@types/newHidiveEpisode.d.ts +++ /dev/null @@ -1,43 +0,0 @@ -export interface NewHidiveEpisode { - description: string; - duration: number; - title: string; - categories: string[]; - contentDownload: ContentDownload; - favourite: boolean; - subEvents: any[]; - thumbnailUrl: string; - longDescription: string; - posterUrl: string; - offlinePlaybackLanguages: string[]; - externalAssetId: string; - maxHeight: number; - rating: Rating; - episodeInformation: EpisodeInformation; - id: number; - accessLevel: string; - playerUrlCallback: string; - thumbnailsPreview: string; - displayableTags: any[]; - plugins: any[]; - watchStatus: string; - computedReleases: any[]; - licences: any[]; - type: string; -} - -export interface ContentDownload { - permission: string; - period: string; -} - -export interface EpisodeInformation { - seasonNumber: number; - episodeNumber: number; - season: number; -} - -export interface Rating { - rating: string; - descriptors: any[]; -} \ No newline at end of file diff --git a/@types/newHidivePlayback.d.ts b/@types/newHidivePlayback.d.ts deleted file mode 100644 index f25c863..0000000 --- a/@types/newHidivePlayback.d.ts +++ /dev/null @@ -1,33 +0,0 @@ -export interface NewHidivePlayback { - watermark: null; - skipMarkers: any[]; - annotations: null; - dash: Format[]; - hls: Format[]; -} - -export interface Format { - subtitles: Subtitle[]; - url: string; - drm: DRM; -} - -export interface DRM { - encryptionMode: string; - containerType: string; - jwtToken: string; - url: string; - keySystems: string[]; -} - -export interface Subtitle { - format: Formats; - language: string; - url: string; -} - -export enum Formats { - Scc = 'scc', - Srt = 'srt', - Vtt = 'vtt', -} diff --git a/@types/newHidiveSearch.d.ts b/@types/newHidiveSearch.d.ts deleted file mode 100644 index 60c70c2..0000000 --- a/@types/newHidiveSearch.d.ts +++ /dev/null @@ -1,91 +0,0 @@ -export interface NewHidiveSearch { - results: Result[]; -} - -export interface Result { - hits: Hit[]; - nbHits: number; - page: number; - nbPages: number; - hitsPerPage: number; - exhaustiveNbHits: boolean; - exhaustiveTypo: boolean; - exhaustive: Exhaustive; - query: string; - params: string; - index: string; - renderingContent: RenderingContent; - processingTimeMS: number; - processingTimingsMS: ProcessingTimingsMS; - serverTimeMS: number; -} - -export interface Exhaustive { - nbHits: boolean; - typo: boolean; -} - -export interface Hit { - type: string; - weight: number; - id: number; - name: string; - description: string; - meta: RenderingContent; - coverUrl: string; - smallCoverUrl: string; - seasonsCount: number; - tags: string[]; - localisations: HitLocalisations; - ratings: Ratings; - objectID: string; - _highlightResult: HighlightResult; -} - -export interface HighlightResult { - name: Description; - description: Description; - tags: Description[]; - localisations: HighlightResultLocalisations; -} - -export interface Description { - value: string; - matchLevel: string; - matchedWords: string[]; - fullyHighlighted?: boolean; -} - -export interface HighlightResultLocalisations { - en_US: PurpleEnUS; -} - -export interface PurpleEnUS { - title: Description; - description: Description; -} - -export interface HitLocalisations { - [language: string]: HitLocalization; -} - -export interface HitLocalization { - title: string; - description: string; -} - -export interface RenderingContent { -} - -export interface Ratings { - US: string[]; -} - -export interface ProcessingTimingsMS { - _request: Request; -} - -export interface Request { - queue: number; - roundTrip: number; -} diff --git a/@types/newHidiveSeason.d.ts b/@types/newHidiveSeason.d.ts deleted file mode 100644 index 0ed1b37..0000000 --- a/@types/newHidiveSeason.d.ts +++ /dev/null @@ -1,89 +0,0 @@ -export interface NewHidiveSeason { - title: string; - description: string; - longDescription: string; - smallCoverUrl: string; - coverUrl: string; - titleUrl: string; - posterUrl: string; - seasonNumber: number; - episodeCount: number; - displayableTags: any[]; - rating: Rating; - contentRating: Rating; - id: number; - series: Series; - episodes: Episode[]; - paging: Paging; - licences: any[]; -} - -export interface Rating { - rating: string; - descriptors: any[]; -} - -export interface Episode { - accessLevel: string; - availablePurchases?: any[]; - licenceIds?: any[]; - type: string; - id: number; - title: string; - description: string; - thumbnailUrl: string; - posterUrl: string; - duration: number; - favourite: boolean; - contentDownload: ContentDownload; - offlinePlaybackLanguages: string[]; - externalAssetId: string; - subEvents: any[]; - maxHeight: number; - thumbnailsPreview: string; - longDescription: string; - episodeInformation: EpisodeInformation; - categories: string[]; - displayableTags: any[]; - watchStatus: string; - computedReleases: any[]; -} - -export interface ContentDownload { - permission: string; -} - -export interface EpisodeInformation { - seasonNumber: number; - episodeNumber: number; - season: number; -} - -export interface Paging { - moreDataAvailable: boolean; - lastSeen: number; -} - -export interface Series { - seriesId: number; - title: string; - description: string; - longDescription: string; - displayableTags: any[]; - rating: Rating; - contentRating: Rating; -} - -export interface NewHidiveSeriesExtra extends Series { - season: NewHidiveSeason; -} - -export interface NewHidiveEpisodeExtra extends Episode { - titleId: number; - nameLong: string; - seasonTitle: string; - seriesTitle: string; - seriesId?: number; - isSelected: boolean; - jwtToken?: string; -} \ No newline at end of file diff --git a/@types/newHidiveSeries.d.ts b/@types/newHidiveSeries.d.ts deleted file mode 100644 index 4391406..0000000 --- a/@types/newHidiveSeries.d.ts +++ /dev/null @@ -1,35 +0,0 @@ -export interface NewHidiveSeries { - id: number; - title: string; - description: string; - longDescription: string; - smallCoverUrl: string; - coverUrl: string; - titleUrl: string; - posterUrl: string; - seasons: Season[]; - rating: Rating; - contentRating: Rating; - displayableTags: any[]; - paging: Paging; -} - -export interface Rating { - rating: string; - descriptors: any[]; -} - -export interface Paging { - moreDataAvailable: boolean; - lastSeen: number; -} - -export interface Season { - title: string; - description: string; - longDescription: string; - seasonNumber: number; - episodeCount: number; - displayableTags: any[]; - id: number; -} diff --git a/@types/objectInfo.d.ts b/@types/objectInfo.d.ts deleted file mode 100644 index 096e2c3..0000000 --- a/@types/objectInfo.d.ts +++ /dev/null @@ -1,211 +0,0 @@ -// Generated by https://quicktype.io - -export interface ObjectInfo { - total: number; - data: CrunchyObject[]; - meta: Record; -} - -export interface CrunchyObject { - __links__?: Links; - channel_id: string; - slug: string; - images: Images; - linked_resource_key: string; - description: string; - promo_description: string; - external_id: string; - title: string; - series_metadata?: SeriesMetadata; - id: string; - slug_title: string; - type: string; - promo_title: string; - movie_listing_metadata?: MovieListingMetadata; - movie_metadata?: MovieMetadata; - playback?: string; - episode_metadata?: EpisodeMetadata; - streams_link?: string; - season_metadata?: SeasonMetadata; - isSelected?: boolean; - f_num: string; - s_num: string; -} - -export interface Links { - 'episode/season': LinkData; - 'episode/series': LinkData; - resource: LinkData; - 'resource/channel': LinkData; - streams: LinkData; -} - -export interface LinkData { - href: string; -} - -export interface EpisodeMetadata { - audio_locale: Locale; - availability_ends: Date; - availability_notes: string; - availability_starts: Date; - available_date: null; - available_offline: boolean; - closed_captions_available: boolean; - duration_ms: number; - eligible_region: string; - episode: string; - episode_air_date: Date; - episode_number: number; - extended_maturity_rating: Record; - free_available_date: Date; - identifier: string; - is_clip: boolean; - is_dubbed: boolean; - is_mature: boolean; - is_premium_only: boolean; - is_subbed: boolean; - mature_blocked: boolean; - maturity_ratings: string[]; - premium_available_date: Date; - premium_date: null; - season_id: string; - season_number: number; - season_slug_title: string; - season_title: string; - sequence_number: number; - series_id: string; - series_slug_title: string; - series_title: string; - subtitle_locales: Locale[]; - tenant_categories?: string[]; - upload_date: Date; - versions: EpisodeMetadataVersion[]; -} - -export interface EpisodeMetadataVersion { - audio_locale: Locale; - guid: string; - is_premium_only: boolean; - media_guid: string; - original: boolean; - season_guid: string; - variant: string; -} - -export interface Images { - poster_tall?: Array; - poster_wide?: Array; - promo_image?: Array; - thumbnail?: Array; -} - -export interface Image { - height: number; - source: string; - type: ImageType; - width: number; -} - -export enum ImageType { - PosterTall = 'poster_tall', - PosterWide = 'poster_wide', - PromoImage = 'promo_image', - Thumbnail = 'thumbnail', -} - -export interface MovieListingMetadata { - availability_notes: string; - available_date: null; - available_offline: boolean; - duration_ms: number; - extended_description: string; - extended_maturity_rating: Record; - first_movie_id: string; - free_available_date: Date; - is_dubbed: boolean; - is_mature: boolean; - is_premium_only: boolean; - is_subbed: boolean; - mature_blocked: boolean; - maturity_ratings: string[]; - movie_release_year: number; - premium_available_date: Date; - premium_date: null; - subtitle_locales: Locale[]; - tenant_categories: string[]; -} - -export interface MovieMetadata { - availability_notes: string; - available_offline: boolean; - closed_captions_available: boolean; - duration_ms: number; - extended_maturity_rating: Record; - is_dubbed: boolean; - is_mature: boolean; - is_premium_only: boolean; - is_subbed: boolean; - mature_blocked: boolean; - maturity_ratings: string[]; - movie_listing_id: string; - movie_listing_slug_title: string; - movie_listing_title: string; -} - -export interface SeasonMetadata { - audio_locale: Locale; - audio_locales: Locale[]; - extended_maturity_rating: Record; - identifier: string; - is_mature: boolean; - mature_blocked: boolean; - maturity_ratings: string[]; - season_display_number: string; - season_sequence_number: number; - subtitle_locales: Locale[]; - versions: SeasonMetadataVersion[]; -} - -export interface SeasonMetadataVersion { - audio_locale: Locale; - guid: string; - original: boolean; - variant: string; -} -export interface SeriesMetadata { - audio_locales: Locale[]; - availability_notes: string; - episode_count: number; - extended_description: string; - extended_maturity_rating: Record; - is_dubbed: boolean; - is_mature: boolean; - is_simulcast: boolean; - is_subbed: boolean; - mature_blocked: boolean; - maturity_ratings: string[]; - season_count: number; - series_launch_year: number; - subtitle_locales: Locale[]; - tenant_categories?: string[]; -} - -export enum Locale { - enUS = 'en-US', - esLA = 'es-LA', - es419 = 'es-419', - esES = 'es-ES', - ptBR = 'pt-BR', - frFR = 'fr-FR', - deDE = 'de-DE', - arME = 'ar-ME', - arSA = 'ar-SA', - itIT = 'it-IT', - ruRU = 'ru-RU', - trTR = 'tr-TR', - hiIN = 'hi-IN', - zhCN = 'zh-CN', - koKR = 'ko-KR', - jaJP = 'ja-JP', -} \ No newline at end of file diff --git a/@types/pkg.d.ts b/@types/pkg.d.ts deleted file mode 100644 index b22e702..0000000 --- a/@types/pkg.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -declare module 'pkg' { - export async function exec(config: string[]); -} \ No newline at end of file diff --git a/@types/playbackData.d.ts b/@types/playbackData.d.ts deleted file mode 100644 index 8b4da69..0000000 --- a/@types/playbackData.d.ts +++ /dev/null @@ -1,119 +0,0 @@ -// Generated by https://quicktype.io -export interface PlaybackData { - total: number; - data: { [key: string]: { [key: string]: StreamDetails } }[]; - meta: Meta; -} - -export interface StreamList { - download_hls: CrunchyStreams; - drm_adaptive_hls: CrunchyStreams; - multitrack_adaptive_hls_v2: CrunchyStreams; - vo_adaptive_hls: CrunchyStreams; - vo_drm_adaptive_hls: CrunchyStreams; - adaptive_hls: CrunchyStreams; - drm_download_dash: CrunchyStreams; - drm_download_hls: CrunchyStreams; - drm_multitrack_adaptive_hls_v2: CrunchyStreams; - vo_drm_adaptive_dash: CrunchyStreams; - adaptive_dash: CrunchyStreams; - urls: CrunchyStreams; - vo_adaptive_dash: CrunchyStreams; - download_dash: CrunchyStreams; - drm_adaptive_dash: CrunchyStreams; -} - -export interface CrunchyStreams { - '': StreamDetails; - 'en-US'?: StreamDetails; - 'es-LA'?: StreamDetails; - 'es-419'?: StreamDetails; - 'es-ES'?: StreamDetails; - 'pt-BR'?: StreamDetails; - 'fr-FR'?: StreamDetails; - 'de-DE'?: StreamDetails; - 'ar-ME'?: StreamDetails; - 'ar-SA'?: StreamDetails; - 'it-IT'?: StreamDetails; - 'ru-RU'?: StreamDetails; - 'tr-TR'?: StreamDetails; - 'hi-IN'?: StreamDetails; - 'zh-CN'?: StreamDetails; - 'ko-KR'?: StreamDetails; - 'ja-JP'?: StreamDetails; - [string: string]: StreamDetails; -} - -export interface StreamDetails { - //hardsub_locale: Locale; - hardsub_locale: string; - url: string; - hardsub_lang?: string; - audio_lang?: string; - type?: string; -} -export interface Meta { - media_id: string; - subtitles: Subtitles; - bifs: string[]; - versions: Version[]; - audio_locale: Locale; - closed_captions: Subtitles; - captions: Subtitles; -} - -export interface Subtitles { - ''?: SubtitleInfo; - 'en-US'?: SubtitleInfo; - 'es-LA'?: SubtitleInfo; - 'es-419'?: SubtitleInfo; - 'es-ES'?: SubtitleInfo; - 'pt-BR'?: SubtitleInfo; - 'fr-FR'?: SubtitleInfo; - 'de-DE'?: SubtitleInfo; - 'ar-ME'?: SubtitleInfo; - 'ar-SA'?: SubtitleInfo; - 'it-IT'?: SubtitleInfo; - 'ru-RU'?: SubtitleInfo; - 'tr-TR'?: SubtitleInfo; - 'hi-IN'?: SubtitleInfo; - 'zh-CN'?: SubtitleInfo; - 'ko-KR'?: SubtitleInfo; - 'ja-JP'?: SubtitleInfo; -} - - -export interface SubtitleInfo { - format: string; - locale: Locale; - url: string; -} -export interface Version { - audio_locale: Locale; - guid: string; - is_premium_only: boolean; - media_guid: string; - original: boolean; - season_guid: string; - variant: string; -} - -export enum Locale { - default = '', - enUS = 'en-US', - esLA = 'es-LA', - es419 = 'es-419', - esES = 'es-ES', - ptBR = 'pt-BR', - frFR = 'fr-FR', - deDE = 'de-DE', - arME = 'ar-ME', - arSA = 'ar-SA', - itIT = 'it-IT', - ruRU = 'ru-RU', - trTR = 'tr-TR', - hiIN = 'hi-IN', - zhCN = 'zh-CN', - koKR = 'ko-KR', - jaJP = 'ja-JP', -} \ No newline at end of file diff --git a/@types/randomEvents.d.ts b/@types/randomEvents.d.ts deleted file mode 100644 index 41ea519..0000000 --- a/@types/randomEvents.d.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { ExtendedProgress, QueueItem } from './messageHandler'; - -export type RandomEvents = { - progress: ExtendedProgress, - finish: undefined, - queueChange: QueueItem[], - current: QueueItem|undefined -} - -export interface RandomEvent { - name: T, - data: RandomEvents[T] -} - -export type Handler = (data: RandomEvent) => unknown; \ No newline at end of file diff --git a/@types/removeNPMAbsolutePaths.d.ts b/@types/removeNPMAbsolutePaths.d.ts deleted file mode 100644 index b48935a..0000000 --- a/@types/removeNPMAbsolutePaths.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -declare module 'removeNPMAbsolutePaths' { - export default async function modulesCleanup(path: string); -} \ No newline at end of file diff --git a/@types/sei-helper.d.ts b/@types/sei-helper.d.ts deleted file mode 100644 index 4617d82..0000000 --- a/@types/sei-helper.d.ts +++ /dev/null @@ -1,14 +0,0 @@ -declare module 'sei-helper' { - export async function question(qStr: string): Promise; - export function cleanupFilename(str: string): string; - export const cookie: { - parse: (data: Record) => Record - }; - export function formatTime(time: number): string -} \ No newline at end of file diff --git a/@types/serviceClassInterface.d.ts b/@types/serviceClassInterface.d.ts deleted file mode 100644 index aefc890..0000000 --- a/@types/serviceClassInterface.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -export interface ServiceClass { - cli: () => Promise -} \ No newline at end of file diff --git a/@types/streamData.d.ts b/@types/streamData.d.ts deleted file mode 100644 index 351c96f..0000000 --- a/@types/streamData.d.ts +++ /dev/null @@ -1,28 +0,0 @@ -// Generated by https://quicktype.io - -export interface StreamData { - items: Item[]; - watchHistorySaveInterval: number; - errors?: Error[] -} - -export interface Error { - detail: string, - code: number -} - -export interface Item { - src: string; - kind: string; - isPromo: boolean; - videoType: string; - aips: Aip[]; - experienceId: string; - showAds: boolean; - id: number; -} - -export interface Aip { - out: number; - in: number; -} diff --git a/@types/updateFile.d.ts b/@types/updateFile.d.ts deleted file mode 100644 index 7f00777..0000000 --- a/@types/updateFile.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -export type UpdateFile = { - lastCheck: number, - nextCheck: number -} \ No newline at end of file diff --git a/@types/ws.d.ts b/@types/ws.d.ts deleted file mode 100644 index 3669f28..0000000 --- a/@types/ws.d.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { GUIConfig } from '../modules/module.cfg-loader'; -import { AuthResponse, CheckTokenResponse, EpisodeListResponse, FolderTypes, QueueItem, ResolveItemsData, SearchData, SearchResponse } from './messageHandler'; - -export type WSMessage = { - name: T, - data: MessageTypes[T][P] -} - -export type WSMessageWithID = WSMessage & { - id: string -} - -export type UnknownWSMessage = { - name: keyof MessageTypes, - data: MessageTypes[keyof MessageTypes][0], - id: string -} - -export type MessageTypes = { - 'auth': [AuthData, AuthResponse], - 'version': [undefined, string], - 'checkToken': [undefined, CheckTokenResponse], - 'search': [SearchData, SearchResponse], - 'default': [string, unknown], - 'availableDubCodes': [undefined, string[]], - 'availableSubCodes': [undefined, string[]], - 'resolveItems': [ResolveItemsData, boolean], - 'listEpisodes': [string, EpisodeListResponse], - 'downloadItem': [QueueItem, undefined], - 'isDownloading': [undefined, boolean], - 'openFolder': [FolderTypes, undefined], - 'changeProvider': [undefined, boolean], - 'type': [undefined, 'crunchy'|'hidive'|'ao'|'adn'|undefined], - 'setup': ['crunchy'|'hidive'|'ao'|'adn'|undefined, undefined], - 'openFile': [[FolderTypes, string], undefined], - 'openURL': [string, undefined], - 'isSetup': [undefined, boolean], - 'setupServer': [GUIConfig, boolean], - 'requirePassword': [undefined, boolean], - 'getQueue': [undefined, QueueItem[]], - 'removeFromQueue': [number, undefined], - 'clearQueue': [undefined, undefined], - 'setDownloadQueue': [boolean, undefined], - 'getDownloadQueue': [undefined, boolean] -} \ No newline at end of file diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 9d5ee24..0000000 --- a/Dockerfile +++ /dev/null @@ -1,39 +0,0 @@ -FROM node AS builder -WORKDIR "/app" -COPY . . - -# Install 7z for packaging - -RUN apt-get update -RUN apt-get install p7zip-full -y - -# Update bin-path for docker/linux - -RUN echo 'ffmpeg: "./bin/ffmpeg/ffmpeg"\nmkvmerge: "./bin/mkvtoolnix/mkvmerge"' > /app/config/bin-path.yml - -#Build AniDL - -RUN npm install -g pnpm -RUN pnpm i -RUN pnpm run build-linux-gui - -# Move build to new Clean Image - -FROM node -WORKDIR "/app" -COPY --from=builder /app/lib/_builds/multi-downloader-nx-linux-x64-gui ./ - -# Install mkvmerge and ffmpeg - -RUN mkdir -p /app/bin/mkvtoolnix -RUN mkdir -p /app/bin/ffmpeg - -RUN apt-get update -RUN apt-get install xdg-utils -y -RUN apt-get install mkvtoolnix -y -#RUN apt-get install ffmpeg -y - -RUN mv /usr/bin/mkvmerge /app/bin/mkvtoolnix/mkvmerge -#RUN mv /usr/bin/ffmpeg /app/bin/ffmpeg/ffmpeg - -CMD [ "/app/aniDL" ] \ No newline at end of file diff --git a/LICENSE.md b/LICENSE.md index 0ce9c55..256c27e 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2019-2021 AniDL +Copyright (c) 2019 AniDL Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/TODO.md b/TODO.md deleted file mode 100644 index 467af29..0000000 --- a/TODO.md +++ /dev/null @@ -1,15 +0,0 @@ -# Todo/Future Ideas list - -- [ ] Look into implementing wvd file support -- [ ] Merge sync branch with latest master - - [ ] Finish implementing old algorithm - - [ ] Look into adding suggested algorithm [#599](https://github.com/anidl/multi-downloader-nx/issues/599) -- [ ] Remove Funimation -- [ ] Remove old hidive API or find a way to make it work -- [ ] Look into adding other services -- [ ] Refactor downloading code - - [ ] Allow audio and video download at the same time - - [ ] Reduce/Refactor the amount of duplicate/boilerplate code required - - [ ] Create a generic service class for the CLI with set inputs/outputs - - [ ] Modularize site modules to ease addition of new sites - - [ ] Create generic MPD/M3U8 playlist downloader diff --git a/adn.ts b/adn.ts deleted file mode 100644 index d9202db..0000000 --- a/adn.ts +++ /dev/null @@ -1,924 +0,0 @@ -// Package Info -import packageJson from './package.json'; - -// Node -import path from 'path'; -import fs from 'fs-extra'; -import crypto from 'crypto'; - -// Plugins -import shlp from 'sei-helper'; -import m3u8 from 'm3u8-parsed'; - -// Modules -import * as fontsData from './modules/module.fontsData'; -import * as langsData from './modules/module.langsData'; -import * as yamlCfg from './modules/module.cfg-loader'; -import * as yargs from './modules/module.app-args'; -import * as reqModule from './modules/module.fetch'; -import Merger, { Font, MergerInput, SubtitleInput } from './modules/module.merger'; -import streamdl from './modules/hls-download'; -import { console } from './modules/log'; -import { domain } from './modules/module.api-urls'; -import { downloaded } from './modules/module.downloadArchive'; -import parseSelect from './modules/module.parseSelect'; -import parseFileName, { Variable } from './modules/module.filename'; -import { AvailableFilenameVars } from './modules/module.args'; - -// Types -import { ServiceClass } from './@types/serviceClassInterface'; -import { AuthData, AuthResponse, SearchData, SearchResponse, SearchResponseItem } from './@types/messageHandler'; -import { sxItem } from './crunchy'; -import { DownloadedMedia } from './@types/hidiveTypes'; -import { ADNSearch, ADNSearchShow } from './@types/adnSearch'; -import { ADNVideo, ADNVideos } from './@types/adnVideos'; -import { ADNPlayerConfig } from './@types/adnPlayerConfig'; -import { ADNStreams } from './@types/adnStreams'; -import { ADNSubtitles } from './@types/adnSubtitles'; - -export default class AnimationDigitalNetwork implements ServiceClass { - public cfg: yamlCfg.ConfigObject; - public locale: string; - private token: Record; - private req: reqModule.Req; - private posAlignMap: { [key: string]: number } = { - 'start': 1, - 'end': 3 - }; - private lineAlignMap: { [key: string]: number } = { - 'middle': 8, - 'end': 4 - }; - private jpnStrings: string[] = [ - 'vostf', - 'vostde' - ]; - private deuStrings: string[] = [ - 'vde' - ]; - private fraStrings: string[] = [ - 'vf' - ]; - private deuSubStrings: string[] = [ - 'vde', - 'vostde' - ]; - private fraSubStrings: string[] = [ - 'vf', - 'vostf' - ]; - - constructor(private debug = false) { - this.cfg = yamlCfg.loadCfg(); - this.token = yamlCfg.loadADNToken(); - this.req = new reqModule.Req(domain, debug, false, 'adn'); - this.locale = 'fr'; - } - - public async cli() { - console.info(`\n=== Multi Downloader NX ${packageJson.version} ===\n`); - const argv = yargs.appArgv(this.cfg.cli); - if (['fr', 'de'].includes(argv.locale)) - this.locale = argv.locale; - if (argv.debug) - this.debug = true; - - // load binaries - this.cfg.bin = await yamlCfg.loadBinCfg(); - if (argv.allDubs) { - argv.dubLang = langsData.dubLanguageCodes; - } - if (argv.auth) { - //Authenticate - await this.doAuth({ - username: argv.username ?? await shlp.question('[Q] LOGIN/EMAIL'), - password: argv.password ?? await shlp.question('[Q] PASSWORD ') - }); - } else if (argv.search && argv.search.length > 2) { - //Search - await this.doSearch({ ...argv, search: argv.search as string }); - } else if (argv.s && !isNaN(parseInt(argv.s,10)) && parseInt(argv.s,10) > 0) { - const selected = await this.selectShow(parseInt(argv.s), argv.e, argv.but, argv.all); - if (selected.isOk) { - for (const select of selected.value) { - if (!(await this.getEpisode(select, {...argv, skipsubs: false}))) { - console.error(`Unable to download selected episode ${select.shortNumber}`); - return false; - } - } - } - return true; - } else { - console.info('No option selected or invalid value entered. Try --help.'); - } - } - - private generateRandomString(length: number) { - const characters = '0123456789abcdef'; - let result = ''; - for (let i = 0; i < length; i++) { - result += characters.charAt(Math.floor(Math.random() * characters.length)); - } - return result; - } - - private parseCookies(cookiesString: string | null): Record { - const cookies: Record = {}; - if (cookiesString) { - cookiesString.split(';').forEach(cookie => { - const parts = cookie.split('='); - const name = parts.shift()?.trim(); - const value = decodeURIComponent(parts.join('=')); - if (name) { - cookies[name] = value; - } - }); - } - return cookies; - } - - private convertToSSATimestamp(timestamp: number): string { - const seconds = Math.floor(timestamp); - const centiseconds = Math.round((timestamp - seconds) * 100); - - const hours = Math.floor(seconds / 3600); - const minutes = Math.floor((seconds % 3600) / 60); - const remainingSeconds = seconds % 60; - - return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${remainingSeconds.toString().padStart(2, '0')}.${centiseconds.toString().padStart(2, '0')}`; - } - - public async doSearch(data: SearchData): Promise { - const limit = 12; - const offset = data.page ? data.page * limit : 0; - const searchReq = await this.req.getData(`https://gw.api.animationdigitalnetwork.fr/show/catalog?maxAgeCategory=18&offset=${offset}&limit=${limit}&search=${encodeURIComponent(data.search)}`, { - 'headers': { - 'X-Target-Distribution': this.locale - } - }); - if (!searchReq.ok || !searchReq.res) { - console.error('Search FAILED!'); - return { isOk: false, reason: new Error('Search failed. No more information provided') }; - } - const searchData = await searchReq.res.json() as ADNSearch; - const searchItems: ADNSearchShow[] = []; - console.info('Search Results:'); - for (const show of searchData.shows) { - searchItems.push(show); - let fullType: string; - if (show.type == 'EPS') { - fullType = `S.${show.id}`; - } else if (show.type == 'MOV' || show.type == 'OAV') { - fullType = `E.${show.id}`; - } else { - fullType = 'Unknown'; - console.warn(`Unknown type ${show.type}, please report this.`); - } - console.log(`[${fullType}] ${show.title}`); - } - return { isOk: true, value: searchItems.flatMap((a): SearchResponseItem => { - return { - id: a.id+'', - image: a.image ?? '/notFound.png', - name: a.title, - rating: a.rating, - desc: a.summary - }; - })}; - } - - public async doAuth(data: AuthData): Promise { - const authData = new URLSearchParams({ - 'username': data.username, - 'password': data.password, - 'source': 'Web', - 'rememberMe': 'true' - }).toString(); - const authReqOpts: reqModule.Params = { - method: 'POST', - body: authData - }; - const authReq = await this.req.getData('https://gw.api.animationdigitalnetwork.fr/authentication/login', authReqOpts); - if(!authReq.ok || !authReq.res){ - console.error('Authentication failed!'); - return { isOk: false, reason: new Error('Authentication failed') }; - } - this.token = await authReq.res.json(); - yamlCfg.saveADNToken(this.token); - console.info('Authentication Success'); - return { isOk: true, value: undefined }; - } - - public async refreshToken() { - const authReq = await this.req.getData('https://gw.api.animationdigitalnetwork.fr/authentication/refresh', { - method: 'POST', - headers: { - Authorization: `Bearer ${this.token.accessToken}`, - 'X-Access-Token': this.token.accessToken, - 'content-type': 'application/json' - }, - body: JSON.stringify({refreshToken: this.token.refreshToken}) - }); - if(!authReq.ok || !authReq.res){ - console.error('Token refresh failed!'); - return { isOk: false, reason: new Error('Token refresh failed') }; - } - this.token = await authReq.res.json(); - yamlCfg.saveADNToken(this.token); - return { isOk: true, value: undefined }; - } - - public async getShow(id: number) { - const getShowData = await this.req.getData(`https://gw.api.animationdigitalnetwork.fr/video/show/${id}?maxAgeCategory=18&limit=-1&order=asc`, { - 'headers': { - 'X-Target-Distribution': this.locale - } - }); - if (!getShowData.ok || !getShowData.res) { - console.error('Failed to get Series Data'); - return { isOk: false }; - } - const showData = await getShowData.res.json() as ADNVideos; - return { isOk: true, value: showData }; - } - - public async listShow(id: number) { - const show = await this.getShow(id); - if (!show.isOk || !show.value) { - console.error('Failed to list show data: Failed to get show'); - return { isOk: false }; - } - if (show.value.videos.length == 0) { - console.error('No episodes found!'); - return { isOk: false }; - } - const showData = show.value.videos[0].show; - console.info(`[S.${showData.id}] ${showData.title}`); - const specials: ADNVideo[] = []; - let episodeIndex = 0, specialIndex = 0; - for (const episode of show.value.videos) { - episode.season = episode.season+''; - const seasonNumberTitleParse = episode.season.match(/\d+/); - const seriesNumberTitleParse = episode.show.title.match(/\d+/); - const episodeNumber = parseInt(episode.shortNumber); - if (seasonNumberTitleParse && !isNaN(parseInt(seasonNumberTitleParse[0]))) { - episode.season = seasonNumberTitleParse[0]; - } else if (seriesNumberTitleParse && !isNaN(parseInt(seriesNumberTitleParse[0]))) { - episode.season = seriesNumberTitleParse[0]; - } else { - episode.season = '1'; - } - show.value.videos[episodeIndex].season = episode.season; - if (!episodeNumber) { - specialIndex++; - const special = show.value.videos.splice(episodeIndex, 1); - special[0].shortNumber = 'S'+specialIndex; - specials.push(...special); - episodeIndex--; - } else { - console.info(` (${episode.id}) [E${episode.shortNumber}] ${episode.number} - ${episode.name}`); - } - episodeIndex++; - } - for (const special of specials) { - console.info(` (${special.id}) [${special.shortNumber}] ${special.number} - ${special.name}`); - } - show.value.videos.push(...specials); - return { isOk: true, value: show.value }; - } - - public async selectShow(id: number, e: string | undefined, but: boolean, all: boolean) { - const getShowData = await this.listShow(id); - if (!getShowData.isOk || !getShowData.value) { - return { isOk: false, value: [] }; - } - console.info(''); - console.info('-'.repeat(30)); - console.info(''); - const showData = getShowData.value; - const doEpsFilter = parseSelect(e as string); - const selEpsArr: ADNVideo[] = []; - for (const episode of showData.videos) { - if ( - all || - but && !doEpsFilter.isSelected([episode.shortNumber, episode.id+'']) || - !but && doEpsFilter.isSelected([episode.shortNumber, episode.id+'']) - ) { - selEpsArr.push({ isSelected: true, ...episode }); - console.info('%s[S%sE%s] %s', - '✓ ', - episode.season, - episode.shortNumber, - episode.name, - ); - } - } - return { isOk: true, value: selEpsArr }; - } - - public async muxStreams(data: DownloadedMedia[], options: yargs.ArgvType) { - this.cfg.bin = await yamlCfg.loadBinCfg(); - let hasAudioStreams = false; - if (options.novids || data.filter(a => a.type === 'Video').length === 0) - return console.info('Skip muxing since no vids are downloaded'); - if (data.some(a => a.type === 'Audio')) { - hasAudioStreams = true; - } - const merger = new Merger({ - onlyVid: hasAudioStreams ? data.filter(a => a.type === 'Video').map((a) : MergerInput => { - if (a.type === 'Subtitle') - throw new Error('Never'); - return { - lang: a.lang, - path: a.path, - }; - }) : [], - skipSubMux: options.skipSubMux, - inverseTrackOrder: false, - keepAllVideos: options.keepAllVideos, - onlyAudio: hasAudioStreams ? data.filter(a => a.type === 'Audio').map((a) : MergerInput => { - if (a.type === 'Subtitle') - throw new Error('Never'); - return { - lang: a.lang, - path: a.path, - }; - }) : [], - output: `${options.output}.${options.mp4 ? 'mp4' : 'mkv'}`, - subtitles: data.filter(a => a.type === 'Subtitle').map((a) : SubtitleInput => { - if (a.type === 'Video') - throw new Error('Never'); - if (a.type === 'Audio') - throw new Error('Never'); - return { - file: a.path, - language: a.language, - closedCaption: a.cc - }; - }), - simul: data.filter(a => a.type === 'Video').map((a) : boolean => { - if (a.type === 'Subtitle') - throw new Error('Never'); - return !a.uncut as boolean; - })[0], - fonts: Merger.makeFontsList(this.cfg.dir.fonts, data.filter(a => a.type === 'Subtitle') as sxItem[]), - videoAndAudio: hasAudioStreams ? [] : data.filter(a => a.type === 'Video').map((a) : MergerInput => { - if (a.type === 'Subtitle') - throw new Error('Never'); - return { - lang: a.lang, - path: a.path, - }; - }), - chapters: data.filter(a => a.type === 'Chapters').map((a) : MergerInput => { - return { - path: a.path, - lang: a.lang - }; - }), - videoTitle: options.videoTitle, - options: { - ffmpeg: options.ffmpegOptions, - mkvmerge: options.mkvmergeOptions - }, - defaults: { - audio: options.defaultAudio, - sub: options.defaultSub - }, - ccTag: options.ccTag - }); - const bin = Merger.checkMerger(this.cfg.bin, options.mp4, options.forceMuxer); - // collect fonts info - // mergers - let isMuxed = false; - if (options.syncTiming) { - await merger.createDelays(); - } - if (bin.MKVmerge) { - await merger.merge('mkvmerge', bin.MKVmerge); - isMuxed = true; - } else if (bin.FFmpeg) { - await merger.merge('ffmpeg', bin.FFmpeg); - isMuxed = true; - } else{ - console.info('\nDone!\n'); - return; - } - if (isMuxed && !options.nocleanup) - merger.cleanUp(); - } - - - public async getEpisode(data: ADNVideo, options: yargs.ArgvType) { - //TODO: Move all the requests for getting the m3u8 here - const res = await this.downloadEpisode(data, options); - if (res === undefined || res.error) { - console.error('Failed to download media list'); - return { isOk: false, reason: new Error('Failed to download media list') }; - } else { - if (!options.skipmux) { - await this.muxStreams(res.data, { ...options, output: res.fileName }); - } else { - console.info('Skipping mux'); - } - downloaded({ - service: 'adn', - type: 's' - }, data.id+'', [data.shortNumber]); - return { isOk: res, value: undefined }; - } - } - - public async downloadEpisode(data: ADNVideo, options: yargs.ArgvType) { - if(!this.token.accessToken){ - console.error('Authentication required!'); - return; - } - - if (!this.cfg.bin.ffmpeg) - this.cfg.bin = await yamlCfg.loadBinCfg(); - - let mediaName = '...'; - let fileName; - const variables: Variable[] = []; - if(data.show.title && data.shortNumber && data.title){ - mediaName = `${data.show.shortTitle ?? data.show.title} - ${data.shortNumber} - ${data.title}`; - } - - const files: DownloadedMedia[] = []; - - let dlFailed = false; - let dlVideoOnce = false; // Variable to save if best selected video quality was downloaded - - const refreshToken = await this.refreshToken(); - if (!refreshToken.isOk) { - console.error('Failed to refresh token'); - return undefined; - } - - const configReq = await this.req.getData(`https://gw.api.animationdigitalnetwork.fr/player/video/${data.id}/configuration`, { - headers: { - Authorization: `Bearer ${this.token.accessToken}`, - 'X-Target-Distribution': this.locale - } - }); - if(!configReq.ok || !configReq.res){ - console.error('Player Config Request failed!'); - return undefined; - } - const configuration = await configReq.res.json() as ADNPlayerConfig; - if (!configuration.player.options.user.hasAccess) { - console.error('You don\'t have access to this video!'); - return undefined; - } - const tokenReq = await this.req.getData(configuration.player.options.user.refreshTokenUrl || 'https://gw.api.animationdigitalnetwork.fr/player/refresh/token', { - method: 'POST', - headers: { - 'X-Player-Refresh-Token': `${configuration.player.options.user.refreshToken}` - } - }); - if(!tokenReq.ok || !tokenReq.res){ - console.error('Player Token Request failed!'); - return undefined; - } - const token = await tokenReq.res.json() as { - refreshToken: string, - accessToken: string, - token: string - }; - - const linksUrl = configuration.player.options.video.url || `https://gw.api.animationdigitalnetwork.fr/player/video/${data.id}/link`; - const key = this.generateRandomString(16); - const decryptionKey = key + '7fac1178830cfe0c'; - - const authorization = crypto.publicEncrypt({ - 'key': '-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCbQrCJBRmaXM4gJidDmcpWDssg\nnumHinCLHAgS4buMtdH7dEGGEUfBofLzoEdt1jqcrCDT6YNhM0aFCqbLOPFtx9cg\n/X2G/G5bPVu8cuFM0L+ehp8s6izK1kjx3OOPH/kWzvstM5tkqgJkNyNEvHdeJl6\nKhS+IFEqwvZqgbBpKuwIDAQAB\n-----END PUBLIC KEY-----', - padding: crypto.constants.RSA_PKCS1_PADDING - }, Buffer.from(JSON.stringify({ - k: key, - t: token.token - }), 'utf-8')).toString('base64'); - - //TODO: Add chapter support - const streamsRequest = await this.req.getData(linksUrl+'?freeWithAds=true&adaptive=true&withMetadata=true&source=Web', { - 'headers': { - 'X-Player-Token': authorization, - 'X-Target-Distribution': this.locale - } - }); - if(!streamsRequest.ok || !streamsRequest.res){ - if (streamsRequest.error?.res.status == 403 || streamsRequest.res?.status == 403) { - console.error('Georestricted!'); - } else { - console.error('Streams request failed!'); - } - return undefined; - } - const streams = await streamsRequest.res.json() as ADNStreams; - for (const streamName in streams.links.streaming) { - let audDub: langsData.LanguageItem; - if (this.jpnStrings.includes(streamName)) { - audDub = langsData.languages.find(a=>a.code == 'jpn') as langsData.LanguageItem; - } else if (this.deuStrings.includes(streamName)) { - audDub = langsData.languages.find(a=>a.code == 'deu') as langsData.LanguageItem; - } else if (this.fraStrings.includes(streamName)) { - audDub = langsData.languages.find(a=>a.code == 'fra') as langsData.LanguageItem; - } else { - console.error(`Language ${streamName} not recognized, please report this.`); - continue; - } - - if (!options.dubLang.includes(audDub.code)) { - continue; - } - - console.info(`Requesting: [${data.id}] ${mediaName} (${audDub.name})`); - - variables.push(...([ - ['title', data.title, true], - ['episode', isNaN(parseFloat(data.shortNumber)) ? data.shortNumber : parseFloat(data.shortNumber), false], - ['service', 'ADN', false], - ['seriesTitle', data.show.shortTitle ?? data.show.title, true], - ['showTitle', data.show.title, true], - ['season', isNaN(parseFloat(data.season)) ? data.season : parseFloat(data.season), false] - ] as [AvailableFilenameVars, string|number, boolean][]).map((a): Variable => { - return { - name: a[0], - replaceWith: a[1], - type: typeof a[1], - sanitize: a[2] - } as Variable; - })); - - console.info('Playlists URL: %s', streams.links.streaming[streamName].auto); - - let tsFile = undefined; - - if (!dlFailed && !options.novids) { - const streamPlaylistsLocationReq = await this.req.getData(streams.links.streaming[streamName].auto); - if (!streamPlaylistsLocationReq.ok || !streamPlaylistsLocationReq.res) { - console.error('CAN\'T FETCH VIDEO PLAYLIST LOCATION!'); - return undefined; - } - const streamPlaylistLocation = await streamPlaylistsLocationReq.res.json() as {'location': string}; - const streamPlaylistsReq = await this.req.getData(streamPlaylistLocation.location); - if (!streamPlaylistsReq.ok || !streamPlaylistsReq.res) { - console.error('CAN\'T FETCH VIDEO PLAYLISTS!'); - dlFailed = true; - } else { - const streamPlaylistBody = await streamPlaylistsReq.res.text(); - const streamPlaylists = m3u8(streamPlaylistBody); - const plServerList: string[] = [], - plStreams: Record> = {}, - plQuality: { - str: string, - dim: string, - CODECS: string, - RESOLUTION: { - width: number, - height: number - } - }[] = []; - for(const pl of streamPlaylists.playlists){ - // set quality - const plResolution = pl.attributes.RESOLUTION; - const plResolutionText = `${plResolution.width}x${plResolution.height}`; - // set codecs - const plCodecs = pl.attributes.CODECS; - // parse uri - const plUri = new URL(pl.uri); - let plServer = plUri.hostname; - // set server list - if (plUri.searchParams.get('cdn')){ - plServer += ` (${plUri.searchParams.get('cdn')})`; - } - if (!plServerList.includes(plServer)){ - plServerList.push(plServer); - } - // add to server - if (!Object.keys(plStreams).includes(plServer)){ - plStreams[plServer] = {}; - } - if( - plStreams[plServer][plResolutionText] - && plStreams[plServer][plResolutionText] != pl.uri - && typeof plStreams[plServer][plResolutionText] != 'undefined' - ) { - console.error(`Non duplicate url for ${plServer} detected, please report to developer!`); - } else{ - plStreams[plServer][plResolutionText] = pl.uri; - } - // set plQualityStr - const plBandwidth = Math.round(pl.attributes.BANDWIDTH/1024); - const qualityStrAdd = `${plResolutionText} (${plBandwidth}KiB/s)`; - const qualityStrRegx = new RegExp(qualityStrAdd.replace(/([:()/])/g, '\\$1'), 'm'); - const qualityStrMatch = !plQuality.map(a => a.str).join('\r\n').match(qualityStrRegx); - if(qualityStrMatch){ - plQuality.push({ - str: qualityStrAdd, - dim: plResolutionText, - CODECS: plCodecs, - RESOLUTION: plResolution - }); - } - } - - options.x = options.x > plServerList.length ? 1 : options.x; - - const plSelectedServer = plServerList[options.x - 1]; - const plSelectedList = plStreams[plSelectedServer]; - plQuality.sort((a, b) => { - const aMatch: RegExpMatchArray | never[] = a.dim.match(/[0-9]+/) || []; - const bMatch: RegExpMatchArray | never[] = b.dim.match(/[0-9]+/) || []; - return parseInt(aMatch[0]) - parseInt(bMatch[0]); - }); - let quality = options.q === 0 ? plQuality.length : options.q; - if(quality > plQuality.length) { - console.warn(`The requested quality of ${options.q} is greater than the maximum ${plQuality.length}.\n[WARN] Therefor the maximum will be capped at ${plQuality.length}.`); - quality = plQuality.length; - } - // When best selected video quality is already downloaded - if(dlVideoOnce && options.dlVideoOnce) { - // Select the lowest resolution with the same codecs - while(quality !=1 && plQuality[quality - 1].CODECS == plQuality[quality - 2].CODECS) { - quality--; - } - } - const selPlUrl = plSelectedList[plQuality.map(a => a.dim)[quality - 1]] ? plSelectedList[plQuality.map(a => a.dim)[quality - 1]] : ''; - console.info(`Servers available:\n\t${plServerList.join('\n\t')}`); - console.info(`Available qualities:\n\t${plQuality.map((a, ind) => `[${ind+1}] ${a.str}`).join('\n\t')}`); - - if(selPlUrl != ''){ - variables.push({ - name: 'height', - type: 'number', - replaceWith: quality === 0 ? plQuality[plQuality.length - 1].RESOLUTION.height as number : plQuality[quality - 1].RESOLUTION.height - }, { - name: 'width', - type: 'number', - replaceWith: quality === 0 ? plQuality[plQuality.length - 1].RESOLUTION.width as number : plQuality[quality - 1].RESOLUTION.width - }); - - console.info(`Selected quality: ${Object.keys(plSelectedList).find(a => plSelectedList[a] === selPlUrl)} @ ${plSelectedServer}`); - console.info('Stream URL:', selPlUrl); - // TODO check filename - fileName = parseFileName(options.fileName, variables, options.numbers, options.override).join(path.sep); - const outFile = parseFileName(options.fileName + '.' + audDub.name, variables, options.numbers, options.override).join(path.sep); - console.info(`Output filename: ${outFile}`); - const chunkPage = await this.req.getData(selPlUrl); - if(!chunkPage.ok || !chunkPage.res){ - console.error('CAN\'T FETCH VIDEO PLAYLIST!'); - dlFailed = true; - } else { - const chunkPageBody = await chunkPage.res.text(); - const chunkPlaylist = m3u8(chunkPageBody); - const totalParts = chunkPlaylist.segments.length; - const mathParts = Math.ceil(totalParts / options.partsize); - const mathMsg = `(${mathParts}*${options.partsize})`; - console.info('Total parts in stream:', totalParts, mathMsg); - tsFile = path.isAbsolute(outFile as string) ? outFile : path.join(this.cfg.dir.content, outFile); - const split = outFile.split(path.sep).slice(0, -1); - split.forEach((val, ind, arr) => { - const isAbsolut = path.isAbsolute(outFile as string); - if (!fs.existsSync(path.join(isAbsolut ? '' : this.cfg.dir.content, ...arr.slice(0, ind), val))) - fs.mkdirSync(path.join(isAbsolut ? '' : this.cfg.dir.content, ...arr.slice(0, ind), val)); - }); - const dlStreamByPl = await new streamdl({ - output: `${tsFile}.ts`, - timeout: options.timeout, - m3u8json: chunkPlaylist, - baseurl: selPlUrl.replace('playlist.m3u8',''), - threads: options.partsize, - fsRetryTime: options.fsRetryTime * 1000, - override: options.force, - callback: options.callbackMaker ? options.callbackMaker({ - fileName: `${path.isAbsolute(outFile) ? outFile.slice(this.cfg.dir.content.length) : outFile}`, - image: data.image, - parent: { - title: data.show.title - }, - title: data.title, - language: audDub - }) : undefined - }).download(); - if (!dlStreamByPl.ok) { - console.error(`DL Stats: ${JSON.stringify(dlStreamByPl.parts)}\n`); - dlFailed = true; - } - files.push({ - type: 'Video', - path: `${tsFile}.ts`, - lang: audDub - }); - dlVideoOnce = true; - } - } else{ - console.error('Quality not selected!\n'); - dlFailed = true; - } - } - } else if (options.novids) { - console.info('Downloading skipped!'); - fileName = parseFileName(options.fileName, variables, options.numbers, options.override).join(path.sep); - } - await this.sleep(options.waittime); - } - - const compiledChapters: string[] = []; - if (options.chapters) { - if (streams.video.tcIntroStart) { - if (streams.video.tcIntroStart != '00:00:00') { - compiledChapters.push( - `CHAPTER${(compiledChapters.length/2)+1}=00:00:00.00`, - `CHAPTER${(compiledChapters.length/2)+1}NAME=Prologue` - ); - } - compiledChapters.push( - `CHAPTER${(compiledChapters.length/2)+1}=${streams.video.tcIntroStart+'.00'}`, - `CHAPTER${(compiledChapters.length/2)+1}NAME=Opening` - ); - compiledChapters.push( - `CHAPTER${(compiledChapters.length/2)+1}=${streams.video.tcIntroEnd+'.00'}`, - `CHAPTER${(compiledChapters.length/2)+1}NAME=Episode` - ); - } else { - compiledChapters.push( - `CHAPTER${(compiledChapters.length/2)+1}=00:00:00.00`, - `CHAPTER${(compiledChapters.length/2)+1}NAME=Episode` - ); - } - - if (streams.video.tcEndingStart) { - compiledChapters.push( - `CHAPTER${(compiledChapters.length/2)+1}=${streams.video.tcEndingStart+'.00'}`, - `CHAPTER${(compiledChapters.length/2)+1}NAME=Ending Start` - ); - compiledChapters.push( - `CHAPTER${(compiledChapters.length/2)+1}=${streams.video.tcEndingEnd+'.00'}`, - `CHAPTER${(compiledChapters.length/2)+1}NAME=Ending End` - ); - } - - if (compiledChapters.length > 0) { - try { - fileName = parseFileName(options.fileName, variables, options.numbers, options.override).join(path.sep); - const outFile = parseFileName(options.fileName, variables, options.numbers, options.override).join(path.sep); - const tsFile = path.isAbsolute(outFile as string) ? outFile : path.join(this.cfg.dir.content, outFile); - const split = outFile.split(path.sep).slice(0, -1); - split.forEach((val, ind, arr) => { - const isAbsolut = path.isAbsolute(outFile as string); - if (!fs.existsSync(path.join(isAbsolut ? '' : this.cfg.dir.content, ...arr.slice(0, ind), val))) - fs.mkdirSync(path.join(isAbsolut ? '' : this.cfg.dir.content, ...arr.slice(0, ind), val)); - }); - fs.writeFileSync(`${tsFile}.txt`, compiledChapters.join('\r\n')); - files.push({ - path: `${tsFile}.txt`, - lang: langsData.languages.find(a=>a.code=='jpn'), - type: 'Chapters' - }); - } catch { - console.error('Failed to write chapter file'); - } - } - } - - if(options.dlsubs.indexOf('all') > -1){ - options.dlsubs = ['all']; - } - - if (options.nosubs) { - console.info('Subtitles downloading disabled from nosubs flag.'); - options.skipsubs = true; - } - - if(!options.skipsubs && options.dlsubs.indexOf('none') == -1) { - if (Object.keys(streams.links.subtitles).length !== 0) { - const subtitlesUrlReq = await this.req.getData(streams.links.subtitles.all); - if(!subtitlesUrlReq.ok || !subtitlesUrlReq.res){ - console.error('Subtitle location request failed!'); - return undefined; - } - const subtitleUrl = await subtitlesUrlReq.res.json() as {'location': string}; - const encryptedSubtitlesReq = await this.req.getData(subtitleUrl.location); - if(!encryptedSubtitlesReq.ok || !encryptedSubtitlesReq.res){ - console.error('Subtitle request failed!'); - return undefined; - } - const encryptedSubtitles = await encryptedSubtitlesReq.res.text(); - const iv = Buffer.from(encryptedSubtitles.slice(0, 24), 'base64'); - const derivedKey = Buffer.from(decryptionKey, 'hex'); - const encryptedData = Buffer.from(encryptedSubtitles.slice(24), 'base64'); - const decipher = crypto.createDecipheriv('aes-128-cbc', derivedKey, iv); - const decryptedData = Buffer.concat([decipher.update(encryptedData), decipher.final()]).toString('utf8'); - - let subIndex = 0; - const subtitles = JSON.parse(decryptedData) as ADNSubtitles; - if (Object.keys(subtitles).length === 0) { - console.warn('No subtitles found.'); - } - for (const subName in subtitles) { - let subLang: langsData.LanguageItem; - if (this.deuSubStrings.includes(subName)) { - subLang = langsData.languages.find(a=>a.code == 'deu') as langsData.LanguageItem; - } else if (this.fraSubStrings.includes(subName)) { - subLang = langsData.languages.find(a=>a.code == 'fra') as langsData.LanguageItem; - } else { - console.error(`Language ${subName} not recognized, please report this.`); - continue; - } - - if (!options.dlsubs.includes(subLang.locale) && !options.dlsubs.includes('all')) { - continue; - } - - const sxData: Partial = {}; - sxData.file = langsData.subsFile(fileName as string, subIndex+'', subLang, false, options.ccTag); - sxData.path = path.join(this.cfg.dir.content, sxData.file); - const split = sxData.path.split(path.sep).slice(0, -1); - split.forEach((val, ind, arr) => { - const isAbsolut = path.isAbsolute(sxData.path as string); - if (!fs.existsSync(path.join(isAbsolut ? '' : this.cfg.dir.content, ...arr.slice(0, ind), val))) - fs.mkdirSync(path.join(isAbsolut ? '' : this.cfg.dir.content, ...arr.slice(0, ind), val)); - }); - sxData.language = subLang; - if(options.dlsubs.includes('all') || options.dlsubs.includes(subLang.locale)) { - let subBody = '[Script Info]' - + '\nScriptType:V4.00+' - + '\nWrapStyle: 0' - + '\nPlayResX: 1280' - + '\nPlayResY: 720' - + '\nScaledBorderAndShadow: yes' - + '' - + '\n[V4+ Styles]' - + '\nFormat: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding' - + `\nStyle: Default,${options.fontName ?? 'Arial'},${options.fontSize ?? 50},&H00FFFFFF,&H00FFFFFF,&H00000000,&H00000000,-1,0,0,0,100,100,0,0,1,1.95,0,2,0,0,70,0` - + '\n[Events]' - + '\nFormat: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text'; - - for (const sub of subtitles[subName]) { - const [start, end, text, lineAlign, positionAlign] = - [sub.startTime, sub.endTime, sub.text, sub.lineAlign, sub.positionAlign]; - for (const subProp in sub) { - switch (subProp) { - case 'startTime': - case 'endTime': - case 'text': - case 'lineAlign': - case 'positionAlign': - break; - default: - console.warn(`json2ass: Unknown style: ${subProp}`); - } - } - const alignment = (this.posAlignMap[positionAlign] || 2) + (this.lineAlignMap[lineAlign] || 0); - const xtext = text - .replace(/ \\N$/g, '\\N') - .replace(/\\N$/, '') - .replace(/\r/g, '') - .replace(/\n/g, '\\N') - .replace(/\\N +/g, '\\N') - .replace(/ +\\N/g, '\\N') - .replace(/(\\N)+/g, '\\N') - .replace(/]*>([^<]*)<\/b>/g, '{\\b1}$1{\\b0}') - .replace(/]*>([^<]*)<\/i>/g, '{\\i1}$1{\\i0}') - .replace(/]*>([^<]*)<\/u>/g, '{\\u1}$1{\\u0}') - .replace(/</g, '<') - .replace(/>/g, '>') - .replace(/&/g, '&') - .replace(/<[^>]>/g, '') - .replace(/\\N$/, '') - .replace(/ +$/, ''); - subBody += `\nDialogue: 0,${this.convertToSSATimestamp(start)},${this.convertToSSATimestamp(end)},Default,,0,0,0,,${(alignment !== 2 ? `{\\a${alignment}}` : '')}${xtext}`; - } - sxData.title = `${subLang.language}`; - sxData.fonts = fontsData.assFonts(subBody) as Font[]; - fs.writeFileSync(sxData.path, subBody); - console.info(`Subtitle converted: ${sxData.file}`); - files.push({ - type: 'Subtitle', - ...sxData as sxItem, - cc: false - }); - } - subIndex++; - } - } else { - console.warn('Couldn\'t find subtitles.'); - } - } else{ - console.info('Subtitles downloading skipped!'); - } - - return { - error: dlFailed, - data: files, - fileName: fileName ? (path.isAbsolute(fileName) ? fileName : path.join(this.cfg.dir.content, fileName)) || './unknown' : './unknown' - }; - } - - public sleep(ms: number) { - return new Promise((resolve) => { - setTimeout(resolve, ms); - }); - } -} \ No newline at end of file diff --git a/ao.ts b/ao.ts deleted file mode 100644 index 591e654..0000000 --- a/ao.ts +++ /dev/null @@ -1,825 +0,0 @@ -// Package Info -import packageJson from './package.json'; - -// Node -import path from 'path'; -import fs from 'fs-extra'; - -// Plugins -import shlp from 'sei-helper'; - -// Modules -import * as fontsData from './modules/module.fontsData'; -import * as langsData from './modules/module.langsData'; -import * as yamlCfg from './modules/module.cfg-loader'; -import * as yargs from './modules/module.app-args'; -import * as reqModule from './modules/module.fetch'; -import Merger, { Font, MergerInput, SubtitleInput } from './modules/module.merger'; -import getKeys, { canDecrypt } from './modules/widevine'; -import streamdl, { M3U8Json } from './modules/hls-download'; -import { exec } from './modules/sei-helper-fixes'; -import { console } from './modules/log'; -import { domain } from './modules/module.api-urls'; -import { downloaded } from './modules/module.downloadArchive'; -import parseSelect from './modules/module.parseSelect'; -import parseFileName, { Variable } from './modules/module.filename'; -import { AvailableFilenameVars } from './modules/module.args'; -import { parse } from './modules/module.transform-mpd'; - -// Types -import { ServiceClass } from './@types/serviceClassInterface'; -import { AuthData, AuthResponse, SearchData, SearchResponse, SearchResponseItem } from './@types/messageHandler'; -import { AOSearchResult, AnimeOnegaiSearch } from './@types/animeOnegaiSearch'; -import { AnimeOnegaiSeries } from './@types/animeOnegaiSeries'; -import { AnimeOnegaiSeasons, Episode } from './@types/animeOnegaiSeasons'; -import { DownloadedMedia } from './@types/hidiveTypes'; -import { AnimeOnegaiStream } from './@types/animeOnegaiStream'; -import { sxItem } from './crunchy'; - -type parsedMultiDubDownload = { - data: { - lang: string, - videoId: string - episode: Episode - }[], - seriesTitle: string, - seasonTitle: string, - episodeTitle: string, - episodeNumber: number, - seasonNumber: number, - seriesID: number, - seasonID: number, - image: string, -} - -export default class AnimeOnegai implements ServiceClass { - public cfg: yamlCfg.ConfigObject; - private token: Record; - private req: reqModule.Req; - public locale: string; - public jpnStrings: string[] = [ - 'Japonés con Subtítulos en Español', - 'Japonés con Subtítulos en Portugués', - 'Japonês com legendas em espanhol', - 'Japonês com legendas em português', - 'Japonés' - ]; - public spaStrings: string[] = [ - 'Doblaje en Español', - 'Dublagem em espanhol', - 'Español', - ]; - public porStrings: string[] = [ - 'Doblaje en Portugués', - 'Dublagem em português' - ]; - private defaultOptions: RequestInit = { - 'headers': { - 'origin': 'https://www.animeonegai.com', - 'referer': 'https://www.animeonegai.com/', - } - }; - - constructor(private debug = false) { - this.cfg = yamlCfg.loadCfg(); - this.token = yamlCfg.loadAOToken(); - this.req = new reqModule.Req(domain, debug, false, 'ao'); - this.locale = 'es'; - } - - public async cli() { - console.info(`\n=== Multi Downloader NX ${packageJson.version} ===\n`); - const argv = yargs.appArgv(this.cfg.cli); - if (['pt', 'es'].includes(argv.locale)) - this.locale = argv.locale; - if (argv.debug) - this.debug = true; - - // load binaries - this.cfg.bin = await yamlCfg.loadBinCfg(); - if (argv.allDubs) { - argv.dubLang = langsData.dubLanguageCodes; - } - if (argv.auth) { - //Authenticate - await this.doAuth({ - username: argv.username ?? await shlp.question('[Q] LOGIN/EMAIL'), - password: argv.password ?? await shlp.question('[Q] PASSWORD ') - }); - } else if (argv.search && argv.search.length > 2) { - //Search - await this.doSearch({ ...argv, search: argv.search as string }); - } else if (argv.s && !isNaN(parseInt(argv.s,10)) && parseInt(argv.s,10) > 0) { - const selected = await this.selectShow(parseInt(argv.s), argv.e, argv.but, argv.all, argv); - if (selected.isOk) { - for (const select of selected.value) { - if (!(await this.downloadEpisode(select, {...argv, skipsubs: false}))) { - console.error(`Unable to download selected episode ${select.episodeNumber}`); - return false; - } - } - } - return true; - } else if (argv.token) { - this.token = {token: argv.token}; - yamlCfg.saveAOToken(this.token); - console.info('Saved token'); - } else { - console.info('No option selected or invalid value entered. Try --help.'); - } - } - - public async doSearch(data: SearchData): Promise { - const searchReq = await this.req.getData(`https://api.animeonegai.com/v1/search/algolia/${encodeURIComponent(data.search)}?lang=${this.locale}`, this.defaultOptions); - if (!searchReq.ok || !searchReq.res) { - console.error('Search FAILED!'); - return { isOk: false, reason: new Error('Search failed. No more information provided') }; - } - const searchData = await searchReq.res.json() as AnimeOnegaiSearch; - const searchItems: AOSearchResult[] = []; - console.info('Search Results:'); - for (const hit of searchData.list) { - searchItems.push(hit); - let fullType: string; - if (hit.asset_type == 2) { - fullType = `S.${hit.ID}`; - } else if (hit.asset_type == 1) { - fullType = `E.${hit.ID}`; - } else { - fullType = 'Unknown'; - console.warn(`Unknown asset type ${hit.asset_type}, please report this.`); - } - console.log(`[${fullType}] ${hit.title}`); - } - return { isOk: true, value: searchItems.filter(a => a.asset_type == 2).flatMap((a): SearchResponseItem => { - return { - id: a.ID+'', - image: a.poster ?? '/notFound.png', - name: a.title, - rating: a.likes, - desc: a.description - }; - })}; - } - - public async doAuth(data: AuthData): Promise { - data; - console.error('Authentication not possible, manual authentication required due to recaptcha. In order to login use the --token flag. You can get the token by logging into the website, and opening the dev console and running the command "localStorage.ott_token"'); - return { isOk: false, reason: new Error('Authentication not possible, manual authentication required do to recaptcha.') }; - } - - public async getShow(id: number) { - const getSeriesData = await this.req.getData(`https://api.animeonegai.com/v1/asset/${id}?lang=${this.locale}`, this.defaultOptions); - if (!getSeriesData.ok || !getSeriesData.res) { - console.error('Failed to get Show Data'); - return { isOk: false }; - } - const seriesData = await getSeriesData.res.json() as AnimeOnegaiSeries; - - const getSeasonData = await this.req.getData(`https://api.animeonegai.com/v1/asset/content/${id}?lang=${this.locale}`, this.defaultOptions); - if (!getSeasonData.ok || !getSeasonData.res) { - console.error('Failed to get Show Data'); - return { isOk: false }; - } - const seasonData = await getSeasonData.res.json() as AnimeOnegaiSeasons[]; - - return { isOk: true, data: seriesData, seasons: seasonData }; - } - - public async listShow(id: number, outputEpisode: boolean = true) { - const series = await this.getShow(id); - if (!series.isOk || !series.data) { - console.error('Failed to list series data: Failed to get series'); - return { isOk: false }; - } - console.info(`[S.${series.data.ID}] ${series.data.title} (${series.seasons.length} Seasons)`); - if (series.seasons.length === 0 && series.data.asset_type !== 1) { - console.info(' No Seasons found!'); - return { isOk: false }; - } - const episodes: { [key: string]: (Episode & { lang?: string })[] } = {}; - for (const season of series.seasons) { - let lang: string | undefined = undefined; - if (this.jpnStrings.includes(season.name.trim())) lang = 'ja'; - else if (this.porStrings.includes(season.name.trim())) lang = 'pt'; - else if (this.spaStrings.includes(season.name.trim())) lang = 'es'; - else {lang = 'unknown';console.error(`Language (${season.name.trim()}) not known, please report this!`);} - for (const episode of season.list) { - if (!episodes[episode.number]) { - episodes[episode.number] = []; - } - /*if (!episodes[episode.number].find(a=>a.lang == lang))*/ episodes[episode.number].push({...episode, lang}); - } - } - //Item is movie, lets define it manually - if (series.data.asset_type === 1 && series.seasons.length === 0) { - let lang: string | undefined; - if (this.jpnStrings.some(str => series.data.title.includes(str))) lang = 'ja'; - else if (this.porStrings.some(str => series.data.title.includes(str))) lang = 'pt'; - else if (this.spaStrings.some(str => series.data.title.includes(str))) lang = 'es'; - else {lang = 'unknown';console.error('Language could not be parsed from movie title, please report this!');} - episodes[1] = [{ - 'video_entry': series.data.video_entry, - 'number': 1, - 'season_id': 1, - 'name': series.data.title, - 'ID': series.data.ID, - 'CreatedAt': series.data.CreatedAt, - 'DeletedAt': series.data.DeletedAt, - 'UpdatedAt': series.data.UpdatedAt, - 'active': series.data.active, - 'description': series.data.description, - 'age_restriction': series.data.age_restriction, - 'asset_id': series.data.ID, - 'ending': null, - 'entry': series.data.entry, - 'stream_url': series.data.stream_url, - 'skip_intro': null, - 'thumbnail': series.data.bg, - 'open_free': false, - lang - }]; // as unknown as (Episode & { lang?: string })[]; - // The above needs to be uncommented if the episode number should be M1 instead of 1 - } - //Enable to output episodes seperate from selection - if (outputEpisode) { - for (const episodeKey in episodes) { - const episode = episodes[episodeKey][0]; - const langs = Array.from(new Set(episodes[episodeKey].map(a=>a.lang))); - console.info(` [E.${episode.ID}] E${episode.number} - ${episode.name} (${langs.map(a=>{ - if (a) return langsData.languages.find(b=>b.ao_locale === a)?.name; - return 'Unknown'; - }).join(', ')})`); - } - } - return { isOk: true, value: episodes, series: series }; - } - - public async selectShow(id: number, e: string | undefined, but: boolean, all: boolean, options: yargs.ArgvType) { - const getShowData = await this.listShow(id, false); - if (!getShowData.isOk || !getShowData.value) { - return { isOk: false, value: [] }; - } - //const showData = getShowData.value; - const doEpsFilter = parseSelect(e as string); - // build selected episodes - const selEpsArr: parsedMultiDubDownload[] = []; - const episodes = getShowData.value; - const seasonNumberTitleParse = getShowData.series.data.title.match(/\d+/); - const seasonNumber = seasonNumberTitleParse ? parseInt(seasonNumberTitleParse[0]) : 1; - for (const episodeKey in getShowData.value) { - const episode = episodes[episodeKey][0]; - const selectedLangs: string[] = []; - const selected: { - lang: string, - videoId: string - episode: Episode - }[] = []; - for (const episode of episodes[episodeKey]) { - const lang = langsData.languages.find(a=>a.ao_locale === episode.lang); - let isSelected = false; - if (typeof selected.find(a=>a.lang == episode.lang) == 'undefined') { - if (options.dubLang.includes(lang?.code ?? 'Unknown')) { - if ((but && !doEpsFilter.isSelected([episode.number+'', episode.ID+''])) || all || (!but && doEpsFilter.isSelected([episode.number+'', episode.ID+'']))) { - isSelected = true; - selected.push({lang: episode.lang as string, videoId: episode.video_entry, episode: episode }); - } - } - const selectedLang = isSelected ? `✓ ${lang?.name ?? 'Unknown'}` : `${lang?.name ?? 'Unknown'}`; - if (!selectedLangs.includes(selectedLang)) { - selectedLangs.push(selectedLang); - } - } - } - if (selected.length > 0) { - selEpsArr.push({ - 'data': selected, - 'seasonNumber': seasonNumber, - 'episodeNumber': episode.number, - 'episodeTitle': episode.name, - 'image': episode.thumbnail, - 'seasonID': episode.season_id, - 'seasonTitle': getShowData.series.data.title, - 'seriesTitle': getShowData.series.data.title, - 'seriesID': getShowData.series.data.ID - }); - } - console.info(` [S${seasonNumber}E${episode.number}] - ${episode.name} (${selectedLangs.join(', ')})`); - } - return { isOk: true, value: selEpsArr, showData: getShowData.series }; - } - - public async downloadEpisode(data: parsedMultiDubDownload, options: yargs.ArgvType): Promise { - const res = await this.downloadMediaList(data, options); - if (res === undefined || res.error) { - return false; - } else { - if (!options.skipmux) { - await this.muxStreams(res.data, { ...options, output: res.fileName }); - } else { - console.info('Skipping mux'); - } - downloaded({ - service: 'ao', - type: 's' - }, data.seasonID+'', [data.episodeNumber+'']); - } - return true; - } - - public async muxStreams(data: DownloadedMedia[], options: yargs.ArgvType) { - this.cfg.bin = await yamlCfg.loadBinCfg(); - let hasAudioStreams = false; - if (options.novids || data.filter(a => a.type === 'Video').length === 0) - return console.info('Skip muxing since no vids are downloaded'); - if (data.some(a => a.type === 'Audio')) { - hasAudioStreams = true; - } - const merger = new Merger({ - onlyVid: hasAudioStreams ? data.filter(a => a.type === 'Video').map((a) : MergerInput => { - if (a.type === 'Subtitle') - throw new Error('Never'); - return { - lang: a.lang, - path: a.path, - }; - }) : [], - skipSubMux: options.skipSubMux, - inverseTrackOrder: false, - keepAllVideos: options.keepAllVideos, - onlyAudio: hasAudioStreams ? data.filter(a => a.type === 'Audio').map((a) : MergerInput => { - if (a.type === 'Subtitle') - throw new Error('Never'); - return { - lang: a.lang, - path: a.path, - }; - }) : [], - output: `${options.output}.${options.mp4 ? 'mp4' : 'mkv'}`, - subtitles: data.filter(a => a.type === 'Subtitle').map((a) : SubtitleInput => { - if (a.type === 'Video') - throw new Error('Never'); - if (a.type === 'Audio') - throw new Error('Never'); - return { - file: a.path, - language: a.language, - closedCaption: a.cc - }; - }), - simul: data.filter(a => a.type === 'Video').map((a) : boolean => { - if (a.type === 'Subtitle') - throw new Error('Never'); - return !a.uncut as boolean; - })[0], - fonts: Merger.makeFontsList(this.cfg.dir.fonts, data.filter(a => a.type === 'Subtitle') as sxItem[]), - videoAndAudio: hasAudioStreams ? [] : data.filter(a => a.type === 'Video').map((a) : MergerInput => { - if (a.type === 'Subtitle') - throw new Error('Never'); - return { - lang: a.lang, - path: a.path, - }; - }), - videoTitle: options.videoTitle, - options: { - ffmpeg: options.ffmpegOptions, - mkvmerge: options.mkvmergeOptions - }, - defaults: { - audio: options.defaultAudio, - sub: options.defaultSub - }, - ccTag: options.ccTag - }); - const bin = Merger.checkMerger(this.cfg.bin, options.mp4, options.forceMuxer); - // collect fonts info - // mergers - let isMuxed = false; - if (options.syncTiming) { - await merger.createDelays(); - } - if (bin.MKVmerge) { - await merger.merge('mkvmerge', bin.MKVmerge); - isMuxed = true; - } else if (bin.FFmpeg) { - await merger.merge('ffmpeg', bin.FFmpeg); - isMuxed = true; - } else{ - console.info('\nDone!\n'); - return; - } - if (isMuxed && !options.nocleanup) - merger.cleanUp(); - } - - public async downloadMediaList(medias: parsedMultiDubDownload, options: yargs.ArgvType) : Promise<{ - data: DownloadedMedia[], - fileName: string, - error: boolean - } | undefined> { - if(!this.token.token){ - console.error('Authentication required!'); - return; - } - - if (!this.cfg.bin.ffmpeg) - this.cfg.bin = await yamlCfg.loadBinCfg(); - - let mediaName = '...'; - let fileName; - const variables: Variable[] = []; - if(medias.seasonTitle && medias.episodeNumber && medias.episodeTitle){ - mediaName = `${medias.seasonTitle} - ${medias.episodeNumber} - ${medias.episodeTitle}`; - } - - const files: DownloadedMedia[] = []; - - let subIndex = 0; - let dlFailed = false; - let dlVideoOnce = false; // Variable to save if best selected video quality was downloaded - - for (const media of medias.data) { - console.info(`Requesting: [E.${media.episode.ID}] ${mediaName}`); - - const AuthHeaders = { - headers: { - Authorization: `Bearer ${this.token.token}`, - 'Referer': 'https://www.animeonegai.com/', - 'Origin': 'https://www.animeonegai.com', - 'Referrer-Policy': 'strict-origin-when-cross-origin', - 'Content-Type': 'application/json' - } - }; - - const playbackReq = await this.req.getData(`https://api.animeonegai.com/v1/media/${media.videoId}?lang=${this.locale}`, AuthHeaders); - if(!playbackReq.ok || !playbackReq.res){ - console.error('Request Stream URLs FAILED!'); - return undefined; - } - const streamData = await playbackReq.res.json() as AnimeOnegaiStream; - - variables.push(...([ - ['title', medias.episodeTitle, true], - ['episode', medias.episodeNumber, false], - ['service', 'AO', false], - ['seriesTitle', medias.seriesTitle, true], - ['showTitle', medias.seasonTitle, true], - ['season', medias.seasonNumber, false] - ] as [AvailableFilenameVars, string|number, boolean][]).map((a): Variable => { - return { - name: a[0], - replaceWith: a[1], - type: typeof a[1], - sanitize: a[2] - } as Variable; - })); - - if (!canDecrypt) { - console.warn('Decryption not enabled!'); - } - - const lang = langsData.languages.find(a=>a.ao_locale == media.lang) as langsData.LanguageItem; - if (!lang) { - console.error(`Unable to find language for code ${media.lang}`); - return; - } - let tsFile = undefined; - - if (!streamData.dash) { - console.error('You don\'t have access to download this content'); - continue; - } - - console.info('Playlists URL: %s', streamData.dash); - - if(!dlFailed && !(options.novids && options.noaudio)){ - const streamPlaylistsReq = await this.req.getData(streamData.dash, AuthHeaders); - if(!streamPlaylistsReq.ok || !streamPlaylistsReq.res){ - console.error('CAN\'T FETCH VIDEO PLAYLISTS!'); - dlFailed = true; - } else { - const streamPlaylistBody = (await streamPlaylistsReq.res.text()).replace(/(.*?)<\/BaseURL>/g, `${streamData.dash.split('/dash/')[0]}/dash/$1`); - //Parse MPD Playlists - const streamPlaylists = await parse(streamPlaylistBody, lang as langsData.LanguageItem, streamData.dash.split('/dash/')[0]+'/dash/'); - - //Get name of CDNs/Servers - const streamServers = Object.keys(streamPlaylists); - - options.x = options.x > streamServers.length ? 1 : options.x; - - const selectedServer = streamServers[options.x - 1]; - const selectedList = streamPlaylists[selectedServer]; - - //set Video Qualities - const videos = selectedList.video.map(item => { - return { - ...item, - resolutionText: `${item.quality.width}x${item.quality.height} (${Math.round(item.bandwidth/1024)}KiB/s)` - }; - }); - - const audios = selectedList.audio.map(item => { - return { - ...item, - resolutionText: `${Math.round(item.bandwidth/1024)}kB/s` - }; - }); - - videos.sort((a, b) => { - return a.quality.width - b.quality.width; - }); - - audios.sort((a, b) => { - return a.bandwidth - b.bandwidth; - }); - - let chosenVideoQuality = options.q === 0 ? videos.length : options.q; - if(chosenVideoQuality > videos.length) { - console.warn(`The requested quality of ${options.q} is greater than the maximum ${videos.length}.\n[WARN] Therefor the maximum will be capped at ${videos.length}.`); - chosenVideoQuality = videos.length; - } - chosenVideoQuality--; - - let chosenAudioQuality = options.q === 0 ? audios.length : options.q; - if(chosenAudioQuality > audios.length) { - chosenAudioQuality = audios.length; - } - chosenAudioQuality--; - - const chosenVideoSegments = videos[chosenVideoQuality]; - const chosenAudioSegments = audios[chosenAudioQuality]; - - console.info(`Servers available:\n\t${streamServers.join('\n\t')}`); - console.info(`Available Video Qualities:\n\t${videos.map((a, ind) => `[${ind+1}] ${a.resolutionText}`).join('\n\t')}`); - console.info(`Available Audio Qualities:\n\t${audios.map((a, ind) => `[${ind+1}] ${a.resolutionText}`).join('\n\t')}`); - - variables.push({ - name: 'height', - type: 'number', - replaceWith: chosenVideoSegments.quality.height - }, { - name: 'width', - type: 'number', - replaceWith: chosenVideoSegments.quality.width - }); - - console.info(`Selected quality: \n\tVideo: ${chosenVideoSegments.resolutionText}\n\tAudio: ${chosenAudioSegments.resolutionText}\n\tServer: ${selectedServer}`); - //console.info('Stream URL:', chosenVideoSegments.segments[0].uri); - // TODO check filename - fileName = parseFileName(options.fileName, variables, options.numbers, options.override).join(path.sep); - const outFile = parseFileName(options.fileName + '.' + lang.name, variables, options.numbers, options.override).join(path.sep); - const tempFile = parseFileName(`temp-${media.videoId}`, variables, options.numbers, options.override).join(path.sep); - const tempTsFile = path.isAbsolute(tempFile as string) ? tempFile : path.join(this.cfg.dir.content, tempFile); - - let [audioDownloaded, videoDownloaded] = [false, false]; - - // When best selected video quality is already downloaded - if(dlVideoOnce && options.dlVideoOnce) { - console.info('Already downloaded video, skipping video download...'); - } else if (options.novids) { - console.info('Skipping video download...'); - } else { - //Download Video - const totalParts = chosenVideoSegments.segments.length; - const mathParts = Math.ceil(totalParts / options.partsize); - const mathMsg = `(${mathParts}*${options.partsize})`; - console.info('Total parts in video stream:', totalParts, mathMsg); - tsFile = path.isAbsolute(outFile as string) ? outFile : path.join(this.cfg.dir.content, outFile); - const split = outFile.split(path.sep).slice(0, -1); - split.forEach((val, ind, arr) => { - const isAbsolut = path.isAbsolute(outFile as string); - if (!fs.existsSync(path.join(isAbsolut ? '' : this.cfg.dir.content, ...arr.slice(0, ind), val))) - fs.mkdirSync(path.join(isAbsolut ? '' : this.cfg.dir.content, ...arr.slice(0, ind), val)); - }); - const videoJson: M3U8Json = { - segments: chosenVideoSegments.segments - }; - try { - const videoDownload = await new streamdl({ - output: chosenVideoSegments.pssh ? `${tempTsFile}.video.enc.mp4` : `${tsFile}.video.mp4`, - timeout: options.timeout, - m3u8json: videoJson, - // baseurl: chunkPlaylist.baseUrl, - threads: options.partsize, - fsRetryTime: options.fsRetryTime * 1000, - override: options.force, - callback: options.callbackMaker ? options.callbackMaker({ - fileName: `${path.isAbsolute(outFile) ? outFile.slice(this.cfg.dir.content.length) : outFile}`, - image: medias.image, - parent: { - title: medias.seasonTitle - }, - title: medias.episodeTitle, - language: lang - }) : undefined - }).download(); - if(!videoDownload.ok){ - console.error(`DL Stats: ${JSON.stringify(videoDownload.parts)}\n`); - dlFailed = true; - } else { - dlVideoOnce = true; - videoDownloaded = true; - } - } catch (e) { - console.error(e); - dlFailed = true; - } - } - - if (chosenAudioSegments && !options.noaudio) { - //Download Audio (if available) - const totalParts = chosenAudioSegments.segments.length; - const mathParts = Math.ceil(totalParts / options.partsize); - const mathMsg = `(${mathParts}*${options.partsize})`; - console.info('Total parts in audio stream:', totalParts, mathMsg); - tsFile = path.isAbsolute(outFile as string) ? outFile : path.join(this.cfg.dir.content, outFile); - const split = outFile.split(path.sep).slice(0, -1); - split.forEach((val, ind, arr) => { - const isAbsolut = path.isAbsolute(outFile as string); - if (!fs.existsSync(path.join(isAbsolut ? '' : this.cfg.dir.content, ...arr.slice(0, ind), val))) - fs.mkdirSync(path.join(isAbsolut ? '' : this.cfg.dir.content, ...arr.slice(0, ind), val)); - }); - const audioJson: M3U8Json = { - segments: chosenAudioSegments.segments - }; - try { - const audioDownload = await new streamdl({ - output: chosenAudioSegments.pssh ? `${tempTsFile}.audio.enc.mp4` : `${tsFile}.audio.mp4`, - timeout: options.timeout, - m3u8json: audioJson, - // baseurl: chunkPlaylist.baseUrl, - threads: options.partsize, - fsRetryTime: options.fsRetryTime * 1000, - override: options.force, - callback: options.callbackMaker ? options.callbackMaker({ - fileName: `${path.isAbsolute(outFile) ? outFile.slice(this.cfg.dir.content.length) : outFile}`, - image: medias.image, - parent: { - title: medias.seasonTitle - }, - title: medias.episodeTitle, - language: lang - }) : undefined - }).download(); - if(!audioDownload.ok){ - console.error(`DL Stats: ${JSON.stringify(audioDownload.parts)}\n`); - dlFailed = true; - } else { - audioDownloaded = true; - } - } catch (e) { - console.error(e); - dlFailed = true; - } - } else if (options.noaudio) { - console.info('Skipping audio download...'); - } - - //Handle Decryption if needed - if ((chosenVideoSegments.pssh || chosenAudioSegments.pssh) && (videoDownloaded || audioDownloaded)) { - console.info('Decryption Needed, attempting to decrypt'); - const encryptionKeys = await getKeys(chosenVideoSegments.pssh, streamData.widevine_proxy, {}); - if (encryptionKeys.length == 0) { - console.error('Failed to get encryption keys'); - return undefined; - } - /*const keys = {} as Record; - encryptionKeys.forEach(function(key) { - keys[key.kid] = key.key; - });*/ - - if (this.cfg.bin.mp4decrypt) { - const commandBase = `--show-progress --key ${encryptionKeys[1].kid}:${encryptionKeys[1].key} `; - const commandVideo = commandBase+`"${tempTsFile}.video.enc.mp4" "${tempTsFile}.video.mp4"`; - const commandAudio = commandBase+`"${tempTsFile}.audio.enc.mp4" "${tempTsFile}.audio.mp4"`; - - if (videoDownloaded) { - console.info('Started decrypting video'); - const decryptVideo = exec('mp4decrypt', `"${this.cfg.bin.mp4decrypt}"`, commandVideo); - if (!decryptVideo.isOk) { - console.error(decryptVideo.err); - console.error(`Decryption failed with exit code ${decryptVideo.err.code}`); - fs.renameSync(`${tempTsFile}.video.enc.mp4`, `${tsFile}.video.enc.mp4`); - return undefined; - } else { - console.info('Decryption done for video'); - if (!options.nocleanup) { - fs.removeSync(`${tempTsFile}.video.enc.mp4`); - } - fs.renameSync(`${tempTsFile}.video.mp4`, `${tsFile}.video.mp4`); - files.push({ - type: 'Video', - path: `${tsFile}.video.mp4`, - lang: lang - }); - } - } - - if (audioDownloaded) { - console.info('Started decrypting audio'); - const decryptAudio = exec('mp4decrypt', `"${this.cfg.bin.mp4decrypt}"`, commandAudio); - if (!decryptAudio.isOk) { - console.error(decryptAudio.err); - console.error(`Decryption failed with exit code ${decryptAudio.err.code}`); - fs.renameSync(`${tempTsFile}.audio.enc.mp4`, `${tsFile}.audio.enc.mp4`); - return undefined; - } else { - if (!options.nocleanup) { - fs.removeSync(`${tempTsFile}.audio.enc.mp4`); - } - fs.renameSync(`${tempTsFile}.audio.mp4`, `${tsFile}.audio.mp4`); - files.push({ - type: 'Audio', - path: `${tsFile}.audio.mp4`, - lang: lang - }); - console.info('Decryption done for audio'); - } - } - } else { - console.warn('mp4decrypt not found, files need decryption. Decryption Keys:', encryptionKeys); - } - } else { - if (videoDownloaded) { - files.push({ - type: 'Video', - path: `${tsFile}.video.mp4`, - lang: lang - }); - } - if (audioDownloaded) { - files.push({ - type: 'Audio', - path: `${tsFile}.audio.mp4`, - lang: lang - }); - } - } - } - } else if (options.novids && options.noaudio) { - fileName = parseFileName(options.fileName, variables, options.numbers, options.override).join(path.sep); - } - - if(options.dlsubs.indexOf('all') > -1){ - options.dlsubs = ['all']; - } - - if (options.nosubs) { - console.info('Subtitles downloading disabled from nosubs flag.'); - options.skipsubs = true; - } - - if (!options.skipsubs && options.dlsubs.indexOf('none') == -1) { - if(streamData.subtitles.length > 0) { - for(const sub of streamData.subtitles) { - const subLang = langsData.languages.find(a => a.ao_locale === sub.lang); - if (!subLang) { - console.warn(`Language not found for subtitle language: ${sub.lang}, Skipping`); - continue; - } - const sxData: Partial = {}; - sxData.file = langsData.subsFile(fileName as string, subIndex+'', subLang, false, options.ccTag); - sxData.path = path.join(this.cfg.dir.content, sxData.file); - sxData.language = subLang; - if((options.dlsubs.includes('all') || options.dlsubs.includes(subLang.locale)) && sub.url.includes('.ass')) { - const getSubtitle = await this.req.getData(sub.url, AuthHeaders); - if (getSubtitle.ok && getSubtitle.res) { - console.info(`Subtitle Downloaded: ${sub.url}`); - const sBody = await getSubtitle.res.text(); - sxData.title = `${subLang.language}`; - sxData.fonts = fontsData.assFonts(sBody) as Font[]; - fs.writeFileSync(sxData.path, sBody); - files.push({ - type: 'Subtitle', - ...sxData as sxItem, - cc: false - }); - } else{ - console.warn(`Failed to download subtitle: ${sxData.file}`); - } - } - subIndex++; - } - } else{ - console.warn('Can\'t find urls for subtitles!'); - } - } - else{ - console.info('Subtitles downloading skipped!'); - } - await this.sleep(options.waittime); - } - return { - error: dlFailed, - data: files, - fileName: fileName ? (path.isAbsolute(fileName) ? fileName : path.join(this.cfg.dir.content, fileName)) || './unknown' : './unknown' - }; - } - - public sleep(ms: number) { - return new Promise((resolve) => { - setTimeout(resolve, ms); - }); - } -} \ No newline at end of file diff --git a/widevine/.gitkeep b/bin/.gitkeep similarity index 100% rename from widevine/.gitkeep rename to bin/.gitkeep diff --git a/config/bin-path.yml b/config/bin-path.yml index 8c08eb7..239b00c 100644 --- a/config/bin-path.yml +++ b/config/bin-path.yml @@ -1,4 +1,2 @@ -ffmpeg: "ffmpeg.exe" -mkvmerge: "mkvmerge.exe" -ffprobe: "ffprobe.exe" -mp4decrypt: "mp4decrypt.exe" +ffmpeg: "./bin/ffmpeg" +mkvmerge: "./bin/mkvtoolnix/mkvmerge.exe" diff --git a/config/cli-defaults.yml b/config/cli-defaults.yml index b12960e..08a6b4b 100644 --- a/config/cli-defaults.yml +++ b/config/cli-defaults.yml @@ -1,24 +1,7 @@ -# Set the quality of the stream, 0 is highest available. -q: 0 -# Set which stream to use -kstream: 1 -# Set which server to use -server: 1 -# How many parts to download at once. Increasing may improve download speed. -partsize: 10 -# Set whether to mux into an mp4 or not. Not recommended. -mp4: false -# Whether to delete any created files or not -nocleanup: false -# Whether to only download the relevant video once -dlVideoOnce: false -# Whether to keep all downloaded videos or only a single copy -keepAllVideos: false -# What to use as the file name template -fileName: "[${service}] ${showTitle} - S${season}E${episode} [${height}p]" -# What Audio languages to download -dubLang: ["jpn"] -# What Subtitle languages to download -dlsubs: ["all"] -# What language Audio to set as default -defaultAudio: "jpn" \ No newline at end of file +releaseGroup: Funimation +videoLayer: 7 +fileSuffix: SIZEp +nServer: 1 +mp4mux: false +muxSubs: false +noCleanUp: false diff --git a/config/dir-path.yml b/config/dir-path.yml index 54c6bb3..f9c4877 100644 --- a/config/dir-path.yml +++ b/config/dir-path.yml @@ -1,2 +1,2 @@ content: ./videos/ -fonts: ./fonts/ +trash: ./videos/_trash/ diff --git a/config/gui.yml b/config/gui.yml deleted file mode 100644 index 87c3f5a..0000000 --- a/config/gui.yml +++ /dev/null @@ -1 +0,0 @@ -port: 3000 diff --git a/crunchy.ts b/crunchy.ts deleted file mode 100644 index 2dfa8a2..0000000 --- a/crunchy.ts +++ /dev/null @@ -1,2541 +0,0 @@ -// build-in -import path from 'path'; -import fs from 'fs-extra'; - -// package program -import packageJson from './package.json'; - -// plugins -import { console } from './modules/log'; -import shlp from 'sei-helper'; -import m3u8 from 'm3u8-parsed'; -import streamdl, { M3U8Json } from './modules/hls-download'; -import { exec } from './modules/sei-helper-fixes'; - -// custom modules -import * as fontsData from './modules/module.fontsData'; -import * as langsData from './modules/module.langsData'; -import * as yamlCfg from './modules/module.cfg-loader'; -import * as yargs from './modules/module.app-args'; -import Merger, { Font, MergerInput, SubtitleInput } from './modules/module.merger'; -import getKeys, { canDecrypt } from './modules/widevine'; -//import vttConvert from './modules/module.vttconvert'; - -// args - -// load req -import { domain, api } from './modules/module.api-urls'; -import * as reqModule from './modules/module.fetch'; -import { CrunchySearch } from './@types/crunchySearch'; -import { CrunchyEpisodeList, CrunchyEpisode } from './@types/crunchyEpisodeList'; -import { CrunchyDownloadOptions, CrunchyEpMeta, CrunchyMuxOptions, CrunchyMultiDownload, DownloadedMedia, ParseItem, SeriesSearch, SeriesSearchItem } from './@types/crunchyTypes'; -import { ObjectInfo } from './@types/objectInfo'; -import parseFileName, { Variable } from './modules/module.filename'; -import { CrunchyStreams, PlaybackData, Subtitles } from './@types/playbackData'; -import { downloaded } from './modules/module.downloadArchive'; -import parseSelect from './modules/module.parseSelect'; -import { AvailableFilenameVars, getDefault } from './modules/module.args'; -import { AuthData, AuthResponse, Episode, ResponseBase, SearchData, SearchResponse, SearchResponseItem } from './@types/messageHandler'; -import { ServiceClass } from './@types/serviceClassInterface'; -import { CrunchyAndroidStreams } from './@types/crunchyAndroidStreams'; -import { CrunchyAndroidEpisodes } from './@types/crunchyAndroidEpisodes'; -import { parse } from './modules/module.transform-mpd'; -import { CrunchyAndroidObject } from './@types/crunchyAndroidObject'; -import { CrunchyChapters, CrunchyChapter, CrunchyOldChapter } from './@types/crunchyChapters'; -import vtt2ass from './modules/module.vtt2ass'; -import { CrunchyPlayStream } from './@types/crunchyPlayStreams'; -import { CrunchyPlayStreams } from './@types/enums'; -import { randomUUID } from 'node:crypto'; - -export type sxItem = { - language: langsData.LanguageItem, - path: string, - file: string - title: string, - fonts: Font[] -} - -export default class Crunchy implements ServiceClass { - public cfg: yamlCfg.ConfigObject; - public api: 'android' | 'web'; - public locale: string; - private token: Record; - private req: reqModule.Req; - private cmsToken: { - cms?: Record, - cms_beta?: Record, - cms_web?: Record - } = {}; - - constructor(private debug = false) { - this.cfg = yamlCfg.loadCfg(); - this.token = yamlCfg.loadCRToken(); - this.req = new reqModule.Req(domain, debug, false, 'cr'); - this.api = 'android'; - this.locale = 'en-US'; - } - - public checkToken(): boolean { - return Object.keys(this.cmsToken.cms ?? {}).length > 0; - } - - public async cli() { - console.info(`\n=== Multi Downloader NX ${packageJson.version} ===\n`); - const argv = yargs.appArgv(this.cfg.cli); - this.api = argv.crapi; - this.locale = argv.locale; - if (argv.debug) - this.debug = true; - - // load binaries - this.cfg.bin = await yamlCfg.loadBinCfg(); - if (argv.allDubs) { - argv.dubLang = langsData.dubLanguageCodes; - } - // select mode - if (argv.silentAuth && !argv.auth) { - await this.doAuth({ - username: argv.username ?? await shlp.question('[Q] LOGIN/EMAIL'), - password: argv.password ?? await shlp.question('[Q] PASSWORD ') - }); - } - if(argv.dlFonts){ - await this.getFonts(); - } - else if(argv.auth){ - await this.doAuth({ - username: argv.username ?? await shlp.question('[Q] LOGIN/EMAIL'), - password: argv.password ?? await shlp.question('[Q] PASSWORD ') - }); - } - else if (argv.token) { - await this.loginWithToken(argv.token); - } - else if(argv.cmsindex){ - await this.refreshToken(); - await this.getCmsData(); - } - else if(argv.new){ - await this.refreshToken(); - await this.getNewlyAdded(argv.page); - } - else if(argv.search && argv.search.length > 2){ - await this.refreshToken(); - await this.doSearch({ ...argv, search: argv.search as string }); - } - else if(argv.series && argv.series.match(/^[0-9A-Z]{9}$/)){ - await this.refreshToken(); - await this.logSeriesById(argv.series as string); - const selected = await this.downloadFromSeriesID(argv.series, { ...argv }); - if (selected.isOk) { - for (const select of selected.value) { - if (!(await this.downloadEpisode(select, {...argv, skipsubs: false}, true))) { - console.error(`Unable to download selected episode ${select.episodeNumber}`); - return false; - } - } - } - return true; - } - else if(argv['movie-listing'] && argv['movie-listing'].match(/^[0-9A-Z]{9}$/)){ - await this.refreshToken(); - await this.logMovieListingById(argv['movie-listing'] as string); - } - else if(argv.s && argv.s.match(/^[0-9A-Z]{9}$/)){ - await this.refreshToken(); - if (argv.dubLang.length > 1) { - console.info('One show can only be downloaded with one dub. Use --srz instead.'); - } - argv.dubLang = [argv.dubLang[0]]; - const selected = await this.getSeasonById(argv.s, argv.numbers, argv.e, argv.but, argv.all); - if (selected.isOk) { - for (const select of selected.value) { - if (!(await this.downloadEpisode(select, {...argv, skipsubs: false }))) { - console.error(`Unable to download selected episode ${select.episodeNumber}`); - return false; - } - } - } - return true; - } - else if(argv.e){ - await this.refreshToken(); - if (argv.dubLang.length > 1) { - console.info('One show can only be downloaded with one dub. Use --srz instead.'); - } - argv.dubLang = [argv.dubLang[0]]; - const selected = await this.getObjectById(argv.e, false); - for (const select of selected as Partial[]) { - if (!(await this.downloadEpisode(select as CrunchyEpMeta, {...argv, skipsubs: false}))) { - console.error(`Unable to download selected episode ${select.episodeNumber}`); - return false; - } - } - return true; - } else if (argv.extid) { - await this.refreshToken(); - if (argv.dubLang.length > 1) { - console.info('One show can only be downloaded with one dub. Use --srz instead.'); - } - argv.dubLang = [argv.dubLang[0]]; - const selected = await this.getObjectById(argv.extid, false, true); - for (const select of selected as Partial[]) { - if (!(await this.downloadEpisode(select as CrunchyEpMeta, {...argv, skipsubs: false}))) { - console.error(`Unable to download selected episode ${select.episodeNumber}`); - return false; - } - } - return true; - } - else{ - console.info('No option selected or invalid value entered. Try --help.'); - } - } - - public async getFonts() { - console.info('Downloading fonts...'); - const fonts = Object.values(fontsData.fontFamilies).reduce((pre, curr) => pre.concat(curr)); - for(const f of fonts) { - const fontLoc = path.join(this.cfg.dir.fonts, f); - if(fs.existsSync(fontLoc) && fs.statSync(fontLoc).size != 0){ - console.info(`${f} already downloaded!`); - } - else{ - const fontFolder = path.dirname(fontLoc); - if(fs.existsSync(fontLoc) && fs.statSync(fontLoc).size == 0){ - fs.unlinkSync(fontLoc); - } - try{ - fs.ensureDirSync(fontFolder); - } - catch(e){ - console.info(''); - } - const fontUrl = fontsData.root + f; - const getFont = await this.req.getData(fontUrl); - if(getFont.ok && getFont.res){ - fs.writeFileSync(fontLoc, Buffer.from(await getFont.res.arrayBuffer())); - console.info(`Downloaded: ${f}`); - } - else{ - console.warn(`Failed to download: ${f}`); - } - } - } - console.info('All required fonts downloaded!'); - } - - public async doAuth(data: AuthData): Promise { - const uuid = randomUUID(); - const authData = new URLSearchParams({ - 'username': data.username, - 'password': data.password, - 'grant_type': 'password', - 'scope': 'offline_access', - 'device_id': uuid, - 'device_type': 'Chrome on Windows' - }).toString(); - const authReqOpts: reqModule.Params = { - method: 'POST', - headers: api.crunchyAuthHeaderMob, - body: authData - }; - const authReq = await this.req.getData(api.beta_auth, authReqOpts); - if(!authReq.ok || !authReq.res){ - console.error('Authentication failed!'); - return { isOk: false, reason: new Error('Authentication failed') }; - } - this.token = await authReq.res.json(); - this.token.device_id = uuid; - this.token.expires = new Date(Date.now() + this.token.expires_in); - yamlCfg.saveCRToken(this.token); - await this.getProfile(); - console.info('Your Country: %s', this.token.country); - return { isOk: true, value: undefined }; - } - - public async doAnonymousAuth(){ - const uuid = randomUUID(); - const authData = new URLSearchParams({ - 'grant_type': 'client_id', - 'scope': 'offline_access', - 'device_id': uuid, - 'device_type': 'Chrome on Windows' - }).toString(); - const authReqOpts: reqModule.Params = { - method: 'POST', - headers: api.crunchyAuthHeaderMob, - body: authData - }; - const authReq = await this.req.getData(api.beta_auth, authReqOpts); - if(!authReq.ok || !authReq.res){ - console.error('Anonymous Authentication failed!'); - return; - } - this.token = await authReq.res.json(); - this.token.device_id = uuid; - this.token.expires = new Date(Date.now() + this.token.expires_in); - yamlCfg.saveCRToken(this.token); - } - - public async getProfile(silent = false) : Promise { - if(!this.token.access_token){ - console.error('No access token!'); - return false; - } - const profileReqOptions = { - headers: { - Authorization: `Bearer ${this.token.access_token}`, - }, - useProxy: true - }; - const profileReq = await this.req.getData(api.beta_profile, profileReqOptions); - if(!profileReq.ok || !profileReq.res){ - console.error('Get profile failed!'); - return false; - } - const profile = await profileReq.res.json(); - if (!silent) { - console.info('USER: %s (%s)', profile.username, profile.email); - } - return true; - } - - public sleep(ms: number) { - return new Promise((resolve) => { - setTimeout(resolve, ms); - }); - } - - public async loginWithToken(refreshToken: string) { - const uuid = randomUUID(); - const authData = new URLSearchParams({ - 'refresh_token': this.token.refresh_token, - 'grant_type': 'refresh_token', - //'grant_type': 'etp_rt_cookie', - 'scope': 'offline_access', - 'device_id': uuid, - 'device_type': 'Chrome on Windows' - }).toString(); - const authReqOpts: reqModule.Params = { - method: 'POST', - headers: {...api.crunchyAuthHeaderMob, Cookie: `etp_rt=${refreshToken}`}, - body: authData - }; - const authReq = await this.req.getData(api.beta_auth, authReqOpts); - if(!authReq.ok || !authReq.res){ - console.error('Token Authentication failed!'); - if (authReq.res?.status == 400) { - console.warn('Token is likely wrong (Or invalid for given API), please login again!'); - } - return; - } - this.token = await authReq.res.json(); - this.token.device_id = uuid; - this.token.expires = new Date(Date.now() + this.token.expires_in); - yamlCfg.saveCRToken(this.token); - await this.getProfile(false); - await this.getCMStoken(true); - } - - public async refreshToken(ifNeeded = false, silent = false) { - if(!this.token.access_token && !this.token.refresh_token || this.token.access_token && !this.token.refresh_token){ - await this.doAnonymousAuth(); - } - else{ - /*if (ifNeeded) - return;*/ - if (!(Date.now() > new Date(this.token.expires).getTime()) && ifNeeded) { - return; - } else { - //console.info('[WARN] The token has expired compleatly. I will try to refresh the token anyway, but you might have to reauth.'); - } - const uuid = this.token.device_id || randomUUID(); - const authData = new URLSearchParams({ - 'refresh_token': this.token.refresh_token, - 'grant_type': 'refresh_token', - //'grant_type': 'etp_rt_cookie', - 'scope': 'offline_access', - 'device_id': uuid, - 'device_type': 'Chrome on Windows' - }).toString(); - const authReqOpts: reqModule.Params = { - method: 'POST', - headers: {...api.crunchyAuthHeaderMob, Cookie: `etp_rt=${this.token.refresh_token}`}, - body: authData - }; - const authReq = await this.req.getData(api.beta_auth, authReqOpts); - if(!authReq.ok || !authReq.res){ - console.error('Token Refresh Failed!'); - if (authReq.res?.status == 400) { - console.warn('Token is likely wrong, please login again!'); - } - return; - } - this.token = await authReq.res.json(); - this.token.device_id = uuid; - this.token.expires = new Date(Date.now() + this.token.expires_in); - yamlCfg.saveCRToken(this.token); - } - if(this.token.refresh_token) { - await this.getProfile(silent); - } else { - console.info('USER: Anonymous'); - } - await this.getCMStoken(ifNeeded); - } - - public async getCMStoken(ifNeeded = false) { - if(!this.token.access_token){ - console.error('No access token!'); - return; - } - - if (ifNeeded && this.cmsToken.cms) { - if (!(Date.now() >= new Date(this.cmsToken.cms.expires).getTime())) { - return; - } - } - - const cmsTokenReqOpts = { - headers: { - Authorization: `Bearer ${this.token.access_token}`, - }, - useProxy: true - }; - const cmsTokenReq = await this.req.getData(api.beta_cmsToken, cmsTokenReqOpts); - if(!cmsTokenReq.ok || !cmsTokenReq.res){ - console.error('Authentication CMS token failed!'); - return; - } - this.cmsToken = await cmsTokenReq.res.json(); - console.info('Your Country: %s\n', this.cmsToken.cms?.bucket.split('/')[1]); - } - - public async getCmsData(){ - // check token - if(!this.cmsToken.cms){ - console.error('Authentication required!'); - return; - } - // opts - const indexReqOpts = [ - api.beta_cms, - this.cmsToken.cms.bucket, - '/index?', - new URLSearchParams({ - 'force_locale': '', - 'preferred_audio_language': 'ja-JP', - 'locale': this.locale, - 'Policy': this.cmsToken.cms.policy, - 'Signature': this.cmsToken.cms.signature, - 'Key-Pair-Id': this.cmsToken.cms.key_pair_id, - }), - ].join(''); - const indexReq = await this.req.getData(indexReqOpts); - if(!indexReq.ok || ! indexReq.res){ - console.error('Get CMS index FAILED!'); - return; - } - console.info(await indexReq.res.json()); - } - - public async doSearch(data: SearchData): Promise{ - if(!this.token.access_token){ - console.error('Authentication required!'); - return { isOk: false, reason: new Error('Not authenticated') }; - } - const searchReqOpts = { - headers: { - Authorization: `Bearer ${this.token.access_token}`, - }, - useProxy: true - }; - const searchStart = data.page ? (data.page-1)*5 : 0; - const searchParams = new URLSearchParams({ - q: data.search, - n: '5', - start: data.page ? `${(data.page-1)*5}` : '0', - type: data['search-type'] ?? getDefault('search-type', this.cfg.cli), - locale: this.locale, - }).toString(); - const searchReq = await this.req.getData(`${api.search}?${searchParams}`, searchReqOpts); - if(!searchReq.ok || ! searchReq.res){ - console.error('Search FAILED!'); - return { isOk: false, reason: new Error('Search failed. No more information provided') }; - } - const searchResults = await searchReq.res.json() as CrunchySearch; - if(searchResults.total < 1){ - console.info('Nothing Found!'); - return { isOk: true, value: [] }; - } - - const searchTypesInfo = { - 'top_results': 'Top results', - 'series': 'Found series', - 'movie_listing': 'Found movie lists', - 'episode': 'Found episodes' - }; - for(const search_item of searchResults.data){ - console.info('%s:', searchTypesInfo[search_item.type as keyof typeof searchTypesInfo]); - // calculate pages - const pageCur = searchStart > 0 ? Math.ceil(searchStart/5) + 1 : 1; - const pageMax = Math.ceil(search_item.count/5); - // pages per category - if(search_item.count < 1){ - console.info(' Nothing Found...'); - } - if(search_item.count > 0){ - if(pageCur > pageMax){ - console.info(' Last page is %s...', pageMax); - continue; - } - for(const item of search_item.items){ - await this.logObject(item); - } - console.info(` Total results: ${search_item.count} (Page: ${pageCur}/${pageMax})`); - } - } - const toSend = searchResults.data.filter(a => a.type === 'series' || a.type === 'movie_listing'); - return { isOk: true, value: toSend.map(a => { - return a.items.map((a): SearchResponseItem => { - const images = (a.images.poster_tall ?? [[ { source: '/notFound.png' } ]])[0]; - return { - id: a.id, - image: images[Math.floor(images.length / 2)].source, - name: a.title, - rating: -1, - desc: a.description - }; - }); - }).reduce((pre, cur) => pre.concat(cur))}; - } - - public async logObject(item: ParseItem, pad?: number, getSeries?: boolean, getMovieListing?: boolean){ - if(this.debug){ - console.info(item); - } - pad = pad ?? 2; - getSeries = getSeries === undefined ? true : getSeries; - getMovieListing = getMovieListing === undefined ? true : getMovieListing; - item.isSelected = item.isSelected === undefined ? false : item.isSelected; - if(!item.type) { - item.type = item.__class__; - } - - //guess item type - //TODO: look into better methods of getting item type - let iType = item.type; - if (!iType) { - if (item.episode_number) { - iType = 'episode'; - } else if (item.season_number) { - iType = 'season'; - } else if (item.season_count) { - iType = 'series'; - } else if (item.media_type == 'movie') { - iType = 'movie'; - } else if (item.movie_release_year) { - iType = 'movie_listing'; - } else { - if (item.identifier !== '') { - const iTypeCheck = item.identifier?.split('|'); - if (iTypeCheck) { - if (iTypeCheck[1] == 'M') { - iType = 'movie'; - } else if (!iTypeCheck[2]) { - iType = 'season'; - } else { - iType = 'episode'; - } - } else { - iType = 'series'; - } - } else { - iType = 'movie_listing'; - } - } - item.type = iType; - } - - const oTypes = { - 'series': 'Z', // SRZ - 'season': 'S', // VOL - 'episode': 'E', // EPI - 'movie_listing': 'F', // FLM - 'movie': 'M', // MED - }; - // check title - item.title = item.title != '' ? item.title : 'NO_TITLE'; - // static data - const oMetadata: string[] = [], - oBooleans: string[] = [], - tMetadata = item.type + '_metadata', - iMetadata = (Object.prototype.hasOwnProperty.call(item, tMetadata) ? item[tMetadata as keyof ParseItem] : item) as Record, - iTitle = [ item.title ]; - - const audio_languages: string[] = []; - - // set object booleans - if(iMetadata.duration_ms){ - oBooleans.push(shlp.formatTime(iMetadata.duration_ms/1000)); - } - if(iMetadata.is_simulcast) { - oBooleans.push('SIMULCAST'); - } - if(iMetadata.is_mature) { - oBooleans.push('MATURE'); - } - if (item.versions) { - for(const version of item.versions) { - audio_languages.push(version.audio_locale); - if (version.original) { - oBooleans.push('SUB'); - } else { - if (!oBooleans.includes('DUB')) { - oBooleans.push('DUB'); - } - } - } - } else { - if(iMetadata.is_subbed){ - oBooleans.push('SUB'); - } - if(iMetadata.is_dubbed){ - oBooleans.push('DUB'); - } - } - if(item.playback && item.type != 'movie_listing') { - oBooleans.push('STREAM'); - } - // set object metadata - if(iMetadata.season_count){ - oMetadata.push(`Seasons: ${iMetadata.season_count}`); - } - if(iMetadata.episode_count){ - oMetadata.push(`EPs: ${iMetadata.episode_count}`); - } - if(item.season_number && !iMetadata.hide_season_title && !iMetadata.hide_season_number){ - oMetadata.push(`Season: ${item.season_number}`); - } - if(item.type == 'episode'){ - if(iMetadata.episode){ - iTitle.unshift(iMetadata.episode); - } - if(!iMetadata.hide_season_title && iMetadata.season_title){ - iTitle.unshift(iMetadata.season_title); - } - } - if(item.is_premium_only){ - iTitle[0] = `☆ ${iTitle[0]}`; - } - // display metadata - if(item.hide_metadata){ - iMetadata.hide_metadata = item.hide_metadata; - } - const showObjectMetadata = oMetadata.length > 0 && !iMetadata.hide_metadata; - const showObjectBooleans = oBooleans.length > 0 && !iMetadata.hide_metadata; - // make obj ids - const objects_ids: string[] = []; - objects_ids.push(oTypes[item.type as keyof typeof oTypes] + ':' + item.id); - if(item.seq_id){ - objects_ids.unshift(item.seq_id); - } - if(item.f_num){ - objects_ids.unshift(item.f_num); - } - if(item.s_num){ - objects_ids.unshift(item.s_num); - } - if(item.external_id){ - objects_ids.push(item.external_id); - } - if(item.ep_num){ - objects_ids.push(item.ep_num); - } - - // show entry - console.info( - '%s%s[%s] %s%s%s', - ''.padStart(item.isSelected ? pad-1 : pad, ' '), - item.isSelected ? '✓' : '', - objects_ids.join('|'), - iTitle.join(' - '), - showObjectMetadata ? ` (${oMetadata.join(', ')})` : '', - showObjectBooleans ? ` [${oBooleans.join(', ')}]` : '', - - ); - if(item.last_public){ - console.info(''.padStart(pad+1, ' '), '- Last updated:', item.last_public); - } - if(item.subtitle_locales){ - iMetadata.subtitle_locales = item.subtitle_locales; - } - if (item.versions && audio_languages.length > 0) { - console.info( - '%s- Versions: %s', - ''.padStart(pad + 2, ' '), - langsData.parseSubtitlesArray(audio_languages) - ); - } - if(iMetadata.subtitle_locales && iMetadata.subtitle_locales.length > 0){ - console.info( - '%s- Subtitles: %s', - ''.padStart(pad + 2, ' '), - langsData.parseSubtitlesArray(iMetadata.subtitle_locales) - ); - } - if(item.availability_notes){ - console.info( - '%s- Availability notes: %s', - ''.padStart(pad + 2, ' '), - item.availability_notes.replace(/\[[^\]]*]?/gm, '') - ); - } - if(item.type == 'series' && getSeries){ - await this.logSeriesById(item.id, pad, true); - console.info(''); - } - if(item.type == 'movie_listing' && getMovieListing){ - await this.logMovieListingById(item.id, pad+2); - console.info(''); - } - } - - public async logSeriesById(id: string, pad?: number, hideSeriesTitle?: boolean){ - // parse - pad = pad || 0; - hideSeriesTitle = hideSeriesTitle !== undefined ? hideSeriesTitle : false; - // check token - if(!this.cmsToken.cms){ - console.error('Authentication required!'); - return; - } - // opts - const AuthHeaders = { - headers: { - Authorization: `Bearer ${this.token.access_token}`, - }, - useProxy: true - }; - // reqs - if(!hideSeriesTitle){ - const seriesReq = await this.req.getData(`${api.cms}/series/${id}?force_locale=&preferred_audio_language=ja-JP&locale=${this.locale}`, AuthHeaders); - if(!seriesReq.ok || !seriesReq.res){ - console.error('Series Request FAILED!'); - return; - } - const seriesData = await seriesReq.res.json(); - await this.logObject(seriesData.data[0], pad, false); - } - // seasons list - const seriesSeasonListReq = await this.req.getData(`${api.cms}/series/${id}/seasons?force_locale=&preferred_audio_language=ja-JP&locale=${this.locale}`, AuthHeaders); - if(!seriesSeasonListReq.ok || !seriesSeasonListReq.res){ - console.error('Series Request FAILED!'); - return; - } - // parse data - const seasonsList = await seriesSeasonListReq.res.json() as SeriesSearch; - if(seasonsList.total < 1){ - console.info('Series is empty!'); - return; - } - for(const item of seasonsList.data){ - await this.logObject(item, pad+2); - } - } - - public async logMovieListingById(id: string, pad?: number){ - pad = pad || 2; - if(!this.cmsToken.cms){ - console.error('Authentication required!'); - return; - } - - // opts - const AuthHeaders = { - headers: { - Authorization: `Bearer ${this.token.access_token}`, - }, - useProxy: true - }; - - //Movie Listing - const movieListingReq = await this.req.getData(`${api.cms}/movie_listings/${id}?force_locale=&preferred_audio_language=ja-JP&locale=${this.locale}`, AuthHeaders); - if(!movieListingReq.ok || !movieListingReq.res){ - console.error('Movie Listing Request FAILED!'); - return; - } - const movieListing = await movieListingReq.res.json(); - if(movieListing.total < 1){ - console.info('Movie Listing is empty!'); - return; - } - for(const item of movieListing.data){ - await this.logObject(item, pad, false, false); - } - - //Movies - const moviesListReq = await this.req.getData(`${api.cms}/movie_listings/${id}/movies?force_locale=&preferred_audio_language=ja-JP&locale=${this.locale}`, AuthHeaders); - if(!moviesListReq.ok || !moviesListReq.res){ - console.error('Movies List Request FAILED!'); - return; - } - const moviesList = await moviesListReq.res.json(); - for(const item of moviesList.data){ - await this.logObject(item, pad + 2); - } - } - - public async getNewlyAdded(page?: number){ - if(!this.token.access_token){ - console.error('Authentication required!'); - return; - } - const newlyAddedReqOpts = { - headers: { - Authorization: `Bearer ${this.token.access_token}`, - }, - useProxy: true - }; - const newlyAddedParams = new URLSearchParams({ - sort_by: 'newly_added', - n: '25', - start: (page ? (page-1)*25 : 0).toString(), - }).toString(); - const newlyAddedReq = await this.req.getData(`${api.beta_browse}?${newlyAddedParams}`, newlyAddedReqOpts); - if(!newlyAddedReq.ok || !newlyAddedReq.res){ - console.error('Get newly added FAILED!'); - return; - } - const newlyAddedResults = await newlyAddedReq.res.json(); - console.info('Newly added:'); - for(const i of newlyAddedResults.items){ - await this.logObject(i, 2); - } - // calculate pages - const itemPad = parseInt(new URL(newlyAddedResults.__href__, domain.api_beta).searchParams.get('start') as string); - const pageCur = itemPad > 0 ? Math.ceil(itemPad/25) + 1 : 1; - const pageMax = Math.ceil(newlyAddedResults.total/25); - console.info(` Total results: ${newlyAddedResults.total} (Page: ${pageCur}/${pageMax})`); - } - - public async getSeasonById(id: string, numbers: number, e: string|undefined, but: boolean, all: boolean) : Promise> { - if(!this.cmsToken.cms){ - console.error('Authentication required!'); - return { isOk: false, reason: new Error('Authentication required') }; - } - - const AuthHeaders = { - headers: { - Authorization: `Bearer ${this.token.access_token}`, - }, - useProxy: true - }; - - - //get show info - const showInfoReq = await this.req.getData(`${api.cms}/seasons/${id}?force_locale=&preferred_audio_language=ja-JP&locale=${this.locale}`, AuthHeaders); - if(!showInfoReq.ok || !showInfoReq.res){ - console.error('Show Request FAILED!'); - return { isOk: false, reason: new Error('Show request failed. No more information provided.') }; - } - const showInfo = await showInfoReq.res.json(); - await this.logObject(showInfo.data[0], 0); - - let episodeList = { total: 0, data: [], meta: {} } as CrunchyEpisodeList; - //get episode info - if (this.api == 'android') { - const reqEpsListOpts = [ - api.beta_cms, - this.cmsToken.cms.bucket, - '/episodes?', - new URLSearchParams({ - 'force_locale': '', - 'preferred_audio_language': 'ja-JP', - 'locale': this.locale, - 'season_id': id, - 'Policy': this.cmsToken.cms.policy, - 'Signature': this.cmsToken.cms.signature, - 'Key-Pair-Id': this.cmsToken.cms.key_pair_id, - }), - ].join(''); - const reqEpsList = await this.req.getData(reqEpsListOpts, AuthHeaders); - if(!reqEpsList.ok || !reqEpsList.res){ - console.error('Episode List Request FAILED!'); - return { isOk: false, reason: new Error('Episode List request failed. No more information provided.') }; - } - //CrunchyEpisodeList - const episodeListAndroid = await reqEpsList.res.json() as CrunchyAndroidEpisodes; - episodeList = { - total: episodeListAndroid.total, - data: episodeListAndroid.items, - meta: {} - }; - } else { - const reqEpsList = await this.req.getData(`${api.cms}/seasons/${id}/episodes?force_locale=&preferred_audio_language=ja-JP&locale=${this.locale}`, AuthHeaders); - if(!reqEpsList.ok || !reqEpsList.res){ - console.error('Episode List Request FAILED!'); - return { isOk: false, reason: new Error('Episode List request failed. No more information provided.') }; - } - //CrunchyEpisodeList - episodeList = await reqEpsList.res.json() as CrunchyEpisodeList; - } - - const epNumList: { - ep: number[], - sp: number - } = { ep: [], sp: 0 }; - const epNumLen = numbers; - - if(episodeList.total < 1){ - console.info(' Season is empty!'); - return { isOk: true, value: [] }; - } - - const doEpsFilter = parseSelect(e as string); - const selectedMedia: CrunchyEpMeta[] = []; - - episodeList.data.forEach((item) => { - item.hide_season_title = true; - if(item.season_title == '' && item.series_title != ''){ - item.season_title = item.series_title; - item.hide_season_title = false; - item.hide_season_number = true; - } - if(item.season_title == '' && item.series_title == ''){ - item.season_title = 'NO_TITLE'; - item.series_title = 'NO_TITLE'; - } - const epNum = item.episode; - let isSpecial = false; - item.isSelected = false; - if(!epNum.match(/^\d+$/) || epNumList.ep.indexOf(parseInt(epNum, 10)) > -1){ - isSpecial = true; - epNumList.sp++; - } - else{ - epNumList.ep.push(parseInt(epNum, 10)); - } - const selEpId = ( - isSpecial - ? 'S' + epNumList.sp.toString().padStart(epNumLen, '0') - : '' + parseInt(epNum, 10).toString().padStart(epNumLen, '0') - ); - // set data - const images = (item.images.thumbnail ?? [[ { source: '/notFound.png' } ]])[0]; - const epMeta: CrunchyEpMeta = { - data: [ - { - mediaId: item.id, - versions: null, - lang: langsData.languages.find(a => a.code == yargs.appArgv(this.cfg.cli).dubLang[0]), - isSubbed: item.is_subbed, - isDubbed: item.is_dubbed - } - ], - seriesTitle: item.series_title, - seasonTitle: item.season_title, - episodeNumber: item.episode, - episodeTitle: item.title, - seasonID: item.season_id, - season: item.season_number, - showID: id, - e: selEpId, - image: images[Math.floor(images.length / 2)].source - }; - // Check for streams_link and update playback var if needed - if (item.__links__?.streams.href) { - epMeta.data[0].playback = item.__links__.streams.href; - if(!item.playback) { - item.playback = item.__links__.streams.href; - } - } - if (item.streams_link) { - epMeta.data[0].playback = item.streams_link; - if(!item.playback) { - item.playback = item.streams_link; - } - } - if (item.versions) { - epMeta.data[0].versions = item.versions; - } - // find episode numbers - if((but && item.playback && !doEpsFilter.isSelected([selEpId, item.id])) || (all && item.playback) || (!but && doEpsFilter.isSelected([selEpId, item.id]) && !item.isSelected && item.playback)){ - selectedMedia.push(epMeta); - item.isSelected = true; - } - // show ep - item.seq_id = selEpId; - this.logObject(item); - }); - - // display - if(selectedMedia.length < 1){ - console.info('\nEpisodes not selected!\n'); - } - - console.info(''); - return { isOk: true, value: selectedMedia }; - } - - public async downloadEpisode(data: CrunchyEpMeta, options: CrunchyDownloadOptions, isSeries?: boolean): Promise { - const res = await this.downloadMediaList(data, options); - if (res === undefined || res.error) { - return false; - } else { - if (!options.skipmux) { - await this.muxStreams(res.data, { ...options, output: res.fileName }); - } else { - console.info('Skipping mux'); - } - if (!isSeries) { - downloaded({ - service: 'crunchy', - type: 's' - }, data.seasonID, [data.e]); - } else { - downloaded({ - service: 'crunchy', - type: 'srz' - }, data.showID, [data.e]); - } - } - return true; - } - - public async getObjectById(e?: string, earlyReturn?: boolean, external_id?: boolean): Promise[]|undefined> { - if(!this.cmsToken.cms){ - console.error('Authentication required!'); - return []; - } - - let convertedObjects; - if (external_id) { - const epFilter = parseSelect(e as string); - const objectIds = []; - for (const ob of epFilter.values) { - const extIdReqOpts = [ - api.beta_cms, - this.cmsToken.cms.bucket, - '/channels/crunchyroll/objects', - '?', - new URLSearchParams({ - 'force_locale': '', - 'preferred_audio_language': 'ja-JP', - 'locale': this.locale, - 'external_id': ob, - 'Policy': this.cmsToken.cms.policy, - 'Signature': this.cmsToken.cms.signature, - 'Key-Pair-Id': this.cmsToken.cms.key_pair_id, - }), - ].join(''); - - const extIdReq = await this.req.getData(extIdReqOpts); - if (!extIdReq.ok || !extIdReq.res) { - console.error('Objects Request FAILED!'); - if (extIdReq.error && extIdReq.error.res && extIdReq.error.res.body) { - console.info('[INFO] Body:', extIdReq.error.res.body); - } - continue; - } - - const oldObjectInfo = await extIdReq.res.json() as Record; - for (const object of oldObjectInfo.items) { - objectIds.push(object.id); - } - } - convertedObjects = objectIds.join(','); - } - - const doEpsFilter = parseSelect(convertedObjects ?? e as string); - - if(doEpsFilter.values.length < 1){ - console.info('\nObjects not selected!\n'); - return []; - } - - // node index.js --service crunchy -e G6497Z43Y,GRZXCMN1W,G62PEZ2E6,G25FVGDEK,GZ7UVPVX5 - console.info('Requested object ID: %s', doEpsFilter.values.join(', ')); - - const AuthHeaders = { - headers: { - Authorization: `Bearer ${this.token.access_token}`, - }, - useProxy: true - }; - - // reqs - let objectInfo: ObjectInfo = { total: 0, data: [], meta: {} }; - if (this.api == 'android') { - const objectReqOpts = [ - api.beta_cms, - this.cmsToken.cms.bucket, - '/objects/', - doEpsFilter.values.join(','), - '?', - new URLSearchParams({ - 'force_locale': '', - 'preferred_audio_language': 'ja-JP', - 'locale': this.locale, - 'Policy': this.cmsToken.cms.policy, - 'Signature': this.cmsToken.cms.signature, - 'Key-Pair-Id': this.cmsToken.cms.key_pair_id, - }), - ].join(''); - const objectReq = await this.req.getData(objectReqOpts, AuthHeaders); - if(!objectReq.ok || !objectReq.res){ - console.error('Objects Request FAILED!'); - if(objectReq.error && objectReq.error.res && objectReq.error.res.body){ - const objectInfo = await objectReq.error.res.json(); - console.info('Body:', JSON.stringify(objectInfo, null, '\t')); - objectInfo.error = true; - return objectInfo; - } - return []; - } - const objectInfoAndroid = await objectReq.res.json() as CrunchyAndroidObject; - objectInfo = { - total: objectInfoAndroid.total, - data: objectInfoAndroid.items, - meta: {} - }; - } else { - const objectReq = await this.req.getData(`${api.cms}/objects/${doEpsFilter.values.join(',')}?force_locale=&preferred_audio_language=ja-JP&locale=${this.locale}`, AuthHeaders); - if(!objectReq.ok || !objectReq.res){ - console.error('Objects Request FAILED!'); - if(objectReq.error && objectReq.error.res && objectReq.error.res.body){ - const objectInfo = await objectReq.error.res.json(); - console.info('Body:', JSON.stringify(objectInfo, null, '\t')); - objectInfo.error = true; - return objectInfo; - } - return []; - } - objectInfo = await objectReq.res.json() as ObjectInfo; - } - - if(earlyReturn){ - return objectInfo; - } - - const selectedMedia: Partial[] = []; - - for(const item of objectInfo.data){ - if(item.type != 'episode' && item.type != 'movie'){ - await this.logObject(item, 2, true, false); - continue; - } - const epMeta: Partial = {}; - - epMeta.data = []; - if (item.episode_metadata) { - item.s_num = 'S:' + item.episode_metadata.season_id; - epMeta.data = [ - { - mediaId: 'E:'+ item.id, - versions: item.episode_metadata.versions, - isSubbed: item.episode_metadata.is_subbed, - isDubbed: item.episode_metadata.is_dubbed - } - ]; - epMeta.seriesTitle = item.episode_metadata.series_title; - epMeta.seasonTitle = item.episode_metadata.season_title; - epMeta.episodeNumber = item.episode_metadata.episode; - epMeta.episodeTitle = item.title; - epMeta.season = item.episode_metadata.season_number; - } else if (item.movie_listing_metadata) { - item.f_num = 'F:' + item.id; - epMeta.data = [ - { - mediaId: 'M:'+ item.id, - isSubbed: item.movie_listing_metadata.is_subbed, - isDubbed: item.movie_listing_metadata.is_dubbed - } - ]; - epMeta.seriesTitle = item.title; - epMeta.seasonTitle = item.title; - epMeta.episodeNumber = 'Movie'; - epMeta.episodeTitle = item.title; - } else if (item.movie_metadata) { - item.f_num = 'F:' + item.id; - epMeta.data = [ - { - mediaId: 'M:'+ item.id, - isSubbed: item.movie_metadata.is_subbed, - isDubbed: item.movie_metadata.is_dubbed - } - ]; - epMeta.season = 0; - epMeta.seriesTitle = item.title; - epMeta.seasonTitle = item.title; - epMeta.episodeNumber = 'Movie'; - epMeta.episodeTitle = item.title; - } - if (item.streams_link) { - epMeta.data[0].playback = item.streams_link; - if(!item.playback) { - item.playback = item.streams_link; - } - selectedMedia.push(epMeta); - item.isSelected = true; - } else if (item.__links__) { - epMeta.data[0].playback = item.__links__.streams.href; - if(!item.playback) { - item.playback = item.__links__.streams.href; - } - selectedMedia.push(epMeta); - item.isSelected = true; - } - await this.logObject(item, 2); - } - console.info(''); - return selectedMedia; - } - - public async downloadMediaList(medias: CrunchyEpMeta, options: CrunchyDownloadOptions) : Promise<{ - data: DownloadedMedia[], - fileName: string, - error: boolean - } | undefined> { - if(!this.cmsToken.cms){ - console.error('Authentication required!'); - return; - } - - if (!this.cfg.bin.ffmpeg) - this.cfg.bin = await yamlCfg.loadBinCfg(); - - let mediaName = '...'; - let fileName; - const variables: Variable[] = []; - if(medias.seasonTitle && medias.episodeNumber && medias.episodeTitle){ - mediaName = `${medias.seasonTitle} - ${medias.episodeNumber} - ${medias.episodeTitle}`; - } - - const files: DownloadedMedia[] = []; - - if(medias.data.every(a => !a.playback)){ - console.warn('Video not available!'); - return undefined; - } - - let dlFailed = false; - let dlVideoOnce = false; // Variable to save if best selected video quality was downloaded - - - for (const mMeta of medias.data) { - console.info(`Requesting: [${mMeta.mediaId}] ${mediaName}`); - - // Make sure we have a media id without a : in it - const currentMediaId = (mMeta.mediaId.includes(':') ? mMeta.mediaId.split(':')[1] : mMeta.mediaId); - - //Make sure token is up-to-date - await this.refreshToken(true, true); - let currentVersion; - let isPrimary = mMeta.isSubbed; - const AuthHeaders: RequestInit = { - headers: { - Authorization: `Bearer ${this.token.access_token}`, - 'X-Cr-Disable-Drm': 'true', - 'X-Cr-Enable-Drm': 'false', - 'X-Cr-Stream-Limits': 'false', - //'X-Cr-Segment-CDN': 'all', - //'User-Agent': 'Crunchyroll/1.8.0 Nintendo Switch/12.3.12.0 UE4/4.27' - } - }; - - //Get Media GUID - let mediaId = mMeta.mediaId; - if (mMeta.versions) { - if (mMeta.lang) { - currentVersion = mMeta.versions.find(a => a.audio_locale == mMeta.lang?.cr_locale); - } else if (options.dubLang.length == 1) { - const currentLang = langsData.languages.find(a => a.code == options.dubLang[0]); - currentVersion = mMeta.versions.find(a => a.audio_locale == currentLang?.cr_locale); - } else if (mMeta.versions.length == 1) { - currentVersion = mMeta.versions[0]; - } - if (!currentVersion?.media_guid) { - console.error('Selected language not found in versions.'); - continue; - } - isPrimary = currentVersion.original; - mediaId = currentVersion?.media_guid; - } - - // If for whatever reason mediaId has a :, return the ID only - if (mediaId.includes(':')) - mediaId = mediaId.split(':')[1]; - - const compiledChapters: string[] = []; - if (options.chapters) { - //Make Chapter Request - const chapterRequest = await this.req.getData(`https://static.crunchyroll.com/skip-events/production/${currentMediaId}.json`); - if(!chapterRequest.ok || !chapterRequest.res){ - //Old Chapter Request Fallback - console.warn('Chapter request failed, attempting old API'); - const oldChapterRequest = await this.req.getData(`https://static.crunchyroll.com/datalab-intro-v2/${currentMediaId}.json`); - if(!oldChapterRequest.ok || !oldChapterRequest.res) { - console.warn('Old Chapter API request failed'); - } else { - console.info('Old Chapter request successful'); - const chapterData = await oldChapterRequest.res.json() as CrunchyOldChapter; - - //Generate Timestamps - const startTime = new Date(0), endTime = new Date(0); - startTime.setSeconds(chapterData.startTime); - endTime.setSeconds(chapterData.endTime); - const startTimeMS = String(chapterData.startTime).split('.')[1], endTimeMS = String(chapterData.endTime).split('.')[1]; - const startMS = startTimeMS ? startTimeMS : '00', endMS = endTimeMS ? endTimeMS : '00'; - const startFormatted = startTime.toISOString().substring(11, 19)+'.'+startMS; - const endFormatted = endTime.toISOString().substring(11, 19)+'.'+endMS; - - //Push Generated Chapters - if (chapterData.startTime > 1) { - compiledChapters.push( - `CHAPTER${(compiledChapters.length/2)+1}=00:00:00.00`, - `CHAPTER${(compiledChapters.length/2)+1}NAME=Prologue` - ); - } - compiledChapters.push( - `CHAPTER${(compiledChapters.length/2)+1}=${startFormatted}`, - `CHAPTER${(compiledChapters.length/2)+1}NAME=Opening` - ); - compiledChapters.push( - `CHAPTER${(compiledChapters.length/2)+1}=${endFormatted}`, - `CHAPTER${(compiledChapters.length/2)+1}NAME=Episode` - ); - } - } else { - //Chapter request succeeded, now let's parse them - console.info('Chapter request successful'); - const chapterData = await chapterRequest.res.json() as CrunchyChapters; - const chapters: CrunchyChapter[] = []; - - //Make a format more usable for the crunchy chapters - for (const chapter in chapterData) { - if (typeof chapterData[chapter] == 'object') { - chapters.push(chapterData[chapter]); - } - } - - if (chapters.length > 0) { - chapters.sort((a, b) => a.start - b.start); - //Check if chapters has an intro - if (!(chapters.find(c => c.type === 'intro') || chapters.find(c => c.type === 'recap'))) { - compiledChapters.push( - `CHAPTER${(compiledChapters.length/2)+1}=00:00:00.00`, - `CHAPTER${(compiledChapters.length/2)+1}NAME=Episode` - ); - } - - //Loop through all the chapters - for (const chapter of chapters) { - if (typeof chapter.start == 'undefined' || typeof chapter.end == 'undefined') continue; - //Generate timestamps - const startTime = new Date(0), endTime = new Date(0); - startTime.setSeconds(chapter.start); - endTime.setSeconds(chapter.end); - const startFormatted = startTime.toISOString().substring(11, 19)+'.00'; - const endFormatted = endTime.toISOString().substring(11, 19)+'.00'; - - //Push generated chapters - if (chapter.type == 'intro') { - if (chapter.start > 0) { - compiledChapters.push( - `CHAPTER${(compiledChapters.length/2)+1}=00:00:00.00`, - `CHAPTER${(compiledChapters.length/2)+1}NAME=Prologue` - ); - } - compiledChapters.push( - `CHAPTER${(compiledChapters.length/2)+1}=${startFormatted}`, - `CHAPTER${(compiledChapters.length/2)+1}NAME=Opening` - ); - compiledChapters.push( - `CHAPTER${(compiledChapters.length/2)+1}=${endFormatted}`, - `CHAPTER${(compiledChapters.length/2)+1}NAME=Episode` - ); - } else { - compiledChapters.push( - `CHAPTER${(compiledChapters.length/2)+1}=${startFormatted}`, - `CHAPTER${(compiledChapters.length/2)+1}NAME=${chapter.type.charAt(0).toUpperCase() + chapter.type.slice(1)} Start` - ); - compiledChapters.push( - `CHAPTER${(compiledChapters.length/2)+1}=${endFormatted}`, - `CHAPTER${(compiledChapters.length/2)+1}NAME=${chapter.type.charAt(0).toUpperCase() + chapter.type.slice(1)} End` - ); - } - } - } - } - } - - const pbData = { total: 0, data: [{}], meta: {} } as PlaybackData; - - let playStream: CrunchyPlayStream | null = null; - if (options.cstream !== 'none') { - const playbackReq = await this.req.getData(`https://cr-play-service.prd.crunchyrollsvc.com/v1/${currentVersion ? currentVersion.guid : currentMediaId}/${CrunchyPlayStreams[options.cstream]}/play`, AuthHeaders); - if (!playbackReq.ok || !playbackReq.res) { - console.error('Non-DRM Request Stream URLs FAILED!'); - } else { - playStream = await playbackReq.res.json() as CrunchyPlayStream; - const derivedPlaystreams = {} as CrunchyStreams; - for (const hardsub in playStream.hardSubs) { - const stream = playStream.hardSubs[hardsub]; - derivedPlaystreams[hardsub] = { - url: stream.url, - 'hardsub_locale': stream.hlang - }; - } - derivedPlaystreams[''] = { - url: playStream.url, - hardsub_locale: '' - }; - pbData.meta = { - audio_locale: playStream.audioLocale, - bifs: [playStream.bifs], - captions: playStream.captions, - closed_captions: playStream.captions, - media_id: playStream.assetId, - subtitles: playStream.subtitles, - versions: playStream.versions - }; - pbData.data[0][`adaptive_${options.cstream}_${playStream.url.includes('m3u8') ? 'hls' : 'dash'}_drm`] = { - ...derivedPlaystreams - }; - } - } - - variables.push(...([ - ['title', medias.episodeTitle, true], - ['episode', isNaN(parseFloat(medias.episodeNumber)) ? medias.episodeNumber : parseFloat(medias.episodeNumber), false], - ['service', 'CR', false], - ['seriesTitle', medias.seriesTitle, true], - ['showTitle', medias.seasonTitle, true], - ['season', medias.season, false] - ] as [AvailableFilenameVars, string|number, boolean][]).map((a): Variable => { - return { - name: a[0], - replaceWith: a[1], - type: typeof a[1], - sanitize: a[2] - } as Variable; - })); - - let streams: any[] = []; - let hsLangs: string[] = []; - const pbStreams = pbData.data[0]; - - if (!canDecrypt) { - console.warn('Decryption not enabled!'); - } - - for (const s of Object.keys(pbStreams)) { - if ( - (s.match(/hls/) || s.match(/dash/)) - && !(s.match(/hls/) && s.match(/drm/)) - && !((!canDecrypt || !this.cfg.bin.mp4decrypt) && s.match(/drm/)) - && !s.match(/trailer/) - ) { - const pb = Object.values(pbStreams[s]).map(v => { - v.hardsub_lang = v.hardsub_locale - ? langsData.fixAndFindCrLC(v.hardsub_locale).locale - : v.hardsub_locale; - if(v.hardsub_lang && hsLangs.indexOf(v.hardsub_lang) < 0){ - hsLangs.push(v.hardsub_lang); - } - return { - ...v, - ...{ format: s } - }; - }); - streams.push(...pb); - } - } - - if (streams.length < 1) { - console.warn('No full streams found!'); - return undefined; - } - - const audDub = langsData.findLang(langsData.fixLanguageTag(pbData.meta.audio_locale as string) || '').code; - hsLangs = langsData.sortTags(hsLangs); - - streams = streams.map((s) => { - s.audio_lang = audDub; - s.hardsub_lang = s.hardsub_lang ? s.hardsub_lang : '-'; - s.type = `${s.format}/${s.audio_lang}/${s.hardsub_lang}`; - return s; - }); - - streams = streams.sort((a, b) => { - if (a.type < b.type) { - return -1; - } - return 0; - }); - - if(options.hslang != 'none'){ - if(hsLangs.indexOf(options.hslang) > -1){ - console.info('Selecting stream with %s hardsubs', langsData.locale2language(options.hslang).language); - streams = streams.filter((s) => { - if(s.hardsub_lang == '-'){ - return false; - } - return s.hardsub_lang == options.hslang; - }); - } - else{ - console.warn('Selected stream with %s hardsubs not available', langsData.locale2language(options.hslang).language); - if(hsLangs.length > 0){ - console.warn('Try other hardsubs stream:', hsLangs.join(', ')); - } - dlFailed = true; - } - } else { - streams = streams.filter((s) => { - return s.hardsub_lang == '-'; - }); - if(streams.length < 1){ - console.warn('Raw streams not available!'); - if(hsLangs.length > 0){ - console.warn('Try hardsubs stream:', hsLangs.join(', ')); - } - dlFailed = true; - } - console.info('Selecting raw stream'); - } - - let curStream: - undefined|typeof streams[0] - = undefined; - if (!dlFailed) { - options.kstream = typeof options.kstream == 'number' ? options.kstream : 1; - options.kstream = options.kstream > streams.length ? 1 : options.kstream; - - streams.forEach((s, i) => { - const isSelected = options.kstream == i + 1 ? '✓' : ' '; - console.info('Full stream found! (%s%s: %s )', isSelected, i + 1, s.type); - }); - - console.info('Downloading video...'); - curStream = streams[options.kstream-1]; - - console.info('Playlists URL: %s (%s)', curStream.url, curStream.type); - } - - let tsFile = undefined; - - // Delete the stream if it's not needed - if (options.novids && options.noaudio) { - if (playStream) { - await this.refreshToken(true, true); - await this.req.getData(`https://cr-play-service.prd.crunchyrollsvc.com/v1/token/${currentVersion ? currentVersion.guid : currentMediaId}/${playStream.token}`, {...{method: 'DELETE'}, ...AuthHeaders}); - } - } - - if(!dlFailed && curStream !== undefined && !(options.novids && options.noaudio)){ - const streamPlaylistsReq = await this.req.getData(curStream.url, AuthHeaders); - if(!streamPlaylistsReq.ok || !streamPlaylistsReq.res){ - console.error('CAN\'T FETCH VIDEO PLAYLISTS!'); - dlFailed = true; - } else { - const streamPlaylistBody = await streamPlaylistsReq.res.text(); - if (streamPlaylistBody.match('MPD')) { - //We have the stream, so go ahead and delete the active stream - if (playStream) { - await this.refreshToken(true, true); - await this.req.getData(`https://cr-play-service.prd.crunchyrollsvc.com/v1/token/${currentVersion ? currentVersion.guid : currentMediaId}/${playStream.token}`, {...{method: 'DELETE'}, ...AuthHeaders}); - } - - //Parse MPD Playlists - const streamPlaylists = await parse(streamPlaylistBody, langsData.findLang(langsData.fixLanguageTag(pbData.meta.audio_locale as string) || ''), curStream.url.match(/.*\.urlset\//)[0]); - - //Get name of CDNs/Servers - const streamServers = Object.keys(streamPlaylists); - - options.x = options.x > streamServers.length ? 1 : options.x; - - const selectedServer = streamServers[options.x - 1]; - const selectedList = streamPlaylists[selectedServer]; - - //set Video Qualities - const videos = selectedList.video.map(item => { - return { - ...item, - resolutionText: `${item.quality.width}x${item.quality.height} (${Math.round(item.bandwidth/1024)}KiB/s)` - }; - }); - - const audios = selectedList.audio.map(item => { - return { - ...item, - resolutionText: `${Math.round(item.bandwidth/1000)}kB/s` - }; - }); - - - videos.sort((a, b) => { - return a.quality.width - b.quality.width; - }); - - audios.sort((a, b) => { - return a.bandwidth - b.bandwidth; - }); - - let chosenVideoQuality = options.q === 0 ? videos.length : options.q; - if(chosenVideoQuality > videos.length) { - console.warn(`The requested quality of ${options.q} is greater than the maximum ${videos.length}.\n[WARN] Therefor the maximum will be capped at ${videos.length}.`); - chosenVideoQuality = videos.length; - } - chosenVideoQuality--; - - let chosenAudioQuality = options.q === 0 ? audios.length : options.q; - if(chosenAudioQuality > audios.length) { - chosenAudioQuality = audios.length; - } - chosenAudioQuality--; - - - const chosenVideoSegments = videos[chosenVideoQuality]; - const chosenAudioSegments = audios[chosenAudioQuality]; - - console.info(`Servers available:\n\t${streamServers.join('\n\t')}`); - console.info(`Available Video Qualities:\n\t${videos.map((a, ind) => `[${ind+1}] ${a.resolutionText}`).join('\n\t')}`); - console.info(`Available Audio Qualities:\n\t${audios.map((a, ind) => `[${ind+1}] ${a.resolutionText}`).join('\n\t')}`); - - variables.push({ - name: 'height', - type: 'number', - replaceWith: chosenVideoSegments.quality.height - }, { - name: 'width', - type: 'number', - replaceWith: chosenVideoSegments.quality.width - }); - - const lang = langsData.languages.find(a => a.code === curStream?.audio_lang); - if (!lang) { - console.error(`Unable to find language for code ${curStream.audio_lang}`); - return; - } - console.info(`Selected quality: \n\tVideo: ${chosenVideoSegments.resolutionText}\n\tAudio: ${chosenAudioSegments.resolutionText}\n\tServer: ${selectedServer}`); - console.info('Stream URL:', chosenVideoSegments.segments[0].uri.split(',.urlset')[0]); - // TODO check filename - fileName = parseFileName(options.fileName, variables, options.numbers, options.override).join(path.sep); - const outFile = parseFileName(options.fileName + '.' + (mMeta.lang?.name || lang.name), variables, options.numbers, options.override).join(path.sep); - const tempFile = parseFileName(`temp-${currentVersion ? currentVersion.guid : currentMediaId}`, variables, options.numbers, options.override).join(path.sep); - const tempTsFile = path.isAbsolute(tempFile as string) ? tempFile : path.join(this.cfg.dir.content, tempFile); - - let [audioDownloaded, videoDownloaded] = [false, false]; - - // When best selected video quality is already downloaded - if(dlVideoOnce && options.dlVideoOnce) { - console.info('Already downloaded video, skipping video download...'); - } else if (options.novids) { - console.info('Skipping video download...'); - } else { - //Download Video - const totalParts = chosenVideoSegments.segments.length; - const mathParts = Math.ceil(totalParts / options.partsize); - const mathMsg = `(${mathParts}*${options.partsize})`; - console.info('Total parts in video stream:', totalParts, mathMsg); - tsFile = path.isAbsolute(outFile as string) ? outFile : path.join(this.cfg.dir.content, outFile); - const split = outFile.split(path.sep).slice(0, -1); - split.forEach((val, ind, arr) => { - const isAbsolut = path.isAbsolute(outFile as string); - if (!fs.existsSync(path.join(isAbsolut ? '' : this.cfg.dir.content, ...arr.slice(0, ind), val))) - fs.mkdirSync(path.join(isAbsolut ? '' : this.cfg.dir.content, ...arr.slice(0, ind), val)); - }); - const videoJson: M3U8Json = { - segments: chosenVideoSegments.segments - }; - const videoDownload = await new streamdl({ - output: chosenVideoSegments.pssh ? `${tempTsFile}.video.enc.m4s` : `${tsFile}.video.m4s`, - timeout: options.timeout, - m3u8json: videoJson, - // baseurl: chunkPlaylist.baseUrl, - threads: options.partsize, - fsRetryTime: options.fsRetryTime * 1000, - override: options.force, - callback: options.callbackMaker ? options.callbackMaker({ - fileName: `${path.isAbsolute(outFile) ? outFile.slice(this.cfg.dir.content.length) : outFile}`, - image: medias.image, - parent: { - title: medias.seasonTitle - }, - title: medias.episodeTitle, - language: lang - }) : undefined - }).download(); - if(!videoDownload.ok){ - console.error(`DL Stats: ${JSON.stringify(videoDownload.parts)}\n`); - dlFailed = true; - } - dlVideoOnce = true; - videoDownloaded = true; - } - - if (chosenAudioSegments && !options.noaudio) { - //Download Audio (if available) - const totalParts = chosenAudioSegments.segments.length; - const mathParts = Math.ceil(totalParts / options.partsize); - const mathMsg = `(${mathParts}*${options.partsize})`; - console.info('Total parts in audio stream:', totalParts, mathMsg); - tsFile = path.isAbsolute(outFile as string) ? outFile : path.join(this.cfg.dir.content, outFile); - const split = outFile.split(path.sep).slice(0, -1); - split.forEach((val, ind, arr) => { - const isAbsolut = path.isAbsolute(outFile as string); - if (!fs.existsSync(path.join(isAbsolut ? '' : this.cfg.dir.content, ...arr.slice(0, ind), val))) - fs.mkdirSync(path.join(isAbsolut ? '' : this.cfg.dir.content, ...arr.slice(0, ind), val)); - }); - const audioJson: M3U8Json = { - segments: chosenAudioSegments.segments - }; - const audioDownload = await new streamdl({ - output: chosenAudioSegments.pssh ? `${tempTsFile}.audio.enc.m4s` : `${tsFile}.audio.m4s`, - timeout: options.timeout, - m3u8json: audioJson, - // baseurl: chunkPlaylist.baseUrl, - threads: options.partsize, - fsRetryTime: options.fsRetryTime * 1000, - override: options.force, - callback: options.callbackMaker ? options.callbackMaker({ - fileName: `${path.isAbsolute(outFile) ? outFile.slice(this.cfg.dir.content.length) : outFile}`, - image: medias.image, - parent: { - title: medias.seasonTitle - }, - title: medias.episodeTitle, - language: lang - }) : undefined - }).download(); - if(!audioDownload.ok){ - console.error(`DL Stats: ${JSON.stringify(audioDownload.parts)}\n`); - dlFailed = true; - } - audioDownloaded = true; - } else if (options.noaudio) { - console.info('Skipping audio download...'); - } - - //Handle Decryption if needed - if ((chosenVideoSegments.pssh || chosenAudioSegments.pssh) && (videoDownloaded || audioDownloaded)) { - const assetIdRegex = chosenVideoSegments.segments[0].uri.match(/\/assets\/(?:p\/)?([^_,]+)/); - const assetId = assetIdRegex ? assetIdRegex[1] : null; - const sessionId = new Date().getUTCMilliseconds().toString().padStart(3, '0') + process.hrtime.bigint().toString().slice(0, 13); - console.info('Decryption Needed, attempting to decrypt'); - - const decReq = await this.req.getData(`${api.drm}`, { - 'method': 'POST', - 'body': JSON.stringify({ - 'accounting_id': 'crunchyroll', - 'asset_id': assetId, - 'session_id': sessionId, - 'user_id': this.token.account_id - }) - }); - if(!decReq.ok || !decReq.res){ - console.error('Request to DRM Authentication failed:', decReq.error?.res.status, decReq.error?.message); - return undefined; - } - const authData = await decReq.res.json() as {'custom_data': string, 'token': string}; - const encryptionKeys = await getKeys(chosenVideoSegments.pssh, 'https://lic.drmtoday.com/license-proxy-widevine/cenc/', { - 'dt-custom-data': authData.custom_data, - 'x-dt-auth-token': authData.token - }); - if (encryptionKeys.length == 0) { - console.error('Failed to get encryption keys'); - return undefined; - } - /*const keys = {} as Record; - encryptionKeys.forEach(function(key) { - keys[key.kid] = key.key; - });*/ - - if (this.cfg.bin.mp4decrypt) { - const commandBase = `--show-progress --key ${encryptionKeys[1].kid}:${encryptionKeys[1].key} `; - const commandVideo = commandBase+`"${tempTsFile}.video.enc.m4s" "${tempTsFile}.video.m4s"`; - const commandAudio = commandBase+`"${tempTsFile}.audio.enc.m4s" "${tempTsFile}.audio.m4s"`; - - if (videoDownloaded) { - console.info('Started decrypting video'); - const decryptVideo = exec('mp4decrypt', `"${this.cfg.bin.mp4decrypt}"`, commandVideo); - if (!decryptVideo.isOk) { - console.error(decryptVideo.err); - console.error(`Decryption failed with exit code ${decryptVideo.err.code}`); - fs.renameSync(`${tempTsFile}.video.enc.m4s`, `${tsFile}.video.enc.m4s`); - return undefined; - } else { - console.info('Decryption done for video'); - if (!options.nocleanup) { - fs.removeSync(`${tempTsFile}.video.enc.m4s`); - } - fs.renameSync(`${tempTsFile}.video.m4s`, `${tsFile}.video.m4s`); - files.push({ - type: 'Video', - path: `${tsFile}.video.m4s`, - lang: lang, - isPrimary: isPrimary - }); - } - } - - if (audioDownloaded) { - console.info('Started decrypting audio'); - const decryptAudio = exec('mp4decrypt', `"${this.cfg.bin.mp4decrypt}"`, commandAudio); - if (!decryptAudio.isOk) { - console.error(decryptAudio.err); - console.error(`Decryption failed with exit code ${decryptAudio.err.code}`); - fs.renameSync(`${tempTsFile}.audio.enc.m4s`, `${tsFile}.audio.enc.m4s`); - return undefined; - } else { - if (!options.nocleanup) { - fs.removeSync(`${tempTsFile}.audio.enc.m4s`); - } - fs.renameSync(`${tempTsFile}.audio.m4s`, `${tsFile}.audio.m4s`); - files.push({ - type: 'Audio', - path: `${tsFile}.audio.m4s`, - lang: lang, - isPrimary: isPrimary - }); - console.info('Decryption done for audio'); - } - } - } else { - console.warn('mp4decrypt not found, files need decryption. Decryption Keys:', encryptionKeys); - } - } else { - if (videoDownloaded) { - files.push({ - type: 'Video', - path: `${tsFile}.video.m4s`, - lang: lang, - isPrimary: isPrimary - }); - } - if (audioDownloaded) { - files.push({ - type: 'Audio', - path: `${tsFile}.audio.m4s`, - lang: lang, - isPrimary: isPrimary - }); - } - } - } else if (!options.novids) { - const streamPlaylists = m3u8(streamPlaylistBody); - const plServerList: string[] = [], - plStreams: Record> = {}, - plQuality: { - str: string, - dim: string, - CODECS: string, - RESOLUTION: { - width: number, - height: number - } - }[] = []; - for(const pl of streamPlaylists.playlists){ - // set quality - const plResolution = pl.attributes.RESOLUTION; - const plResolutionText = `${plResolution.width}x${plResolution.height}`; - // set codecs - const plCodecs = pl.attributes.CODECS; - // parse uri - const plUri = new URL(pl.uri); - let plServer = plUri.hostname; - // set server list - if (plUri.searchParams.get('cdn')){ - plServer += ` (${plUri.searchParams.get('cdn')})`; - } - if (!plServerList.includes(plServer)){ - plServerList.push(plServer); - } - // add to server - if (!Object.keys(plStreams).includes(plServer)){ - plStreams[plServer] = {}; - } - if( - plStreams[plServer][plResolutionText] - && plStreams[plServer][plResolutionText] != pl.uri - && typeof plStreams[plServer][plResolutionText] != 'undefined' - ) { - console.error(`Non duplicate url for ${plServer} detected, please report to developer!`); - } else{ - plStreams[plServer][plResolutionText] = pl.uri; - } - // set plQualityStr - const plBandwidth = Math.round(pl.attributes.BANDWIDTH/1024); - const qualityStrAdd = `${plResolutionText} (${plBandwidth}KiB/s)`; - const qualityStrRegx = new RegExp(qualityStrAdd.replace(/([:()/])/g, '\\$1'), 'm'); - const qualityStrMatch = !plQuality.map(a => a.str).join('\r\n').match(qualityStrRegx); - if(qualityStrMatch){ - plQuality.push({ - str: qualityStrAdd, - dim: plResolutionText, - CODECS: plCodecs, - RESOLUTION: plResolution - }); - } - } - - options.x = options.x > plServerList.length ? 1 : options.x; - - const plSelectedServer = plServerList[options.x - 1]; - const plSelectedList = plStreams[plSelectedServer]; - plQuality.sort((a, b) => { - const aMatch: RegExpMatchArray | never[] = a.dim.match(/[0-9]+/) || []; - const bMatch: RegExpMatchArray | never[] = b.dim.match(/[0-9]+/) || []; - return parseInt(aMatch[0]) - parseInt(bMatch[0]); - }); - let quality = options.q === 0 ? plQuality.length : options.q; - if(quality > plQuality.length) { - console.warn(`The requested quality of ${options.q} is greater than the maximum ${plQuality.length}.\n[WARN] Therefor the maximum will be capped at ${plQuality.length}.`); - quality = plQuality.length; - } - // When best selected video quality is already downloaded - if(dlVideoOnce && options.dlVideoOnce) { - // Select the lowest resolution with the same codecs - while(quality !=1 && plQuality[quality - 1].CODECS == plQuality[quality - 2].CODECS) { - quality--; - } - } - const selPlUrl = plSelectedList[plQuality.map(a => a.dim)[quality - 1]] ? plSelectedList[plQuality.map(a => a.dim)[quality - 1]] : ''; - console.info(`Servers available:\n\t${plServerList.join('\n\t')}`); - console.info(`Available qualities:\n\t${plQuality.map((a, ind) => `[${ind+1}] ${a.str}`).join('\n\t')}`); - - if(selPlUrl != ''){ - variables.push({ - name: 'height', - type: 'number', - replaceWith: quality === 0 ? plQuality[plQuality.length - 1].RESOLUTION.height as number : plQuality[quality - 1].RESOLUTION.height - }, { - name: 'width', - type: 'number', - replaceWith: quality === 0 ? plQuality[plQuality.length - 1].RESOLUTION.width as number : plQuality[quality - 1].RESOLUTION.width - }); - const lang = langsData.languages.find(a => a.code === curStream?.audio_lang); - if (!lang) { - console.error(`Unable to find language for code ${curStream.audio_lang}`); - return; - } - console.info(`Selected quality: ${Object.keys(plSelectedList).find(a => plSelectedList[a] === selPlUrl)} @ ${plSelectedServer}`); - console.info('Stream URL:', selPlUrl); - // TODO check filename - fileName = parseFileName(options.fileName, variables, options.numbers, options.override).join(path.sep); - const outFile = parseFileName(options.fileName + '.' + (mMeta.lang?.name || lang.name), variables, options.numbers, options.override).join(path.sep); - console.info(`Output filename: ${outFile}`); - const chunkPage = await this.req.getData(selPlUrl); - if(!chunkPage.ok || !chunkPage.res){ - console.error('CAN\'T FETCH VIDEO PLAYLIST!'); - dlFailed = true; - } else { - // We have the stream, so go ahead and delete the active stream - if (playStream) { - await this.refreshToken(true, true); - await this.req.getData(`https://cr-play-service.prd.crunchyrollsvc.com/v1/token/${currentVersion ? currentVersion.guid : currentMediaId}/${playStream.token}`, {...{method: 'DELETE'}, ...AuthHeaders}); - } - - const chunkPageBody = await chunkPage.res.text(); - const chunkPlaylist = m3u8(chunkPageBody); - const totalParts = chunkPlaylist.segments.length; - const mathParts = Math.ceil(totalParts / options.partsize); - const mathMsg = `(${mathParts}*${options.partsize})`; - console.info('Total parts in stream:', totalParts, mathMsg); - tsFile = path.isAbsolute(outFile as string) ? outFile : path.join(this.cfg.dir.content, outFile); - const split = outFile.split(path.sep).slice(0, -1); - split.forEach((val, ind, arr) => { - const isAbsolut = path.isAbsolute(outFile as string); - if (!fs.existsSync(path.join(isAbsolut ? '' : this.cfg.dir.content, ...arr.slice(0, ind), val))) - fs.mkdirSync(path.join(isAbsolut ? '' : this.cfg.dir.content, ...arr.slice(0, ind), val)); - }); - const dlStreamByPl = await new streamdl({ - output: `${tsFile}.ts`, - timeout: options.timeout, - m3u8json: chunkPlaylist, - // baseurl: chunkPlaylist.baseUrl, - threads: options.partsize, - fsRetryTime: options.fsRetryTime * 1000, - override: options.force, - callback: options.callbackMaker ? options.callbackMaker({ - fileName: `${path.isAbsolute(outFile) ? outFile.slice(this.cfg.dir.content.length) : outFile}`, - image: medias.image, - parent: { - title: medias.seasonTitle - }, - title: medias.episodeTitle, - language: lang - }) : undefined - }).download(); - if (!dlStreamByPl.ok) { - console.error(`DL Stats: ${JSON.stringify(dlStreamByPl.parts)}\n`); - dlFailed = true; - } - files.push({ - type: 'Video', - path: `${tsFile}.ts`, - lang: lang, - isPrimary: isPrimary - }); - dlVideoOnce = true; - } - } else{ - console.error('Quality not selected!\n'); - dlFailed = true; - } - } else if (options.novids) { - fileName = parseFileName(options.fileName, variables, options.numbers, options.override).join(path.sep); - console.info('Downloading skipped!'); - } - } - } else if (options.novids && options.noaudio) { - fileName = parseFileName(options.fileName, variables, options.numbers, options.override).join(path.sep); - } - - if (compiledChapters.length > 0) { - try { - fileName = parseFileName(options.fileName, variables, options.numbers, options.override).join(path.sep); - const outFile = parseFileName(options.fileName + '.' + mMeta.lang?.name, variables, options.numbers, options.override).join(path.sep); - tsFile = path.isAbsolute(outFile as string) ? outFile : path.join(this.cfg.dir.content, outFile); - const split = outFile.split(path.sep).slice(0, -1); - split.forEach((val, ind, arr) => { - const isAbsolut = path.isAbsolute(outFile as string); - if (!fs.existsSync(path.join(isAbsolut ? '' : this.cfg.dir.content, ...arr.slice(0, ind), val))) - fs.mkdirSync(path.join(isAbsolut ? '' : this.cfg.dir.content, ...arr.slice(0, ind), val)); - }); - const lang = langsData.languages.find(a => a.code === curStream?.audio_lang); - if (!lang) { - console.error(`Unable to find language for code ${curStream.audio_lang}`); - return; - } - fs.writeFileSync(`${tsFile}.txt`, compiledChapters.join('\r\n')); - files.push({ - path: `${tsFile}.txt`, - lang: lang, - type: 'Chapters' - }); - } catch { - console.error('Failed to write chapter file'); - } - } - - if(options.dlsubs.indexOf('all') > -1){ - options.dlsubs = ['all']; - } - - if(options.hslang != 'none'){ - console.warn('Subtitles downloading disabled for hardsubs streams.'); - options.skipsubs = true; - } - - if (options.nosubs) { - console.info('Subtitles downloading disabled from nosubs flag.'); - options.skipsubs = true; - } - - if(!options.skipsubs && options.dlsubs.indexOf('none') == -1){ - if(pbData.meta.subtitles && Object.values(pbData.meta.subtitles).length > 0){ - const subsData = Object.values(pbData.meta.subtitles); - const capsData = Object.values(pbData.meta.closed_captions); - const subsDataMapped = subsData.map((s) => { - const subLang = langsData.fixAndFindCrLC(s.language); - return { - ...s, - isCC: false, - locale: subLang, - language: subLang.locale - }; - }).concat( - capsData.map((s) => { - const subLang = langsData.fixAndFindCrLC(s.language); - return { - ...s, - isCC: true, - locale: subLang, - language: subLang.locale - }; - }) - ); - const subsArr = langsData.sortSubtitles(subsDataMapped, 'language'); - for(const subsIndex in subsArr){ - const subsItem = subsArr[subsIndex]; - const langItem = subsItem.locale; - const sxData: Partial = {}; - sxData.language = langItem; - const isSigns = langItem.code === audDub && !subsItem.isCC; - const isCC = subsItem.isCC; - sxData.file = langsData.subsFile(fileName as string, subsIndex, langItem, isCC, options.ccTag, isSigns, subsItem.format); - sxData.path = path.join(this.cfg.dir.content, sxData.file); - const split = sxData.path.split(path.sep).slice(0, -1); - split.forEach((val, ind, arr) => { - const isAbsolut = path.isAbsolute(sxData.path as string); - if (!fs.existsSync(path.join(isAbsolut ? '' : this.cfg.dir.content, ...arr.slice(0, ind), val))) - fs.mkdirSync(path.join(isAbsolut ? '' : this.cfg.dir.content, ...arr.slice(0, ind), val)); - }); - if (files.some(a => a.type === 'Subtitle' && (a.language.cr_locale == langItem.cr_locale || a.language.locale == langItem.locale) && a.cc === isCC && a.signs === isSigns)) - continue; - if(options.dlsubs.includes('all') || options.dlsubs.includes(langItem.locale)){ - const subsAssReq = await this.req.getData(subsItem.url); - if(subsAssReq.ok && subsAssReq.res){ - let sBody = await subsAssReq.res.text(); - if (subsItem.format == 'vtt') { - const chosenFontSize = options.originalFontSize ? undefined : options.fontSize; - if (!options.originalFontSize) sBody = sBody.replace(/( font-size:.+?;)/g, '').replace(/(font-size:.+?;)/g, ''); - sBody = vtt2ass(undefined, chosenFontSize, sBody, '', undefined, options.fontName); - sxData.fonts = fontsData.assFonts(sBody) as Font[]; - sxData.file = sxData.file.replace('.vtt','.ass'); - } else { - sBody = '\ufeff' + sBody; - const sBodySplit = sBody.split('\r\n'); - sBodySplit.splice(2, 0, 'ScaledBorderAndShadow: yes'); - sBody = sBodySplit.join('\r\n'); - sxData.title = sBody.split('\r\n')[1].replace(/^Title: /, ''); - sxData.title = `${langItem.language} / ${sxData.title}`; - sxData.fonts = fontsData.assFonts(sBody) as Font[]; - } - fs.writeFileSync(sxData.path, sBody); - console.info(`Subtitle downloaded: ${sxData.file}`); - files.push({ - type: 'Subtitle', - ...sxData as sxItem, - cc: isCC, - signs: isSigns, - }); - } - else{ - console.warn(`Failed to download subtitle: ${sxData.file}`); - } - } - } - } - else{ - console.warn('Can\'t find urls for subtitles!'); - } - } else{ - console.info('Subtitles downloading skipped!'); - } - - await this.sleep(options.waittime); - } - return { - error: dlFailed, - data: files, - fileName: fileName ? (path.isAbsolute(fileName) ? fileName : path.join(this.cfg.dir.content, fileName)) || './unknown' : './unknown' - }; - } - - public async muxStreams(data: DownloadedMedia[], options: CrunchyMuxOptions) { - this.cfg.bin = await yamlCfg.loadBinCfg(); - let hasAudioStreams = false; - if (options.novids || data.filter(a => a.type === 'Video').length === 0) - return console.info('Skip muxing since no vids are downloaded'); - if (data.some(a => a.type === 'Audio')) { - hasAudioStreams = true; - } - const merger = new Merger({ - onlyVid: hasAudioStreams ? data.filter(a => a.type === 'Video').map((a) : MergerInput => { - return { - lang: a.lang, - path: a.path, - }; - }) : [], - skipSubMux: options.skipSubMux, - onlyAudio: hasAudioStreams ? data.filter(a => a.type === 'Audio').map((a) : MergerInput => { - return { - lang: a.lang, - path: a.path, - }; - }) : [], - output: `${options.output}.${options.mp4 ? 'mp4' : 'mkv'}`, - subtitles: data.filter(a => a.type === 'Subtitle').map((a) : SubtitleInput => { - return { - file: a.path, - language: a.language, - closedCaption: a.cc, - signs: a.signs, - }; - }), - simul: false, - keepAllVideos: options.keepAllVideos, - fonts: Merger.makeFontsList(this.cfg.dir.fonts, data.filter(a => a.type === 'Subtitle') as sxItem[]), - videoAndAudio: hasAudioStreams ? [] : data.filter(a => a.type === 'Video').map((a) : MergerInput => { - return { - lang: a.lang, - path: a.path, - }; - }), - chapters: data.filter(a => a.type === 'Chapters').map((a) : MergerInput => { - return { - path: a.path, - lang: a.lang - }; - }), - videoTitle: options.videoTitle, - options: { - ffmpeg: options.ffmpegOptions, - mkvmerge: options.mkvmergeOptions - }, - defaults: { - audio: options.defaultAudio, - sub: options.defaultSub - }, - ccTag: options.ccTag - }); - const bin = Merger.checkMerger(this.cfg.bin, options.mp4, options.forceMuxer); - // collect fonts info - // mergers - let isMuxed = false; - if (options.syncTiming) { - await merger.createDelays(); - } - if (bin.MKVmerge) { - await merger.merge('mkvmerge', bin.MKVmerge); - isMuxed = true; - } else if (bin.FFmpeg) { - await merger.merge('ffmpeg', bin.FFmpeg); - isMuxed = true; - } else{ - console.info('\nDone!\n'); - return; - } - if (isMuxed && !options.nocleanup) - merger.cleanUp(); - } - - public async listSeriesID(id: string, data?: CrunchyMultiDownload): Promise<{ list: Episode[], data: Record}> { - await this.refreshToken(true, true); - let serieshasversions = true; - const parsed = await this.parseSeriesById(id); - if (!parsed) - return { data: {}, list: [] }; - const result = this.parseSeriesResult(parsed); - const episodes : Record = {}; - for(const season of Object.keys(result) as unknown as number[]) { - for (const key of Object.keys(result[season])) { - const s = result[season][key]; - if (data?.s && s.id !== data.s) continue; - (await this.getSeasonDataById(s))?.data?.forEach(episode => { - //TODO: Make sure the below code is ok - //Prepare the episode array - let item; - const seasonIdentifier = s.identifier ? s.identifier.split('|')[1] : `S${episode.season_number}`; - if (!(Object.prototype.hasOwnProperty.call(episodes, `${seasonIdentifier}E${episode.episode || episode.episode_number}`))) { - item = episodes[`${seasonIdentifier}E${episode.episode || episode.episode_number}`] = { - items: [] as CrunchyEpisode[], - langs: [] as langsData.LanguageItem[] - }; - } else { - item = episodes[`${seasonIdentifier}E${episode.episode || episode.episode_number}`]; - } - - if (episode.versions) { - //Iterate over episode versions for audio languages - for (const version of episode.versions) { - //Make sure there is only one of the same language - if (!item.langs.find(a => a?.cr_locale == version.audio_locale)) { - //Push to arrays if there is no duplicates of the same language. - item.items.push(episode); - item.langs.push(langsData.languages.find(a => a.cr_locale == version.audio_locale) as langsData.LanguageItem); - } - } - } else { - //Episode didn't have versions, mark it as such to be logged. - serieshasversions = false; - //Make sure there is only one of the same language - if (!item.langs.find(a => a?.cr_locale == episode.audio_locale)) { - //Push to arrays if there is no duplicates of the same language. - item.items.push(episode); - item.langs.push(langsData.languages.find(a => a.cr_locale == episode.audio_locale) as langsData.LanguageItem); - } - } - }); - } - } - - const itemIndexes = { - sp: 1, - no: 1 - }; - - for (const key of Object.keys(episodes)) { - const item = episodes[key]; - const isSpecial = !item.items[0].episode.match(/^\d+$/); - episodes[`${isSpecial ? 'S' : 'E'}${itemIndexes[isSpecial ? 'sp' : 'no']}`] = item; - if (isSpecial) - itemIndexes.sp++; - else - itemIndexes.no++; - delete episodes[key]; - } - - // Sort episodes to have specials at the end - const specials = Object.entries(episodes).filter(a => a[0].startsWith('S')), - normal = Object.entries(episodes).filter(a => a[0].startsWith('E')), - sortedEpisodes = Object.fromEntries([...normal, ...specials]); - - for (const key of Object.keys(sortedEpisodes)) { - const item = sortedEpisodes[key]; - console.info(`[${key}] ${ - item.items.find(a => !a.season_title.match(/\(\w+ Dub\)/))?.season_title ?? item.items[0].season_title.replace(/\(\w+ Dub\)/g, '').trimEnd() - } - Season ${item.items[0].season_number} - ${item.items[0].title} [${ - item.items.map((a, index) => { - return `${a.is_premium_only ? '☆ ' : ''}${item.langs[index]?.name ?? 'Unknown'}`; - }).join(', ') - }]`); - } - - if (!serieshasversions) { - console.warn('Couldn\'t find versions on some episodes, fell back to old method.'); - } - - return { data: sortedEpisodes, list: Object.entries(sortedEpisodes).map(([key, value]) => { - const images = (value.items[0].images.thumbnail ?? [[ { source: '/notFound.png' } ]])[0]; - const seconds = Math.floor(value.items[0].duration_ms / 1000); - return { - e: key.startsWith('E') ? key.slice(1) : key, - lang: value.langs.map(a => a?.code), - name: value.items[0].title, - season: value.items[0].season_number.toString(), - seriesTitle: value.items[0].series_title.replace(/\(\w+ Dub\)/g, '').trimEnd(), - seasonTitle: value.items[0].season_title.replace(/\(\w+ Dub\)/g, '').trimEnd(), - episode: value.items[0].episode_number?.toString() ?? value.items[0].episode ?? '?', - id: value.items[0].season_id, - img: images[Math.floor(images.length / 2)].source, - description: value.items[0].description, - time: `${Math.floor(seconds / 60)}:${seconds % 60}` - }; - })}; - } - - public async downloadFromSeriesID(id: string, data: CrunchyMultiDownload) : Promise> { - const { data: episodes } = await this.listSeriesID(id, data); - console.info(''); - console.info('-'.repeat(30)); - console.info(''); - const selected = this.itemSelectMultiDub(episodes, data.dubLang, data.but, data.all, data.e); - for (const key of Object.keys(selected)) { - const item = selected[key]; - console.info(`[S${item.season}E${item.episodeNumber}] - ${item.episodeTitle} [${ - item.data.map(a => { - return `✓ ${a.lang?.name || 'Unknown Language'}`; - }).join(', ') - }]`); - } - return { isOk: true, value: Object.values(selected) }; - } - - public itemSelectMultiDub (eps: Record, dubLang: string[], but?: boolean, all?: boolean, e?: string, ) { - const doEpsFilter = parseSelect(e as string); - - const ret: Record = {}; - - for (const key of Object.keys(eps)) { - const itemE = eps[key]; - itemE.items.forEach((item, index) => { - if (!dubLang.includes(itemE.langs[index]?.code)) - return; - item.hide_season_title = true; - if(item.season_title == '' && item.series_title != ''){ - item.season_title = item.series_title; - item.hide_season_title = false; - item.hide_season_number = true; - } - if(item.season_title == '' && item.series_title == ''){ - item.season_title = 'NO_TITLE'; - item.series_title = 'NO_TITLE'; - } - - const epNum = key.startsWith('E') ? key.slice(1) : key; - // set data - const images = (item.images.thumbnail ?? [[ { source: '/notFound.png' } ]])[0]; - const epMeta: CrunchyEpMeta = { - data: [ - { - mediaId: item.id, - versions: item.versions, - isSubbed: item.is_subbed, - isDubbed: item.is_dubbed - } - ], - seriesTitle: itemE.items.find(a => !a.series_title.match(/\(\w+ Dub\)/))?.series_title ?? itemE.items[0].series_title.replace(/\(\w+ Dub\)/g, '').trimEnd(), - seasonTitle: itemE.items.find(a => !a.season_title.match(/\(\w+ Dub\)/))?.season_title ?? itemE.items[0].season_title.replace(/\(\w+ Dub\)/g, '').trimEnd(), - episodeNumber: item.episode, - episodeTitle: item.title, - seasonID: item.season_id, - season: item.season_number, - showID: item.series_id, - e: epNum, - image: images[Math.floor(images.length / 2)].source, - }; - if (item.__links__?.streams?.href) { - epMeta.data[0].playback = item.__links__.streams.href; - if(!item.playback) { - item.playback = item.__links__.streams.href; - } - } - if (item.streams_link) { - epMeta.data[0].playback = item.streams_link; - if(!item.playback) { - item.playback = item.streams_link; - } - } - // find episode numbers - if(item.playback && ((but && !doEpsFilter.isSelected([epNum, item.id])) || (all || (doEpsFilter.isSelected([epNum, item.id])) && !but))) { - if (Object.prototype.hasOwnProperty.call(ret, key)) { - const epMe = ret[key]; - epMe.data.push({ - lang: itemE.langs[index], - ...epMeta.data[0] - }); - } else { - epMeta.data[0].lang = itemE.langs[index]; - ret[key] = { - ...epMeta - }; - } - } - // show ep - item.seq_id = epNum; - }); - } - return ret; - } - - public parseSeriesResult (seasonsList: SeriesSearch) : Record> { - const ret: Record> = {}; - let i = 0; - for (const item of seasonsList.data) { - i++; - for (const lang of langsData.languages) { - //TODO: Make sure the below code is fine - let season_number = item.season_number; - if (item.versions) { - season_number = i; - } - if (!Object.prototype.hasOwnProperty.call(ret, season_number)) - ret[season_number] = {}; - if (item.title.includes(`(${lang.name} Dub)`) || item.title.includes(`(${lang.name})`)) { - ret[season_number][lang.code] = item; - } else if (item.is_subbed && !item.is_dubbed && lang.code == 'jpn') { - ret[season_number][lang.code] = item; - } else if (item.is_dubbed && lang.code === 'eng' && !langsData.languages.some(a => item.title.includes(`(${a.name})`) || item.title.includes(`(${a.name} Dub)`))) { // Dubbed with no more infos will be treated as eng dubs - ret[season_number][lang.code] = item; - //TODO: look into if below is stable - } else if (item.audio_locale == lang.cr_locale) { - ret[season_number][lang.code] = item; - } - } - } - return ret; - } - - public async parseSeriesById(id: string) { - if(!this.cmsToken.cms){ - console.error('Authentication required!'); - return; - } - - const AuthHeaders = { - headers: { - Authorization: `Bearer ${this.token.access_token}`, - }, - useProxy: true - }; - - // seasons list - const seriesSeasonListReq = await this.req.getData(`${api.cms}/series/${id}/seasons?force_locale=&preferred_audio_language=ja-JP&locale=${this.locale}`, AuthHeaders); - if(!seriesSeasonListReq.ok || !seriesSeasonListReq.res){ - console.error('Series Request FAILED!'); - return; - } - // parse data - const seasonsList = await seriesSeasonListReq.res.json() as SeriesSearch; - if(seasonsList.total < 1){ - console.info('Series is empty!'); - return; - } - return seasonsList; - } - - public async getSeasonDataById(item: SeriesSearchItem, log = false){ - if(!this.cmsToken.cms){ - console.error('Authentication required!'); - return; - } - - const AuthHeaders = { - headers: { - Authorization: `Bearer ${this.token.access_token}`, - }, - useProxy: true - }; - - //get show info - const showInfoReq = await this.req.getData(`${api.cms}/seasons/${item.id}?force_locale=&preferred_audio_language=ja-JP&locale=${this.locale}`, AuthHeaders); - if(!showInfoReq.ok || !showInfoReq.res){ - console.error('Show Request FAILED!'); - return; - } - const showInfo = await showInfoReq.res.json(); - if (log) - await this.logObject(showInfo, 0); - - let episodeList = { total: 0, data: [], meta: {} } as CrunchyEpisodeList; - //get episode info - if (this.api == 'android') { - const reqEpsListOpts = [ - api.beta_cms, - this.cmsToken.cms.bucket, - '/episodes?', - new URLSearchParams({ - 'force_locale': '', - 'preferred_audio_language': 'ja-JP', - 'locale': this.locale, - 'season_id': item.id, - 'Policy': this.cmsToken.cms.policy, - 'Signature': this.cmsToken.cms.signature, - 'Key-Pair-Id': this.cmsToken.cms.key_pair_id, - }), - ].join(''); - const reqEpsList = await this.req.getData(reqEpsListOpts, AuthHeaders); - if(!reqEpsList.ok || !reqEpsList.res){ - console.error('Episode List Request FAILED!'); - return; - } - //CrunchyEpisodeList - const episodeListAndroid = await reqEpsList.res.json() as CrunchyAndroidEpisodes; - episodeList = { - total: episodeListAndroid.total, - data: episodeListAndroid.items, - meta: {} - }; - } else { - const reqEpsList = await this.req.getData(`${api.cms}/seasons/${item.id}/episodes?force_locale=&preferred_audio_language=ja-JP&locale=${this.locale}`, AuthHeaders); - if(!reqEpsList.ok || !reqEpsList.res){ - console.error('Episode List Request FAILED!'); - return; - } - //CrunchyEpisodeList - episodeList = await reqEpsList.res.json() as CrunchyEpisodeList; - } - - if(episodeList.total < 1){ - console.info(' Season is empty!'); - return; - } - return episodeList; - } - -} diff --git a/dev.js b/dev.js deleted file mode 100644 index 5342348..0000000 --- a/dev.js +++ /dev/null @@ -1,21 +0,0 @@ -const { exec } = require('child_process'); -const path = require('path'); -const toRun = process.argv.slice(2).join(' ').split('---'); - -const waitForProcess = async (proc) => { - return new Promise((resolve, reject) => { - proc.stdout?.on('data', (data) => process.stdout.write(data)); - proc.stderr?.on('data', (data) => process.stderr.write(data)); - proc.on('close', resolve); - proc.on('error', reject); - }); -}; - -(async () => { - await waitForProcess(exec('pnpm run tsc test false')); - for (let command of toRun) { - await waitForProcess(exec(`node index.js --service hidive ${command}`, { - cwd: path.join(__dirname, 'lib') - })); - } -})(); \ No newline at end of file diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 4231816..0cb42ae 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -1,7 +1,5 @@ ## Change Log -This changelog is out of date and wont be continued. Please see the releases comments, or if not present the commit comments. - ### 4.7.0 (unreleased) - Change subtitles parser from ttml to vtt - Improve help command diff --git a/docs/DOCUMENTATION.md b/docs/DOCUMENTATION.md deleted file mode 100644 index 4d9543f..0000000 --- a/docs/DOCUMENTATION.md +++ /dev/null @@ -1,453 +0,0 @@ -# multi-downloader-nx (5.1.5v) - -If you find any bugs in this documentation or in the program itself please report it [over on GitHub](https://github.com/anidl/multi-downloader-nx/issues). - -## Legal Warning - -This application is not endorsed by or affiliated with *Crunchyroll*, *Hidive*, *AnimeOnegai*, or *AnimationDigitalNetwork*. -This application enables you to download videos for offline viewing which may be forbidden by law in your country. -The usage of this application may also cause a violation of the *Terms of Service* between you and the stream provider. -This tool is not responsible for your actions; please make an informed decision before using this application. - -## CLI Options -### Legend - - `${someText}` shows that you should replace this text with your own - - e.g. `--username ${someText}` -> `--username Izuco` - -### Authentication -#### `--auth` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **cli-default Entry** -| --- | --- | --- | --- | --- | ---| -| All | `--auth ` | `boolean` | `No`| `NaN` | `NaN` | - -Most of the shows on both services are only accessible if you payed for the service. -In order for them to know who you are you are required to log in. -If you trigger this command, you will be prompted for the username and password for the selected service -#### `--username` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **Default** |**cli-default Entry** -| --- | --- | --- | --- | --- | --- | ---| -| All | `--username ${username}` | `string` | `No`| `NaN` | `undefined`| `username: ` | - -Set the username to use for the authentication. If not provided, you will be prompted for the input -#### `--password` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **Default** |**cli-default Entry** -| --- | --- | --- | --- | --- | --- | ---| -| All | `--password ${password}` | `string` | `No`| `NaN` | `undefined`| `password: ` | - -Set the password to use for the authentication. If not provided, you will be prompted for the input -#### `--silentAuth` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **Default** |**cli-default Entry** -| --- | --- | --- | --- | --- | --- | ---| -| Crunchyroll | `--silentAuth ` | `boolean` | `No`| `NaN` | `false`| `silentAuth: ` | - -Authenticate every time the script runs. Use at your own risk. -#### `--token` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **Default** |**cli-default Entry** -| --- | --- | --- | --- | --- | --- | ---| -| Crunchyroll, AnimeOnegai | `--token ${token}` | `string` | `No`| `NaN` | `undefined`| `token: ` | - -Allows you to login with your token (Example on crunchy is Refresh Token/etp-rt cookie) -### Fonts -#### `--dlFonts` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **cli-default Entry** -| --- | --- | --- | --- | --- | ---| -| Crunchyroll | `--dlFonts ` | `boolean` | `No`| `NaN` | `NaN` | - -Crunchyroll uses a variaty of fonts for the subtitles. -Use this command to download all the fonts and add them to the muxed **mkv** file. -#### `--fontName` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **cli-default Entry** -| --- | --- | --- | --- | --- | ---| -| Hidive, AnimationDigitalNetwork | `--fontName ${fontName}` | `string` | `No`| `NaN` | `NaN` | - -Set the font to use in subtiles -### Search -#### `--search` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **cli-default Entry** -| --- | --- | --- | --- | --- | ---| -| All | `--search ${search}` | `string` | `No`| `-f` | `NaN` | - -Search of an anime by the given string -#### `--search-type` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **Choices** | **Default** |**cli-default Entry** -| --- | --- | --- | --- | --- | --- | --- | ---| -| Crunchyroll | `--search-type ${type}` | `string` | `No`| `NaN` | [`''`, `top_results`, `series`, `movie_listing`, `episode`] | ``| `search-type: ` | - -Search only for type of anime listings (e.g. episodes, series) -#### `--page` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **cli-default Entry** -| --- | --- | --- | --- | --- | ---| -| Crunchyroll, Hidive | `--page ${page}` | `number` | `No`| `-p` | `NaN` | - -The output is organized in pages. Use this command to output the items for the given page -#### `--locale` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **Choices** | **Default** |**cli-default Entry** -| --- | --- | --- | --- | --- | --- | --- | ---| -| Crunchyroll, AnimeOnegai, AnimationDigitalNetwork | `--locale ${locale}` | `string` | `No`| `NaN` | [`''`, `en-US`, `en-IN`, `es-LA`, `es-419`, `es-ES`, `pt-BR`, `pt-PT`, `fr-FR`, `de-DE`, `ar-ME`, `ar-SA`, `it-IT`, `ru-RU`, `tr-TR`, `hi-IN`, `zh-CN`, `zh-TW`, `zh-HK`, `ko-KR`, `ca-ES`, `pl-PL`, `th-TH`, `ta-IN`, `ms-MY`, `vi-VN`, `id-ID`, `te-IN`, `fr`, `de`, `''`, `es`, `pt`] | `en-US`| `locale: ` | - -Set the local that will be used for the API. -#### `--new` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **cli-default Entry** -| --- | --- | --- | --- | --- | ---| -| Crunchyroll, Hidive | `--new ` | `boolean` | `No`| `NaN` | `NaN` | - -Get last updated series list -### Downloading -#### `--movie-listing` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **cli-default Entry** -| --- | --- | --- | --- | --- | ---| -| Crunchyroll | `--movie-listing ${ID}` | `string` | `No`| `--flm` | `NaN` | - -Get video list by Movie Listing ID -#### `--series` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **cli-default Entry** -| --- | --- | --- | --- | --- | ---| -| Crunchyroll | `--series ${ID}` | `string` | `No`| `--srz` | `NaN` | - -Requested is the ID of a show not a season. -#### `-s` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **cli-default Entry** -| --- | --- | --- | --- | --- | ---| -| All | `-s ${ID}` | `string` | `No`| `NaN` | `NaN` | - -Used to set the season ID to download from -#### `-e` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **cli-default Entry** -| --- | --- | --- | --- | --- | ---| -| All | `-e ${selection}` | `string` | `No`| `--episode` | `NaN` | - -Set the episode(s) to download from any given show. -For multiple selection: 1-4 OR 1,2,3,4 -For special episodes: S1-4 OR S1,S2,S3,S4 where S is the special letter -#### `--extid` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **cli-default Entry** -| --- | --- | --- | --- | --- | ---| -| Crunchyroll | `--extid ${selection}` | `string` | `No`| `--externalid` | `NaN` | - -Set the external id to lookup/download. -Allows you to download or view legacy Crunchyroll Ids -#### `-q` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **Default** |**cli-default Entry** -| --- | --- | --- | --- | --- | --- | ---| -| All | `-q ${qualityLevel}` | `number` | `No`| `NaN` | `0`| `q: ` | - -Set the quality level. Use 0 to use the maximum quality. -#### `--dlVideoOnce` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **Default** |**cli-default Entry** -| --- | --- | --- | --- | --- | --- | ---| -| Crunchyroll, AnimeOnegai | `--dlVideoOnce ` | `boolean` | `No`| `NaN` | `false`| `dlVideoOnce: ` | - -If selected, the best selected quality will be downloaded only for the first language, -then the worst video quality with the same audio quality will be downloaded for every other language. -By the later merge of the videos, no quality difference will be present. -This will speed up the download speed, if multiple languages are selected. -#### `--chapters` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **Default** |**cli-default Entry** -| --- | --- | --- | --- | --- | --- | ---| -| Crunchyroll, AnimationDigitalNetwork | `--chapters ` | `boolean` | `No`| `NaN` | `true`| `chapters: ` | - -Will fetch the chapters and add them into the final video. -Currently only works with mkvmerge. -#### `--crapi` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **Choices** | **Default** |**cli-default Entry** -| --- | --- | --- | --- | --- | --- | --- | ---| -| Crunchyroll | `--crapi ` | `string` | `No`| `NaN` | [`android`, `web`] | `web`| `crapi: ` | - -If set to Android, it has lower quality, but Non-DRM streams, -If set to Web, it has a higher quality adaptive stream, but everything is DRM. -#### `--removeBumpers` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **Default** |**cli-default Entry** -| --- | --- | --- | --- | --- | --- | ---| -| Hidive | `--removeBumpers ` | `boolean` | `No`| `NaN` | `true`| `removeBumpers: ` | - -If selected, it will remove the bumpers such as the hidive intro from the final file. -Currently disabling this sometimes results in bugs such as video/audio desync -#### `--originalFontSize` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **Default** |**cli-default Entry** -| --- | --- | --- | --- | --- | --- | ---| -| Hidive | `--originalFontSize ` | `boolean` | `No`| `NaN` | `true`| `originalFontSize: ` | - -If selected, it will prefer to keep the original Font Size defined by the service. -#### `-x` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **Choices** | **Default** |**cli-default Entry** -| --- | --- | --- | --- | --- | --- | --- | ---| -| Crunchyroll | `-x ${server}` | `number` | `No`| `--server` | [`1`, `2`, `3`, `4`] | `1`| `x: ` | - -Select the server to use -#### `--kstream` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **Choices** | **Default** |**cli-default Entry** -| --- | --- | --- | --- | --- | --- | --- | ---| -| Crunchyroll | `--kstream ${stream}` | `number` | `No`| `-k` | [`1`, `2`, `3`, `4`, `5`, `6`, `7`, `8`, `9`, `10`] | `1`| `kstream: ` | - -Select specific stream -#### `--cstream` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **Choices** | **Default** |**cli-default Entry** -| --- | --- | --- | --- | --- | --- | --- | ---| -| Crunchyroll | `--cstream ${device}` | `string` | `No`| `--cs` | [`chrome`, `firefox`, `safari`, `edge`, `fallback`, `ps4`, `ps5`, `switch`, `samsungtv`, `lgtv`, `rokutv`, `android`, `iphone`, `ipad`, `none`] | `chrome`| `cstream: ` | - -Select specific crunchy play stream by device, or disable stream with "none" -#### `--hslang` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **Choices** | **Default** |**cli-default Entry** -| --- | --- | --- | --- | --- | --- | --- | ---| -| Crunchyroll | `--hslang ${hslang}` | `string` | `No`| `NaN` | [`none`, `en`, `en-IN`, `es-419`, `es-ES`, `pt-BR`, `pt-PT`, `fr`, `de`, `ar`, `it`, `ru`, `tr`, `hi`, `zh`, `zh-CN`, `zh-TW`, `zh-HK`, `ko`, `ca-ES`, `pl-PL`, `th-TH`, `ta-IN`, `ms-MY`, `vi-VN`, `id-ID`, `te-IN`, `ja`] | `none`| `hslang: ` | - -Download video with specific hardsubs -#### `--dlsubs` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **Choices** | **Default** |**cli-default Entry** -| --- | --- | --- | --- | --- | --- | --- | ---| -| All | `--dlsubs ${sub1} ${sub2}` | `array` | `No`| `NaN` | [`all`, `none`, `en`, `en-IN`, `es-419`, `es-ES`, `pt-BR`, `pt-PT`, `fr`, `de`, `ar`, `it`, `ru`, `tr`, `hi`, `zh`, `zh-CN`, `zh-TW`, `zh-HK`, `ko`, `ca-ES`, `pl-PL`, `th-TH`, `ta-IN`, `ms-MY`, `vi-VN`, `id-ID`, `te-IN`, `ja`] | `all`| `dlsubs: ` | - -Download subtitles by language tag (space-separated) -Crunchy Only: en, en-IN, es-419, es-419, es-ES, pt-BR, pt-PT, fr, de, ar, ar, it, ru, tr, hi, zh-CN, zh-TW, zh-HK, ko, ca-ES, pl-PL, th-TH, ta-IN, ms-MY, vi-VN, id-ID, te-IN, ja -#### `--novids` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **cli-default Entry** -| --- | --- | --- | --- | --- | ---| -| All | `--novids ` | `boolean` | `No`| `NaN` | `NaN` | - -Skip downloading videos -#### `--noaudio` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **cli-default Entry** -| --- | --- | --- | --- | --- | ---| -| Crunchyroll, Hidive | `--noaudio ` | `boolean` | `No`| `NaN` | `NaN` | - -Skip downloading audio -#### `--nosubs` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **cli-default Entry** -| --- | --- | --- | --- | --- | ---| -| All | `--nosubs ` | `boolean` | `No`| `NaN` | `NaN` | - -Skip downloading subtitles -#### `--dubLang` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **Choices** | **Default** |**cli-default Entry** -| --- | --- | --- | --- | --- | --- | --- | ---| -| All | `--dubLang ${dub1} ${dub2}` | `array` | `No`| `NaN` | [`eng`, `spa`, `spa-419`, `spa-ES`, `por`, `fra`, `deu`, `ara-ME`, `ara`, `ita`, `rus`, `tur`, `hin`, `cmn`, `zho`, `chi`, `zh-HK`, `kor`, `cat`, `pol`, `tha`, `tam`, `may`, `vie`, `ind`, `tel`, `jpn`] | `jpn`| `dubLang: ` | - -Set the language to download: -Crunchy Only: eng, eng, spa, spa-419, spa-ES, por, por, fra, deu, ara-ME, ara, ita, rus, tur, hin, zho, chi, zh-HK, kor, cat, pol, tha, tam, may, vie, ind, tel, jpn -#### `--all` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **Default** |**cli-default Entry** -| --- | --- | --- | --- | --- | --- | ---| -| All | `--all ` | `boolean` | `No`| `NaN` | `false`| `all: ` | - -Used to download all episodes from the show -#### `--fontSize` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **Default** |**cli-default Entry** -| --- | --- | --- | --- | --- | --- | ---| -| All | `--fontSize ${fontSize}` | `number` | `No`| `NaN` | `55`| `fontSize: ` | - -When converting the subtitles to ass, this will change the font size -In most cases, requires "--originaFontSize false" to take effect -#### `--combineLines` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **cli-default Entry** -| --- | --- | --- | --- | --- | ---| -| Hidive | `--combineLines ` | `boolean` | `No`| `NaN` | `NaN` | - -If selected, will prevent a line from shifting downwards -#### `--allDubs` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **cli-default Entry** -| --- | --- | --- | --- | --- | ---| -| All | `--allDubs ` | `boolean` | `No`| `NaN` | `NaN` | - -If selected, all available dubs will get downloaded -#### `--timeout` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **Default** |**cli-default Entry** -| --- | --- | --- | --- | --- | --- | ---| -| All | `--timeout ${timeout}` | `number` | `No`| `NaN` | `15000`| `timeout: ` | - -Set the timeout of all download reqests. Set in millisecods -#### `--waittime` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **Default** |**cli-default Entry** -| --- | --- | --- | --- | --- | --- | ---| -| Crunchyroll, Hidive | `--waittime ${waittime}` | `number` | `No`| `NaN` | `0`| `waittime: ` | - -Set the time the program waits between downloads. Set in millisecods -#### `--simul` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **Default** |**cli-default Entry** -| --- | --- | --- | --- | --- | --- | ---| -| Hidive | `--simul ` | `boolean` | `No`| `NaN` | `false`| `simul: ` | - -Force downloading simulcast version instead of uncut version (if available). -#### `--but` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **cli-default Entry** -| --- | --- | --- | --- | --- | ---| -| All | `--but ` | `boolean` | `No`| `NaN` | `NaN` | - -Download everything but the -e selection -#### `--downloadArchive` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **cli-default Entry** -| --- | --- | --- | --- | --- | ---| -| All | `--downloadArchive ` | `boolean` | `No`| `NaN` | `NaN` | - -Used to download all archived shows -#### `--addArchive` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **cli-default Entry** -| --- | --- | --- | --- | --- | ---| -| All | `--addArchive ` | `boolean` | `No`| `NaN` | `NaN` | - -Used to add the `-s` and `--srz` to downloadArchive -#### `--partsize` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **Default** |**cli-default Entry** -| --- | --- | --- | --- | --- | --- | ---| -| All | `--partsize ${amount}` | `number` | `No`| `NaN` | `10`| `partsize: ` | - -Set the amount of parts to download at once -If you have a good connection try incresing this number to get a higher overall speed -#### `--fsRetryTime` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **Default** |**cli-default Entry** -| --- | --- | --- | --- | --- | --- | ---| -| All | `--fsRetryTime ${time in seconds}` | `number` | `No`| `NaN` | `5`| `fsRetryTime: ` | - -Set the time the downloader waits before retrying if an error while writing the file occurs -#### `--force` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **Choices** | **cli-default Entry** -| --- | --- | --- | --- | --- | --- | ---| -| All | `--force ${option}` | `string` | `No`| `NaN` | [`y`, `Y`, `n`, `N`, `c`, `C`] | `NaN` | - -If a file already exists, the tool will ask you how to proceed. With this, you can answer in advance. -### Muxing -#### `--mp4` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **Default** |**cli-default Entry** -| --- | --- | --- | --- | --- | --- | ---| -| All | `--mp4 ` | `boolean` | `No`| `NaN` | `false`| `mp4: ` | - -If selected, the output file will be an mp4 file (not recommended tho) -#### `--keepAllVideos` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **Default** |**cli-default Entry** -| --- | --- | --- | --- | --- | --- | ---| -| Crunchyroll, Hidive | `--keepAllVideos ` | `boolean` | `No`| `NaN` | `false`| `keepAllVideos: ` | - -If set to true, it will keep all videos in the merge process, rather than discarding the extra videos. -#### `--syncTiming` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **Default** |**cli-default Entry** -| --- | --- | --- | --- | --- | --- | ---| -| Crunchyroll, Hidive | `--syncTiming ` | `boolean` | `No`| `NaN` | `false`| `syncTiming: ` | - -If enabled attempts to sync timing for multi-dub downloads. -NOTE: This is currently experimental and syncs audio and subtitles, though subtitles has a lot of guesswork -If you find bugs with this, please report it in the discord or github -#### `--skipmux` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **cli-default Entry** -| --- | --- | --- | --- | --- | ---| -| All | `--skipmux ` | `boolean` | `No`| `NaN` | `NaN` | - -Skip muxing video, audio and subtitles -#### `--nocleanup` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **Default** |**cli-default Entry** -| --- | --- | --- | --- | --- | --- | ---| -| All | `--nocleanup ` | `boolean` | `No`| `NaN` | `false`| `nocleanup: ` | - -Don't delete subtitle, audio and video files after muxing -#### `--skipSubMux` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **Default** |**cli-default Entry** -| --- | --- | --- | --- | --- | --- | ---| -| All | `--skipSubMux ` | `boolean` | `No`| `NaN` | `false`| `skipSubMux: ` | - -Skip muxing the subtitles -#### `--forceMuxer` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **Choices** | **Default** |**cli-default Entry** -| --- | --- | --- | --- | --- | --- | --- | ---| -| All | `--forceMuxer ${muxer}` | `string` | `No`| `NaN` | [`ffmpeg`, `mkvmerge`] | `undefined`| `forceMuxer: ` | - -Force the program to use said muxer or don't mux if the given muxer is not present -#### `--videoTitle` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **cli-default Entry** -| --- | --- | --- | --- | --- | ---| -| All | `--videoTitle ${title}` | `string` | `No`| `NaN` | `NaN` | - -Set the video track name of the merged file -#### `--mkvmergeOptions` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **Default** |**cli-default Entry** -| --- | --- | --- | --- | --- | --- | ---| -| All | `--mkvmergeOptions ${args}` | `array` | `No`| `NaN` | `--no-date,--disable-track-statistics-tags,--engage no_variable_data`| `mkvmergeOptions: ` | - -Set the options given to mkvmerge -#### `--ffmpegOptions` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **Default** |**cli-default Entry** -| --- | --- | --- | --- | --- | --- | ---| -| All | `--ffmpegOptions ${args}` | `array` | `No`| `NaN` | ``| `ffmpegOptions: ` | - -Set the options given to ffmpeg -#### `--defaultAudio` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **Default** |**cli-default Entry** -| --- | --- | --- | --- | --- | --- | ---| -| All | `--defaultAudio ${args}` | `string` | `No`| `NaN` | `eng`| `defaultAudio: ` | - -Set the default audio track by language code -Possible Values: eng, eng, spa, spa-419, spa-ES, por, por, fra, deu, ara-ME, ara, ita, rus, tur, hin, cmn, zho, chi, zh-HK, kor, cat, pol, tha, tam, may, vie, ind, tel, jpn -#### `--defaultSub` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **Default** |**cli-default Entry** -| --- | --- | --- | --- | --- | --- | ---| -| All | `--defaultSub ${args}` | `string` | `No`| `NaN` | `eng`| `defaultSub: ` | - -Set the default subtitle track by language code -Possible Values: eng, eng, spa, spa-419, spa-ES, por, por, fra, deu, ara-ME, ara, ita, rus, tur, hin, cmn, zho, chi, zh-HK, kor, cat, pol, tha, tam, may, vie, ind, tel, jpn -### Filename Template -#### `--fileName` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **Default** |**cli-default Entry** -| --- | --- | --- | --- | --- | --- | ---| -| All | `--fileName ${fileName}` | `string` | `No`| `NaN` | `[${service}] ${showTitle} - S${season}E${episode} [${height}p]`| `fileName: ` | - -Set the filename template. Use ${variable_name} to insert variables. -You can also create folders by inserting a path seperator in the filename -You may use 'title', 'episode', 'showTitle', 'seriesTitle', 'season', 'width', 'height', 'service' as variables. -#### `--numbers` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **Default** |**cli-default Entry** -| --- | --- | --- | --- | --- | --- | ---| -| All | `--numbers ${number}` | `number` | `No`| `NaN` | `2`| `numbers: ` | - -Set how long a number in the title should be at least. -Set in config: 3; Episode number: 5; Output: 005 -Set in config: 2; Episode number: 1; Output: 01 -Set in config: 1; Episode number: 20; Output: 20 -#### `--override` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **Default** |**cli-default Entry** -| --- | --- | --- | --- | --- | --- | ---| -| All | `--override "${toOverride}='${value}'"` | `array` | `No`| `NaN` | ``| `override: ` | - -Override a template variable -#### `--ccTag` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **Default** |**cli-default Entry** -| --- | --- | --- | --- | --- | --- | ---| -| All | `--ccTag ${tag}` | `string` | `No`| `NaN` | `cc`| `ccTag: ` | - -Used to set the name for subtitles that contain tranlations for none verbal communication (e.g. signs) -### Debug -#### `--nosess` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **Default** |**cli-default Entry** -| --- | --- | --- | --- | --- | --- | ---| -| All | `--nosess ` | `boolean` | `No`| `NaN` | `false`| `nosess: ` | - -Reset session cookie for testing purposes -#### `--debug` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **Default** |**cli-default Entry** -| --- | --- | --- | --- | --- | --- | ---| -| All | `--debug ` | `boolean` | `No`| `NaN` | `false`| `debug: ` | - -Debug mode (tokens may be revealed in the console output) -### Utilities -#### `--service` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **Choices** | **Default** |**cli-default Entry** -| --- | --- | --- | --- | --- | --- | --- | ---| -| All | `--service ${service}` | `string` | `Yes`| `NaN` | [`crunchy`, `hidive`, `ao`, `adn`] | ``| `service: ` | - -Set the service you want to use -#### `--update` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **cli-default Entry** -| --- | --- | --- | --- | --- | ---| -| All | `--update ` | `boolean` | `No`| `NaN` | `NaN` | - -Force the tool to check for updates (code version only) -#### `--skipUpdate` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **Default** |**cli-default Entry** -| --- | --- | --- | --- | --- | --- | ---| -| All | `--skipUpdate ` | `boolean` | `No`| `NaN` | `false`| `skipUpdate: ` | - -If true, the tool won't check for updates -### Help -#### `--help` -| **Service** | **Usage** | **Type** | **Required** | **Alias** | **cli-default Entry** -| --- | --- | --- | --- | --- | ---| -| All | `--help ` | `boolean` | `No`| `-h` | `NaN` | - -Show the help output -### GUI diff --git a/docs/README.md b/docs/README.md index c93b0be..9b5e748 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,107 +1,84 @@ -# Anime Downloader NX by AniDL +# Funimation Downloader NX -[![Discord Shield](https://discord.com/api/guilds/884479461997805568/widget.png?style=banner2)](https://discord.gg/qEpbWen5vq) +Funimation Downloader NX is capable of downloading videos from the *Funimation* streaming service. -This downloader can download anime from different sites. Currently supported are *Crunchyroll*, *Hidive*, *AnimeOnegai*, and *AnimationDigitalNetwork*. +Fork of @seiya-dev's Funimation Downloader NX ## Legal Warning -This application is not endorsed by or affiliated with *Crunchyroll*, *Hidive*, *AnimeOnegai*, or *AnimationDigitalNetwork*. This application enables you to download videos for offline viewing which may be forbidden by law in your country. The usage of this application may also cause a violation of the *Terms of Service* between you and the stream provider. This tool is not responsible for your actions; please make an informed decision before using this application. +This application is not endorsed by or affiliated with *Funimation*. This application enables you to download videos for offline viewing which may be forbidden by law in your country. The usage of this application may also cause a violation of the *Terms of Service* between you and the stream provider. This tool is not responsible for your actions; please make an informed decision before using this application. -## Dependencies +## Prerequisites +* NodeJS >= 12.4.0 (https://nodejs.org/) +* NPM >= 6.9.0 (https://www.npmjs.org/) * ffmpeg >= 4.0.0 (https://www.videohelp.com/software/ffmpeg) -* MKVToolNix >= 60.0.0 (https://www.videohelp.com/software/MKVToolNix) +* MKVToolNix >= 20.0.0 (https://www.videohelp.com/software/MKVToolNix) ### Paths Configuration By default this application uses the following paths to programs (main executables): - -* `ffmpeg.exe` (From PATH) -* `ffprobe.exe` (From PATH) -* `mkvmerge.exe` (From PATH) -* `mp4decrypt.exe` (From PATH) +* `./bin/mkvmerge` +* `./bin/ffmpeg` To change these paths you need to edit `bin-path.yml` in `./config/` directory. -## CLI Information +### Node Modules -See [the documentation](https://github.com/anidl/multi-downloader-nx/blob/master/docs/DOCUMENTATION.md) for a complete list of what options are available. You can define defaults for the commands by editing the `cli-defaults.yml` file in the `./config/` directory. +After installing NodeJS with NPM go to directory with `package.json` file and type: `npm i`. +* [check dependencies](https://david-dm.org/anidl/funimation-downloader-nx) -### Example usage +## CLI Options -#### Logging in +### Authentication -Most services require you to be logged in, in order to download from, an example of how you would login is: +* `--auth` enter auth mode -```shell -AniDL --service {ServiceName} --auth -``` +### Get Show ID -#### Searching +* `--search ` sets the show title for search -In order to find the IDs to download, you can search from each service by using the `--search` flag like this: +### Download Video -```shell -AniDL --service {ServiceName} --search {SearchTerm} -``` +* `-s -e ` sets the show id and episode ids (comma-separated, hyphen-sequence) +* `-q ` sets the video layer quality [1...10] (optional, 0 is max) +* `--alt` alternative episode listing (if available) +* `--sub` switch from English dub to Japanese dub with subtitles +* `--simul` force select simulcast version instead of uncut version +* `-x` select server +* `--novids` skip download videos (for downloading subtitles only) +* `--nosubs` skip download subtitles for Dub (if available) -#### Downloading +### Proxy -Once you have the ID which you can obtain from using the search or other means, you are ready to download, which you can do like this: +* `--proxy ` http(s)/socks proxy WHATWG url (ex. https://myproxyhost:1080) +* `--proxy-auth ` Colon-separated username and password for proxy +* `--ssp` don't use proxy for stream downloading -```shell -AniDL --service {ServiceName} -s {SeasonID} -e {EpisodeNumber} -``` +### Muxing -## Building and running from source +`[note] this application mux into mkv by default` +* `--mp4` mux into mp4 +* `--mks` add subtitles to mkv or mp4 (if available) -### Build Dependencies +### Filenaming (optional) -Dependencies that are only required for running from code. These are not required if you are using the prebuilt binaries. +* `-a ` release group ("Funimation" by default) +* `-t ` show title override +* `--ep ` episode number override (ignored in batch mode) +* `--suffix ` filename suffix override (first "SIZEp" will be replaced with actual video size, "SIZEp" by default) -* NodeJS >= 18.0.0 (https://nodejs.org/) -* NPM >= 6.9.0 (https://www.npmjs.org/) -* PNPM >= 7.0.0 (https://pnpm.io/) +### Utility -### Build Setup +* `--nocleanup` move unnecessary files to trash folder after completion instead of deleting +* `-h`, `--help` show all options -Please note that NodeJS, NPM, and PNPM must be installed on your system. For instructions on how to install pnpm, check (https://pnpm.io/installation) +## Filename Template -First clone this repo `git clone https://github.com/anidl/multi-downloader-nx.git`. +[`release group`] `title` - `episode` [`suffix`].`extension` -`cd` into the cloned directory and run `pnpm i`. Next, decide if you want to package the application, build the code, or run from typescript. +## CLI Examples -### Run from TypeScript - -You can run the code from native TypeScript, this requires ts-node which you can install with pnpm with the following command: `pnpm -g i ts-node` - -Afterwords, you can run the application like this: - -* CLI: `ts-node -T ./index.ts --help` - -### Run as JavaScript - -If you want to build the application into JavaScript code to run, you can do that as well like this: - -* CLI: `pnpm run prebuild-cli` -* GUI: `pnpm run prebuild-gui` - -Then you can cd into the `lib` folder and you will be able to run the CLI or GUI as follows: - -* CLI: `node ./index.js --help` -* GUI: `node ./gui.js` - -### Build the application into an executable - -If you want to package the application, run pnpm run build-`{platform}`-`{type}` where `{platform}` is the operating system (currently the choices are windows, linux, macos, alpine, android, and arm) and `{type}` is cli or gui. - -## DRM Decryption - -### Decryption Requirements - -* mp4decrypt >= Any (http://www.bento4.com/) - Only required for decrypting - -### Instructions - -In order to decrypt DRM content, you will need to have a dumped CDM, after that you will need to place the CDM files (`device_client_id_blob` and `device_private_key`) into the `./widevine/` directory. For legal reasons we do not include the CDM with the software, and you will have to source one yourself. +* `node funi --search "My Hero"` search "My Hero" in title +* `node funi -s 124389 -e 1,2,3` download episodes 1-3 from show with id 124389 +* `node funi -s 124389 -e 1-3,2-7,s1-2` download episodes 1-7 and "S"-episodes 1-2 from show with id 124389 diff --git a/eslint.config.mjs b/eslint.config.mjs deleted file mode 100644 index 0770387..0000000 --- a/eslint.config.mjs +++ /dev/null @@ -1,64 +0,0 @@ -// @ts-check - -import eslint from '@eslint/js'; -import tseslint from 'typescript-eslint'; -import react from 'eslint-plugin-react'; - -export default tseslint.config( - eslint.configs.recommended, - ...tseslint.configs.recommended, - { - rules: { - 'no-console': 2, - 'react/prop-types': 0, - 'react-hooks/exhaustive-deps': 0, - '@typescript-eslint/no-explicit-any': 'off', - '@typescript-eslint/no-unsafe-declaration-merging': 'warn', - '@typescript-eslint/no-unused-vars' : 'warn', - 'indent': [ - 'error', - 2 - ], - 'linebreak-style': [ - 'warn', - 'windows' - ], - 'quotes': [ - 'error', - 'single' - ], - 'semi': [ - 'error', - 'always' - ] - }, - plugins: { - react - }, - languageOptions: { - parserOptions: { - ecmaFeatures: { - jsx: true, - }, - ecmaVersion: 2020, - sourceType: 'module' - }, - parser: tseslint.parser - } - }, - { - ignores: [ - '**/lib', - '**/videos/*.ts', - '**/build', - 'dev.js', - 'tsc.ts' - ] - }, - { - files: ['gui/react/**/*'], - rules: { - 'no-console': 0 - } - } -); \ No newline at end of file diff --git a/funi.js b/funi.js new file mode 100644 index 0000000..d0fb258 --- /dev/null +++ b/funi.js @@ -0,0 +1,894 @@ +#!/usr/bin/env node + +// modules build-in +const fs = require('fs'); +const path = require('path'); + +// package json +const packageJson = require('./package.json'); + +// program name +console.log(`\n=== Funimation Downloader NX ${packageJson.version} ===\n`); +const api_host = 'https://prod-api-funimationnow.dadcdigital.com/api'; + +// modules extra +const yaml = require('yaml'); +const shlp = require('sei-helper'); +const { lookpath } = require('lookpath'); +const m3u8 = require('m3u8-parsed'); +const crypto = require('crypto'); +const got = require('got'); +const iso639 = require('iso-639'); + +// extra +const appYargs = require('./modules/module.app-args'); +const getYamlCfg = require('./modules/module.cfg-loader'); +const getData = require('./modules/module.getdata.js'); +const vttConvert = require('./modules/module.vttconvert'); + +// new-cfg +const cfgFolder = path.join(__dirname, '/config'); +const binCfgFile = path.join(cfgFolder, 'bin-path'); +const dirCfgFile = path.join(cfgFolder, 'dir-path'); +const cliCfgFile = path.join(cfgFolder, 'cli-defaults'); +const tokenFile = path.join(cfgFolder, 'token'); + +// params +let cfg = { + bin: getYamlCfg(binCfgFile), + dir: getYamlCfg(dirCfgFile), + cli: getYamlCfg(cliCfgFile), +}; + +// token +let token = getYamlCfg(tokenFile); +token = token.token ? token.token : false; + +// info if token not set +if(!token){ + console.log('[INFO] Token not set!\n'); +} + +// cli +const argv = appYargs.appArgv(cfg.cli); + +// check page +if(!isNaN(parseInt(argv.p, 10)) && parseInt(argv.p, 10) > 0){ + argv.p = parseInt(argv.p, 10); +} +else{ + argv.p = 1; +} + +// fn variables +let fnTitle = '', + fnEpNum = '', + fnSuffix = '', + fnOutput = '', + tsDlPath = false, + stDlPath = undefined, + batchDL = false; + +// select mode +if(argv.auth){ + auth(); +} +else if(argv.search){ + searchShow(); +} +else if(argv.s && !isNaN(parseInt(argv.s, 10)) && parseInt(argv.s, 10) > 0){ + getShow(); +} +else{ + appYargs.showHelp(); + process.exit(); +} + +// auth +async function auth(){ + let authOpts = {}; + authOpts.user = await shlp.question('[Q] LOGIN/EMAIL'); + authOpts.pass = await shlp.question('[Q] PASSWORD '); + let authData = await getData({ + baseUrl: api_host, + url: '/auth/login/', + useProxy: true, + auth: authOpts, + debug: argv.debug, + }); + if(authData.ok){ + authData = JSON.parse(authData.res.body); + if(authData.token){ + console.log('[INFO] Authentication success, your token: %s%s\n', authData.token.slice(0,8),'*'.repeat(32)); + fs.writeFileSync(tokenFile + '.yml', yaml.stringify({'token': authData.token})); + } + else if(authData.error){ + console.log('[ERROR]%s\n', authData.error); + process.exit(1); + } + } +} + +// search show +async function searchShow(){ + let qs = {unique: true, limit: 100, q: argv.search, offset: (argv.p-1)*1000 }; + let searchData = await getData({ + baseUrl: api_host, + url: '/source/funimation/search/auto/', + querystring: qs, + token: token, + useToken: true, + useProxy: true, + debug: argv.debug, + }); + if(!searchData.ok){return;} + searchData = JSON.parse(searchData.res.body); + if(searchData.detail){ + console.log(`[ERROR] ${searchData.detail}`); + return; + } + if(searchData.items && searchData.items.hits){ + let shows = searchData.items.hits; + console.log('[INFO] Search Results:'); + for(let ssn in shows){ + console.log(`[#${shows[ssn].id}] ${shows[ssn].title}` + (shows[ssn].tx_date?` (${shows[ssn].tx_date})`:'')); + } + } + console.log('[INFO] Total shows found: %s\n',searchData.count); +} + +// get show +async function getShow(){ + // show main data + let showData = await getData({ + baseUrl: api_host, + url: `/source/catalog/title/${parseInt(argv.s, 10)}`, + token: token, + useToken: true, + useProxy: true, + debug: argv.debug, + }); + // check errors + if(!showData.ok){return;} + showData = JSON.parse(showData.res.body); + if(showData.status){ + console.log('[ERROR] Error #%d: %s\n', showData.status, showData.data.errors[0].detail); + process.exit(1); + } + else if(!showData.items || showData.items.length<1){ + console.log('[ERROR] Show not found\n'); + process.exit(0); + } + showData = showData.items[0]; + console.log('[#%s] %s (%s)',showData.id,showData.title,showData.releaseYear); + // show episodes + let qs = { limit: -1, sort: 'order', sort_direction: 'ASC', title_id: parseInt(argv.s,10) }; + if(argv.alt){ qs.language = 'English'; } + let episodesData = await getData({ + baseUrl: api_host, + url: '/funimation/episodes/', + querystring: qs, + token: token, + useToken: true, + useProxy: true, + debug: argv.debug, + }); + if(!episodesData.ok){return;} + let eps = JSON.parse(episodesData.res.body).items, fnSlug = [], is_selected = false; + argv.e = typeof argv.e == 'number' || typeof argv.e == 'string' ? argv.e.toString() : ''; + argv.e = argv.e.match(',') ? argv.e.split(',') : [argv.e]; + let epSelList = argv.e, epSelRanges = [], epSelEps = []; + epSelList = epSelList.map((e)=>{ + if(e.match('-')){ + e = e.split('-'); + if( e[0].match(/^(?:[A-Z]+|)\d+$/i) && e[1].match(/^\d+$/) ){ + e[0] = e[0].replace(/^(?:([A-Z]+)|)(0+)/i,'$1'); + let letter = e[0].match(/^([A-Z]+)\d+$/i) ? e[0].match(/^([A-Z]+)\d+$/i)[1].toUpperCase() : ''; + e[0] = e[0].replace(/^[A-Z]+(\d+)$/i,'$1'); + e[0] = parseInt(e[0]); + e[1] = parseInt(e[1]); + if(e[0] < e[1]){ + for(let i=e[0];i 0 ? `, ${eps[e].audio.join(', ')}` : ''; + let rtm_str = eps[e].item.runtime !== '' ? eps[e].item.runtime : '??:??'; + // console string + let episodeIdStr = epStrId; + let conOut = `[${episodeIdStr}] `; + conOut += `${eps[e].item.titleName+tx_snum} - ${tx_type+tx_enum} ${eps[e].item.episodeName} `; + conOut += `(${rtm_str}) [${qua_str+aud_str}]`; + conOut += is_selected ? ' (selected)' : ''; + conOut += eps.length-1 == e ? '\n' : ''; + console.log(conOut); + } + if(fnSlug.length>1){ + batchDL = true; + } + if(fnSlug.length<1){ + console.log('[INFO] Episodes not selected!\n'); + process.exit(); + } + else{ + console.log('[INFO] Selected Episodes: %s\n',epSelEps.join(', ')); + for(let fnEp=0;fnEp 0 && m.type == 'Non-Encrypted'){ + let dub_type = m.language; + let selUncut = !argv.simul && uncut[dub_type] && m.version.match(/uncut/i) + ? true + : (!uncut[dub_type] || argv.simul && m.version.match(/simulcast/i) ? true : false); + if(dub_type == 'Japanese' && argv.sub && selUncut){ + streamId = m.id; + stDlPath = m.subtitles; + selected = true; + } + else if(dub_type == dubType[argv.dub] && !argv.sub && selUncut){ + streamId = m.id; + stDlPath = m.subtitles; + selected = true; + } + console.log(`[#${m.id}] ${dub_type} [${m.version}]`,(selected?'(selected)':''),(m.subtitles.subLangAvailable?'':'(defaulted to Englisch subtitles)')); + } + } + + if(streamId<1){ + console.log('[ERROR] Track not selected\n'); + return; + } + else{ + let streamData = await getData({ + baseUrl: api_host, + url: `/source/catalog/video/${streamId}/signed`, + token: token, + dinstid: 'uuid', + useToken: true, + useProxy: true, + debug: argv.debug, + }); + if(!streamData.ok){return;} + streamData = JSON.parse(streamData.res.body); + tsDlPath = false; + if(streamData.errors){ + console.log('[ERROR] Error #%s: %s\n',streamData.errors[0].code,streamData.errors[0].detail); + return; + } + else{ + for(let u in streamData.items){ + if(streamData.items[u].videoType == 'm3u8'){ + tsDlPath = streamData.items[u].src; + break; + } + } + } + if(!tsDlPath){ + console.log('[ERROR] Unknown error\n'); + return; + } + else{ + await downloadStreams(); + } + } +} + +function getSubsUrl(m){ + if(argv.nosubs && !argv.sub){ + return false; + } + + let subLang = argv.subLang + + const subType = { + 'enUS': 'English', + 'esLA': 'Spanish (Latin Am)', + 'ptBR': 'Portuguese (Brazil)' + }; + + let subLangAvailable = m.some(a => { + return a.ext == 'vtt' && a.language === subType[subLang] + }); + + if (!subLangAvailable) { + subLang = 'enUS'; + } + + for(let i in m){ + let fpp = m[i].filePath.split('.'); + let fpe = fpp[fpp.length-1]; + if(fpe == 'vtt' && m[i].language === subType[subLang]) { + return { + path: m[i].filePath, + ext: `.${subLang}`, + langName: subType[subLang], + subLangAvailable: subLangAvailable + }; + } + } + return false; +} + +async function downloadStreams(){ + + // req playlist + let plQualityReq = await getData({ + url: tsDlPath, + useProxy: (argv.ssp ? false : true), + debug: argv.debug, + }); + if(!plQualityReq.ok){return;} + + let plQualityLinkList = m3u8(plQualityReq.res.body); + + let mainServersList = [ + 'vmfst-api.prd.funimationsvc.com', + 'd132fumi6di1wa.cloudfront.net', + 'funiprod.akamaized.net', + ]; + + let plServerList = [], + plStreams = {}, + plLayersStr = [], + plLayersRes = {}, + plMaxLayer = 1, + plNewIds = 1, + plAud = { uri: '' }; + + // new uris + let vplReg = /streaming_video_(\d+)_(\d+)_(\d+)_index\.m3u8/; + if(plQualityLinkList.playlists[0].uri.match(vplReg)){ + if(plQualityLinkList.mediaGroups.AUDIO['audio-aacl-128']){ + let audioData = plQualityLinkList.mediaGroups.AUDIO['audio-aacl-128'], + audioEl = Object.keys(audioData); + audioData = audioData[audioEl[0]]; + plAud = { ...audioData, ...{ langStr: audioEl[0] } }; + } + plQualityLinkList.playlists.sort((a, b) => { + let av = parseInt(a.uri.match(vplReg)[3]); + let bv = parseInt(b.uri.match(vplReg)[3]); + if(av > bv){ + return 1; + } + if (av < bv) { + return -1; + } + return 0; + }); + } + + for(let s of plQualityLinkList.playlists){ + if(s.uri.match(/_Layer(\d+)\.m3u8/) || s.uri.match(vplReg)){ + // set layer and max layer + let plLayerId = 0; + if(s.uri.match(/_Layer(\d+)\.m3u8/)){ + plLayerId = parseInt(s.uri.match(/_Layer(\d+)\.m3u8/)[1]); + } + else{ + plLayerId = plNewIds, plNewIds++; + } + plMaxLayer = plMaxLayer < plLayerId ? plLayerId : plMaxLayer; + // set urls and servers + let plUrlDl = s.uri; + let plServer = new URL(plUrlDl).host; + if(!plServerList.includes(plServer)){ + plServerList.push(plServer); + } + if(!Object.keys(plStreams).includes(plServer)){ + plStreams[plServer] = {}; + } + if(plStreams[plServer][plLayerId] && plStreams[plServer][plLayerId] != plUrlDl){ + console.log(`[WARN] Non duplicate url for ${plServer} detected, please report to developer!`); + } + else{ + plStreams[plServer][plLayerId] = plUrlDl; + } + // set plLayersStr + let plResolution = `${s.attributes.RESOLUTION.height}p`; + plLayersRes[plLayerId] = plResolution; + let plBandwidth = Math.round(s.attributes.BANDWIDTH/1024); + if(plLayerId<10){ + plLayerId = plLayerId.toString().padStart(2,' '); + } + let qualityStrAdd = `${plLayerId}: ${plResolution} (${plBandwidth}KiB/s)`; + let qualityStrRegx = new RegExp(qualityStrAdd.replace(/(:|\(|\)|\/)/g,'\\$1'),'m'); + let qualityStrMatch = !plLayersStr.join('\r\n').match(qualityStrRegx); + if(qualityStrMatch){ + plLayersStr.push(qualityStrAdd); + } + } + else { + console.log(s.uri); + } + } + + for(let s of mainServersList){ + if(plServerList.includes(s)){ + plServerList.splice(plServerList.indexOf(s), 1); + plServerList.unshift(s); + break; + } + } + + if(typeof argv.q == 'object' && argv.q.length > 1){ + argv.q = argv.q[argv.q.length-1]; + } + + argv.q = argv.q < 1 || argv.q > plMaxLayer ? plMaxLayer : argv.q; + + let plSelectedServer = plServerList[argv.x-1]; + let plSelectedList = plStreams[plSelectedServer]; + let videoUrl = argv.x < plServerList.length+1 && plSelectedList[argv.q] ? plSelectedList[argv.q] : ''; + + plLayersStr.sort(); + console.log(`[INFO] Servers available:\n\t${plServerList.join('\n\t')}`); + console.log(`[INFO] Available qualities:\n\t${plLayersStr.join('\n\t')}`); + + if(videoUrl != ''){ + console.log(`[INFO] Selected layer: ${argv.q} (${plLayersRes[argv.q]}) @ ${plSelectedServer}`); + console.log('[INFO] Stream URL:',videoUrl); + fnSuffix = argv.suffix.replace('SIZEp',plLayersRes[argv.q]); + fnOutput = shlp.cleanupFilename(`[${argv.a}] ${fnTitle} - ${fnEpNum} [${fnSuffix}]`); + console.log(`[INFO] Output filename: ${fnOutput}.ts`); + } + else if(argv.x > plServerList.length){ + console.log('[ERROR] Server not selected!\n'); + return; + } + else{ + console.log('[ERROR] Layer not selected!\n'); + return; + } + + let dlFailed = false; + let dlFailedA = false; + + + video: if (!argv.novids) { + // download video + let reqVideo = await getData({ + url: videoUrl, + useProxy: (argv.ssp ? false : true), + debug: argv.debug, + }); + if (!reqVideo.ok) { break video; } + + let chunkList = m3u8(reqVideo.res.body); + + let tsFile = path.join(cfg.dir.content, fnOutput); + dlFailed = !await downloadFile(tsFile, chunkList); + } + else{ + console.log('[INFO] Skip video downloading...\n'); + } + + if (!argv.noaudio && plAud.uri) { + // download audio + let reqAudio = await getData({ + url: plAud.uri, + useProxy: (argv.ssp ? false : true), + debug: argv.debug, + }); + if (!reqAudio.ok) { return; } + + let chunkListA = m3u8(reqAudio.res.body); + + let tsFileA = path.join(cfg.dir.content, fnOutput + `.${plAud.language}`); + + dlFailedA = !await downloadFile(tsFileA, chunkListA); + } + + // add subs + let subsUrl = stDlPath ? stDlPath.path : false; + let subsExt = !argv.mp4 || argv.mp4 && !argv.mks && argv.ass ? '.ass' : '.srt'; + let addSubs = argv.mks && subsUrl ? true : false; + let subFile; + let subTrashFile; + + // download subtitles + if(subsUrl){ + console.log('[INFO] Downloading subtitles...'); + console.log(subsUrl); + let subsSrc = await getData({ + url: subsUrl, + useProxy: true, + debug: argv.debug, + }); + if(subsSrc.ok){ + let assData = vttConvert(subsSrc.res.body, (subsExt == '.srt' ? true : false), stDlPath.langName ); + subFile = path.join(cfg.dir.content, fnOutput) + stDlPath.ext + subsExt; + subTrashFile = path.join(cfg.dir.trash, fnOutput) + stDlPath.ext + subsExt; + fs.writeFileSync(subFile, assData); + console.log('[INFO] Subtitles downloaded!'); + } + else{ + console.log('[ERROR] Failed to download subtitles!'); + addSubs = false; + } + } + + if(dlFailed || dlFailedA){ + console.log('\n[INFO] TS file not fully downloaded, skip muxing video...\n'); + return; + } + + if(argv.skipmux){ + return; + } + + let muxTrg = path.join(cfg.dir.content, fnOutput); + let muxTrgA = ''; + let tshTrg = path.join(cfg.dir.trash, fnOutput); + let tshTrgA = ''; + + if(!fs.existsSync(`${muxTrg}.ts`) || !fs.statSync(`${muxTrg}.ts`).isFile()){ + console.log('\n[INFO] TS file not found, skip muxing video...\n'); + return; + } + + if(plAud.uri){ + muxTrgA = path.join(cfg.dir.content, fnOutput + `.${plAud.language}`); + tshTrgA = path.join(cfg.dir.trash, fnOutput + `.${plAud.language}`); + if(!fs.existsSync(`${muxTrgA}.ts`) || !fs.statSync(`${muxTrgA}.ts`).isFile()){ + console.log('\n[INFO] TS file not found, skip muxing video...\n'); + return; + } + } + + let langCode; + for (let lang in iso639.iso_639_2) { + let langObj = iso639.iso_639_2[lang]; + if (langObj.hasOwnProperty('639-1') && langObj['639-1'] === plAud['language']) { + langCode = langObj['639-2']; + } + } + if (!langCode) + langCode = argv.sub ? 'jpn' : 'eng'; + + // usage + let usableMKVmerge = true; + let usableFFmpeg = true; + + // check exec path + let mkvmergebinfile = await lookpath(path.join(cfg.bin.mkvmerge)); + let ffmpegbinfile = await lookpath(path.join(cfg.bin.ffmpeg)); + + // check exec + if( !argv.mp4 && !mkvmergebinfile ){ + console.log('[WARN] MKVMerge not found, skip using this...'); + usableMKVmerge = false; + } + if( !usableMKVmerge && !ffmpegbinfile || argv.mp4 && !ffmpegbinfile ){ + console.log('[WARN] FFmpeg not found, skip using this...'); + usableFFmpeg = false; + } + if ( argv.novids ){ + console.log('[INFO] Video not downloaded. Skip muxing video.'); + } + + // ftag + argv.ftag = argv.ftag ? argv.ftag : argv.a; + argv.ftag = shlp.cleanupFilename(argv.ftag); + // select muxer + if(!argv.mp4 && usableMKVmerge){ + // mux to mkv + let mkvmux = []; + mkvmux.push('-o',`${muxTrg}.mkv`); + mkvmux.push('--no-date','--disable-track-statistics-tags','--engage','no_variable_data'); + mkvmux.push('--track-name',`0:[${argv.ftag}]`); + + if(plAud.uri){ + mkvmux.push('--video-tracks','0','--no-audio'); + mkvmux.push('--no-subtitles','--no-attachments'); + mkvmux.push(`${muxTrg}.ts`); + mkvmux.push('--language',`0:${langCode}`); + mkvmux.push('--no-video','--audio-tracks','0'); + mkvmux.push('--no-subtitles','--no-attachments'); + mkvmux.push(`${muxTrgA}.ts`); + } + else{ + mkvmux.push('--language',`1:${langCode}`); + mkvmux.push('--video-tracks','0','--audio-tracks','1'); + mkvmux.push('--no-subtitles','--no-attachments'); + mkvmux.push(`${muxTrg}.ts`); + } + if(addSubs){ + mkvmux.push('--language','0:eng'); + mkvmux.push(`${subFile ? subFile : muxTrg + subsExt}`); + } + fs.writeFileSync(`${muxTrg}.json`,JSON.stringify(mkvmux,null,' ')); + shlp.exec('mkvmerge',`"${mkvmergebinfile}"`,`@"${muxTrg}.json"`); + fs.unlinkSync(`${muxTrg}.json`); + } + else if(usableFFmpeg){ + let ffext = !argv.mp4 ? 'mkv' : 'mp4'; + let ffmux = `-i "${muxTrg}.ts" `; + ffmux += plAud.uri ? `-i "${muxTrgA}.ts" ` : ''; + ffmux += addSubs ? `-i "${subFile ? subFile : muxTrg + subsExt}" ` : ''; + ffmux += plAud.uri ? '-map 1:a ' : ''; + ffmux += '-map 0 -c:v copy -c:a copy '; + ffmux += addSubs ? `-map ${plAud.uri ? 2 : 1} ` : ''; + ffmux += addSubs && !argv.mp4 ? '-c:s ass ' : ''; + ffmux += addSubs && argv.mp4 ? '-c:s mov_text ' : ''; + ffmux += '-metadata encoding_tool="no_variable_data" '; + ffmux += `-metadata:s:v:0 title="[${argv.a}]" -metadata:s:a:${plAud.uri?1:0} language=${langCode} `; + ffmux += addSubs ? '-metadata:s:s:0 language=eng ' : ''; + ffmux += `"${muxTrg}.${ffext}"`; + // mux to mkv + shlp.exec('ffmpeg',`"${ffmpegbinfile}"`,ffmux); + } + else{ + console.log('\n[INFO] Done!\n'); + return; + } + if(argv.notrashfolder && argv.nocleanup){ + // don't move or delete temp files + } + else if(argv.nocleanup){ + fs.renameSync(muxTrg+'.ts', tshTrg + '.ts'); + if (plAud.uri) + fs.renameSync(muxTrgA+'.ts', tshTrgA + '.ts'); + if(subsUrl && addSubs){ + fs.renameSync(subFile ? subFile : muxTrg+subsExt, subTrashFile ? subTrashFile : tshTrg + subsExt); + } + } + else{ + fs.unlinkSync(muxTrg+'.ts'); + if (plAud.uri) + fs.unlinkSync(muxTrgA+'.ts'); + if(subsUrl && addSubs){ + fs.unlinkSync(subFile ? subFile : muxTrg + subsExt); + } + } + console.log('\n[INFO] Done!\n'); +} + +async function downloadFile(filename, chunkList) { + let offset = 0; + fileCheck: if (fs.existsSync(filename + '.ts')) { + if (fs.existsSync(filename + '.ts.resume')) { + const resume = JSON.parse(fs.readFileSync(`${filename}.ts.resume`)); + if (resume.total === chunkList.segments.length) { + offset = resume.downloaded; + break fileCheck; + } + } + let rwts = await shlp.question(`[Q] File «${filename + '.ts'}» already exists! Rewrite? (y/N)`); + rwts = rwts || 'N'; + if (!['Y', 'y'].includes(rwts[0])) { + return false; + } + fs.unlinkSync(filename + '.ts'); + } + + let start = Date.now(); + + console.log(`[INFO] Started ${filename}.ts`); + for (let i = offset; i < chunkList.segments.length; i+=argv.partsize) { + let cur = []; + for (let a = 0; a < Math.min(argv.partsize, chunkList.segments.length - i); a++) { + cur.push(downloadPart(chunkList.segments[i + a], i + a, chunkList.segments.length) + .catch(e => e)); + } + + let p = await Promise.all(cur); + if (p.some(el => el instanceof Error)) { + console.log(`[ERROR] An error occured while downloading ${filename}.ts`); + return false; + } + + fs.writeFileSync(`${filename}.ts.resume`, JSON.stringify({ total: chunkList.segments.length, downloaded: i + argv.partsize }, null, 4)); + + for (let a = 0; a < p.length; a++) { + fs.writeFileSync(filename + '.ts', p[a].content, { flag: 'a' }); + } + + logDownloadInfo(start, i + Math.min(argv.partsize, chunkList.segments.length - i), + chunkList.segments.length, i + Math.min(argv.partsize, chunkList.segments.length - i), + chunkList.segments.length); + } + + if (fs.existsSync(`${filename}.ts.resume`)) + fs.unlinkSync(`${filename}.ts.resume`); + + console.log(`[INFO] Finished ${filename}.ts`); + return true; +} + +async function downloadPart(chunk, index) { + + let key = await generateCrypto(chunk, index); + + let headers = { + 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:70.0) Gecko/20100101 Firefox/70.0' + }; + + if (chunk.byterange) + headers.Range = `bytes=${chunk.byterange.offset}-${chunk.byterange.offset+chunk.byterange.length-1}`; + + let res = (await got({ + url: chunk.uri, + headers, + responseType: 'buffer' + }).catch(error => console.log(`[ERROR] ${error.name}: ${error.code||error.message}`))); + + if (!res.body) { return new Error('Invalid State'); } + try { + let dec = key.update(res.body); + dec = Buffer.concat([dec, key.final()]); + return { content: dec, index: index}; + } catch (e) { return e; } +} + +let keys = {}; +async function generateCrypto(chunk, index) { + let key = keys[chunk.key.uri]; + if (!key) { + let reqKey = await getData({ + url: chunk.key.uri, + responseType: 'buffer' + }); + + if (!reqKey.ok) { console.log('[ERROR] Can\'t get key'); return; } + key = reqKey.res.body; + keys[chunk.key.uri] = key; + } + let iv = Buffer.alloc(16); + let ivs = chunk.key.iv ? chunk.key.iv : [0, 0, 0, index]; + for (let i in ivs) { + iv.writeUInt32BE(ivs[i], i * 4); + } + key = crypto.createDecipheriv('aes-128-cbc', key, iv); + return key; +} + +/* Snacked from hls-download */ +function logDownloadInfo (dateStart, partsDL, partsTotal, partsDLRes, partsTotalRes) { + const dateElapsed = Date.now() - dateStart; + const percentFxd = (partsDL / partsTotal * 100).toFixed(); + const percent = percentFxd < 100 ? percentFxd : (partsTotal == partsDL ? 100 : 99); + const revParts = parseInt(dateElapsed * (partsTotal / partsDL - 1)); + const time = shlp.formatTime((revParts / 1000).toFixed()); + console.log(`[INFO] ${partsDLRes} of ${partsTotalRes} parts downloaded [${percent}%] (${time})`); +} + +// make proxy URL +function buildProxy(proxyBaseUrl, proxyAuth){ + if(!proxyBaseUrl.match(/^(https?|socks4|socks5):/)){ + proxyBaseUrl = 'http://' + proxyBaseUrl; + } + + let proxyCfg = new URL(proxyBaseUrl); + let proxyStr = `${proxyCfg.protocol}//`; + + if(typeof proxyCfg.hostname != 'string' || proxyCfg.hostname == ''){ + throw new Error('[ERROR] Hostname and port required for proxy!'); + } + + if(proxyAuth && typeof proxyAuth == 'string' && proxyAuth.match(':')){ + proxyCfg.username = proxyAuth.split(':')[0]; + proxyCfg.password = proxyAuth.split(':')[1]; + proxyStr += `${proxyCfg.username}:${proxyCfg.password}@`; + } + + proxyStr += proxyCfg.hostname; + + if(!proxyCfg.port && proxyCfg.protocol == 'http:'){ + proxyStr += ':80'; + } + else if(!proxyCfg.port && proxyCfg.protocol == 'https:'){ + proxyStr += ':443'; + } + + return proxyStr; +} diff --git a/gui.ts b/gui.ts deleted file mode 100644 index 5bb963e..0000000 --- a/gui.ts +++ /dev/null @@ -1,3 +0,0 @@ -process.env.isGUI = 'true'; -import './modules/log'; -import './gui/server/index'; \ No newline at end of file diff --git a/gui/react/.babelrc b/gui/react/.babelrc deleted file mode 100644 index 4c2774a..0000000 --- a/gui/react/.babelrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "presets": ["@babel/preset-env","@babel/preset-react", "@babel/preset-typescript"] -} \ No newline at end of file diff --git a/gui/react/.env b/gui/react/.env deleted file mode 100644 index f373e87..0000000 --- a/gui/react/.env +++ /dev/null @@ -1,2 +0,0 @@ -PORT=3002 -CI=false \ No newline at end of file diff --git a/gui/react/package.json b/gui/react/package.json deleted file mode 100644 index 77c44b7..0000000 --- a/gui/react/package.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "name": "anidl-gui", - "version": "1.0.0", - "private": true, - "dependencies": { - "@emotion/react": "^11.11.4", - "@emotion/styled": "^11.11.5", - "@mui/icons-material": "^5.15.20", - "@mui/lab": "^5.0.0-alpha.170", - "@mui/material": "^5.15.20", - "concurrently": "^8.2.2", - "notistack": "^2.0.8", - "react": "^18.3.1", - "react-dom": "^18.3.1", - "typescript": "^5.5.2", - "uuid": "^9.0.1", - "ws": "^8.17.1" - }, - "devDependencies": { - "@babel/cli": "^7.24.7", - "@babel/core": "^7.24.7", - "@babel/preset-env": "^7.24.7", - "@babel/preset-react": "^7.24.7", - "@babel/preset-typescript": "^7.24.7", - "@types/node": "^20.14.6", - "@types/react": "^18.3.3", - "@types/react-dom": "^18.3.0", - "@types/uuid": "^9.0.8", - "babel-loader": "^9.1.3", - "css-loader": "^7.1.2", - "html-webpack-plugin": "^5.6.0", - "style-loader": "^3.3.4", - "ts-node": "^10.9.2", - "webpack": "^5.92.1", - "webpack-cli": "^5.1.4", - "webpack-dev-server": "^5.0.4" - }, - "proxy": "http://localhost:3000", - "scripts": { - "build": "npx tsc && npx webpack", - "start": "npx concurrently -k npm:frontend npm:backend", - "frontend": "npx webpack-dev-server", - "backend": "npx ts-node -T ../../gui.ts" - }, - "browserslist": { - "production": [ - ">0.2%", - "not dead", - "not op_mini all" - ], - "development": [ - "last 1 chrome version", - "last 1 firefox version", - "last 1 safari version" - ] - } -} diff --git a/gui/react/pnpm-lock.yaml b/gui/react/pnpm-lock.yaml deleted file mode 100644 index 4099120..0000000 --- a/gui/react/pnpm-lock.yaml +++ /dev/null @@ -1,5482 +0,0 @@ -lockfileVersion: '6.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -dependencies: - '@emotion/react': - specifier: ^11.11.4 - version: 11.11.4(@types/react@18.3.3)(react@18.3.1) - '@emotion/styled': - specifier: ^11.11.5 - version: 11.11.5(@emotion/react@11.11.4)(@types/react@18.3.3)(react@18.3.1) - '@mui/icons-material': - specifier: ^5.15.20 - version: 5.15.20(@mui/material@5.15.20)(@types/react@18.3.3)(react@18.3.1) - '@mui/lab': - specifier: ^5.0.0-alpha.170 - version: 5.0.0-alpha.170(@emotion/react@11.11.4)(@emotion/styled@11.11.5)(@mui/material@5.15.20)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) - '@mui/material': - specifier: ^5.15.20 - version: 5.15.20(@emotion/react@11.11.4)(@emotion/styled@11.11.5)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) - concurrently: - specifier: ^8.2.2 - version: 8.2.2 - notistack: - specifier: ^2.0.8 - version: 2.0.8(@emotion/react@11.11.4)(@emotion/styled@11.11.5)(@mui/material@5.15.20)(react-dom@18.3.1)(react@18.3.1) - react: - specifier: ^18.3.1 - version: 18.3.1 - react-dom: - specifier: ^18.3.1 - version: 18.3.1(react@18.3.1) - typescript: - specifier: ^5.5.2 - version: 5.5.2 - uuid: - specifier: ^9.0.1 - version: 9.0.1 - ws: - specifier: ^8.17.1 - version: 8.17.1 - -devDependencies: - '@babel/cli': - specifier: ^7.24.7 - version: 7.24.7(@babel/core@7.24.7) - '@babel/core': - specifier: ^7.24.7 - version: 7.24.7 - '@babel/preset-env': - specifier: ^7.24.7 - version: 7.24.7(@babel/core@7.24.7) - '@babel/preset-react': - specifier: ^7.24.7 - version: 7.24.7(@babel/core@7.24.7) - '@babel/preset-typescript': - specifier: ^7.24.7 - version: 7.24.7(@babel/core@7.24.7) - '@types/node': - specifier: ^20.14.6 - version: 20.14.6 - '@types/react': - specifier: ^18.3.3 - version: 18.3.3 - '@types/react-dom': - specifier: ^18.3.0 - version: 18.3.0 - '@types/uuid': - specifier: ^9.0.8 - version: 9.0.8 - babel-loader: - specifier: ^9.1.3 - version: 9.1.3(@babel/core@7.24.7)(webpack@5.92.1) - css-loader: - specifier: ^7.1.2 - version: 7.1.2(webpack@5.92.1) - html-webpack-plugin: - specifier: ^5.6.0 - version: 5.6.0(webpack@5.92.1) - style-loader: - specifier: ^3.3.4 - version: 3.3.4(webpack@5.92.1) - ts-node: - specifier: ^10.9.2 - version: 10.9.2(@types/node@20.14.6)(typescript@5.5.2) - webpack: - specifier: ^5.92.1 - version: 5.92.1(webpack-cli@5.1.4) - webpack-cli: - specifier: ^5.1.4 - version: 5.1.4(webpack-dev-server@5.0.4)(webpack@5.92.1) - webpack-dev-server: - specifier: ^5.0.4 - version: 5.0.4(webpack-cli@5.1.4)(webpack@5.92.1) - -packages: - - /@ampproject/remapping@2.3.0: - resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} - engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/gen-mapping': 0.3.5 - '@jridgewell/trace-mapping': 0.3.25 - dev: true - - /@babel/cli@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-8dfPprJgV4O14WTx+AQyEA+opgUKPrsIXX/MdL50J1n06EQJ6m1T+CdsJe0qEC0B/Xl85i+Un5KVAxd/PACX9A==} - engines: {node: '>=6.9.0'} - hasBin: true - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@jridgewell/trace-mapping': 0.3.25 - commander: 6.2.1 - convert-source-map: 2.0.0 - fs-readdir-recursive: 1.1.0 - glob: 7.2.3 - make-dir: 2.1.0 - slash: 2.0.0 - optionalDependencies: - '@nicolo-ribaudo/chokidar-2': 2.1.8-no-fsevents.3 - chokidar: 3.6.0 - dev: true - - /@babel/code-frame@7.18.6: - resolution: {integrity: sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/highlight': 7.18.6 - dev: false - - /@babel/code-frame@7.24.7: - resolution: {integrity: sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/highlight': 7.24.7 - picocolors: 1.0.0 - dev: true - - /@babel/compat-data@7.24.7: - resolution: {integrity: sha512-qJzAIcv03PyaWqxRgO4mSU3lihncDT296vnyuE2O8uA4w3UHWI4S3hgeZd1L8W1Bft40w9JxJ2b412iDUFFRhw==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/core@7.24.7: - resolution: {integrity: sha512-nykK+LEK86ahTkX/3TgauT0ikKoNCfKHEaZYTUVupJdTLzGNvrblu4u6fa7DhZONAltdf8e662t/abY8idrd/g==} - engines: {node: '>=6.9.0'} - dependencies: - '@ampproject/remapping': 2.3.0 - '@babel/code-frame': 7.24.7 - '@babel/generator': 7.24.7 - '@babel/helper-compilation-targets': 7.24.7 - '@babel/helper-module-transforms': 7.24.7(@babel/core@7.24.7) - '@babel/helpers': 7.24.7 - '@babel/parser': 7.24.7 - '@babel/template': 7.24.7 - '@babel/traverse': 7.24.7 - '@babel/types': 7.24.7 - convert-source-map: 2.0.0 - debug: 4.3.4 - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/generator@7.24.7: - resolution: {integrity: sha512-oipXieGC3i45Y1A41t4tAqpnEZWgB/lC6Ehh6+rOviR5XWpTtMmLN+fGjz9vOiNRt0p6RtO6DtD0pdU3vpqdSA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.7 - '@jridgewell/gen-mapping': 0.3.5 - '@jridgewell/trace-mapping': 0.3.25 - jsesc: 2.5.2 - dev: true - - /@babel/helper-annotate-as-pure@7.22.5: - resolution: {integrity: sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.0 - dev: true - - /@babel/helper-annotate-as-pure@7.24.7: - resolution: {integrity: sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.7 - dev: true - - /@babel/helper-builder-binary-assignment-operator-visitor@7.24.7: - resolution: {integrity: sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/traverse': 7.24.7 - '@babel/types': 7.24.7 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/helper-compilation-targets@7.24.7: - resolution: {integrity: sha512-ctSdRHBi20qWOfy27RUb4Fhp07KSJ3sXcuSvTrXrc4aG8NSYDo1ici3Vhg9bg69y5bj0Mr1lh0aeEgTvc12rMg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/compat-data': 7.24.7 - '@babel/helper-validator-option': 7.24.7 - browserslist: 4.23.0 - lru-cache: 5.1.1 - semver: 6.3.1 - dev: true - - /@babel/helper-create-class-features-plugin@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-kTkaDl7c9vO80zeX1rJxnuRpEsD5tA81yh11X1gQo+PhSti3JS+7qeZo9U4RHobKRiFPKaGK3svUAeb8D0Q7eg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-annotate-as-pure': 7.24.7 - '@babel/helper-environment-visitor': 7.24.7 - '@babel/helper-function-name': 7.24.7 - '@babel/helper-member-expression-to-functions': 7.24.7 - '@babel/helper-optimise-call-expression': 7.24.7 - '@babel/helper-replace-supers': 7.24.7(@babel/core@7.24.7) - '@babel/helper-skip-transparent-expression-wrappers': 7.24.7 - '@babel/helper-split-export-declaration': 7.24.7 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/helper-create-regexp-features-plugin@7.22.15(@babel/core@7.24.7): - resolution: {integrity: sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-annotate-as-pure': 7.22.5 - regexpu-core: 5.3.2 - semver: 6.3.1 - dev: true - - /@babel/helper-create-regexp-features-plugin@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-03TCmXy2FtXJEZfbXDTSqq1fRJArk7lX9DOFC/47VthYcxyIOx+eXQmdo6DOQvrbpIix+KfXwvuXdFDZHxt+rA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-annotate-as-pure': 7.24.7 - regexpu-core: 5.3.2 - semver: 6.3.1 - dev: true - - /@babel/helper-define-polyfill-provider@0.6.1(@babel/core@7.24.7): - resolution: {integrity: sha512-o7SDgTJuvx5vLKD6SFvkydkSMBvahDKGiNJzG22IZYXhiqoe9efY7zocICBgzHV4IRg5wdgl2nEL/tulKIEIbA==} - peerDependencies: - '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-compilation-targets': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - debug: 4.3.4 - lodash.debounce: 4.0.8 - resolve: 1.22.1 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/helper-environment-visitor@7.24.7: - resolution: {integrity: sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.7 - dev: true - - /@babel/helper-function-name@7.24.7: - resolution: {integrity: sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.24.7 - '@babel/types': 7.24.7 - dev: true - - /@babel/helper-hoist-variables@7.24.7: - resolution: {integrity: sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.7 - dev: true - - /@babel/helper-member-expression-to-functions@7.24.7: - resolution: {integrity: sha512-LGeMaf5JN4hAT471eJdBs/GK1DoYIJ5GCtZN/EsL6KUiiDZOvO/eKE11AMZJa2zP4zk4qe9V2O/hxAmkRc8p6w==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/traverse': 7.24.7 - '@babel/types': 7.24.7 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/helper-module-imports@7.18.6: - resolution: {integrity: sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.20.7 - dev: false - - /@babel/helper-module-imports@7.24.7: - resolution: {integrity: sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/traverse': 7.24.7 - '@babel/types': 7.24.7 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/helper-module-transforms@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-1fuJEwIrp+97rM4RWdO+qrRsZlAeL1lQJoPqtCYWv0NL115XM93hIH4CSRln2w52SqvmY5hqdtauB6QFCDiZNQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-environment-visitor': 7.24.7 - '@babel/helper-module-imports': 7.24.7 - '@babel/helper-simple-access': 7.24.7 - '@babel/helper-split-export-declaration': 7.24.7 - '@babel/helper-validator-identifier': 7.24.7 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/helper-optimise-call-expression@7.24.7: - resolution: {integrity: sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.7 - dev: true - - /@babel/helper-plugin-utils@7.24.7: - resolution: {integrity: sha512-Rq76wjt7yz9AAc1KnlRKNAi/dMSVWgDRx43FHoJEbcYU6xOWaE2dVPwcdTukJrjxS65GITyfbvEYHvkirZ6uEg==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-remap-async-to-generator@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-9pKLcTlZ92hNZMQfGCHImUpDOlAgkkpqalWEeftW5FBya75k8Li2ilerxkM/uBEj01iBZXcCIB/bwvDYgWyibA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-annotate-as-pure': 7.24.7 - '@babel/helper-environment-visitor': 7.24.7 - '@babel/helper-wrap-function': 7.24.7 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/helper-replace-supers@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-qTAxxBM81VEyoAY0TtLrx1oAEJc09ZK67Q9ljQToqCnA+55eNwCORaxlKyu+rNfX86o8OXRUSNUnrtsAZXM9sg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-environment-visitor': 7.24.7 - '@babel/helper-member-expression-to-functions': 7.24.7 - '@babel/helper-optimise-call-expression': 7.24.7 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/helper-simple-access@7.24.7: - resolution: {integrity: sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/traverse': 7.24.7 - '@babel/types': 7.24.7 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/helper-skip-transparent-expression-wrappers@7.24.7: - resolution: {integrity: sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/traverse': 7.24.7 - '@babel/types': 7.24.7 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/helper-split-export-declaration@7.24.7: - resolution: {integrity: sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.7 - dev: true - - /@babel/helper-string-parser@7.19.4: - resolution: {integrity: sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==} - engines: {node: '>=6.9.0'} - dev: false - - /@babel/helper-string-parser@7.24.1: - resolution: {integrity: sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-string-parser@7.24.7: - resolution: {integrity: sha512-7MbVt6xrwFQbunH2DNQsAP5sTGxfqQtErvBIvIMi6EQnbgUOuVYanvREcmFrOPhoXBrTtjhhP+lW+o5UfK+tDg==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-validator-identifier@7.19.1: - resolution: {integrity: sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==} - engines: {node: '>=6.9.0'} - dev: false - - /@babel/helper-validator-identifier@7.22.20: - resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-validator-identifier@7.24.7: - resolution: {integrity: sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-validator-option@7.24.7: - resolution: {integrity: sha512-yy1/KvjhV/ZCL+SM7hBrvnZJ3ZuT9OuZgIJAGpPEToANvc3iM6iDvBnRjtElWibHU6n8/LPR/EjX9EtIEYO3pw==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-wrap-function@7.24.7: - resolution: {integrity: sha512-N9JIYk3TD+1vq/wn77YnJOqMtfWhNewNE+DJV4puD2X7Ew9J4JvrzrFDfTfyv5EgEXVy9/Wt8QiOErzEmv5Ifw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-function-name': 7.24.7 - '@babel/template': 7.24.7 - '@babel/traverse': 7.24.7 - '@babel/types': 7.24.7 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/helpers@7.24.7: - resolution: {integrity: sha512-NlmJJtvcw72yRJRcnCmGvSi+3jDEg8qFu3z0AFoymmzLx5ERVWyzd9kVXr7Th9/8yIJi2Zc6av4Tqz3wFs8QWg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.24.7 - '@babel/types': 7.24.7 - dev: true - - /@babel/highlight@7.18.6: - resolution: {integrity: sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-validator-identifier': 7.19.1 - chalk: 2.4.2 - js-tokens: 4.0.0 - dev: false - - /@babel/highlight@7.24.7: - resolution: {integrity: sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-validator-identifier': 7.24.7 - chalk: 2.4.2 - js-tokens: 4.0.0 - picocolors: 1.0.0 - dev: true - - /@babel/parser@7.24.7: - resolution: {integrity: sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw==} - engines: {node: '>=6.0.0'} - hasBin: true - dependencies: - '@babel/types': 7.24.7 - dev: true - - /@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-TiT1ss81W80eQsN+722OaeQMY/G4yTb4G9JrqeiDADs3N8lbPMGldWi9x8tyqCW5NLx1Jh2AvkE6r6QvEltMMQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-environment-visitor': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - dev: true - - /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-unaQgZ/iRu/By6tsjMZzpeBZjChYfLYry6HrEXPoz3KmfF0sVBQ1l8zKMQ4xRGLWVsjuvB8nQfjNP/DcfEOCsg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - dev: true - - /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.13.0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - '@babel/helper-skip-transparent-expression-wrappers': 7.24.7 - '@babel/plugin-transform-optional-chaining': 7.24.7(@babel/core@7.24.7) - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-utA4HuR6F4Vvcr+o4DnjL8fCOlgRFGbeeBEGNg3ZTrLFw6VWG5XmUrvcQ0FjIYMU2ST4XcR2Wsp7t9qOAPnxMg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-environment-visitor': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - dev: true - - /@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.24.7): - resolution: {integrity: sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - dev: true - - /@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.24.7): - resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - dev: true - - /@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.24.7): - resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - dev: true - - /@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.24.7): - resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - dev: true - - /@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.24.7): - resolution: {integrity: sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - dev: true - - /@babel/plugin-syntax-export-namespace-from@7.8.3(@babel/core@7.24.7): - resolution: {integrity: sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - dev: true - - /@babel/plugin-syntax-import-assertions@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-Ec3NRUMoi8gskrkBe3fNmEQfxDvY8bgfQpz6jlk/41kX9eUjvpyqWU7PBP/pLAvMaSQjbMNKJmvX57jP+M6bPg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - dev: true - - /@babel/plugin-syntax-import-attributes@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-hbX+lKKeUMGihnK8nvKqmXBInriT3GVjzXKFriV3YC6APGxMbP8RZNFwy91+hocLXq90Mta+HshoB31802bb8A==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - dev: true - - /@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.24.7): - resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - dev: true - - /@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.24.7): - resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - dev: true - - /@babel/plugin-syntax-jsx@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - dev: true - - /@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.24.7): - resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - dev: true - - /@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.24.7): - resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - dev: true - - /@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.24.7): - resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - dev: true - - /@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.24.7): - resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - dev: true - - /@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.24.7): - resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - dev: true - - /@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.24.7): - resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - dev: true - - /@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.24.7): - resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - dev: true - - /@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.24.7): - resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - dev: true - - /@babel/plugin-syntax-typescript@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-c/+fVeJBB0FeKsFvwytYiUD+LBvhHjGSI0g446PRGdSVGZLRNArBUno2PETbAly3tpiNAQR5XaZ+JslxkotsbA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - dev: true - - /@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.24.7): - resolution: {integrity: sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.24.7) - '@babel/helper-plugin-utils': 7.24.7 - dev: true - - /@babel/plugin-transform-arrow-functions@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - dev: true - - /@babel/plugin-transform-async-generator-functions@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-o+iF77e3u7ZS4AoAuJvapz9Fm001PuD2V3Lp6OSE4FYQke+cSewYtnek+THqGRWyQloRCyvWL1OkyfNEl9vr/g==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-environment-visitor': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - '@babel/helper-remap-async-to-generator': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.24.7) - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/plugin-transform-async-to-generator@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-SQY01PcJfmQ+4Ash7NE+rpbLFbmqA2GPIgqzxfFTL4t1FKRq4zTms/7htKpoCUI9OcFYgzqfmCdH53s6/jn5fA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-module-imports': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - '@babel/helper-remap-async-to-generator': 7.24.7(@babel/core@7.24.7) - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/plugin-transform-block-scoped-functions@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - dev: true - - /@babel/plugin-transform-block-scoping@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-Nd5CvgMbWc+oWzBsuaMcbwjJWAcp5qzrbg69SZdHSP7AMY0AbWFqFO0WTFCA1jxhMCwodRwvRec8k0QUbZk7RQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - dev: true - - /@babel/plugin-transform-class-properties@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-vKbfawVYayKcSeSR5YYzzyXvsDFWU2mD8U5TFeXtbCPLFUqe7GyCgvO6XDHzje862ODrOwy6WCPmKeWHbCFJ4w==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-create-class-features-plugin': 7.24.7(@babel/core@7.24.7) - '@babel/helper-plugin-utils': 7.24.7 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/plugin-transform-class-static-block@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-HMXK3WbBPpZQufbMG4B46A90PkuuhN9vBCb5T8+VAHqvAqvcLi+2cKoukcpmUYkszLhScU3l1iudhrks3DggRQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.12.0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-create-class-features-plugin': 7.24.7(@babel/core@7.24.7) - '@babel/helper-plugin-utils': 7.24.7 - '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.24.7) - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/plugin-transform-classes@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-CFbbBigp8ln4FU6Bpy6g7sE8B/WmCmzvivzUC6xDAdWVsjYTXijpuuGJmYkAaoWAzcItGKT3IOAbxRItZ5HTjw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-annotate-as-pure': 7.24.7 - '@babel/helper-compilation-targets': 7.24.7 - '@babel/helper-environment-visitor': 7.24.7 - '@babel/helper-function-name': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - '@babel/helper-replace-supers': 7.24.7(@babel/core@7.24.7) - '@babel/helper-split-export-declaration': 7.24.7 - globals: 11.12.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/plugin-transform-computed-properties@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-25cS7v+707Gu6Ds2oY6tCkUwsJ9YIDbggd9+cu9jzzDgiNq7hR/8dkzxWfKWnTic26vsI3EsCXNd4iEB6e8esQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - '@babel/template': 7.24.7 - dev: true - - /@babel/plugin-transform-destructuring@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-19eJO/8kdCQ9zISOf+SEUJM/bAUIsvY3YDnXZTupUCQ8LgrWnsG/gFB9dvXqdXnRXMAM8fvt7b0CBKQHNGy1mw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - dev: true - - /@babel/plugin-transform-dotall-regex@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-create-regexp-features-plugin': 7.24.7(@babel/core@7.24.7) - '@babel/helper-plugin-utils': 7.24.7 - dev: true - - /@babel/plugin-transform-duplicate-keys@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - dev: true - - /@babel/plugin-transform-dynamic-import@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-sc3X26PhZQDb3JhORmakcbvkeInvxz+A8oda99lj7J60QRuPZvNAk9wQlTBS1ZynelDrDmTU4pw1tyc5d5ZMUg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.24.7) - dev: true - - /@babel/plugin-transform-exponentiation-operator@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-Rqe/vSc9OYgDajNIK35u7ot+KeCoetqQYFXM4Epf7M7ez3lWlOjrDjrwMei6caCVhfdw+mIKD4cgdGNy5JQotQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-builder-binary-assignment-operator-visitor': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/plugin-transform-export-namespace-from@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-v0K9uNYsPL3oXZ/7F9NNIbAj2jv1whUEtyA6aujhekLs56R++JDQuzRcP2/z4WX5Vg/c5lE9uWZA0/iUoFhLTA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.24.7) - dev: true - - /@babel/plugin-transform-for-of@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - '@babel/helper-skip-transparent-expression-wrappers': 7.24.7 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/plugin-transform-function-name@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-U9FcnA821YoILngSmYkW6FjyQe2TyZD5pHt4EVIhmcTkrJw/3KqcrRSxuOo5tFZJi7TE19iDyI1u+weTI7bn2w==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-compilation-targets': 7.24.7 - '@babel/helper-function-name': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - dev: true - - /@babel/plugin-transform-json-strings@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-2yFnBGDvRuxAaE/f0vfBKvtnvvqU8tGpMHqMNpTN2oWMKIR3NqFkjaAgGwawhqK/pIN2T3XdjGPdaG0vDhOBGw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.24.7) - dev: true - - /@babel/plugin-transform-literals@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-vcwCbb4HDH+hWi8Pqenwnjy+UiklO4Kt1vfspcQYFhJdpthSnW8XvWGyDZWKNVrVbVViI/S7K9PDJZiUmP2fYQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - dev: true - - /@babel/plugin-transform-logical-assignment-operators@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.24.7) - dev: true - - /@babel/plugin-transform-member-expression-literals@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - dev: true - - /@babel/plugin-transform-modules-amd@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-module-transforms': 7.24.7(@babel/core@7.24.7) - '@babel/helper-plugin-utils': 7.24.7 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/plugin-transform-modules-commonjs@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-iFI8GDxtevHJ/Z22J5xQpVqFLlMNstcLXh994xifFwxxGslr2ZXXLWgtBeLctOD63UFDArdvN6Tg8RFw+aEmjQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-module-transforms': 7.24.7(@babel/core@7.24.7) - '@babel/helper-plugin-utils': 7.24.7 - '@babel/helper-simple-access': 7.24.7 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/plugin-transform-modules-systemjs@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-GYQE0tW7YoaN13qFh3O1NCY4MPkUiAH3fiF7UcV/I3ajmDKEdG3l+UOcbAm4zUE3gnvUU+Eni7XrVKo9eO9auw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-hoist-variables': 7.24.7 - '@babel/helper-module-transforms': 7.24.7(@babel/core@7.24.7) - '@babel/helper-plugin-utils': 7.24.7 - '@babel/helper-validator-identifier': 7.24.7 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/plugin-transform-modules-umd@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-module-transforms': 7.24.7(@babel/core@7.24.7) - '@babel/helper-plugin-utils': 7.24.7 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/plugin-transform-named-capturing-groups-regex@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-/jr7h/EWeJtk1U/uz2jlsCioHkZk1JJZVcc8oQsJ1dUlaJD83f4/6Zeh2aHt9BIFokHIsSeDfhUmju0+1GPd6g==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-create-regexp-features-plugin': 7.24.7(@babel/core@7.24.7) - '@babel/helper-plugin-utils': 7.24.7 - dev: true - - /@babel/plugin-transform-new-target@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - dev: true - - /@babel/plugin-transform-nullish-coalescing-operator@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-Ts7xQVk1OEocqzm8rHMXHlxvsfZ0cEF2yomUqpKENHWMF4zKk175Y4q8H5knJes6PgYad50uuRmt3UJuhBw8pQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.24.7) - dev: true - - /@babel/plugin-transform-numeric-separator@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-e6q1TiVUzvH9KRvicuxdBTUj4AdKSRwzIyFFnfnezpCfP2/7Qmbb8qbU2j7GODbl4JMkblitCQjKYUaX/qkkwA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.24.7) - dev: true - - /@babel/plugin-transform-object-rest-spread@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-4QrHAr0aXQCEFni2q4DqKLD31n2DL+RxcwnNjDFkSG0eNQ/xCavnRkfCUjsyqGC2OviNJvZOF/mQqZBw7i2C5Q==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-compilation-targets': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.24.7) - '@babel/plugin-transform-parameters': 7.24.7(@babel/core@7.24.7) - dev: true - - /@babel/plugin-transform-object-super@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - '@babel/helper-replace-supers': 7.24.7(@babel/core@7.24.7) - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/plugin-transform-optional-catch-binding@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-uLEndKqP5BfBbC/5jTwPxLh9kqPWWgzN/f8w6UwAIirAEqiIVJWWY312X72Eub09g5KF9+Zn7+hT7sDxmhRuKA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.24.7) - dev: true - - /@babel/plugin-transform-optional-chaining@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-tK+0N9yd4j+x/4hxF3F0e0fu/VdcxU18y5SevtyM/PCFlQvXbR0Zmlo2eBrKtVipGNFzpq56o8WsIIKcJFUCRQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - '@babel/helper-skip-transparent-expression-wrappers': 7.24.7 - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.24.7) - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/plugin-transform-parameters@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - dev: true - - /@babel/plugin-transform-private-methods@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-COTCOkG2hn4JKGEKBADkA8WNb35TGkkRbI5iT845dB+NyqgO8Hn+ajPbSnIQznneJTa3d30scb6iz/DhH8GsJQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-create-class-features-plugin': 7.24.7(@babel/core@7.24.7) - '@babel/helper-plugin-utils': 7.24.7 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/plugin-transform-private-property-in-object@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-9z76mxwnwFxMyxZWEgdgECQglF2Q7cFLm0kMf8pGwt+GSJsY0cONKj/UuO4bOH0w/uAel3ekS4ra5CEAyJRmDA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-annotate-as-pure': 7.24.7 - '@babel/helper-create-class-features-plugin': 7.24.7(@babel/core@7.24.7) - '@babel/helper-plugin-utils': 7.24.7 - '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.24.7) - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/plugin-transform-property-literals@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - dev: true - - /@babel/plugin-transform-react-display-name@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-H/Snz9PFxKsS1JLI4dJLtnJgCJRoo0AUm3chP6NYr+9En1JMKloheEiLIhlp5MDVznWo+H3AAC1Mc8lmUEpsgg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - dev: true - - /@babel/plugin-transform-react-jsx-development@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-QG9EnzoGn+Qar7rxuW+ZOsbWOt56FvvI93xInqsZDC5fsekx1AlIO4KIJ5M+D0p0SqSH156EpmZyXq630B8OlQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/plugin-transform-react-jsx': 7.24.7(@babel/core@7.24.7) - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/plugin-transform-react-jsx@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-+Dj06GDZEFRYvclU6k4bme55GKBEWUmByM/eoKuqg4zTNQHiApWRhQph5fxQB2wAEFvRzL1tOEj1RJ19wJrhoA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-annotate-as-pure': 7.24.7 - '@babel/helper-module-imports': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - '@babel/plugin-syntax-jsx': 7.24.7(@babel/core@7.24.7) - '@babel/types': 7.24.7 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/plugin-transform-react-pure-annotations@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-PLgBVk3fzbmEjBJ/u8kFzOqS9tUeDjiaWud/rRym/yjCo/M9cASPlnrd2ZmmZpQT40fOOrvR8jh+n8jikrOhNA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-annotate-as-pure': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - dev: true - - /@babel/plugin-transform-regenerator@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - regenerator-transform: 0.15.2 - dev: true - - /@babel/plugin-transform-reserved-words@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - dev: true - - /@babel/plugin-transform-shorthand-properties@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - dev: true - - /@babel/plugin-transform-spread@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - '@babel/helper-skip-transparent-expression-wrappers': 7.24.7 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/plugin-transform-sticky-regex@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-kHPSIJc9v24zEml5geKg9Mjx5ULpfncj0wRpYtxbvKyTtHCYDkVE3aHQ03FrpEo4gEe2vrJJS1Y9CJTaThA52g==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - dev: true - - /@babel/plugin-transform-template-literals@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - dev: true - - /@babel/plugin-transform-typeof-symbol@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-VtR8hDy7YLB7+Pet9IarXjg/zgCMSF+1mNS/EQEiEaUPoFXCVsHG64SIxcaaI2zJgRiv+YmgaQESUfWAdbjzgg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - dev: true - - /@babel/plugin-transform-typescript@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-iLD3UNkgx2n/HrjBesVbYX6j0yqn/sJktvbtKKgcaLIQ4bTTQ8obAypc1VpyHPD2y4Phh9zHOaAt8e/L14wCpw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-annotate-as-pure': 7.24.7 - '@babel/helper-create-class-features-plugin': 7.24.7(@babel/core@7.24.7) - '@babel/helper-plugin-utils': 7.24.7 - '@babel/plugin-syntax-typescript': 7.24.7(@babel/core@7.24.7) - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/plugin-transform-unicode-escapes@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - dev: true - - /@babel/plugin-transform-unicode-property-regex@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-create-regexp-features-plugin': 7.24.7(@babel/core@7.24.7) - '@babel/helper-plugin-utils': 7.24.7 - dev: true - - /@babel/plugin-transform-unicode-regex@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-hlQ96MBZSAXUq7ltkjtu3FJCCSMx/j629ns3hA3pXnBXjanNP0LHi+JpPeA81zaWgVK1VGH95Xuy7u0RyQ8kMg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-create-regexp-features-plugin': 7.24.7(@babel/core@7.24.7) - '@babel/helper-plugin-utils': 7.24.7 - dev: true - - /@babel/plugin-transform-unicode-sets-regex@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-2G8aAvF4wy1w/AGZkemprdGMRg5o6zPNhbHVImRz3lss55TYCBd6xStN19rt8XJHq20sqV0JbyWjOWwQRwV/wg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-create-regexp-features-plugin': 7.24.7(@babel/core@7.24.7) - '@babel/helper-plugin-utils': 7.24.7 - dev: true - - /@babel/preset-env@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-1YZNsc+y6cTvWlDHidMBsQZrZfEFjRIo/BZCT906PMdzOyXtSLTgqGdrpcuTDCXyd11Am5uQULtDIcCfnTc8fQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/compat-data': 7.24.7 - '@babel/core': 7.24.7 - '@babel/helper-compilation-targets': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - '@babel/helper-validator-option': 7.24.7 - '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.24.7) - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.24.7) - '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.24.7) - '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.24.7) - '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.24.7) - '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.24.7) - '@babel/plugin-syntax-import-assertions': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-syntax-import-attributes': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.24.7) - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.24.7) - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.24.7) - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.24.7) - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.24.7) - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.24.7) - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.24.7) - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.24.7) - '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.24.7) - '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.24.7) - '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.24.7) - '@babel/plugin-transform-arrow-functions': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-async-generator-functions': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-async-to-generator': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-block-scoped-functions': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-block-scoping': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-class-properties': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-class-static-block': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-classes': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-computed-properties': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-destructuring': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-dotall-regex': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-duplicate-keys': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-dynamic-import': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-exponentiation-operator': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-export-namespace-from': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-for-of': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-function-name': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-json-strings': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-literals': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-logical-assignment-operators': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-member-expression-literals': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-modules-amd': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-modules-commonjs': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-modules-systemjs': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-modules-umd': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-named-capturing-groups-regex': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-new-target': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-nullish-coalescing-operator': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-numeric-separator': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-object-rest-spread': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-object-super': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-optional-catch-binding': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-optional-chaining': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-parameters': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-private-methods': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-private-property-in-object': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-property-literals': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-regenerator': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-reserved-words': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-shorthand-properties': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-spread': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-sticky-regex': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-template-literals': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-typeof-symbol': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-unicode-escapes': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-unicode-property-regex': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-unicode-regex': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-unicode-sets-regex': 7.24.7(@babel/core@7.24.7) - '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.24.7) - babel-plugin-polyfill-corejs2: 0.4.10(@babel/core@7.24.7) - babel-plugin-polyfill-corejs3: 0.10.4(@babel/core@7.24.7) - babel-plugin-polyfill-regenerator: 0.6.1(@babel/core@7.24.7) - core-js-compat: 3.36.1 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.24.7): - resolution: {integrity: sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==} - peerDependencies: - '@babel/core': ^7.0.0-0 || ^8.0.0-0 <8.0.0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - '@babel/types': 7.24.0 - esutils: 2.0.3 - dev: true - - /@babel/preset-react@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-AAH4lEkpmzFWrGVlHaxJB7RLH21uPQ9+He+eFLWHmF9IuFQVugz8eAsamaW0DXRrTfco5zj1wWtpdcXJUOfsag==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - '@babel/helper-validator-option': 7.24.7 - '@babel/plugin-transform-react-display-name': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-react-jsx': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-react-jsx-development': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-react-pure-annotations': 7.24.7(@babel/core@7.24.7) - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/preset-typescript@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-SyXRe3OdWwIwalxDg5UtJnJQO+YPcTfwiIY2B0Xlddh9o7jpWLvv8X1RthIeDOxQ+O1ML5BLPCONToObyVQVuQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - '@babel/helper-validator-option': 7.24.7 - '@babel/plugin-syntax-jsx': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-modules-commonjs': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-typescript': 7.24.7(@babel/core@7.24.7) - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/regjsgen@0.8.0: - resolution: {integrity: sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==} - dev: true - - /@babel/runtime@7.20.13: - resolution: {integrity: sha512-gt3PKXs0DBoL9xCvOIIZ2NEqAGZqHjAnmVbfQtB620V0uReIQutpel14KcneZuer7UioY8ALKZ7iocavvzTNFA==} - engines: {node: '>=6.9.0'} - dependencies: - regenerator-runtime: 0.13.11 - dev: false - - /@babel/runtime@7.24.4: - resolution: {integrity: sha512-dkxf7+hn8mFBwKjs9bvBlArzLVxVbS8usaPUDd5p2a9JCL9tB8OaOVN1isD4+Xyk4ns89/xeOmbQvgdK7IIVdA==} - engines: {node: '>=6.9.0'} - dependencies: - regenerator-runtime: 0.14.1 - - /@babel/template@7.24.7: - resolution: {integrity: sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.24.7 - '@babel/parser': 7.24.7 - '@babel/types': 7.24.7 - dev: true - - /@babel/traverse@7.24.7: - resolution: {integrity: sha512-yb65Ed5S/QAcewNPh0nZczy9JdYXkkAbIsEo+P7BE7yO3txAY30Y/oPa3QkQ5It3xVG2kpKMg9MsdxZaO31uKA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.24.7 - '@babel/generator': 7.24.7 - '@babel/helper-environment-visitor': 7.24.7 - '@babel/helper-function-name': 7.24.7 - '@babel/helper-hoist-variables': 7.24.7 - '@babel/helper-split-export-declaration': 7.24.7 - '@babel/parser': 7.24.7 - '@babel/types': 7.24.7 - debug: 4.3.4 - globals: 11.12.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/types@7.20.7: - resolution: {integrity: sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-string-parser': 7.19.4 - '@babel/helper-validator-identifier': 7.19.1 - to-fast-properties: 2.0.0 - dev: false - - /@babel/types@7.24.0: - resolution: {integrity: sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-string-parser': 7.24.1 - '@babel/helper-validator-identifier': 7.22.20 - to-fast-properties: 2.0.0 - dev: true - - /@babel/types@7.24.7: - resolution: {integrity: sha512-XEFXSlxiG5td2EJRe8vOmRbaXVgfcBlszKujvVmWIK/UpywWljQCfzAv3RQCGujWQ1RD4YYWEAqDXfuJiy8f5Q==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-string-parser': 7.24.7 - '@babel/helper-validator-identifier': 7.24.7 - to-fast-properties: 2.0.0 - dev: true - - /@cspotcode/source-map-support@0.8.1: - resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} - engines: {node: '>=12'} - dependencies: - '@jridgewell/trace-mapping': 0.3.9 - dev: true - - /@discoveryjs/json-ext@0.5.7: - resolution: {integrity: sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==} - engines: {node: '>=10.0.0'} - dev: true - - /@emotion/babel-plugin@11.11.0: - resolution: {integrity: sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==} - dependencies: - '@babel/helper-module-imports': 7.18.6 - '@babel/runtime': 7.24.4 - '@emotion/hash': 0.9.1 - '@emotion/memoize': 0.8.1 - '@emotion/serialize': 1.1.4 - babel-plugin-macros: 3.1.0 - convert-source-map: 1.9.0 - escape-string-regexp: 4.0.0 - find-root: 1.1.0 - source-map: 0.5.7 - stylis: 4.2.0 - dev: false - - /@emotion/cache@11.11.0: - resolution: {integrity: sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ==} - dependencies: - '@emotion/memoize': 0.8.1 - '@emotion/sheet': 1.2.2 - '@emotion/utils': 1.2.1 - '@emotion/weak-memoize': 0.3.1 - stylis: 4.2.0 - dev: false - - /@emotion/hash@0.9.1: - resolution: {integrity: sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==} - dev: false - - /@emotion/is-prop-valid@1.2.2: - resolution: {integrity: sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==} - dependencies: - '@emotion/memoize': 0.8.1 - dev: false - - /@emotion/memoize@0.8.1: - resolution: {integrity: sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==} - dev: false - - /@emotion/react@11.11.4(@types/react@18.3.3)(react@18.3.1): - resolution: {integrity: sha512-t8AjMlF0gHpvvxk5mAtCqR4vmxiGHCeJBaQO6gncUSdklELOgtwjerNY2yuJNfwnc6vi16U/+uMF+afIawJ9iw==} - peerDependencies: - '@types/react': '*' - react: '>=16.8.0' - peerDependenciesMeta: - '@types/react': - optional: true - dependencies: - '@babel/runtime': 7.20.13 - '@emotion/babel-plugin': 11.11.0 - '@emotion/cache': 11.11.0 - '@emotion/serialize': 1.1.4 - '@emotion/use-insertion-effect-with-fallbacks': 1.0.1(react@18.3.1) - '@emotion/utils': 1.2.1 - '@emotion/weak-memoize': 0.3.1 - '@types/react': 18.3.3 - hoist-non-react-statics: 3.3.2 - react: 18.3.1 - dev: false - - /@emotion/serialize@1.1.4: - resolution: {integrity: sha512-RIN04MBT8g+FnDwgvIUi8czvr1LU1alUMI05LekWB5DGyTm8cCBMCRpq3GqaiyEDRptEXOyXnvZ58GZYu4kBxQ==} - dependencies: - '@emotion/hash': 0.9.1 - '@emotion/memoize': 0.8.1 - '@emotion/unitless': 0.8.1 - '@emotion/utils': 1.2.1 - csstype: 3.1.1 - dev: false - - /@emotion/sheet@1.2.2: - resolution: {integrity: sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==} - dev: false - - /@emotion/styled@11.11.5(@emotion/react@11.11.4)(@types/react@18.3.3)(react@18.3.1): - resolution: {integrity: sha512-/ZjjnaNKvuMPxcIiUkf/9SHoG4Q196DRl1w82hQ3WCsjo1IUR8uaGWrC6a87CrYAW0Kb/pK7hk8BnLgLRi9KoQ==} - peerDependencies: - '@emotion/react': ^11.0.0-rc.0 - '@types/react': '*' - react: '>=16.8.0' - peerDependenciesMeta: - '@types/react': - optional: true - dependencies: - '@babel/runtime': 7.20.13 - '@emotion/babel-plugin': 11.11.0 - '@emotion/is-prop-valid': 1.2.2 - '@emotion/react': 11.11.4(@types/react@18.3.3)(react@18.3.1) - '@emotion/serialize': 1.1.4 - '@emotion/use-insertion-effect-with-fallbacks': 1.0.1(react@18.3.1) - '@emotion/utils': 1.2.1 - '@types/react': 18.3.3 - react: 18.3.1 - dev: false - - /@emotion/unitless@0.8.1: - resolution: {integrity: sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==} - dev: false - - /@emotion/use-insertion-effect-with-fallbacks@1.0.1(react@18.3.1): - resolution: {integrity: sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==} - peerDependencies: - react: '>=16.8.0' - dependencies: - react: 18.3.1 - dev: false - - /@emotion/utils@1.2.1: - resolution: {integrity: sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==} - dev: false - - /@emotion/weak-memoize@0.3.1: - resolution: {integrity: sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==} - dev: false - - /@floating-ui/core@1.6.0: - resolution: {integrity: sha512-PcF++MykgmTj3CIyOQbKA/hDzOAiqI3mhuoN44WRCopIs1sgoDoU4oty4Jtqaj/y3oDU6fnVSm4QG0a3t5i0+g==} - dependencies: - '@floating-ui/utils': 0.2.1 - dev: false - - /@floating-ui/dom@1.6.3: - resolution: {integrity: sha512-RnDthu3mzPlQ31Ss/BTwQ1zjzIhr3lk1gZB1OC56h/1vEtaXkESrOqL5fQVMfXpwGtRwX+YsZBdyHtJMQnkArw==} - dependencies: - '@floating-ui/core': 1.6.0 - '@floating-ui/utils': 0.2.1 - dev: false - - /@floating-ui/react-dom@2.0.8(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-HOdqOt3R3OGeTKidaLvJKcgg75S6tibQ3Tif4eyd91QnIJWr0NLvoXFpJA/j8HqkFSL68GDca9AuyWEHlhyClw==} - peerDependencies: - react: '>=16.8.0' - react-dom: '>=16.8.0' - dependencies: - '@floating-ui/dom': 1.6.3 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - - /@floating-ui/utils@0.2.1: - resolution: {integrity: sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q==} - dev: false - - /@isaacs/cliui@8.0.2: - resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} - engines: {node: '>=12'} - dependencies: - string-width: 5.1.2 - string-width-cjs: /string-width@4.2.3 - strip-ansi: 7.1.0 - strip-ansi-cjs: /strip-ansi@6.0.1 - wrap-ansi: 8.1.0 - wrap-ansi-cjs: /wrap-ansi@7.0.0 - dev: true - - /@jridgewell/gen-mapping@0.3.5: - resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} - engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/set-array': 1.2.1 - '@jridgewell/sourcemap-codec': 1.4.15 - '@jridgewell/trace-mapping': 0.3.25 - dev: true - - /@jridgewell/resolve-uri@3.1.2: - resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} - engines: {node: '>=6.0.0'} - dev: true - - /@jridgewell/set-array@1.2.1: - resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} - engines: {node: '>=6.0.0'} - dev: true - - /@jridgewell/source-map@0.3.6: - resolution: {integrity: sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==} - dependencies: - '@jridgewell/gen-mapping': 0.3.5 - '@jridgewell/trace-mapping': 0.3.25 - dev: true - - /@jridgewell/sourcemap-codec@1.4.15: - resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} - dev: true - - /@jridgewell/trace-mapping@0.3.25: - resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} - dependencies: - '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.4.15 - dev: true - - /@jridgewell/trace-mapping@0.3.9: - resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} - dependencies: - '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.4.15 - dev: true - - /@leichtgewicht/ip-codec@2.0.5: - resolution: {integrity: sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==} - dev: true - - /@mui/base@5.0.0-beta.40(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-I/lGHztkCzvwlXpjD2+SNmvNQvB4227xBXhISPjEaJUXGImOQ9f3D2Yj/T3KasSI/h0MLWy74X0J6clhPmsRbQ==} - engines: {node: '>=12.0.0'} - peerDependencies: - '@types/react': ^17.0.0 || ^18.0.0 - react: ^17.0.0 || ^18.0.0 - react-dom: ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - '@types/react': - optional: true - dependencies: - '@babel/runtime': 7.24.4 - '@floating-ui/react-dom': 2.0.8(react-dom@18.3.1)(react@18.3.1) - '@mui/types': 7.2.14(@types/react@18.3.3) - '@mui/utils': 5.15.14(@types/react@18.3.3)(react@18.3.1) - '@popperjs/core': 2.11.8 - '@types/react': 18.3.3 - clsx: 2.1.0 - prop-types: 15.8.1 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - - /@mui/core-downloads-tracker@5.15.20: - resolution: {integrity: sha512-DoL2ppgldL16utL8nNyj/P12f8mCNdx/Hb/AJnX9rLY4b52hCMIx1kH83pbXQ6uMy6n54M3StmEbvSGoj2OFuA==} - dev: false - - /@mui/icons-material@5.15.20(@mui/material@5.15.20)(@types/react@18.3.3)(react@18.3.1): - resolution: {integrity: sha512-oGcKmCuHaYbAAoLN67WKSXtHmEgyWcJToT1uRtmPyxMj9N5uqwc/mRtEnst4Wj/eGr+zYH2FiZQ79v9k7kSk1Q==} - engines: {node: '>=12.0.0'} - peerDependencies: - '@mui/material': ^5.0.0 - '@types/react': ^17.0.0 || ^18.0.0 - react: ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - '@types/react': - optional: true - dependencies: - '@babel/runtime': 7.24.4 - '@mui/material': 5.15.20(@emotion/react@11.11.4)(@emotion/styled@11.11.5)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) - '@types/react': 18.3.3 - react: 18.3.1 - dev: false - - /@mui/lab@5.0.0-alpha.170(@emotion/react@11.11.4)(@emotion/styled@11.11.5)(@mui/material@5.15.20)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-0bDVECGmrNjd3+bLdcLiwYZ0O4HP5j5WSQm5DV6iA/Z9kr8O6AnvZ1bv9ImQbbX7Gj3pX4o43EKwCutj3EQxQg==} - engines: {node: '>=12.0.0'} - peerDependencies: - '@emotion/react': ^11.5.0 - '@emotion/styled': ^11.3.0 - '@mui/material': '>=5.15.0' - '@types/react': ^17.0.0 || ^18.0.0 - react: ^17.0.0 || ^18.0.0 - react-dom: ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - '@emotion/react': - optional: true - '@emotion/styled': - optional: true - '@types/react': - optional: true - dependencies: - '@babel/runtime': 7.24.4 - '@emotion/react': 11.11.4(@types/react@18.3.3)(react@18.3.1) - '@emotion/styled': 11.11.5(@emotion/react@11.11.4)(@types/react@18.3.3)(react@18.3.1) - '@mui/base': 5.0.0-beta.40(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) - '@mui/material': 5.15.20(@emotion/react@11.11.4)(@emotion/styled@11.11.5)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) - '@mui/system': 5.15.15(@emotion/react@11.11.4)(@emotion/styled@11.11.5)(@types/react@18.3.3)(react@18.3.1) - '@mui/types': 7.2.14(@types/react@18.3.3) - '@mui/utils': 5.15.14(@types/react@18.3.3)(react@18.3.1) - '@types/react': 18.3.3 - clsx: 2.1.0 - prop-types: 15.8.1 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - - /@mui/material@5.15.20(@emotion/react@11.11.4)(@emotion/styled@11.11.5)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-tVq3l4qoXx/NxUgIx/x3lZiPn/5xDbdTE8VrLczNpfblLYZzlrbxA7kb9mI8NoBF6+w9WE9IrxWnKK5KlPI2bg==} - engines: {node: '>=12.0.0'} - peerDependencies: - '@emotion/react': ^11.5.0 - '@emotion/styled': ^11.3.0 - '@types/react': ^17.0.0 || ^18.0.0 - react: ^17.0.0 || ^18.0.0 - react-dom: ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - '@emotion/react': - optional: true - '@emotion/styled': - optional: true - '@types/react': - optional: true - dependencies: - '@babel/runtime': 7.24.4 - '@emotion/react': 11.11.4(@types/react@18.3.3)(react@18.3.1) - '@emotion/styled': 11.11.5(@emotion/react@11.11.4)(@types/react@18.3.3)(react@18.3.1) - '@mui/base': 5.0.0-beta.40(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) - '@mui/core-downloads-tracker': 5.15.20 - '@mui/system': 5.15.20(@emotion/react@11.11.4)(@emotion/styled@11.11.5)(@types/react@18.3.3)(react@18.3.1) - '@mui/types': 7.2.14(@types/react@18.3.3) - '@mui/utils': 5.15.20(@types/react@18.3.3)(react@18.3.1) - '@types/react': 18.3.3 - '@types/react-transition-group': 4.4.10 - clsx: 2.1.0 - csstype: 3.1.3 - prop-types: 15.8.1 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - react-is: 18.2.0 - react-transition-group: 4.4.5(react-dom@18.3.1)(react@18.3.1) - dev: false - - /@mui/private-theming@5.15.14(@types/react@18.3.3)(react@18.3.1): - resolution: {integrity: sha512-UH0EiZckOWcxiXLX3Jbb0K7rC8mxTr9L9l6QhOZxYc4r8FHUkefltV9VDGLrzCaWh30SQiJvAEd7djX3XXY6Xw==} - engines: {node: '>=12.0.0'} - peerDependencies: - '@types/react': ^17.0.0 || ^18.0.0 - react: ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - '@types/react': - optional: true - dependencies: - '@babel/runtime': 7.24.4 - '@mui/utils': 5.15.14(@types/react@18.3.3)(react@18.3.1) - '@types/react': 18.3.3 - prop-types: 15.8.1 - react: 18.3.1 - dev: false - - /@mui/private-theming@5.15.20(@types/react@18.3.3)(react@18.3.1): - resolution: {integrity: sha512-BK8F94AIqSrnaPYXf2KAOjGZJgWfvqAVQ2gVR3EryvQFtuBnG6RwodxrCvd3B48VuMy6Wsk897+lQMUxJyk+6g==} - engines: {node: '>=12.0.0'} - peerDependencies: - '@types/react': ^17.0.0 || ^18.0.0 - react: ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - '@types/react': - optional: true - dependencies: - '@babel/runtime': 7.24.4 - '@mui/utils': 5.15.20(@types/react@18.3.3)(react@18.3.1) - '@types/react': 18.3.3 - prop-types: 15.8.1 - react: 18.3.1 - dev: false - - /@mui/styled-engine@5.15.14(@emotion/react@11.11.4)(@emotion/styled@11.11.5)(react@18.3.1): - resolution: {integrity: sha512-RILkuVD8gY6PvjZjqnWhz8fu68dVkqhM5+jYWfB5yhlSQKg+2rHkmEwm75XIeAqI3qwOndK6zELK5H6Zxn4NHw==} - engines: {node: '>=12.0.0'} - peerDependencies: - '@emotion/react': ^11.4.1 - '@emotion/styled': ^11.3.0 - react: ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - '@emotion/react': - optional: true - '@emotion/styled': - optional: true - dependencies: - '@babel/runtime': 7.24.4 - '@emotion/cache': 11.11.0 - '@emotion/react': 11.11.4(@types/react@18.3.3)(react@18.3.1) - '@emotion/styled': 11.11.5(@emotion/react@11.11.4)(@types/react@18.3.3)(react@18.3.1) - csstype: 3.1.3 - prop-types: 15.8.1 - react: 18.3.1 - dev: false - - /@mui/system@5.15.15(@emotion/react@11.11.4)(@emotion/styled@11.11.5)(@types/react@18.3.3)(react@18.3.1): - resolution: {integrity: sha512-aulox6N1dnu5PABsfxVGOZffDVmlxPOVgj56HrUnJE8MCSh8lOvvkd47cebIVQQYAjpwieXQXiDPj5pwM40jTQ==} - engines: {node: '>=12.0.0'} - peerDependencies: - '@emotion/react': ^11.5.0 - '@emotion/styled': ^11.3.0 - '@types/react': ^17.0.0 || ^18.0.0 - react: ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - '@emotion/react': - optional: true - '@emotion/styled': - optional: true - '@types/react': - optional: true - dependencies: - '@babel/runtime': 7.24.4 - '@emotion/react': 11.11.4(@types/react@18.3.3)(react@18.3.1) - '@emotion/styled': 11.11.5(@emotion/react@11.11.4)(@types/react@18.3.3)(react@18.3.1) - '@mui/private-theming': 5.15.14(@types/react@18.3.3)(react@18.3.1) - '@mui/styled-engine': 5.15.14(@emotion/react@11.11.4)(@emotion/styled@11.11.5)(react@18.3.1) - '@mui/types': 7.2.14(@types/react@18.3.3) - '@mui/utils': 5.15.14(@types/react@18.3.3)(react@18.3.1) - '@types/react': 18.3.3 - clsx: 2.1.0 - csstype: 3.1.3 - prop-types: 15.8.1 - react: 18.3.1 - dev: false - - /@mui/system@5.15.20(@emotion/react@11.11.4)(@emotion/styled@11.11.5)(@types/react@18.3.3)(react@18.3.1): - resolution: {integrity: sha512-LoMq4IlAAhxzL2VNUDBTQxAb4chnBe8JvRINVNDiMtHE2PiPOoHlhOPutSxEbaL5mkECPVWSv6p8JEV+uykwIA==} - engines: {node: '>=12.0.0'} - peerDependencies: - '@emotion/react': ^11.5.0 - '@emotion/styled': ^11.3.0 - '@types/react': ^17.0.0 || ^18.0.0 - react: ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - '@emotion/react': - optional: true - '@emotion/styled': - optional: true - '@types/react': - optional: true - dependencies: - '@babel/runtime': 7.24.4 - '@emotion/react': 11.11.4(@types/react@18.3.3)(react@18.3.1) - '@emotion/styled': 11.11.5(@emotion/react@11.11.4)(@types/react@18.3.3)(react@18.3.1) - '@mui/private-theming': 5.15.20(@types/react@18.3.3)(react@18.3.1) - '@mui/styled-engine': 5.15.14(@emotion/react@11.11.4)(@emotion/styled@11.11.5)(react@18.3.1) - '@mui/types': 7.2.14(@types/react@18.3.3) - '@mui/utils': 5.15.20(@types/react@18.3.3)(react@18.3.1) - '@types/react': 18.3.3 - clsx: 2.1.0 - csstype: 3.1.3 - prop-types: 15.8.1 - react: 18.3.1 - dev: false - - /@mui/types@7.2.14(@types/react@18.3.3): - resolution: {integrity: sha512-MZsBZ4q4HfzBsywtXgM1Ksj6HDThtiwmOKUXH1pKYISI9gAVXCNHNpo7TlGoGrBaYWZTdNoirIN7JsQcQUjmQQ==} - peerDependencies: - '@types/react': ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - '@types/react': - optional: true - dependencies: - '@types/react': 18.3.3 - dev: false - - /@mui/utils@5.15.14(@types/react@18.3.3)(react@18.3.1): - resolution: {integrity: sha512-0lF/7Hh/ezDv5X7Pry6enMsbYyGKjADzvHyo3Qrc/SSlTsQ1VkbDMbH0m2t3OR5iIVLwMoxwM7yGd+6FCMtTFA==} - engines: {node: '>=12.0.0'} - peerDependencies: - '@types/react': ^17.0.0 || ^18.0.0 - react: ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - '@types/react': - optional: true - dependencies: - '@babel/runtime': 7.24.4 - '@types/prop-types': 15.7.12 - '@types/react': 18.3.3 - prop-types: 15.8.1 - react: 18.3.1 - react-is: 18.2.0 - dev: false - - /@mui/utils@5.15.20(@types/react@18.3.3)(react@18.3.1): - resolution: {integrity: sha512-mAbYx0sovrnpAu1zHc3MDIhPqL8RPVC5W5xcO1b7PiSCJPtckIZmBkp8hefamAvUiAV8gpfMOM6Zb+eSisbI2A==} - engines: {node: '>=12.0.0'} - peerDependencies: - '@types/react': ^17.0.0 || ^18.0.0 - react: ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - '@types/react': - optional: true - dependencies: - '@babel/runtime': 7.24.4 - '@types/prop-types': 15.7.12 - '@types/react': 18.3.3 - prop-types: 15.8.1 - react: 18.3.1 - react-is: 18.2.0 - dev: false - - /@nicolo-ribaudo/chokidar-2@2.1.8-no-fsevents.3: - resolution: {integrity: sha512-s88O1aVtXftvp5bCPB7WnmXc5IwOZZ7YPuwNPt+GtOOXpPvad1LfbmjYv+qII7zP6RU2QGnqve27dnLycEnyEQ==} - requiresBuild: true - dev: true - optional: true - - /@pkgjs/parseargs@0.11.0: - resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} - engines: {node: '>=14'} - requiresBuild: true - dev: true - optional: true - - /@popperjs/core@2.11.8: - resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==} - dev: false - - /@tsconfig/node10@1.0.11: - resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==} - dev: true - - /@tsconfig/node12@1.0.11: - resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} - dev: true - - /@tsconfig/node14@1.0.3: - resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} - dev: true - - /@tsconfig/node16@1.0.4: - resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} - dev: true - - /@types/body-parser@1.19.5: - resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==} - dependencies: - '@types/connect': 3.4.38 - '@types/node': 20.14.6 - dev: true - - /@types/bonjour@3.5.13: - resolution: {integrity: sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==} - dependencies: - '@types/node': 20.14.6 - dev: true - - /@types/connect-history-api-fallback@1.5.4: - resolution: {integrity: sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==} - dependencies: - '@types/express-serve-static-core': 4.19.0 - '@types/node': 20.14.6 - dev: true - - /@types/connect@3.4.38: - resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} - dependencies: - '@types/node': 20.14.6 - dev: true - - /@types/eslint-scope@3.7.7: - resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==} - dependencies: - '@types/eslint': 8.56.7 - '@types/estree': 1.0.5 - dev: true - - /@types/eslint@8.56.7: - resolution: {integrity: sha512-SjDvI/x3zsZnOkYZ3lCt9lOZWZLB2jIlNKz+LBgCtDurK0JZcwucxYHn1w2BJkD34dgX9Tjnak0txtq4WTggEA==} - dependencies: - '@types/estree': 1.0.5 - '@types/json-schema': 7.0.15 - dev: true - - /@types/estree@1.0.5: - resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} - dev: true - - /@types/express-serve-static-core@4.19.0: - resolution: {integrity: sha512-bGyep3JqPCRry1wq+O5n7oiBgGWmeIJXPjXXCo8EK0u8duZGSYar7cGqd3ML2JUsLGeB7fmc06KYo9fLGWqPvQ==} - dependencies: - '@types/node': 20.14.6 - '@types/qs': 6.9.14 - '@types/range-parser': 1.2.7 - '@types/send': 0.17.4 - dev: true - - /@types/express@4.17.21: - resolution: {integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==} - dependencies: - '@types/body-parser': 1.19.5 - '@types/express-serve-static-core': 4.19.0 - '@types/qs': 6.9.14 - '@types/serve-static': 1.15.7 - dev: true - - /@types/html-minifier-terser@6.1.0: - resolution: {integrity: sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==} - dev: true - - /@types/http-errors@2.0.4: - resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==} - dev: true - - /@types/http-proxy@1.17.14: - resolution: {integrity: sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==} - dependencies: - '@types/node': 20.14.6 - dev: true - - /@types/json-schema@7.0.15: - resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - dev: true - - /@types/mime@1.3.5: - resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} - dev: true - - /@types/node-forge@1.3.11: - resolution: {integrity: sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==} - dependencies: - '@types/node': 20.14.6 - dev: true - - /@types/node@20.14.6: - resolution: {integrity: sha512-JbA0XIJPL1IiNnU7PFxDXyfAwcwVVrOoqyzzyQTyMeVhBzkJVMSkC1LlVsRQ2lpqiY4n6Bb9oCS6lzDKVQxbZw==} - dependencies: - undici-types: 5.26.5 - dev: true - - /@types/parse-json@4.0.0: - resolution: {integrity: sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==} - dev: false - - /@types/prop-types@15.7.12: - resolution: {integrity: sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==} - - /@types/qs@6.9.14: - resolution: {integrity: sha512-5khscbd3SwWMhFqylJBLQ0zIu7c1K6Vz0uBIt915BI3zV0q1nfjRQD3RqSBcPaO6PHEF4ov/t9y89fSiyThlPA==} - dev: true - - /@types/range-parser@1.2.7: - resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} - dev: true - - /@types/react-dom@18.3.0: - resolution: {integrity: sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==} - dependencies: - '@types/react': 18.3.3 - dev: true - - /@types/react-transition-group@4.4.10: - resolution: {integrity: sha512-hT/+s0VQs2ojCX823m60m5f0sL5idt9SO6Tj6Dg+rdphGPIeJbJ6CxvBYkgkGKrYeDjvIpKTR38UzmtHJOGW3Q==} - dependencies: - '@types/react': 18.3.3 - dev: false - - /@types/react@18.3.3: - resolution: {integrity: sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==} - dependencies: - '@types/prop-types': 15.7.12 - csstype: 3.1.3 - - /@types/retry@0.12.2: - resolution: {integrity: sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==} - dev: true - - /@types/send@0.17.4: - resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==} - dependencies: - '@types/mime': 1.3.5 - '@types/node': 20.14.6 - dev: true - - /@types/serve-index@1.9.4: - resolution: {integrity: sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==} - dependencies: - '@types/express': 4.17.21 - dev: true - - /@types/serve-static@1.15.7: - resolution: {integrity: sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==} - dependencies: - '@types/http-errors': 2.0.4 - '@types/node': 20.14.6 - '@types/send': 0.17.4 - dev: true - - /@types/sockjs@0.3.36: - resolution: {integrity: sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==} - dependencies: - '@types/node': 20.14.6 - dev: true - - /@types/uuid@9.0.8: - resolution: {integrity: sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==} - dev: true - - /@types/ws@8.5.10: - resolution: {integrity: sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==} - dependencies: - '@types/node': 20.14.6 - dev: true - - /@webassemblyjs/ast@1.12.1: - resolution: {integrity: sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==} - dependencies: - '@webassemblyjs/helper-numbers': 1.11.6 - '@webassemblyjs/helper-wasm-bytecode': 1.11.6 - dev: true - - /@webassemblyjs/floating-point-hex-parser@1.11.6: - resolution: {integrity: sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==} - dev: true - - /@webassemblyjs/helper-api-error@1.11.6: - resolution: {integrity: sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==} - dev: true - - /@webassemblyjs/helper-buffer@1.12.1: - resolution: {integrity: sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==} - dev: true - - /@webassemblyjs/helper-numbers@1.11.6: - resolution: {integrity: sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==} - dependencies: - '@webassemblyjs/floating-point-hex-parser': 1.11.6 - '@webassemblyjs/helper-api-error': 1.11.6 - '@xtuc/long': 4.2.2 - dev: true - - /@webassemblyjs/helper-wasm-bytecode@1.11.6: - resolution: {integrity: sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==} - dev: true - - /@webassemblyjs/helper-wasm-section@1.12.1: - resolution: {integrity: sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==} - dependencies: - '@webassemblyjs/ast': 1.12.1 - '@webassemblyjs/helper-buffer': 1.12.1 - '@webassemblyjs/helper-wasm-bytecode': 1.11.6 - '@webassemblyjs/wasm-gen': 1.12.1 - dev: true - - /@webassemblyjs/ieee754@1.11.6: - resolution: {integrity: sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==} - dependencies: - '@xtuc/ieee754': 1.2.0 - dev: true - - /@webassemblyjs/leb128@1.11.6: - resolution: {integrity: sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==} - dependencies: - '@xtuc/long': 4.2.2 - dev: true - - /@webassemblyjs/utf8@1.11.6: - resolution: {integrity: sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==} - dev: true - - /@webassemblyjs/wasm-edit@1.12.1: - resolution: {integrity: sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==} - dependencies: - '@webassemblyjs/ast': 1.12.1 - '@webassemblyjs/helper-buffer': 1.12.1 - '@webassemblyjs/helper-wasm-bytecode': 1.11.6 - '@webassemblyjs/helper-wasm-section': 1.12.1 - '@webassemblyjs/wasm-gen': 1.12.1 - '@webassemblyjs/wasm-opt': 1.12.1 - '@webassemblyjs/wasm-parser': 1.12.1 - '@webassemblyjs/wast-printer': 1.12.1 - dev: true - - /@webassemblyjs/wasm-gen@1.12.1: - resolution: {integrity: sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==} - dependencies: - '@webassemblyjs/ast': 1.12.1 - '@webassemblyjs/helper-wasm-bytecode': 1.11.6 - '@webassemblyjs/ieee754': 1.11.6 - '@webassemblyjs/leb128': 1.11.6 - '@webassemblyjs/utf8': 1.11.6 - dev: true - - /@webassemblyjs/wasm-opt@1.12.1: - resolution: {integrity: sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==} - dependencies: - '@webassemblyjs/ast': 1.12.1 - '@webassemblyjs/helper-buffer': 1.12.1 - '@webassemblyjs/wasm-gen': 1.12.1 - '@webassemblyjs/wasm-parser': 1.12.1 - dev: true - - /@webassemblyjs/wasm-parser@1.12.1: - resolution: {integrity: sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==} - dependencies: - '@webassemblyjs/ast': 1.12.1 - '@webassemblyjs/helper-api-error': 1.11.6 - '@webassemblyjs/helper-wasm-bytecode': 1.11.6 - '@webassemblyjs/ieee754': 1.11.6 - '@webassemblyjs/leb128': 1.11.6 - '@webassemblyjs/utf8': 1.11.6 - dev: true - - /@webassemblyjs/wast-printer@1.12.1: - resolution: {integrity: sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==} - dependencies: - '@webassemblyjs/ast': 1.12.1 - '@xtuc/long': 4.2.2 - dev: true - - /@webpack-cli/configtest@2.1.1(webpack-cli@5.1.4)(webpack@5.92.1): - resolution: {integrity: sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==} - engines: {node: '>=14.15.0'} - peerDependencies: - webpack: 5.x.x - webpack-cli: 5.x.x - dependencies: - webpack: 5.92.1(webpack-cli@5.1.4) - webpack-cli: 5.1.4(webpack-dev-server@5.0.4)(webpack@5.92.1) - dev: true - - /@webpack-cli/info@2.0.2(webpack-cli@5.1.4)(webpack@5.92.1): - resolution: {integrity: sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==} - engines: {node: '>=14.15.0'} - peerDependencies: - webpack: 5.x.x - webpack-cli: 5.x.x - dependencies: - webpack: 5.92.1(webpack-cli@5.1.4) - webpack-cli: 5.1.4(webpack-dev-server@5.0.4)(webpack@5.92.1) - dev: true - - /@webpack-cli/serve@2.0.5(webpack-cli@5.1.4)(webpack-dev-server@5.0.4)(webpack@5.92.1): - resolution: {integrity: sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==} - engines: {node: '>=14.15.0'} - peerDependencies: - webpack: 5.x.x - webpack-cli: 5.x.x - webpack-dev-server: '*' - peerDependenciesMeta: - webpack-dev-server: - optional: true - dependencies: - webpack: 5.92.1(webpack-cli@5.1.4) - webpack-cli: 5.1.4(webpack-dev-server@5.0.4)(webpack@5.92.1) - webpack-dev-server: 5.0.4(webpack-cli@5.1.4)(webpack@5.92.1) - dev: true - - /@xtuc/ieee754@1.2.0: - resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==} - dev: true - - /@xtuc/long@4.2.2: - resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==} - dev: true - - /accepts@1.3.8: - resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} - engines: {node: '>= 0.6'} - dependencies: - mime-types: 2.1.35 - negotiator: 0.6.3 - dev: true - - /acorn-import-attributes@1.9.5(acorn@8.11.3): - resolution: {integrity: sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==} - peerDependencies: - acorn: ^8 - dependencies: - acorn: 8.11.3 - dev: true - - /acorn-walk@8.3.2: - resolution: {integrity: sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==} - engines: {node: '>=0.4.0'} - dev: true - - /acorn@8.11.3: - resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} - engines: {node: '>=0.4.0'} - hasBin: true - dev: true - - /ajv-formats@2.1.1(ajv@8.12.0): - resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} - peerDependencies: - ajv: ^8.0.0 - peerDependenciesMeta: - ajv: - optional: true - dependencies: - ajv: 8.12.0 - dev: true - - /ajv-keywords@3.5.2(ajv@6.12.6): - resolution: {integrity: sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==} - peerDependencies: - ajv: ^6.9.1 - dependencies: - ajv: 6.12.6 - dev: true - - /ajv-keywords@5.1.0(ajv@8.12.0): - resolution: {integrity: sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==} - peerDependencies: - ajv: ^8.8.2 - dependencies: - ajv: 8.12.0 - fast-deep-equal: 3.1.3 - dev: true - - /ajv@6.12.6: - resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - dependencies: - fast-deep-equal: 3.1.3 - fast-json-stable-stringify: 2.1.0 - json-schema-traverse: 0.4.1 - uri-js: 4.4.1 - dev: true - - /ajv@8.12.0: - resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==} - dependencies: - fast-deep-equal: 3.1.3 - json-schema-traverse: 1.0.0 - require-from-string: 2.0.2 - uri-js: 4.4.1 - dev: true - - /ansi-html-community@0.0.8: - resolution: {integrity: sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==} - engines: {'0': node >= 0.8.0} - hasBin: true - dev: true - - /ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - - /ansi-regex@6.0.1: - resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} - engines: {node: '>=12'} - dev: true - - /ansi-styles@3.2.1: - resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} - engines: {node: '>=4'} - dependencies: - color-convert: 1.9.3 - - /ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} - dependencies: - color-convert: 2.0.1 - - /ansi-styles@6.2.1: - resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} - engines: {node: '>=12'} - dev: true - - /anymatch@3.1.3: - resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} - engines: {node: '>= 8'} - requiresBuild: true - dependencies: - normalize-path: 3.0.0 - picomatch: 2.3.1 - dev: true - - /arg@4.1.3: - resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} - dev: true - - /array-flatten@1.1.1: - resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} - dev: true - - /babel-loader@9.1.3(@babel/core@7.24.7)(webpack@5.92.1): - resolution: {integrity: sha512-xG3ST4DglodGf8qSwv0MdeWLhrDsw/32QMdTO5T1ZIp9gQur0HkCyFs7Awskr10JKXFXwpAhiCuYX5oGXnRGbw==} - engines: {node: '>= 14.15.0'} - peerDependencies: - '@babel/core': ^7.12.0 - webpack: '>=5' - dependencies: - '@babel/core': 7.24.7 - find-cache-dir: 4.0.0 - schema-utils: 4.2.0 - webpack: 5.92.1(webpack-cli@5.1.4) - dev: true - - /babel-plugin-macros@3.1.0: - resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==} - engines: {node: '>=10', npm: '>=6'} - dependencies: - '@babel/runtime': 7.24.4 - cosmiconfig: 7.1.0 - resolve: 1.22.1 - dev: false - - /babel-plugin-polyfill-corejs2@0.4.10(@babel/core@7.24.7): - resolution: {integrity: sha512-rpIuu//y5OX6jVU+a5BCn1R5RSZYWAl2Nar76iwaOdycqb6JPxediskWFMMl7stfwNJR4b7eiQvh5fB5TEQJTQ==} - peerDependencies: - '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - dependencies: - '@babel/compat-data': 7.24.7 - '@babel/core': 7.24.7 - '@babel/helper-define-polyfill-provider': 0.6.1(@babel/core@7.24.7) - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - dev: true - - /babel-plugin-polyfill-corejs3@0.10.4(@babel/core@7.24.7): - resolution: {integrity: sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg==} - peerDependencies: - '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-define-polyfill-provider': 0.6.1(@babel/core@7.24.7) - core-js-compat: 3.36.1 - transitivePeerDependencies: - - supports-color - dev: true - - /babel-plugin-polyfill-regenerator@0.6.1(@babel/core@7.24.7): - resolution: {integrity: sha512-JfTApdE++cgcTWjsiCQlLyFBMbTUft9ja17saCc93lgV33h4tuCVj7tlvu//qpLwaG+3yEz7/KhahGrUMkVq9g==} - peerDependencies: - '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-define-polyfill-provider': 0.6.1(@babel/core@7.24.7) - transitivePeerDependencies: - - supports-color - dev: true - - /balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - dev: true - - /batch@0.6.1: - resolution: {integrity: sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==} - dev: true - - /binary-extensions@2.3.0: - resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} - engines: {node: '>=8'} - requiresBuild: true - dev: true - - /body-parser@1.20.2: - resolution: {integrity: sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==} - engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} - dependencies: - bytes: 3.1.2 - content-type: 1.0.5 - debug: 2.6.9 - depd: 2.0.0 - destroy: 1.2.0 - http-errors: 2.0.0 - iconv-lite: 0.4.24 - on-finished: 2.4.1 - qs: 6.11.0 - raw-body: 2.5.2 - type-is: 1.6.18 - unpipe: 1.0.0 - transitivePeerDependencies: - - supports-color - dev: true - - /bonjour-service@1.2.1: - resolution: {integrity: sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw==} - dependencies: - fast-deep-equal: 3.1.3 - multicast-dns: 7.2.5 - dev: true - - /boolbase@1.0.0: - resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} - dev: true - - /brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - dev: true - - /brace-expansion@2.0.1: - resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} - dependencies: - balanced-match: 1.0.2 - dev: true - - /braces@3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} - engines: {node: '>=8'} - requiresBuild: true - dependencies: - fill-range: 7.0.1 - dev: true - - /browserslist@4.23.0: - resolution: {integrity: sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} - hasBin: true - dependencies: - caniuse-lite: 1.0.30001607 - electron-to-chromium: 1.4.729 - node-releases: 2.0.14 - update-browserslist-db: 1.0.13(browserslist@4.23.0) - dev: true - - /buffer-from@1.1.2: - resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - dev: true - - /bundle-name@4.1.0: - resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} - engines: {node: '>=18'} - dependencies: - run-applescript: 7.0.0 - dev: true - - /bytes@3.0.0: - resolution: {integrity: sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==} - engines: {node: '>= 0.8'} - dev: true - - /bytes@3.1.2: - resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} - engines: {node: '>= 0.8'} - dev: true - - /call-bind@1.0.7: - resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} - engines: {node: '>= 0.4'} - dependencies: - es-define-property: 1.0.0 - es-errors: 1.3.0 - function-bind: 1.1.2 - get-intrinsic: 1.2.4 - set-function-length: 1.2.2 - dev: true - - /callsites@3.1.0: - resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} - engines: {node: '>=6'} - dev: false - - /camel-case@4.1.2: - resolution: {integrity: sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==} - dependencies: - pascal-case: 3.1.2 - tslib: 2.6.2 - dev: true - - /caniuse-lite@1.0.30001607: - resolution: {integrity: sha512-WcvhVRjXLKFB/kmOFVwELtMxyhq3iM/MvmXcyCe2PNf166c39mptscOc/45TTS96n2gpNV2z7+NakArTWZCQ3w==} - dev: true - - /chalk@2.4.2: - resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} - engines: {node: '>=4'} - dependencies: - ansi-styles: 3.2.1 - escape-string-regexp: 1.0.5 - supports-color: 5.5.0 - - /chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - dev: false - - /chokidar@3.6.0: - resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} - engines: {node: '>= 8.10.0'} - requiresBuild: true - dependencies: - anymatch: 3.1.3 - braces: 3.0.2 - glob-parent: 5.1.2 - is-binary-path: 2.1.0 - is-glob: 4.0.3 - normalize-path: 3.0.0 - readdirp: 3.6.0 - optionalDependencies: - fsevents: 2.3.3 - dev: true - - /chrome-trace-event@1.0.3: - resolution: {integrity: sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==} - engines: {node: '>=6.0'} - dev: true - - /clean-css@5.3.3: - resolution: {integrity: sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==} - engines: {node: '>= 10.0'} - dependencies: - source-map: 0.6.1 - dev: true - - /cliui@8.0.1: - resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} - engines: {node: '>=12'} - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - dev: false - - /clone-deep@4.0.1: - resolution: {integrity: sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==} - engines: {node: '>=6'} - dependencies: - is-plain-object: 2.0.4 - kind-of: 6.0.3 - shallow-clone: 3.0.1 - dev: true - - /clsx@1.2.1: - resolution: {integrity: sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==} - engines: {node: '>=6'} - dev: false - - /clsx@2.1.0: - resolution: {integrity: sha512-m3iNNWpd9rl3jvvcBnu70ylMdrXt8Vlq4HYadnU5fwcOtvkSQWPmj7amUcDT2qYI7risszBjI5AUIUox9D16pg==} - engines: {node: '>=6'} - dev: false - - /color-convert@1.9.3: - resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} - dependencies: - color-name: 1.1.3 - - /color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} - dependencies: - color-name: 1.1.4 - - /color-name@1.1.3: - resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} - - /color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - - /colorette@2.0.20: - resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} - dev: true - - /commander@10.0.1: - resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} - engines: {node: '>=14'} - dev: true - - /commander@2.20.3: - resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} - dev: true - - /commander@6.2.1: - resolution: {integrity: sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==} - engines: {node: '>= 6'} - dev: true - - /commander@8.3.0: - resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} - engines: {node: '>= 12'} - dev: true - - /common-path-prefix@3.0.0: - resolution: {integrity: sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==} - dev: true - - /compressible@2.0.18: - resolution: {integrity: sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==} - engines: {node: '>= 0.6'} - dependencies: - mime-db: 1.52.0 - dev: true - - /compression@1.7.4: - resolution: {integrity: sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==} - engines: {node: '>= 0.8.0'} - dependencies: - accepts: 1.3.8 - bytes: 3.0.0 - compressible: 2.0.18 - debug: 2.6.9 - on-headers: 1.0.2 - safe-buffer: 5.1.2 - vary: 1.1.2 - transitivePeerDependencies: - - supports-color - dev: true - - /concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - dev: true - - /concurrently@8.2.2: - resolution: {integrity: sha512-1dP4gpXFhei8IOtlXRE/T/4H88ElHgTiUzh71YUmtjTEHMSRS2Z/fgOxHSxxusGHogsRfxNq1vyAwxSC+EVyDg==} - engines: {node: ^14.13.0 || >=16.0.0} - hasBin: true - dependencies: - chalk: 4.1.2 - date-fns: 2.30.0 - lodash: 4.17.21 - rxjs: 7.8.1 - shell-quote: 1.8.1 - spawn-command: 0.0.2 - supports-color: 8.1.1 - tree-kill: 1.2.2 - yargs: 17.7.2 - dev: false - - /connect-history-api-fallback@2.0.0: - resolution: {integrity: sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==} - engines: {node: '>=0.8'} - dev: true - - /content-disposition@0.5.4: - resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} - engines: {node: '>= 0.6'} - dependencies: - safe-buffer: 5.2.1 - dev: true - - /content-type@1.0.5: - resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} - engines: {node: '>= 0.6'} - dev: true - - /convert-source-map@1.9.0: - resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} - dev: false - - /convert-source-map@2.0.0: - resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - dev: true - - /cookie-signature@1.0.6: - resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} - dev: true - - /cookie@0.6.0: - resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} - engines: {node: '>= 0.6'} - dev: true - - /core-js-compat@3.36.1: - resolution: {integrity: sha512-Dk997v9ZCt3X/npqzyGdTlq6t7lDBhZwGvV94PKzDArjp7BTRm7WlDAXYd/OWdeFHO8OChQYRJNJvUCqCbrtKA==} - dependencies: - browserslist: 4.23.0 - dev: true - - /core-util-is@1.0.3: - resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} - dev: true - - /cosmiconfig@7.1.0: - resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==} - engines: {node: '>=10'} - dependencies: - '@types/parse-json': 4.0.0 - import-fresh: 3.3.0 - parse-json: 5.2.0 - path-type: 4.0.0 - yaml: 1.10.2 - dev: false - - /create-require@1.1.1: - resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} - dev: true - - /cross-spawn@7.0.3: - resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} - engines: {node: '>= 8'} - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - dev: true - - /css-loader@7.1.2(webpack@5.92.1): - resolution: {integrity: sha512-6WvYYn7l/XEGN8Xu2vWFt9nVzrCn39vKyTEFf/ExEyoksJjjSZV/0/35XPlMbpnr6VGhZIUg5yJrL8tGfes/FA==} - engines: {node: '>= 18.12.0'} - peerDependencies: - '@rspack/core': 0.x || 1.x - webpack: ^5.27.0 - peerDependenciesMeta: - '@rspack/core': - optional: true - webpack: - optional: true - dependencies: - icss-utils: 5.1.0(postcss@8.4.38) - postcss: 8.4.38 - postcss-modules-extract-imports: 3.1.0(postcss@8.4.38) - postcss-modules-local-by-default: 4.0.5(postcss@8.4.38) - postcss-modules-scope: 3.2.0(postcss@8.4.38) - postcss-modules-values: 4.0.0(postcss@8.4.38) - postcss-value-parser: 4.2.0 - semver: 7.6.0 - webpack: 5.92.1(webpack-cli@5.1.4) - dev: true - - /css-select@4.3.0: - resolution: {integrity: sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==} - dependencies: - boolbase: 1.0.0 - css-what: 6.1.0 - domhandler: 4.3.1 - domutils: 2.8.0 - nth-check: 2.1.1 - dev: true - - /css-what@6.1.0: - resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} - engines: {node: '>= 6'} - dev: true - - /cssesc@3.0.0: - resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} - engines: {node: '>=4'} - hasBin: true - dev: true - - /csstype@3.1.1: - resolution: {integrity: sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==} - dev: false - - /csstype@3.1.3: - resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} - - /date-fns@2.30.0: - resolution: {integrity: sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==} - engines: {node: '>=0.11'} - dependencies: - '@babel/runtime': 7.24.4 - dev: false - - /debug@2.6.9: - resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.0.0 - dev: true - - /debug@4.3.4: - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.2 - dev: true - - /default-browser-id@5.0.0: - resolution: {integrity: sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==} - engines: {node: '>=18'} - dev: true - - /default-browser@5.2.1: - resolution: {integrity: sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==} - engines: {node: '>=18'} - dependencies: - bundle-name: 4.1.0 - default-browser-id: 5.0.0 - dev: true - - /default-gateway@6.0.3: - resolution: {integrity: sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==} - engines: {node: '>= 10'} - dependencies: - execa: 5.1.1 - dev: true - - /define-data-property@1.1.4: - resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} - engines: {node: '>= 0.4'} - dependencies: - es-define-property: 1.0.0 - es-errors: 1.3.0 - gopd: 1.0.1 - dev: true - - /define-lazy-prop@3.0.0: - resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==} - engines: {node: '>=12'} - dev: true - - /depd@1.1.2: - resolution: {integrity: sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==} - engines: {node: '>= 0.6'} - dev: true - - /depd@2.0.0: - resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} - engines: {node: '>= 0.8'} - dev: true - - /destroy@1.2.0: - resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} - engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} - dev: true - - /detect-node@2.1.0: - resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==} - dev: true - - /diff@4.0.2: - resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} - engines: {node: '>=0.3.1'} - dev: true - - /dns-packet@5.6.1: - resolution: {integrity: sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==} - engines: {node: '>=6'} - dependencies: - '@leichtgewicht/ip-codec': 2.0.5 - dev: true - - /dom-converter@0.2.0: - resolution: {integrity: sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==} - dependencies: - utila: 0.4.0 - dev: true - - /dom-helpers@5.2.1: - resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==} - dependencies: - '@babel/runtime': 7.24.4 - csstype: 3.1.3 - dev: false - - /dom-serializer@1.4.1: - resolution: {integrity: sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==} - dependencies: - domelementtype: 2.3.0 - domhandler: 4.3.1 - entities: 2.2.0 - dev: true - - /domelementtype@2.3.0: - resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} - dev: true - - /domhandler@4.3.1: - resolution: {integrity: sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==} - engines: {node: '>= 4'} - dependencies: - domelementtype: 2.3.0 - dev: true - - /domutils@2.8.0: - resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==} - dependencies: - dom-serializer: 1.4.1 - domelementtype: 2.3.0 - domhandler: 4.3.1 - dev: true - - /dot-case@3.0.4: - resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==} - dependencies: - no-case: 3.0.4 - tslib: 2.6.2 - dev: true - - /eastasianwidth@0.2.0: - resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - dev: true - - /ee-first@1.1.1: - resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - dev: true - - /electron-to-chromium@1.4.729: - resolution: {integrity: sha512-bx7+5Saea/qu14kmPTDHQxkp2UnziG3iajUQu3BxFvCOnpAJdDbMV4rSl+EqFDkkpNNVUFlR1kDfpL59xfy1HA==} - dev: true - - /emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - - /emoji-regex@9.2.2: - resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - dev: true - - /encodeurl@1.0.2: - resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} - engines: {node: '>= 0.8'} - dev: true - - /enhanced-resolve@5.17.0: - resolution: {integrity: sha512-dwDPwZL0dmye8Txp2gzFmA6sxALaSvdRDjPH0viLcKrtlOL3tw62nWWweVD1SdILDTJrbrL6tdWVN58Wo6U3eA==} - engines: {node: '>=10.13.0'} - dependencies: - graceful-fs: 4.2.11 - tapable: 2.2.1 - dev: true - - /entities@2.2.0: - resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==} - dev: true - - /envinfo@7.12.0: - resolution: {integrity: sha512-Iw9rQJBGpJRd3rwXm9ft/JiGoAZmLxxJZELYDQoPRZ4USVhkKtIcNBPw6U+/K2mBpaqM25JSV6Yl4Az9vO2wJg==} - engines: {node: '>=4'} - hasBin: true - dev: true - - /error-ex@1.3.2: - resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} - dependencies: - is-arrayish: 0.2.1 - dev: false - - /es-define-property@1.0.0: - resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} - engines: {node: '>= 0.4'} - dependencies: - get-intrinsic: 1.2.4 - dev: true - - /es-errors@1.3.0: - resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} - engines: {node: '>= 0.4'} - dev: true - - /es-module-lexer@1.5.0: - resolution: {integrity: sha512-pqrTKmwEIgafsYZAGw9kszYzmagcE/n4dbgwGWLEXg7J4QFJVQRBld8j3Q3GNez79jzxZshq0bcT962QHOghjw==} - dev: true - - /escalade@3.1.2: - resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} - engines: {node: '>=6'} - - /escape-html@1.0.3: - resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} - dev: true - - /escape-string-regexp@1.0.5: - resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} - engines: {node: '>=0.8.0'} - - /escape-string-regexp@4.0.0: - resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} - engines: {node: '>=10'} - dev: false - - /eslint-scope@5.1.1: - resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} - engines: {node: '>=8.0.0'} - dependencies: - esrecurse: 4.3.0 - estraverse: 4.3.0 - dev: true - - /esrecurse@4.3.0: - resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} - engines: {node: '>=4.0'} - dependencies: - estraverse: 5.3.0 - dev: true - - /estraverse@4.3.0: - resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} - engines: {node: '>=4.0'} - dev: true - - /estraverse@5.3.0: - resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} - engines: {node: '>=4.0'} - dev: true - - /esutils@2.0.3: - resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} - engines: {node: '>=0.10.0'} - dev: true - - /etag@1.8.1: - resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} - engines: {node: '>= 0.6'} - dev: true - - /eventemitter3@4.0.7: - resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} - dev: true - - /events@3.3.0: - resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} - engines: {node: '>=0.8.x'} - dev: true - - /execa@5.1.1: - resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} - engines: {node: '>=10'} - dependencies: - cross-spawn: 7.0.3 - get-stream: 6.0.1 - human-signals: 2.1.0 - is-stream: 2.0.1 - merge-stream: 2.0.0 - npm-run-path: 4.0.1 - onetime: 5.1.2 - signal-exit: 3.0.7 - strip-final-newline: 2.0.0 - dev: true - - /express@4.19.2: - resolution: {integrity: sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==} - engines: {node: '>= 0.10.0'} - dependencies: - accepts: 1.3.8 - array-flatten: 1.1.1 - body-parser: 1.20.2 - content-disposition: 0.5.4 - content-type: 1.0.5 - cookie: 0.6.0 - cookie-signature: 1.0.6 - debug: 2.6.9 - depd: 2.0.0 - encodeurl: 1.0.2 - escape-html: 1.0.3 - etag: 1.8.1 - finalhandler: 1.2.0 - fresh: 0.5.2 - http-errors: 2.0.0 - merge-descriptors: 1.0.1 - methods: 1.1.2 - on-finished: 2.4.1 - parseurl: 1.3.3 - path-to-regexp: 0.1.7 - proxy-addr: 2.0.7 - qs: 6.11.0 - range-parser: 1.2.1 - safe-buffer: 5.2.1 - send: 0.18.0 - serve-static: 1.15.0 - setprototypeof: 1.2.0 - statuses: 2.0.1 - type-is: 1.6.18 - utils-merge: 1.0.1 - vary: 1.1.2 - transitivePeerDependencies: - - supports-color - dev: true - - /fast-deep-equal@3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - dev: true - - /fast-json-stable-stringify@2.1.0: - resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - dev: true - - /fastest-levenshtein@1.0.16: - resolution: {integrity: sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==} - engines: {node: '>= 4.9.1'} - dev: true - - /faye-websocket@0.11.4: - resolution: {integrity: sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==} - engines: {node: '>=0.8.0'} - dependencies: - websocket-driver: 0.7.4 - dev: true - - /fill-range@7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} - engines: {node: '>=8'} - requiresBuild: true - dependencies: - to-regex-range: 5.0.1 - dev: true - - /finalhandler@1.2.0: - resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==} - engines: {node: '>= 0.8'} - dependencies: - debug: 2.6.9 - encodeurl: 1.0.2 - escape-html: 1.0.3 - on-finished: 2.4.1 - parseurl: 1.3.3 - statuses: 2.0.1 - unpipe: 1.0.0 - transitivePeerDependencies: - - supports-color - dev: true - - /find-cache-dir@4.0.0: - resolution: {integrity: sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg==} - engines: {node: '>=14.16'} - dependencies: - common-path-prefix: 3.0.0 - pkg-dir: 7.0.0 - dev: true - - /find-root@1.1.0: - resolution: {integrity: sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==} - dev: false - - /find-up@4.1.0: - resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} - engines: {node: '>=8'} - dependencies: - locate-path: 5.0.0 - path-exists: 4.0.0 - dev: true - - /find-up@6.3.0: - resolution: {integrity: sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - locate-path: 7.2.0 - path-exists: 5.0.0 - dev: true - - /flat@5.0.2: - resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} - hasBin: true - dev: true - - /follow-redirects@1.15.6: - resolution: {integrity: sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==} - engines: {node: '>=4.0'} - peerDependencies: - debug: '*' - peerDependenciesMeta: - debug: - optional: true - dev: true - - /foreground-child@3.1.1: - resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} - engines: {node: '>=14'} - dependencies: - cross-spawn: 7.0.3 - signal-exit: 4.1.0 - dev: true - - /forwarded@0.2.0: - resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} - engines: {node: '>= 0.6'} - dev: true - - /fresh@0.5.2: - resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} - engines: {node: '>= 0.6'} - dev: true - - /fs-readdir-recursive@1.1.0: - resolution: {integrity: sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==} - dev: true - - /fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - dev: true - - /fsevents@2.3.3: - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /function-bind@1.1.1: - resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} - - /function-bind@1.1.2: - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - dev: true - - /gensync@1.0.0-beta.2: - resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} - engines: {node: '>=6.9.0'} - dev: true - - /get-caller-file@2.0.5: - resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} - engines: {node: 6.* || 8.* || >= 10.*} - dev: false - - /get-intrinsic@1.2.4: - resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} - engines: {node: '>= 0.4'} - dependencies: - es-errors: 1.3.0 - function-bind: 1.1.2 - has-proto: 1.0.3 - has-symbols: 1.0.3 - hasown: 2.0.2 - dev: true - - /get-stream@6.0.1: - resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} - engines: {node: '>=10'} - dev: true - - /glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} - requiresBuild: true - dependencies: - is-glob: 4.0.3 - dev: true - - /glob-to-regexp@0.4.1: - resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} - dev: true - - /glob@10.3.12: - resolution: {integrity: sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==} - engines: {node: '>=16 || 14 >=14.17'} - hasBin: true - dependencies: - foreground-child: 3.1.1 - jackspeak: 2.3.6 - minimatch: 9.0.4 - minipass: 7.0.4 - path-scurry: 1.10.2 - dev: true - - /glob@7.2.3: - resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - deprecated: Glob versions prior to v9 are no longer supported - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - dev: true - - /globals@11.12.0: - resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} - engines: {node: '>=4'} - dev: true - - /gopd@1.0.1: - resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} - dependencies: - get-intrinsic: 1.2.4 - dev: true - - /graceful-fs@4.2.11: - resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - dev: true - - /handle-thing@2.0.1: - resolution: {integrity: sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==} - dev: true - - /has-flag@3.0.0: - resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} - engines: {node: '>=4'} - - /has-flag@4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} - - /has-property-descriptors@1.0.2: - resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} - dependencies: - es-define-property: 1.0.0 - dev: true - - /has-proto@1.0.3: - resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} - engines: {node: '>= 0.4'} - dev: true - - /has-symbols@1.0.3: - resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} - engines: {node: '>= 0.4'} - dev: true - - /has@1.0.3: - resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} - engines: {node: '>= 0.4.0'} - dependencies: - function-bind: 1.1.1 - - /hasown@2.0.2: - resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} - engines: {node: '>= 0.4'} - dependencies: - function-bind: 1.1.2 - dev: true - - /he@1.2.0: - resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} - hasBin: true - dev: true - - /hoist-non-react-statics@3.3.2: - resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} - dependencies: - react-is: 16.13.1 - dev: false - - /hpack.js@2.1.6: - resolution: {integrity: sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==} - dependencies: - inherits: 2.0.4 - obuf: 1.1.2 - readable-stream: 2.3.8 - wbuf: 1.7.3 - dev: true - - /html-entities@2.5.2: - resolution: {integrity: sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==} - dev: true - - /html-minifier-terser@6.1.0: - resolution: {integrity: sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==} - engines: {node: '>=12'} - hasBin: true - dependencies: - camel-case: 4.1.2 - clean-css: 5.3.3 - commander: 8.3.0 - he: 1.2.0 - param-case: 3.0.4 - relateurl: 0.2.7 - terser: 5.30.3 - dev: true - - /html-webpack-plugin@5.6.0(webpack@5.92.1): - resolution: {integrity: sha512-iwaY4wzbe48AfKLZ/Cc8k0L+FKG6oSNRaZ8x5A/T/IVDGyXcbHncM9TdDa93wn0FsSm82FhTKW7f3vS61thXAw==} - engines: {node: '>=10.13.0'} - peerDependencies: - '@rspack/core': 0.x || 1.x - webpack: ^5.20.0 - peerDependenciesMeta: - '@rspack/core': - optional: true - webpack: - optional: true - dependencies: - '@types/html-minifier-terser': 6.1.0 - html-minifier-terser: 6.1.0 - lodash: 4.17.21 - pretty-error: 4.0.0 - tapable: 2.2.1 - webpack: 5.92.1(webpack-cli@5.1.4) - dev: true - - /htmlparser2@6.1.0: - resolution: {integrity: sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==} - dependencies: - domelementtype: 2.3.0 - domhandler: 4.3.1 - domutils: 2.8.0 - entities: 2.2.0 - dev: true - - /http-deceiver@1.2.7: - resolution: {integrity: sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==} - dev: true - - /http-errors@1.6.3: - resolution: {integrity: sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==} - engines: {node: '>= 0.6'} - dependencies: - depd: 1.1.2 - inherits: 2.0.3 - setprototypeof: 1.1.0 - statuses: 1.5.0 - dev: true - - /http-errors@2.0.0: - resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} - engines: {node: '>= 0.8'} - dependencies: - depd: 2.0.0 - inherits: 2.0.4 - setprototypeof: 1.2.0 - statuses: 2.0.1 - toidentifier: 1.0.1 - dev: true - - /http-parser-js@0.5.8: - resolution: {integrity: sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==} - dev: true - - /http-proxy-middleware@2.0.6(@types/express@4.17.21): - resolution: {integrity: sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==} - engines: {node: '>=12.0.0'} - peerDependencies: - '@types/express': ^4.17.13 - peerDependenciesMeta: - '@types/express': - optional: true - dependencies: - '@types/express': 4.17.21 - '@types/http-proxy': 1.17.14 - http-proxy: 1.18.1 - is-glob: 4.0.3 - is-plain-obj: 3.0.0 - micromatch: 4.0.5 - transitivePeerDependencies: - - debug - dev: true - - /http-proxy@1.18.1: - resolution: {integrity: sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==} - engines: {node: '>=8.0.0'} - dependencies: - eventemitter3: 4.0.7 - follow-redirects: 1.15.6 - requires-port: 1.0.0 - transitivePeerDependencies: - - debug - dev: true - - /human-signals@2.1.0: - resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} - engines: {node: '>=10.17.0'} - dev: true - - /iconv-lite@0.4.24: - resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} - engines: {node: '>=0.10.0'} - dependencies: - safer-buffer: 2.1.2 - dev: true - - /icss-utils@5.1.0(postcss@8.4.38): - resolution: {integrity: sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==} - engines: {node: ^10 || ^12 || >= 14} - peerDependencies: - postcss: ^8.1.0 - dependencies: - postcss: 8.4.38 - dev: true - - /import-fresh@3.3.0: - resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} - engines: {node: '>=6'} - dependencies: - parent-module: 1.0.1 - resolve-from: 4.0.0 - dev: false - - /import-local@3.1.0: - resolution: {integrity: sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==} - engines: {node: '>=8'} - hasBin: true - dependencies: - pkg-dir: 4.2.0 - resolve-cwd: 3.0.0 - dev: true - - /inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - dev: true - - /inherits@2.0.3: - resolution: {integrity: sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==} - dev: true - - /inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - dev: true - - /interpret@3.1.1: - resolution: {integrity: sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==} - engines: {node: '>=10.13.0'} - dev: true - - /ipaddr.js@1.9.1: - resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} - engines: {node: '>= 0.10'} - dev: true - - /ipaddr.js@2.1.0: - resolution: {integrity: sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ==} - engines: {node: '>= 10'} - dev: true - - /is-arrayish@0.2.1: - resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - dev: false - - /is-binary-path@2.1.0: - resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} - engines: {node: '>=8'} - requiresBuild: true - dependencies: - binary-extensions: 2.3.0 - dev: true - - /is-core-module@2.11.0: - resolution: {integrity: sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==} - dependencies: - has: 1.0.3 - - /is-docker@3.0.0: - resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - hasBin: true - dev: true - - /is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - requiresBuild: true - dev: true - - /is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - - /is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} - requiresBuild: true - dependencies: - is-extglob: 2.1.1 - dev: true - - /is-inside-container@1.0.0: - resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} - engines: {node: '>=14.16'} - hasBin: true - dependencies: - is-docker: 3.0.0 - dev: true - - /is-network-error@1.1.0: - resolution: {integrity: sha512-tUdRRAnhT+OtCZR/LxZelH/C7QtjtFrTu5tXCA8pl55eTUElUHT+GPYV8MBMBvea/j+NxQqVt3LbWMRir7Gx9g==} - engines: {node: '>=16'} - dev: true - - /is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - requiresBuild: true - dev: true - - /is-plain-obj@3.0.0: - resolution: {integrity: sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==} - engines: {node: '>=10'} - dev: true - - /is-plain-object@2.0.4: - resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==} - engines: {node: '>=0.10.0'} - dependencies: - isobject: 3.0.1 - dev: true - - /is-stream@2.0.1: - resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} - engines: {node: '>=8'} - dev: true - - /is-wsl@3.1.0: - resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==} - engines: {node: '>=16'} - dependencies: - is-inside-container: 1.0.0 - dev: true - - /isarray@1.0.0: - resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} - dev: true - - /isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - dev: true - - /isobject@3.0.1: - resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} - engines: {node: '>=0.10.0'} - dev: true - - /jackspeak@2.3.6: - resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} - engines: {node: '>=14'} - dependencies: - '@isaacs/cliui': 8.0.2 - optionalDependencies: - '@pkgjs/parseargs': 0.11.0 - dev: true - - /jest-worker@27.5.1: - resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} - engines: {node: '>= 10.13.0'} - dependencies: - '@types/node': 20.14.6 - merge-stream: 2.0.0 - supports-color: 8.1.1 - dev: true - - /js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - - /jsesc@0.5.0: - resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} - hasBin: true - dev: true - - /jsesc@2.5.2: - resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} - engines: {node: '>=4'} - hasBin: true - dev: true - - /json-parse-even-better-errors@2.3.1: - resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - - /json-schema-traverse@0.4.1: - resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - dev: true - - /json-schema-traverse@1.0.0: - resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} - dev: true - - /json5@2.2.3: - resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} - engines: {node: '>=6'} - hasBin: true - dev: true - - /kind-of@6.0.3: - resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} - engines: {node: '>=0.10.0'} - dev: true - - /launch-editor@2.6.1: - resolution: {integrity: sha512-eB/uXmFVpY4zezmGp5XtU21kwo7GBbKB+EQ+UZeWtGb9yAM5xt/Evk+lYH3eRNAtId+ej4u7TYPFZ07w4s7rRw==} - dependencies: - picocolors: 1.0.0 - shell-quote: 1.8.1 - dev: true - - /lines-and-columns@1.2.4: - resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - dev: false - - /loader-runner@4.3.0: - resolution: {integrity: sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==} - engines: {node: '>=6.11.5'} - dev: true - - /locate-path@5.0.0: - resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} - engines: {node: '>=8'} - dependencies: - p-locate: 4.1.0 - dev: true - - /locate-path@7.2.0: - resolution: {integrity: sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - p-locate: 6.0.0 - dev: true - - /lodash.debounce@4.0.8: - resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} - dev: true - - /lodash@4.17.21: - resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - - /loose-envify@1.4.0: - resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} - hasBin: true - dependencies: - js-tokens: 4.0.0 - dev: false - - /lower-case@2.0.2: - resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} - dependencies: - tslib: 2.6.2 - dev: true - - /lru-cache@10.2.0: - resolution: {integrity: sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==} - engines: {node: 14 || >=16.14} - dev: true - - /lru-cache@5.1.1: - resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} - dependencies: - yallist: 3.1.1 - dev: true - - /lru-cache@6.0.0: - resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} - engines: {node: '>=10'} - dependencies: - yallist: 4.0.0 - dev: true - - /make-dir@2.1.0: - resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==} - engines: {node: '>=6'} - dependencies: - pify: 4.0.1 - semver: 5.7.2 - dev: true - - /make-error@1.3.6: - resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} - dev: true - - /media-typer@0.3.0: - resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} - engines: {node: '>= 0.6'} - dev: true - - /memfs@4.8.1: - resolution: {integrity: sha512-7q/AdPzf2WpwPlPL4v1kE2KsJsHl7EF4+hAeVzlyanr2+YnR21NVn9mDqo+7DEaKDRsQy8nvxPlKH4WqMtiO0w==} - engines: {node: '>= 4.0.0'} - dependencies: - tslib: 2.6.2 - dev: true - - /merge-descriptors@1.0.1: - resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==} - dev: true - - /merge-stream@2.0.0: - resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - dev: true - - /methods@1.1.2: - resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} - engines: {node: '>= 0.6'} - dev: true - - /micromatch@4.0.5: - resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} - engines: {node: '>=8.6'} - dependencies: - braces: 3.0.2 - picomatch: 2.3.1 - dev: true - - /mime-db@1.52.0: - resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} - engines: {node: '>= 0.6'} - dev: true - - /mime-types@2.1.35: - resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} - engines: {node: '>= 0.6'} - dependencies: - mime-db: 1.52.0 - dev: true - - /mime@1.6.0: - resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} - engines: {node: '>=4'} - hasBin: true - dev: true - - /mimic-fn@2.1.0: - resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} - engines: {node: '>=6'} - dev: true - - /minimalistic-assert@1.0.1: - resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} - dev: true - - /minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - dependencies: - brace-expansion: 1.1.11 - dev: true - - /minimatch@9.0.4: - resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==} - engines: {node: '>=16 || 14 >=14.17'} - dependencies: - brace-expansion: 2.0.1 - dev: true - - /minipass@7.0.4: - resolution: {integrity: sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==} - engines: {node: '>=16 || 14 >=14.17'} - dev: true - - /ms@2.0.0: - resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} - dev: true - - /ms@2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - dev: true - - /ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - dev: true - - /multicast-dns@7.2.5: - resolution: {integrity: sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==} - hasBin: true - dependencies: - dns-packet: 5.6.1 - thunky: 1.1.0 - dev: true - - /nanoid@3.3.7: - resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - dev: true - - /negotiator@0.6.3: - resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} - engines: {node: '>= 0.6'} - dev: true - - /neo-async@2.6.2: - resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} - dev: true - - /no-case@3.0.4: - resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} - dependencies: - lower-case: 2.0.2 - tslib: 2.6.2 - dev: true - - /node-forge@1.3.1: - resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==} - engines: {node: '>= 6.13.0'} - dev: true - - /node-releases@2.0.14: - resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==} - dev: true - - /normalize-path@3.0.0: - resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} - engines: {node: '>=0.10.0'} - requiresBuild: true - dev: true - - /notistack@2.0.8(@emotion/react@11.11.4)(@emotion/styled@11.11.5)(@mui/material@5.15.20)(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-/IY14wkFp5qjPgKNvAdfL5Jp6q90+MjgKTPh4c81r/lW70KeuX6b9pE/4f8L4FG31cNudbN9siiFS5ql1aSLRw==} - peerDependencies: - '@emotion/react': ^11.4.1 - '@emotion/styled': ^11.3.0 - '@mui/material': ^5.0.0 - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - '@emotion/react': - optional: true - '@emotion/styled': - optional: true - dependencies: - '@emotion/react': 11.11.4(@types/react@18.3.3)(react@18.3.1) - '@emotion/styled': 11.11.5(@emotion/react@11.11.4)(@types/react@18.3.3)(react@18.3.1) - '@mui/material': 5.15.20(@emotion/react@11.11.4)(@emotion/styled@11.11.5)(@types/react@18.3.3)(react-dom@18.3.1)(react@18.3.1) - clsx: 1.2.1 - hoist-non-react-statics: 3.3.2 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - - /npm-run-path@4.0.1: - resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} - engines: {node: '>=8'} - dependencies: - path-key: 3.1.1 - dev: true - - /nth-check@2.1.1: - resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} - dependencies: - boolbase: 1.0.0 - dev: true - - /object-assign@4.1.1: - resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} - engines: {node: '>=0.10.0'} - dev: false - - /object-inspect@1.13.1: - resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} - dev: true - - /obuf@1.1.2: - resolution: {integrity: sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==} - dev: true - - /on-finished@2.4.1: - resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} - engines: {node: '>= 0.8'} - dependencies: - ee-first: 1.1.1 - dev: true - - /on-headers@1.0.2: - resolution: {integrity: sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==} - engines: {node: '>= 0.8'} - dev: true - - /once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - dependencies: - wrappy: 1.0.2 - dev: true - - /onetime@5.1.2: - resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} - engines: {node: '>=6'} - dependencies: - mimic-fn: 2.1.0 - dev: true - - /open@10.1.0: - resolution: {integrity: sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==} - engines: {node: '>=18'} - dependencies: - default-browser: 5.2.1 - define-lazy-prop: 3.0.0 - is-inside-container: 1.0.0 - is-wsl: 3.1.0 - dev: true - - /p-limit@2.3.0: - resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} - engines: {node: '>=6'} - dependencies: - p-try: 2.2.0 - dev: true - - /p-limit@4.0.0: - resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - yocto-queue: 1.0.0 - dev: true - - /p-locate@4.1.0: - resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} - engines: {node: '>=8'} - dependencies: - p-limit: 2.3.0 - dev: true - - /p-locate@6.0.0: - resolution: {integrity: sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - p-limit: 4.0.0 - dev: true - - /p-retry@6.2.0: - resolution: {integrity: sha512-JA6nkq6hKyWLLasXQXUrO4z8BUZGUt/LjlJxx8Gb2+2ntodU/SS63YZ8b0LUTbQ8ZB9iwOfhEPhg4ykKnn2KsA==} - engines: {node: '>=16.17'} - dependencies: - '@types/retry': 0.12.2 - is-network-error: 1.1.0 - retry: 0.13.1 - dev: true - - /p-try@2.2.0: - resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} - engines: {node: '>=6'} - dev: true - - /param-case@3.0.4: - resolution: {integrity: sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==} - dependencies: - dot-case: 3.0.4 - tslib: 2.6.2 - dev: true - - /parent-module@1.0.1: - resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} - engines: {node: '>=6'} - dependencies: - callsites: 3.1.0 - dev: false - - /parse-json@5.2.0: - resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} - engines: {node: '>=8'} - dependencies: - '@babel/code-frame': 7.18.6 - error-ex: 1.3.2 - json-parse-even-better-errors: 2.3.1 - lines-and-columns: 1.2.4 - dev: false - - /parseurl@1.3.3: - resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} - engines: {node: '>= 0.8'} - dev: true - - /pascal-case@3.1.2: - resolution: {integrity: sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==} - dependencies: - no-case: 3.0.4 - tslib: 2.6.2 - dev: true - - /path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} - dev: true - - /path-exists@5.0.0: - resolution: {integrity: sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dev: true - - /path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - dev: true - - /path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - dev: true - - /path-parse@1.0.7: - resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - - /path-scurry@1.10.2: - resolution: {integrity: sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==} - engines: {node: '>=16 || 14 >=14.17'} - dependencies: - lru-cache: 10.2.0 - minipass: 7.0.4 - dev: true - - /path-to-regexp@0.1.7: - resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} - dev: true - - /path-type@4.0.0: - resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} - engines: {node: '>=8'} - dev: false - - /picocolors@1.0.0: - resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} - dev: true - - /picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - requiresBuild: true - dev: true - - /pify@4.0.1: - resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} - engines: {node: '>=6'} - dev: true - - /pkg-dir@4.2.0: - resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} - engines: {node: '>=8'} - dependencies: - find-up: 4.1.0 - dev: true - - /pkg-dir@7.0.0: - resolution: {integrity: sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==} - engines: {node: '>=14.16'} - dependencies: - find-up: 6.3.0 - dev: true - - /postcss-modules-extract-imports@3.1.0(postcss@8.4.38): - resolution: {integrity: sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==} - engines: {node: ^10 || ^12 || >= 14} - peerDependencies: - postcss: ^8.1.0 - dependencies: - postcss: 8.4.38 - dev: true - - /postcss-modules-local-by-default@4.0.5(postcss@8.4.38): - resolution: {integrity: sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw==} - engines: {node: ^10 || ^12 || >= 14} - peerDependencies: - postcss: ^8.1.0 - dependencies: - icss-utils: 5.1.0(postcss@8.4.38) - postcss: 8.4.38 - postcss-selector-parser: 6.0.16 - postcss-value-parser: 4.2.0 - dev: true - - /postcss-modules-scope@3.2.0(postcss@8.4.38): - resolution: {integrity: sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ==} - engines: {node: ^10 || ^12 || >= 14} - peerDependencies: - postcss: ^8.1.0 - dependencies: - postcss: 8.4.38 - postcss-selector-parser: 6.0.16 - dev: true - - /postcss-modules-values@4.0.0(postcss@8.4.38): - resolution: {integrity: sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==} - engines: {node: ^10 || ^12 || >= 14} - peerDependencies: - postcss: ^8.1.0 - dependencies: - icss-utils: 5.1.0(postcss@8.4.38) - postcss: 8.4.38 - dev: true - - /postcss-selector-parser@6.0.16: - resolution: {integrity: sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==} - engines: {node: '>=4'} - dependencies: - cssesc: 3.0.0 - util-deprecate: 1.0.2 - dev: true - - /postcss-value-parser@4.2.0: - resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} - dev: true - - /postcss@8.4.38: - resolution: {integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==} - engines: {node: ^10 || ^12 || >=14} - dependencies: - nanoid: 3.3.7 - picocolors: 1.0.0 - source-map-js: 1.2.0 - dev: true - - /pretty-error@4.0.0: - resolution: {integrity: sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==} - dependencies: - lodash: 4.17.21 - renderkid: 3.0.0 - dev: true - - /process-nextick-args@2.0.1: - resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} - dev: true - - /prop-types@15.8.1: - resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} - dependencies: - loose-envify: 1.4.0 - object-assign: 4.1.1 - react-is: 16.13.1 - dev: false - - /proxy-addr@2.0.7: - resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} - engines: {node: '>= 0.10'} - dependencies: - forwarded: 0.2.0 - ipaddr.js: 1.9.1 - dev: true - - /punycode@2.3.1: - resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} - engines: {node: '>=6'} - dev: true - - /qs@6.11.0: - resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==} - engines: {node: '>=0.6'} - dependencies: - side-channel: 1.0.6 - dev: true - - /randombytes@2.1.0: - resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} - dependencies: - safe-buffer: 5.2.1 - dev: true - - /range-parser@1.2.1: - resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} - engines: {node: '>= 0.6'} - dev: true - - /raw-body@2.5.2: - resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} - engines: {node: '>= 0.8'} - dependencies: - bytes: 3.1.2 - http-errors: 2.0.0 - iconv-lite: 0.4.24 - unpipe: 1.0.0 - dev: true - - /react-dom@18.3.1(react@18.3.1): - resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==} - peerDependencies: - react: ^18.3.1 - dependencies: - loose-envify: 1.4.0 - react: 18.3.1 - scheduler: 0.23.2 - dev: false - - /react-is@16.13.1: - resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} - dev: false - - /react-is@18.2.0: - resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==} - dev: false - - /react-transition-group@4.4.5(react-dom@18.3.1)(react@18.3.1): - resolution: {integrity: sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==} - peerDependencies: - react: '>=16.6.0' - react-dom: '>=16.6.0' - dependencies: - '@babel/runtime': 7.24.4 - dom-helpers: 5.2.1 - loose-envify: 1.4.0 - prop-types: 15.8.1 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - dev: false - - /react@18.3.1: - resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} - engines: {node: '>=0.10.0'} - dependencies: - loose-envify: 1.4.0 - dev: false - - /readable-stream@2.3.8: - resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} - dependencies: - core-util-is: 1.0.3 - inherits: 2.0.4 - isarray: 1.0.0 - process-nextick-args: 2.0.1 - safe-buffer: 5.1.2 - string_decoder: 1.1.1 - util-deprecate: 1.0.2 - dev: true - - /readable-stream@3.6.2: - resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} - engines: {node: '>= 6'} - dependencies: - inherits: 2.0.4 - string_decoder: 1.3.0 - util-deprecate: 1.0.2 - dev: true - - /readdirp@3.6.0: - resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} - engines: {node: '>=8.10.0'} - requiresBuild: true - dependencies: - picomatch: 2.3.1 - dev: true - - /rechoir@0.8.0: - resolution: {integrity: sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==} - engines: {node: '>= 10.13.0'} - dependencies: - resolve: 1.22.1 - dev: true - - /regenerate-unicode-properties@10.1.1: - resolution: {integrity: sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==} - engines: {node: '>=4'} - dependencies: - regenerate: 1.4.2 - dev: true - - /regenerate@1.4.2: - resolution: {integrity: sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==} - dev: true - - /regenerator-runtime@0.13.11: - resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==} - dev: false - - /regenerator-runtime@0.14.1: - resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} - - /regenerator-transform@0.15.2: - resolution: {integrity: sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==} - dependencies: - '@babel/runtime': 7.24.4 - dev: true - - /regexpu-core@5.3.2: - resolution: {integrity: sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==} - engines: {node: '>=4'} - dependencies: - '@babel/regjsgen': 0.8.0 - regenerate: 1.4.2 - regenerate-unicode-properties: 10.1.1 - regjsparser: 0.9.1 - unicode-match-property-ecmascript: 2.0.0 - unicode-match-property-value-ecmascript: 2.1.0 - dev: true - - /regjsparser@0.9.1: - resolution: {integrity: sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==} - hasBin: true - dependencies: - jsesc: 0.5.0 - dev: true - - /relateurl@0.2.7: - resolution: {integrity: sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==} - engines: {node: '>= 0.10'} - dev: true - - /renderkid@3.0.0: - resolution: {integrity: sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==} - dependencies: - css-select: 4.3.0 - dom-converter: 0.2.0 - htmlparser2: 6.1.0 - lodash: 4.17.21 - strip-ansi: 6.0.1 - dev: true - - /require-directory@2.1.1: - resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} - engines: {node: '>=0.10.0'} - dev: false - - /require-from-string@2.0.2: - resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} - engines: {node: '>=0.10.0'} - dev: true - - /requires-port@1.0.0: - resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} - dev: true - - /resolve-cwd@3.0.0: - resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} - engines: {node: '>=8'} - dependencies: - resolve-from: 5.0.0 - dev: true - - /resolve-from@4.0.0: - resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} - engines: {node: '>=4'} - dev: false - - /resolve-from@5.0.0: - resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} - engines: {node: '>=8'} - dev: true - - /resolve@1.22.1: - resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==} - hasBin: true - dependencies: - is-core-module: 2.11.0 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - - /retry@0.13.1: - resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} - engines: {node: '>= 4'} - dev: true - - /rimraf@5.0.5: - resolution: {integrity: sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==} - engines: {node: '>=14'} - hasBin: true - dependencies: - glob: 10.3.12 - dev: true - - /run-applescript@7.0.0: - resolution: {integrity: sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==} - engines: {node: '>=18'} - dev: true - - /rxjs@7.8.1: - resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} - dependencies: - tslib: 2.6.2 - dev: false - - /safe-buffer@5.1.2: - resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} - dev: true - - /safe-buffer@5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - dev: true - - /safer-buffer@2.1.2: - resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - dev: true - - /scheduler@0.23.2: - resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} - dependencies: - loose-envify: 1.4.0 - dev: false - - /schema-utils@3.3.0: - resolution: {integrity: sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==} - engines: {node: '>= 10.13.0'} - dependencies: - '@types/json-schema': 7.0.15 - ajv: 6.12.6 - ajv-keywords: 3.5.2(ajv@6.12.6) - dev: true - - /schema-utils@4.2.0: - resolution: {integrity: sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==} - engines: {node: '>= 12.13.0'} - dependencies: - '@types/json-schema': 7.0.15 - ajv: 8.12.0 - ajv-formats: 2.1.1(ajv@8.12.0) - ajv-keywords: 5.1.0(ajv@8.12.0) - dev: true - - /select-hose@2.0.0: - resolution: {integrity: sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==} - dev: true - - /selfsigned@2.4.1: - resolution: {integrity: sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==} - engines: {node: '>=10'} - dependencies: - '@types/node-forge': 1.3.11 - node-forge: 1.3.1 - dev: true - - /semver@5.7.2: - resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} - hasBin: true - dev: true - - /semver@6.3.1: - resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} - hasBin: true - dev: true - - /semver@7.6.0: - resolution: {integrity: sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==} - engines: {node: '>=10'} - hasBin: true - dependencies: - lru-cache: 6.0.0 - dev: true - - /send@0.18.0: - resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==} - engines: {node: '>= 0.8.0'} - dependencies: - debug: 2.6.9 - depd: 2.0.0 - destroy: 1.2.0 - encodeurl: 1.0.2 - escape-html: 1.0.3 - etag: 1.8.1 - fresh: 0.5.2 - http-errors: 2.0.0 - mime: 1.6.0 - ms: 2.1.3 - on-finished: 2.4.1 - range-parser: 1.2.1 - statuses: 2.0.1 - transitivePeerDependencies: - - supports-color - dev: true - - /serialize-javascript@6.0.2: - resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==} - dependencies: - randombytes: 2.1.0 - dev: true - - /serve-index@1.9.1: - resolution: {integrity: sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==} - engines: {node: '>= 0.8.0'} - dependencies: - accepts: 1.3.8 - batch: 0.6.1 - debug: 2.6.9 - escape-html: 1.0.3 - http-errors: 1.6.3 - mime-types: 2.1.35 - parseurl: 1.3.3 - transitivePeerDependencies: - - supports-color - dev: true - - /serve-static@1.15.0: - resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==} - engines: {node: '>= 0.8.0'} - dependencies: - encodeurl: 1.0.2 - escape-html: 1.0.3 - parseurl: 1.3.3 - send: 0.18.0 - transitivePeerDependencies: - - supports-color - dev: true - - /set-function-length@1.2.2: - resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} - engines: {node: '>= 0.4'} - dependencies: - define-data-property: 1.1.4 - es-errors: 1.3.0 - function-bind: 1.1.2 - get-intrinsic: 1.2.4 - gopd: 1.0.1 - has-property-descriptors: 1.0.2 - dev: true - - /setprototypeof@1.1.0: - resolution: {integrity: sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==} - dev: true - - /setprototypeof@1.2.0: - resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} - dev: true - - /shallow-clone@3.0.1: - resolution: {integrity: sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==} - engines: {node: '>=8'} - dependencies: - kind-of: 6.0.3 - dev: true - - /shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} - dependencies: - shebang-regex: 3.0.0 - dev: true - - /shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} - dev: true - - /shell-quote@1.8.1: - resolution: {integrity: sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==} - - /side-channel@1.0.6: - resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - get-intrinsic: 1.2.4 - object-inspect: 1.13.1 - dev: true - - /signal-exit@3.0.7: - resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} - dev: true - - /signal-exit@4.1.0: - resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} - engines: {node: '>=14'} - dev: true - - /slash@2.0.0: - resolution: {integrity: sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==} - engines: {node: '>=6'} - dev: true - - /sockjs@0.3.24: - resolution: {integrity: sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==} - dependencies: - faye-websocket: 0.11.4 - uuid: 8.3.2 - websocket-driver: 0.7.4 - dev: true - - /source-map-js@1.2.0: - resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} - engines: {node: '>=0.10.0'} - dev: true - - /source-map-support@0.5.21: - resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} - dependencies: - buffer-from: 1.1.2 - source-map: 0.6.1 - dev: true - - /source-map@0.5.7: - resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} - engines: {node: '>=0.10.0'} - dev: false - - /source-map@0.6.1: - resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} - engines: {node: '>=0.10.0'} - dev: true - - /spawn-command@0.0.2: - resolution: {integrity: sha512-zC8zGoGkmc8J9ndvml8Xksr1Amk9qBujgbF0JAIWO7kXr43w0h/0GJNM/Vustixu+YE8N/MTrQ7N31FvHUACxQ==} - dev: false - - /spdy-transport@3.0.0: - resolution: {integrity: sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==} - dependencies: - debug: 4.3.4 - detect-node: 2.1.0 - hpack.js: 2.1.6 - obuf: 1.1.2 - readable-stream: 3.6.2 - wbuf: 1.7.3 - transitivePeerDependencies: - - supports-color - dev: true - - /spdy@4.0.2: - resolution: {integrity: sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==} - engines: {node: '>=6.0.0'} - dependencies: - debug: 4.3.4 - handle-thing: 2.0.1 - http-deceiver: 1.2.7 - select-hose: 2.0.0 - spdy-transport: 3.0.0 - transitivePeerDependencies: - - supports-color - dev: true - - /statuses@1.5.0: - resolution: {integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==} - engines: {node: '>= 0.6'} - dev: true - - /statuses@2.0.1: - resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} - engines: {node: '>= 0.8'} - dev: true - - /string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} - dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 - - /string-width@5.1.2: - resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} - engines: {node: '>=12'} - dependencies: - eastasianwidth: 0.2.0 - emoji-regex: 9.2.2 - strip-ansi: 7.1.0 - dev: true - - /string_decoder@1.1.1: - resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} - dependencies: - safe-buffer: 5.1.2 - dev: true - - /string_decoder@1.3.0: - resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} - dependencies: - safe-buffer: 5.2.1 - dev: true - - /strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} - dependencies: - ansi-regex: 5.0.1 - - /strip-ansi@7.1.0: - resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} - engines: {node: '>=12'} - dependencies: - ansi-regex: 6.0.1 - dev: true - - /strip-final-newline@2.0.0: - resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} - engines: {node: '>=6'} - dev: true - - /style-loader@3.3.4(webpack@5.92.1): - resolution: {integrity: sha512-0WqXzrsMTyb8yjZJHDqwmnwRJvhALK9LfRtRc6B4UTWe8AijYLZYZ9thuJTZc2VfQWINADW/j+LiJnfy2RoC1w==} - engines: {node: '>= 12.13.0'} - peerDependencies: - webpack: ^5.0.0 - dependencies: - webpack: 5.92.1(webpack-cli@5.1.4) - dev: true - - /stylis@4.2.0: - resolution: {integrity: sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==} - dev: false - - /supports-color@5.5.0: - resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} - engines: {node: '>=4'} - dependencies: - has-flag: 3.0.0 - - /supports-color@7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} - dependencies: - has-flag: 4.0.0 - dev: false - - /supports-color@8.1.1: - resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} - engines: {node: '>=10'} - dependencies: - has-flag: 4.0.0 - - /supports-preserve-symlinks-flag@1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} - - /tapable@2.2.1: - resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} - engines: {node: '>=6'} - dev: true - - /terser-webpack-plugin@5.3.10(webpack@5.92.1): - resolution: {integrity: sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==} - engines: {node: '>= 10.13.0'} - peerDependencies: - '@swc/core': '*' - esbuild: '*' - uglify-js: '*' - webpack: ^5.1.0 - peerDependenciesMeta: - '@swc/core': - optional: true - esbuild: - optional: true - uglify-js: - optional: true - dependencies: - '@jridgewell/trace-mapping': 0.3.25 - jest-worker: 27.5.1 - schema-utils: 3.3.0 - serialize-javascript: 6.0.2 - terser: 5.30.3 - webpack: 5.92.1(webpack-cli@5.1.4) - dev: true - - /terser@5.30.3: - resolution: {integrity: sha512-STdUgOUx8rLbMGO9IOwHLpCqolkDITFFQSMYYwKE1N2lY6MVSaeoi10z/EhWxRc6ybqoVmKSkhKYH/XUpl7vSA==} - engines: {node: '>=10'} - hasBin: true - dependencies: - '@jridgewell/source-map': 0.3.6 - acorn: 8.11.3 - commander: 2.20.3 - source-map-support: 0.5.21 - dev: true - - /thunky@1.1.0: - resolution: {integrity: sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==} - dev: true - - /to-fast-properties@2.0.0: - resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} - engines: {node: '>=4'} - - /to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} - requiresBuild: true - dependencies: - is-number: 7.0.0 - dev: true - - /toidentifier@1.0.1: - resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} - engines: {node: '>=0.6'} - dev: true - - /tree-kill@1.2.2: - resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} - hasBin: true - dev: false - - /ts-node@10.9.2(@types/node@20.14.6)(typescript@5.5.2): - resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} - hasBin: true - peerDependencies: - '@swc/core': '>=1.2.50' - '@swc/wasm': '>=1.2.50' - '@types/node': '*' - typescript: '>=2.7' - peerDependenciesMeta: - '@swc/core': - optional: true - '@swc/wasm': - optional: true - dependencies: - '@cspotcode/source-map-support': 0.8.1 - '@tsconfig/node10': 1.0.11 - '@tsconfig/node12': 1.0.11 - '@tsconfig/node14': 1.0.3 - '@tsconfig/node16': 1.0.4 - '@types/node': 20.14.6 - acorn: 8.11.3 - acorn-walk: 8.3.2 - arg: 4.1.3 - create-require: 1.1.1 - diff: 4.0.2 - make-error: 1.3.6 - typescript: 5.5.2 - v8-compile-cache-lib: 3.0.1 - yn: 3.1.1 - dev: true - - /tslib@2.6.2: - resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} - - /type-is@1.6.18: - resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} - engines: {node: '>= 0.6'} - dependencies: - media-typer: 0.3.0 - mime-types: 2.1.35 - dev: true - - /typescript@5.5.2: - resolution: {integrity: sha512-NcRtPEOsPFFWjobJEtfihkLCZCXZt/os3zf8nTxjVH3RvTSxjrCamJpbExGvYOF+tFHc3pA65qpdwPbzjohhew==} - engines: {node: '>=14.17'} - hasBin: true - - /undici-types@5.26.5: - resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} - dev: true - - /unicode-canonical-property-names-ecmascript@2.0.0: - resolution: {integrity: sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==} - engines: {node: '>=4'} - dev: true - - /unicode-match-property-ecmascript@2.0.0: - resolution: {integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==} - engines: {node: '>=4'} - dependencies: - unicode-canonical-property-names-ecmascript: 2.0.0 - unicode-property-aliases-ecmascript: 2.1.0 - dev: true - - /unicode-match-property-value-ecmascript@2.1.0: - resolution: {integrity: sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==} - engines: {node: '>=4'} - dev: true - - /unicode-property-aliases-ecmascript@2.1.0: - resolution: {integrity: sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==} - engines: {node: '>=4'} - dev: true - - /unpipe@1.0.0: - resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} - engines: {node: '>= 0.8'} - dev: true - - /update-browserslist-db@1.0.13(browserslist@4.23.0): - resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==} - hasBin: true - peerDependencies: - browserslist: '>= 4.21.0' - dependencies: - browserslist: 4.23.0 - escalade: 3.1.2 - picocolors: 1.0.0 - dev: true - - /uri-js@4.4.1: - resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - dependencies: - punycode: 2.3.1 - dev: true - - /util-deprecate@1.0.2: - resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - dev: true - - /utila@0.4.0: - resolution: {integrity: sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==} - dev: true - - /utils-merge@1.0.1: - resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} - engines: {node: '>= 0.4.0'} - dev: true - - /uuid@8.3.2: - resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} - hasBin: true - dev: true - - /uuid@9.0.1: - resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} - hasBin: true - dev: false - - /v8-compile-cache-lib@3.0.1: - resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} - dev: true - - /vary@1.1.2: - resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} - engines: {node: '>= 0.8'} - dev: true - - /watchpack@2.4.1: - resolution: {integrity: sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==} - engines: {node: '>=10.13.0'} - dependencies: - glob-to-regexp: 0.4.1 - graceful-fs: 4.2.11 - dev: true - - /wbuf@1.7.3: - resolution: {integrity: sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==} - dependencies: - minimalistic-assert: 1.0.1 - dev: true - - /webpack-cli@5.1.4(webpack-dev-server@5.0.4)(webpack@5.92.1): - resolution: {integrity: sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==} - engines: {node: '>=14.15.0'} - hasBin: true - peerDependencies: - '@webpack-cli/generators': '*' - webpack: 5.x.x - webpack-bundle-analyzer: '*' - webpack-dev-server: '*' - peerDependenciesMeta: - '@webpack-cli/generators': - optional: true - webpack-bundle-analyzer: - optional: true - webpack-dev-server: - optional: true - dependencies: - '@discoveryjs/json-ext': 0.5.7 - '@webpack-cli/configtest': 2.1.1(webpack-cli@5.1.4)(webpack@5.92.1) - '@webpack-cli/info': 2.0.2(webpack-cli@5.1.4)(webpack@5.92.1) - '@webpack-cli/serve': 2.0.5(webpack-cli@5.1.4)(webpack-dev-server@5.0.4)(webpack@5.92.1) - colorette: 2.0.20 - commander: 10.0.1 - cross-spawn: 7.0.3 - envinfo: 7.12.0 - fastest-levenshtein: 1.0.16 - import-local: 3.1.0 - interpret: 3.1.1 - rechoir: 0.8.0 - webpack: 5.92.1(webpack-cli@5.1.4) - webpack-dev-server: 5.0.4(webpack-cli@5.1.4)(webpack@5.92.1) - webpack-merge: 5.10.0 - dev: true - - /webpack-dev-middleware@7.2.1(webpack@5.92.1): - resolution: {integrity: sha512-hRLz+jPQXo999Nx9fXVdKlg/aehsw1ajA9skAneGmT03xwmyuhvF93p6HUKKbWhXdcERtGTzUCtIQr+2IQegrA==} - engines: {node: '>= 18.12.0'} - peerDependencies: - webpack: ^5.0.0 - peerDependenciesMeta: - webpack: - optional: true - dependencies: - colorette: 2.0.20 - memfs: 4.8.1 - mime-types: 2.1.35 - on-finished: 2.4.1 - range-parser: 1.2.1 - schema-utils: 4.2.0 - webpack: 5.92.1(webpack-cli@5.1.4) - dev: true - - /webpack-dev-server@5.0.4(webpack-cli@5.1.4)(webpack@5.92.1): - resolution: {integrity: sha512-dljXhUgx3HqKP2d8J/fUMvhxGhzjeNVarDLcbO/EWMSgRizDkxHQDZQaLFL5VJY9tRBj2Gz+rvCEYYvhbqPHNA==} - engines: {node: '>= 18.12.0'} - hasBin: true - peerDependencies: - webpack: ^5.0.0 - webpack-cli: '*' - peerDependenciesMeta: - webpack: - optional: true - webpack-cli: - optional: true - dependencies: - '@types/bonjour': 3.5.13 - '@types/connect-history-api-fallback': 1.5.4 - '@types/express': 4.17.21 - '@types/serve-index': 1.9.4 - '@types/serve-static': 1.15.7 - '@types/sockjs': 0.3.36 - '@types/ws': 8.5.10 - ansi-html-community: 0.0.8 - bonjour-service: 1.2.1 - chokidar: 3.6.0 - colorette: 2.0.20 - compression: 1.7.4 - connect-history-api-fallback: 2.0.0 - default-gateway: 6.0.3 - express: 4.19.2 - graceful-fs: 4.2.11 - html-entities: 2.5.2 - http-proxy-middleware: 2.0.6(@types/express@4.17.21) - ipaddr.js: 2.1.0 - launch-editor: 2.6.1 - open: 10.1.0 - p-retry: 6.2.0 - rimraf: 5.0.5 - schema-utils: 4.2.0 - selfsigned: 2.4.1 - serve-index: 1.9.1 - sockjs: 0.3.24 - spdy: 4.0.2 - webpack: 5.92.1(webpack-cli@5.1.4) - webpack-cli: 5.1.4(webpack-dev-server@5.0.4)(webpack@5.92.1) - webpack-dev-middleware: 7.2.1(webpack@5.92.1) - ws: 8.17.1 - transitivePeerDependencies: - - bufferutil - - debug - - supports-color - - utf-8-validate - dev: true - - /webpack-merge@5.10.0: - resolution: {integrity: sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==} - engines: {node: '>=10.0.0'} - dependencies: - clone-deep: 4.0.1 - flat: 5.0.2 - wildcard: 2.0.1 - dev: true - - /webpack-sources@3.2.3: - resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==} - engines: {node: '>=10.13.0'} - dev: true - - /webpack@5.92.1(webpack-cli@5.1.4): - resolution: {integrity: sha512-JECQ7IwJb+7fgUFBlrJzbyu3GEuNBcdqr1LD7IbSzwkSmIevTm8PF+wej3Oxuz/JFBUZ6O1o43zsPkwm1C4TmA==} - engines: {node: '>=10.13.0'} - hasBin: true - peerDependencies: - webpack-cli: '*' - peerDependenciesMeta: - webpack-cli: - optional: true - dependencies: - '@types/eslint-scope': 3.7.7 - '@types/estree': 1.0.5 - '@webassemblyjs/ast': 1.12.1 - '@webassemblyjs/wasm-edit': 1.12.1 - '@webassemblyjs/wasm-parser': 1.12.1 - acorn: 8.11.3 - acorn-import-attributes: 1.9.5(acorn@8.11.3) - browserslist: 4.23.0 - chrome-trace-event: 1.0.3 - enhanced-resolve: 5.17.0 - es-module-lexer: 1.5.0 - eslint-scope: 5.1.1 - events: 3.3.0 - glob-to-regexp: 0.4.1 - graceful-fs: 4.2.11 - json-parse-even-better-errors: 2.3.1 - loader-runner: 4.3.0 - mime-types: 2.1.35 - neo-async: 2.6.2 - schema-utils: 3.3.0 - tapable: 2.2.1 - terser-webpack-plugin: 5.3.10(webpack@5.92.1) - watchpack: 2.4.1 - webpack-cli: 5.1.4(webpack-dev-server@5.0.4)(webpack@5.92.1) - webpack-sources: 3.2.3 - transitivePeerDependencies: - - '@swc/core' - - esbuild - - uglify-js - dev: true - - /websocket-driver@0.7.4: - resolution: {integrity: sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==} - engines: {node: '>=0.8.0'} - dependencies: - http-parser-js: 0.5.8 - safe-buffer: 5.2.1 - websocket-extensions: 0.1.4 - dev: true - - /websocket-extensions@0.1.4: - resolution: {integrity: sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==} - engines: {node: '>=0.8.0'} - dev: true - - /which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true - dependencies: - isexe: 2.0.0 - dev: true - - /wildcard@2.0.1: - resolution: {integrity: sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==} - dev: true - - /wrap-ansi@7.0.0: - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} - engines: {node: '>=10'} - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - - /wrap-ansi@8.1.0: - resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} - engines: {node: '>=12'} - dependencies: - ansi-styles: 6.2.1 - string-width: 5.1.2 - strip-ansi: 7.1.0 - dev: true - - /wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - dev: true - - /ws@8.17.1: - resolution: {integrity: sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: '>=5.0.2' - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - - /y18n@5.0.8: - resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} - engines: {node: '>=10'} - dev: false - - /yallist@3.1.1: - resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - dev: true - - /yallist@4.0.0: - resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - dev: true - - /yaml@1.10.2: - resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} - engines: {node: '>= 6'} - dev: false - - /yargs-parser@21.1.1: - resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} - engines: {node: '>=12'} - dev: false - - /yargs@17.7.2: - resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} - engines: {node: '>=12'} - dependencies: - cliui: 8.0.1 - escalade: 3.1.2 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - string-width: 4.2.3 - y18n: 5.0.8 - yargs-parser: 21.1.1 - dev: false - - /yn@3.1.1: - resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} - engines: {node: '>=6'} - dev: true - - /yocto-queue@1.0.0: - resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==} - engines: {node: '>=12.20'} - dev: true diff --git a/gui/react/public/favicon.webp b/gui/react/public/favicon.webp deleted file mode 100644 index 279efcf..0000000 Binary files a/gui/react/public/favicon.webp and /dev/null differ diff --git a/gui/react/public/index.html b/gui/react/public/index.html deleted file mode 100644 index e0f99bb..0000000 --- a/gui/react/public/index.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - Multi Downloader - - - - - -
- - diff --git a/gui/react/public/notFound.png b/gui/react/public/notFound.png deleted file mode 100644 index 7843e7c..0000000 Binary files a/gui/react/public/notFound.png and /dev/null differ diff --git a/gui/react/src/@types/FC.d.ts b/gui/react/src/@types/FC.d.ts deleted file mode 100644 index 5ec3de1..0000000 --- a/gui/react/src/@types/FC.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -type FCWithChildren = React.FC<{ - children?: React.ReactNode[]|React.ReactNode -} & T> \ No newline at end of file diff --git a/gui/react/src/App.tsx b/gui/react/src/App.tsx deleted file mode 100644 index 8f278f3..0000000 --- a/gui/react/src/App.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import React from 'react'; -import Layout from './Layout'; - -const App: React.FC = () => { - return ( - - ); -}; - -export default App; diff --git a/gui/react/src/Layout.tsx b/gui/react/src/Layout.tsx deleted file mode 100644 index 478ae91..0000000 --- a/gui/react/src/Layout.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import React from 'react'; -import AuthButton from './components/AuthButton'; -import { Box, Button } from '@mui/material'; -import MainFrame from './components/MainFrame/MainFrame'; -import LogoutButton from './components/LogoutButton'; -import AddToQueue from './components/AddToQueue/AddToQueue'; -import { messageChannelContext } from './provider/MessageChannel'; -import { ClearAll, Folder } from '@mui/icons-material'; -import StartQueueButton from './components/StartQueue'; -import MenuBar from './components/MenuBar/MenuBar'; - -const Layout: React.FC = () => { - - const messageHandler = React.useContext(messageChannelContext); - - return - - - - - - - - - - - ; -}; - -export default Layout; \ No newline at end of file diff --git a/gui/react/src/Style.tsx b/gui/react/src/Style.tsx deleted file mode 100644 index 1195472..0000000 --- a/gui/react/src/Style.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import React from 'react'; -import { Container, Box, ThemeProvider, createTheme, Theme } from '@mui/material'; - -const makeTheme = (mode: 'dark'|'light') : Partial => { - return createTheme({ - palette: { - mode, - }, - }); -}; - -const Style: FCWithChildren = ({children}) => { - return - - {children} - ; -}; - -export default Style; \ No newline at end of file diff --git a/gui/react/src/components/AddToQueue/AddToQueue.tsx b/gui/react/src/components/AddToQueue/AddToQueue.tsx deleted file mode 100644 index 6e19041..0000000 --- a/gui/react/src/components/AddToQueue/AddToQueue.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import { Add } from '@mui/icons-material'; -import { Box, Button, Dialog, Divider, Typography } from '@mui/material'; -import React from 'react'; -import DownloadSelector from './DownloadSelector/DownloadSelector'; -import EpisodeListing from './DownloadSelector/Listing/EpisodeListing'; -import SearchBox from './SearchBox/SearchBox'; - -const AddToQueue: React.FC = () => { - const [isOpen, setOpen] = React.useState(false); - - return - - setOpen(false)} maxWidth='md' PaperProps={{ elevation:4 }}> - - - - setOpen(false)} /> - - - - ; -}; - -export default AddToQueue; \ No newline at end of file diff --git a/gui/react/src/components/AddToQueue/DownloadSelector/DownloadSelector.tsx b/gui/react/src/components/AddToQueue/DownloadSelector/DownloadSelector.tsx deleted file mode 100644 index 586518b..0000000 --- a/gui/react/src/components/AddToQueue/DownloadSelector/DownloadSelector.tsx +++ /dev/null @@ -1,327 +0,0 @@ -import React, { ChangeEvent } from 'react'; -import { Box, Button, Divider, FormControl, InputBase, InputLabel, Link, MenuItem, Select, TextField, Tooltip, Typography } from '@mui/material'; -import useStore from '../../../hooks/useStore'; -import MultiSelect from '../../reusable/MultiSelect'; -import { messageChannelContext } from '../../../provider/MessageChannel'; -import LoadingButton from '@mui/lab/LoadingButton'; -import { useSnackbar } from 'notistack'; -import InfoOutlinedIcon from '@mui/icons-material/InfoOutlined'; - -type DownloadSelectorProps = { - onFinish?: () => unknown -} - -const DownloadSelector: React.FC = ({ onFinish }) => { - const messageHandler = React.useContext(messageChannelContext); - const [store, dispatch] = useStore(); - const [availableDubs, setAvailableDubs] = React.useState([]); - const [availableSubs, setAvailableSubs ] = React.useState([]); - const [ loading, setLoading ] = React.useState(false); - const { enqueueSnackbar } = useSnackbar(); - const ITEM_HEIGHT = 48; - const ITEM_PADDING_TOP = 8; - - React.useEffect(() => { - (async () => { - /* If we don't wait the response is undefined? */ - await new Promise((resolve) => setTimeout(() => resolve(undefined), 100)); - const dubLang = messageHandler?.handleDefault('dubLang'); - const subLang = messageHandler?.handleDefault('dlsubs'); - const q = messageHandler?.handleDefault('q'); - const fileName = messageHandler?.handleDefault('fileName'); - const dlVideoOnce = messageHandler?.handleDefault('dlVideoOnce'); - const result = await Promise.all([dubLang, subLang, q, fileName, dlVideoOnce]); - dispatch({ - type: 'downloadOptions', - payload: { - ...store.downloadOptions, - dubLang: result[0], - dlsubs: result[1], - q: result[2], - fileName: result[3], - dlVideoOnce: result[4], - } - }); - setAvailableDubs(await messageHandler?.availableDubCodes() ?? []); - setAvailableSubs(await messageHandler?.availableSubCodes() ?? []); - })(); - }, []); - - const addToQueue = async () => { - setLoading(true); - const res = await messageHandler?.resolveItems(store.downloadOptions); - if (!res) - return enqueueSnackbar('The request failed. Please check if the ID is correct.', { - variant: 'error' - }); - setLoading(false); - if (onFinish) - onFinish(); - }; - - const listEpisodes = async () => { - if (!store.downloadOptions.id) { - return enqueueSnackbar('Please enter a ID', { - variant: 'error' - }); - } - setLoading(true); - const res = await messageHandler?.listEpisodes(store.downloadOptions.id); - if (!res || !res.isOk) { - setLoading(false); - return enqueueSnackbar('The request failed. Please check if the ID is correct.', { - variant: 'error' - }); - } else { - dispatch({ - type: 'episodeListing', - payload: res.value - }); - } - setLoading(false); - }; - - return - - - - - General Options - - { - dispatch({ - type: 'downloadOptions', - payload: { ...store.downloadOptions, id: e.target.value } - }); - }} label='Show ID'/> - { - const parsed = parseInt(e.target.value); - if (isNaN(parsed) || parsed < 0 || parsed > 10) - return; - dispatch({ - type: 'downloadOptions', - payload: { ...store.downloadOptions, q: parsed } - }); - }} label='Quality Level (0 for max)'/> - - - - - - - Simulcast is only supported on Hidive - } - arrow placement='top' - > - - - - - - - - Episode Options - - - - { - dispatch({ - type: 'downloadOptions', - payload: { ...store.downloadOptions, e: e.target.value } - }); - }} placeholder='Episode Select'/> - - List
Episodes
-
-
- - -
- - - Language Options - - { - dispatch({ - type: 'downloadOptions', - payload: { ...store.downloadOptions, dubLang: e } - }); - }} - allOption - /> - - { - dispatch({ - type: 'downloadOptions', - payload: { ...store.downloadOptions, dlsubs: e } - }); - }} - /> - - Hardsubs are only supported on Crunchyroll - - } - arrow placement='top'> - - - - - Hardsub Language - - - - - - - Downloads the hardsub version of the selected subtitle.
Subtitles are displayed PERMANENTLY!
You can choose only 1 subtitle per video! - - } arrow placement='top'> - -
-
-
-
-
- - - { - dispatch({ - type: 'downloadOptions', - payload: { ...store.downloadOptions, fileName: e.target.value } - }); - }} sx={{ width: '87%' }} label='Filename Overwrite' /> - - Click here to see the documentation - - } arrow placement='top'> - - - - - - - - - Add to Queue - - ; -}; - -export default DownloadSelector; \ No newline at end of file diff --git a/gui/react/src/components/AddToQueue/DownloadSelector/Listing/EpisodeListing.tsx b/gui/react/src/components/AddToQueue/DownloadSelector/Listing/EpisodeListing.tsx deleted file mode 100644 index fdd393c..0000000 --- a/gui/react/src/components/AddToQueue/DownloadSelector/Listing/EpisodeListing.tsx +++ /dev/null @@ -1,191 +0,0 @@ -import { Box, List, ListItem, Typography, Divider, Dialog, Select, MenuItem, FormControl, InputLabel, Checkbox } from '@mui/material'; -import { CheckBox, CheckBoxOutlineBlank } from '@mui/icons-material'; -import React from 'react'; -import useStore from '../../../../hooks/useStore'; -import ContextMenu from '../../../reusable/ContextMenu'; -import { useSnackbar } from 'notistack'; - - -const EpisodeListing: React.FC = () => { - const [store, dispatch] = useStore(); - - const [season, setSeason] = React.useState<'all'|string>('all'); - const { enqueueSnackbar } = useSnackbar(); - - const seasons = React.useMemo(() => { - const s: string[] = []; - for (const {season} of store.episodeListing) { - if (s.includes(season)) - continue; - s.push(season); - } - return s; - }, [ store.episodeListing ]); - - const [selected, setSelected] = React.useState([]); - - React.useEffect(() => { - setSelected(parseSelect(store.downloadOptions.e)); - }, [ store.episodeListing ]); - - const close = () => { - dispatch({ - type: 'episodeListing', - payload: [] - }); - dispatch({ - type: 'downloadOptions', - payload: { - ...store.downloadOptions, - e: `${([...new Set([...parseSelect(store.downloadOptions.e), ...selected])]).join(',')}` - } - }); - }; - - const getEpisodesForSeason = (season: string|'all') => { - return store.episodeListing.filter((a) => season === 'all' ? true : a.season === season); - }; - - return 0} onClose={close} scroll='paper' maxWidth='xl' sx={{ p: 2 }}> - - - Episodes - - - Season - - - - - - selected.includes(a.e)) && !store.episodeListing.every(a => selected.includes(a.e))} - checked={store.episodeListing.every(a => selected.includes(a.e))} - onChange={() => { - if (selected.length > 0) { - setSelected([]); - } else { - setSelected(getEpisodesForSeason(season).map(a => a.e)); - } - }} - /> - - {getEpisodesForSeason(season).map((item, index, { length }) => { - const e = isNaN(parseInt(item.e)) ? item.e : parseInt(item.e); - const idStr = `S${item.season}E${e}`; - const isSelected = selected.includes(e.toString()); - const imageRef = React.createRef(); - const summaryRef = React.createRef(); - return - { - let arr: string[] = []; - if (isSelected) { - arr = [...selected.filter(a => a !== e.toString())]; - } else { - arr = [...selected, e.toString()]; - } - setSelected(arr.filter(a => a.length > 0)); - }}> - { isSelected ? : } - - {idStr} - - thumbnail - - - - {item.name} - - - {item.time.startsWith('00:') ? item.time.slice(3) : item.time} - - - - {item.description} - - - -
- Available audio languages: {item.lang.join(', ')} -
-
-
-
- { - await navigator.clipboard.writeText(item.img); - enqueueSnackbar('Copied URL to clipboard', { - variant: 'info' - }); - }}, - { - text: 'Open image in new tab', - onClick: () => { - window.open(item.img); - } - } ]} popupItem={imageRef} /> - { - await navigator.clipboard.writeText(item.description!); - enqueueSnackbar('Copied summary to clipboard', { - variant: 'info' - }); - }, - text: 'Copy summary to clipboard' - } - ]} popupItem={summaryRef} /> - {index < length - 1 && } -
; - })} -
-
; -}; - -const parseSelect = (s: string): string[] => { - const ret: string[] = []; - s.split(',').forEach(item => { - if (item.includes('-')) { - const split = item.split('-'); - if (split.length !== 2) - return; - const match = split[0].match(/[A-Za-z]+/); - if (match && match.length > 0) { - if (match.index && match.index !== 0) { - return; - } - const letters = split[0].substring(0, match[0].length); - const number = parseInt(split[0].substring(match[0].length)); - const b = parseInt(split[1]); - if (isNaN(number) || isNaN(b)) { - return; - } - for (let i = number; i <= b; i++) { - ret.push(`${letters}${i}`); - } - - } else { - const a = parseInt(split[0]); - const b = parseInt(split[1]); - if (isNaN(a) || isNaN(b)) { - return; - } - for (let i = a; i <= b; i++) { - ret.push(`${i}`); - } - } - } else { - ret.push(item); - } - }); - return [...new Set(ret)]; -}; - -export default EpisodeListing; diff --git a/gui/react/src/components/AddToQueue/SearchBox/SearchBox.css b/gui/react/src/components/AddToQueue/SearchBox/SearchBox.css deleted file mode 100644 index 8964e52..0000000 --- a/gui/react/src/components/AddToQueue/SearchBox/SearchBox.css +++ /dev/null @@ -1,8 +0,0 @@ -.listitem-hover:hover { - -webkit-filter: brightness(70%); - filter: brightness(70%); -} - -.listitem-hover { - transition: filter 0.1s ease-in; -} \ No newline at end of file diff --git a/gui/react/src/components/AddToQueue/SearchBox/SearchBox.tsx b/gui/react/src/components/AddToQueue/SearchBox/SearchBox.tsx deleted file mode 100644 index 063821c..0000000 --- a/gui/react/src/components/AddToQueue/SearchBox/SearchBox.tsx +++ /dev/null @@ -1,119 +0,0 @@ -import React from 'react'; -import { Box, ClickAwayListener, Divider, List, ListItem, Paper, TextField, Typography } from '@mui/material'; -import { SearchResponse } from '../../../../../../@types/messageHandler'; -import useStore from '../../../hooks/useStore'; -import { messageChannelContext } from '../../../provider/MessageChannel'; -import './SearchBox.css'; -import ContextMenu from '../../reusable/ContextMenu'; -import { useSnackbar } from 'notistack'; - -const SearchBox: React.FC = () => { - const messageHandler = React.useContext(messageChannelContext); - const [store, dispatch] = useStore(); - const [search, setSearch] = React.useState(''); - - const [focus, setFocus] = React.useState(false); - - const [searchResult, setSearchResult] = React.useState(); - const anchor = React.useRef(null); - - const { enqueueSnackbar } = useSnackbar(); - - const selectItem = (id: string) => { - dispatch({ - type: 'downloadOptions', - payload: { - ...store.downloadOptions, - id - } - }); - }; - - React.useEffect(() => { - if (search.trim().length === 0) - return setSearchResult({ isOk: true, value: [] }); - - const timeOutId = setTimeout(async () => { - if (search.trim().length > 3) { - const s = await messageHandler?.search({search}); - if (s && s.isOk) - s.value = s.value.slice(0, 10); - setSearchResult(s); - } - }, 500); - return () => clearTimeout(timeOutId); - }, [search]); - - const anchorBounding = anchor.current?.getBoundingClientRect(); - return setFocus(false)}> - - setFocus(true)} onChange={e => setSearch(e.target.value)} variant='outlined' label='Search' fullWidth /> - {searchResult !== undefined && searchResult.isOk && searchResult.value.length > 0 && focus && - - - {searchResult && searchResult.isOk ? - searchResult.value.map((a, ind, arr) => { - const imageRef = React.createRef(); - const summaryRef = React.createRef(); - return - { - selectItem(a.id); - setFocus(false); - }}> - - - thumbnail - - - - {a.name} - - {a.desc && - {a.desc} - } - {a.lang && - Languages: {a.lang.join(', ')} - } - - ID: {a.id} - - - - - { - await navigator.clipboard.writeText(a.image); - enqueueSnackbar('Copied URL to clipboard', { - variant: 'info' - }); - }}, - { - text: 'Open image in new tab', - onClick: () => { - window.open(a.image); - } - } ]} popupItem={imageRef} /> - {a.desc && - { - await navigator.clipboard.writeText(a.desc!); - enqueueSnackbar('Copied summary to clipboard', { - variant: 'info' - }); - }, - text: 'Copy summary to clipboard' - } - ]} popupItem={summaryRef} /> - } - {(ind < arr.length - 1) && } - ; - }) - : <>} - - } - - ; -}; - -export default SearchBox; diff --git a/gui/react/src/components/AuthButton.tsx b/gui/react/src/components/AuthButton.tsx deleted file mode 100644 index 8f5d273..0000000 --- a/gui/react/src/components/AuthButton.tsx +++ /dev/null @@ -1,112 +0,0 @@ -import { Button, CircularProgress, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle, TextField } from '@mui/material'; -import { Check, Close } from '@mui/icons-material'; -import React from 'react'; -import { messageChannelContext } from '../provider/MessageChannel'; -import Require from './Require'; -import { useSnackbar } from 'notistack'; - -const AuthButton: React.FC = () => { - const snackbar = useSnackbar(); - - const [open, setOpen] = React.useState(false); - - const [username, setUsername] = React.useState(''); - const [password, setPassword] = React.useState(''); - - const [usernameError, setUsernameError] = React.useState(false); - const [passwordError, setPasswordError] = React.useState(false); - - const messageChannel = React.useContext(messageChannelContext); - - const [loading, setLoading] = React.useState(false); - const [error, setError] = React.useState(undefined); - const [authed, setAuthed] = React.useState(false); - - const checkAuth = async () => { - setAuthed((await messageChannel?.checkToken())?.isOk ?? false); - }; - - React.useEffect(() => { checkAuth(); }, []); - - const handleSubmit = async () => { - if (!messageChannel) - throw new Error('Invalid state'); //The components to confirm only render if the messageChannel is not undefinded - if (username.trim().length === 0) - return setUsernameError(true); - if (password.trim().length === 0) - return setPasswordError(true); - setUsernameError(false); - setPasswordError(false); - setLoading(true); - - const res = await messageChannel.auth({ username, password }); - if (res.isOk) { - setOpen(false); - snackbar.enqueueSnackbar('Logged in', { - variant: 'success' - }); - setUsername(''); - setPassword(''); - } else { - setError(res.reason); - } - await checkAuth(); - setLoading(false); - }; - - return - - - Error during Authentication - - {error?.name} - {error?.message} - - - - - - Authentication - - - Here, you need to enter your username (most likely your Email) and your password.
- These information are not stored anywhere and are only used to authenticate with the service once. -
- setUsername(e.target.value)} - disabled={loading} - /> - setPassword(e.target.value)} - disabled={loading} - /> -
- - {loading && } - - - -
- -
; -}; - -export default AuthButton; \ No newline at end of file diff --git a/gui/react/src/components/LogoutButton.tsx b/gui/react/src/components/LogoutButton.tsx deleted file mode 100644 index 916db7a..0000000 --- a/gui/react/src/components/LogoutButton.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import { ExitToApp } from '@mui/icons-material'; -import { Button } from '@mui/material'; -import React from 'react'; -import useStore from '../hooks/useStore'; -import { messageChannelContext } from '../provider/MessageChannel'; -import Require from './Require'; - -const LogoutButton: React.FC = () => { - const messageChannel = React.useContext(messageChannelContext); - const [, dispatch] = useStore(); - - const logout = async () => { - if (await messageChannel?.isDownloading()) - return alert('You are currently downloading. Please finish the download first.'); - if (await messageChannel?.logout()) - dispatch({ - type: 'service', - payload: undefined - }); - else - alert('Unable to change service'); - }; - - return - - ; - -}; - -export default LogoutButton; \ No newline at end of file diff --git a/gui/react/src/components/MainFrame/DownloadManager/DownloadManager.tsx b/gui/react/src/components/MainFrame/DownloadManager/DownloadManager.tsx deleted file mode 100644 index 7917707..0000000 --- a/gui/react/src/components/MainFrame/DownloadManager/DownloadManager.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import React from 'react'; -import { ExtendedProgress, QueueItem } from '../../../../../../@types/messageHandler'; -import { RandomEvent } from '../../../../../../@types/randomEvents'; -import { messageChannelContext } from '../../../provider/MessageChannel'; - -const useDownloadManager = () => { - const messageHandler = React.useContext(messageChannelContext); - - const [progressData, setProgressData] = React.useState(); - const [current, setCurrent] = React.useState(); - - React.useEffect(() => { - const handler = (ev: RandomEvent<'progress'>) => { - console.log(ev.data); - setProgressData(ev.data); - }; - - const currentHandler = (ev: RandomEvent<'current'>) => { - setCurrent(ev.data); - }; - - const finishHandler = () => { - setProgressData(undefined); - }; - - messageHandler?.randomEvents.on('progress', handler); - messageHandler?.randomEvents.on('current', currentHandler); - messageHandler?.randomEvents.on('finish', finishHandler); - - return () => { - messageHandler?.randomEvents.removeListener('progress', handler); - messageHandler?.randomEvents.removeListener('finish', finishHandler); - messageHandler?.randomEvents.removeListener('current', currentHandler); - }; - }, [messageHandler]); - - return { data: progressData, current}; -}; - -export default useDownloadManager; \ No newline at end of file diff --git a/gui/react/src/components/MainFrame/MainFrame.tsx b/gui/react/src/components/MainFrame/MainFrame.tsx deleted file mode 100644 index 425b321..0000000 --- a/gui/react/src/components/MainFrame/MainFrame.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import { Box } from '@mui/material'; -import React from 'react'; -import Queue from './Queue/Queue'; - -const MainFrame: React.FC = () => { - return - - ; -}; - -export default MainFrame; \ No newline at end of file diff --git a/gui/react/src/components/MainFrame/Queue/Queue.tsx b/gui/react/src/components/MainFrame/Queue/Queue.tsx deleted file mode 100644 index 7707f74..0000000 --- a/gui/react/src/components/MainFrame/Queue/Queue.tsx +++ /dev/null @@ -1,420 +0,0 @@ -import { Badge, Box, Button, CircularProgress, Divider, IconButton, LinearProgress, Skeleton, Tooltip, Typography } from '@mui/material'; -import React from 'react'; -import { messageChannelContext } from '../../../provider/MessageChannel'; -import { queueContext } from '../../../provider/QueueProvider'; -import DeleteIcon from '@mui/icons-material/Delete'; - -import useDownloadManager from '../DownloadManager/DownloadManager'; - -const Queue: React.FC = () => { - const { data, current } = useDownloadManager(); - const queue = React.useContext(queueContext); - const msg = React.useContext(messageChannelContext); - - - if (!msg) - return <>Never; - - return data || queue.length > 0 ? <> - {data && <> - - - Thumbnail - - - - - - {data.downloadInfo.parent.title} - - - {data.downloadInfo.title} - - - - - - Downloading: {data.downloadInfo.language.name} - - - - - - - - {data.progress.cur} / {(data.progress.total)} parts ({data.progress.percent}% | {formatTime(data.progress.time)} | {(data.progress.downloadSpeed / 1024 / 1024).toFixed(2)} MB/s | {(data.progress.bytes / 1024 / 1024).toFixed(2)}MB) - - - - - - - - } - { - current && !data && <> - - - Thumbnail - - - - - - {current.parent.title} - - - {current.title} - - - - - - - Downloading: - - - - - - - - - - 0 / ? parts (0% | XX:XX | 0 MB/s | 0MB) - - - - - - - - } - {queue.map((queueItem, index, { length }) => { - return - - Thumbnail - - - - {queueItem.parent.title} - - - S{queueItem.parent.season}E{queueItem.episode} - - - {queueItem.title} - - - - - Dub(s): {queueItem.dubLang.join(', ')} - - - Sub(s): {queueItem.dlsubs.join(', ')} - - - Quality: {queueItem.q} - - - - - { - msg.removeFromQueue(index); - }} - sx={{ - backgroundColor: '#ff573a25', - height: '40px', - transition: '250ms', - '&:hover' : { - backgroundColor: '#ff573a', - } - }}> - - - - - - - - ; - })} - : - - Selected episodes will be shown here - - - - - - - - - - - - - - - - ; -}; - -const formatTime = (time: number) => { - time = Math.floor(time / 1000); - const minutes = Math.floor(time / 60); - time = time % 60; - - return `${minutes.toFixed(0).length < 2 ? `0${minutes}` : minutes}m${time.toFixed(0).length < 2 ? `0${time}` : time}s`; -}; - -export default Queue; \ No newline at end of file diff --git a/gui/react/src/components/MenuBar/MenuBar.tsx b/gui/react/src/components/MenuBar/MenuBar.tsx deleted file mode 100644 index 00f5ed8..0000000 --- a/gui/react/src/components/MenuBar/MenuBar.tsx +++ /dev/null @@ -1,124 +0,0 @@ -import { Box, Button, Menu, MenuItem, Typography } from '@mui/material'; -import React from 'react'; -import { messageChannelContext } from '../../provider/MessageChannel'; -import useStore from '../../hooks/useStore'; -import { StoreState } from '../../provider/Store'; - -const MenuBar: React.FC = () => { - const [ openMenu, setMenuOpen ] = React.useState<'settings'|'help'|undefined>(); - const [anchorEl, setAnchorEl] = React.useState(null); - const [store, dispatch] = useStore(); - - const messageChannel = React.useContext(messageChannelContext); - - React.useEffect(() => { - (async () => { - if (!messageChannel || store.version !== '') - return; - dispatch({ - type: 'version', - payload: await messageChannel.version() - }); - })(); - }, [messageChannel]); - - const transformService = (service: StoreState['service']) => { - switch(service) { - case 'crunchy': - return 'Crunchyroll'; - case 'hidive': - return 'Hidive'; - case 'ao': - return 'AnimeOnegai'; - case 'adn': - return 'AnimationDigitalNetwork'; - } - }; - - const msg = React.useContext(messageChannelContext); - - const handleClick = (event: React.MouseEvent, n: 'settings'|'help') => { - setAnchorEl(event.currentTarget); - setMenuOpen(n); - }; - const handleClose = () => { - setAnchorEl(null); - setMenuOpen(undefined); - }; - - if (!msg) - return <>; - - return - - - - - - { - msg.openFolder('config'); - handleClose(); - }}> - Open settings folder - - { - msg.openFile(['config', 'bin-path.yml']); - handleClose(); - }}> - Open FFmpeg/Mkvmerge file - - { - msg.openFile(['config', 'cli-defaults.yml']); - handleClose(); - }}> - Open advanced options - - { - msg.openFolder('content'); - handleClose(); - }}> - Open output path - - - - { - msg.openURL('https://github.com/anidl/multi-downloader-nx'); - handleClose(); - }}> - GitHub - - { - msg.openURL('https://github.com/anidl/multi-downloader-nx/issues/new?assignees=AnimeDL,AnidlSupport&labels=bug&template=bug.yml&title=BUG'); - handleClose(); - }}> - Report a bug - - { - msg.openURL('https://github.com/anidl/multi-downloader-nx/graphs/contributors'); - handleClose(); - }}> - Contributors - - { - msg.openURL('https://discord.gg/qEpbWen5vq'); - handleClose(); - }}> - Discord - - { - handleClose(); - }}> - Version: {store.version} - - - - {transformService(store.service)} - - ; -}; - -export default MenuBar; diff --git a/gui/react/src/components/Require.tsx b/gui/react/src/components/Require.tsx deleted file mode 100644 index 847541f..0000000 --- a/gui/react/src/components/Require.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import React from 'react'; -import { Box, Backdrop, CircularProgress } from '@mui/material'; - -export type RequireType = { - value?: T -} - -const Require = (props: React.PropsWithChildren>) => { - return props.value === undefined ? - - : {props.children}; -}; - -export default Require; \ No newline at end of file diff --git a/gui/react/src/components/StartQueue.tsx b/gui/react/src/components/StartQueue.tsx deleted file mode 100644 index 05b630c..0000000 --- a/gui/react/src/components/StartQueue.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import { PauseCircleFilled, PlayCircleFilled } from '@mui/icons-material'; -import { Button } from '@mui/material'; -import React from 'react'; -import { messageChannelContext } from '../provider/MessageChannel'; -import Require from './Require'; - -const StartQueueButton: React.FC = () => { - const messageChannel = React.useContext(messageChannelContext); - const [start, setStart] = React.useState(false); - const msg = React.useContext(messageChannelContext); - - React.useEffect(() => { - (async () => { - if (!msg) - return alert('Invalid state: msg not found'); - setStart(await msg.getDownloadQueue()); - })(); - }, []); - - const change = async () => { - if (await messageChannel?.isDownloading()) - alert('The current download will be finished before the queue stops'); - msg?.setDownloadQueue(!start); - setStart(!start); - }; - - return - - ; - -}; - -export default StartQueueButton; \ No newline at end of file diff --git a/gui/react/src/components/reusable/ContextMenu.tsx b/gui/react/src/components/reusable/ContextMenu.tsx deleted file mode 100644 index dc08610..0000000 --- a/gui/react/src/components/reusable/ContextMenu.tsx +++ /dev/null @@ -1,65 +0,0 @@ -import { Box, Button, Divider, List, SxProps } from '@mui/material'; -import React from 'react'; - -export type Option = { - text: string, - onClick: () => unknown -} - -export type ContextMenuProps = { - options: ('divider'|Option)[], - popupItem: React.RefObject -} - -const buttonSx: SxProps = { - '&:hover': { - background: 'rgb(0, 30, 60)' - }, - fontSize: '0.7rem', - minHeight: '30px', - justifyContent: 'center', - p: 0 -}; - -function ContextMenu(props: ContextMenuProps) { - const [anchor, setAnchor] = React.useState( { x: 0, y: 0 } ); - - const [show, setShow] = React.useState(false); - - React.useEffect(() => { - const { popupItem: ref } = props; - if (ref.current === null) - return; - const listener = (ev: MouseEvent) => { - ev.preventDefault(); - setAnchor({ x: ev.x + 10, y: ev.y + 10 }); - setShow(true); - }; - ref.current.addEventListener('contextmenu', listener); - - return () => { - if (ref.current) - ref.current.removeEventListener('contextmenu', listener); - }; - }, [ props.popupItem ]); - - return show ? - - {props.options.map((item, i) => { - return item === 'divider' ? : - ; - })} - - - - : <>; -} - -export default ContextMenu; diff --git a/gui/react/src/components/reusable/LinearProgressWithLabel.tsx b/gui/react/src/components/reusable/LinearProgressWithLabel.tsx deleted file mode 100644 index 28ac451..0000000 --- a/gui/react/src/components/reusable/LinearProgressWithLabel.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import { LinearProgressProps, Box, LinearProgress, Typography } from '@mui/material'; -import React from 'react'; - -// The following code has been taken from the mui example -// Thanks for that mui - -export type LinearProgressWithLabelProps = LinearProgressProps & { value: number }; - -const LinearProgressWithLabel: React.FC = (props) => { - return ( - - - - - - {`${Math.round( - props.value, - )}%`} - - - ); -}; - -export default LinearProgressWithLabel; \ No newline at end of file diff --git a/gui/react/src/components/reusable/MultiSelect.tsx b/gui/react/src/components/reusable/MultiSelect.tsx deleted file mode 100644 index 5e3b272..0000000 --- a/gui/react/src/components/reusable/MultiSelect.tsx +++ /dev/null @@ -1,74 +0,0 @@ -import React from 'react'; -import { FormControl, InputLabel, MenuItem, OutlinedInput, Select, Theme, useTheme } from '@mui/material'; - -export type MultiSelectProps = { - values: string[], - selected: string[], - onChange: (values: string[]) => unknown, - title: string, - allOption?: boolean -} - -const ITEM_HEIGHT = 48; -const ITEM_PADDING_TOP = 8; -const MenuProps = { - PaperProps: { - style: { - maxHeight: ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP, - width: 250 - } - } -}; - -function getStyles(name: string, personName: readonly string[], theme: Theme) { - return { - fontWeight: - (personName ?? []).indexOf(name) === -1 - ? theme.typography.fontWeightRegular - : theme.typography.fontWeightMedium - }; -} - -const MultiSelect: React.FC = (props) => { - const theme = useTheme(); - - return
- - {props.title} - - -
; -}; - -export default MultiSelect; \ No newline at end of file diff --git a/gui/react/src/hooks/useStore.tsx b/gui/react/src/hooks/useStore.tsx deleted file mode 100644 index 9d9b302..0000000 --- a/gui/react/src/hooks/useStore.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import React from 'react'; -import { StoreAction, StoreContext, StoreState } from '../provider/Store'; - -const useStore = () => { - const context = React.useContext(StoreContext as unknown as React.Context<[StoreState, React.Dispatch>]>); - if (!context) { - throw new Error('useStore must be used under Store'); - } - return context; -}; - -export default useStore; \ No newline at end of file diff --git a/gui/react/src/index.tsx b/gui/react/src/index.tsx deleted file mode 100644 index 42f0a07..0000000 --- a/gui/react/src/index.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import React from 'react'; -import { createRoot } from 'react-dom/client'; -import App from './App'; -import ServiceProvider from './provider/ServiceProvider'; -import Style from './Style'; -import MessageChannel from './provider/MessageChannel'; -import { Box, IconButton } from '@mui/material'; -import { CloseOutlined } from '@mui/icons-material'; -import { SnackbarProvider, SnackbarKey } from 'notistack'; -import Store from './provider/Store'; -import ErrorHandler from './provider/ErrorHandler'; -import QueueProvider from './provider/QueueProvider'; - -document.body.style.backgroundColor = 'rgb(0, 30, 60)'; -document.body.style.display = 'flex'; -document.body.style.justifyContent = 'center'; - -const notistackRef = React.createRef(); -const onClickDismiss = (key: SnackbarKey | undefined) => () => { - if (notistackRef.current) - notistackRef.current.closeSnackbar(key); -}; - -const container = document.getElementById('root'); -const root = createRoot(container as HTMLElement); -root.render( - - - ( - - - - )} - > - - - - -); \ No newline at end of file diff --git a/gui/react/src/provider/ErrorHandler.tsx b/gui/react/src/provider/ErrorHandler.tsx deleted file mode 100644 index e2ae86f..0000000 --- a/gui/react/src/provider/ErrorHandler.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import { Box, Typography } from '@mui/material'; -import React from 'react'; - -export default class ErrorHandler extends React.Component<{ - children: React.ReactNode|React.ReactNode[] -}, { - error?: { - er: Error, - stack: React.ErrorInfo - } -}> { - - constructor(props: { - children: React.ReactNode|React.ReactNode[] - }) { - super(props); - this.state = { error: undefined }; - } - - componentDidCatch(er: Error, stack: React.ErrorInfo) { - this.setState({ error: { er, stack } }); - } - - render(): React.ReactNode { - return this.state.error ? - - - {`${this.state.error.er.name}: ${this.state.error.er.message}`} -
- {this.state.error.stack.componentStack?.split('\n').map(a => { - return <> - {a} -
- ; - })} -
-
: this.props.children; - } -} \ No newline at end of file diff --git a/gui/react/src/provider/MessageChannel.tsx b/gui/react/src/provider/MessageChannel.tsx deleted file mode 100644 index 56e6147..0000000 --- a/gui/react/src/provider/MessageChannel.tsx +++ /dev/null @@ -1,244 +0,0 @@ -import React from 'react'; -import { MessageHandler } from '../../../../@types/messageHandler'; -import useStore from '../hooks/useStore'; -import type { MessageTypes, WSMessage, WSMessageWithID } from '../../../../@types/ws'; -import type { Handler, RandomEvent, RandomEvents } from '../../../../@types/randomEvents'; -import { Avatar, Box, Button, TextField, Typography } from '@mui/material'; -import { v4 } from 'uuid'; -import { useSnackbar } from 'notistack'; -import { LockOutlined, PowerSettingsNew } from '@mui/icons-material'; -import { GUIConfig } from '../../../../modules/module.cfg-loader'; - -export type FrontEndMessages = (MessageHandler & { randomEvents: RandomEventHandler, logout: () => Promise }); - -export class RandomEventHandler { - private handler: { - [eventName in keyof RandomEvents]: Handler[] - } = { - progress: [], - finish: [], - queueChange: [], - current: [] - }; - - public on(name: T, listener: Handler) { - if (Object.prototype.hasOwnProperty.call(this.handler, name)) { - this.handler[name].push(listener as any); - } else { - this.handler[name] = [ listener as any ]; - } - } - - public emit(name: keyof RandomEvents, data: RandomEvent) { - (this.handler[name] ?? []).forEach(handler => handler(data as any)); - } - - public removeListener(name: T, listener: Handler) { - this.handler[name] = (this.handler[name] as Handler[]).filter(a => a !== listener) as any; - } -} - -export const messageChannelContext = React.createContext(undefined); - -async function messageAndResponse(socket: WebSocket, msg: WSMessage): Promise> { - const id = v4(); - const ret = new Promise>((resolve) => { - const handler = function({ data }: MessageEvent) { - const parsed = JSON.parse(data.toString()) as WSMessageWithID; - if (parsed.id === id) { - socket.removeEventListener('message', handler); - resolve(parsed); - } - }; - socket.addEventListener('message', handler); - }); - const toSend = msg as WSMessageWithID; - toSend.id = id; - - socket.send(JSON.stringify(toSend)); - return ret; -} - -const MessageChannelProvider: FCWithChildren = ({ children }) => { - - const [store, dispatch] = useStore(); - const [socket, setSocket] = React.useState(); - const [publicWS, setPublicWS] = React.useState(); - const [usePassword, setUsePassword] = React.useState<'waiting'|'yes'|'no'>('waiting'); - const [isSetup, setIsSetup] = React.useState<'waiting'|'yes'|'no'>('waiting'); - - const { enqueueSnackbar } = useSnackbar(); - - React.useEffect(() => { - const wss = new WebSocket(`${location.protocol == 'https:' ? 'wss' : 'ws'}://${process.env.NODE_ENV === 'development' ? 'localhost:3000' : window.location.host}/public`); - wss.addEventListener('open', () => { - setPublicWS(wss); - }); - wss.addEventListener('error', () => { - enqueueSnackbar('Unable to connect to server. Please reload the page to try again.', { variant: 'error' }); - }); - }, []); - - React.useEffect(() => { - (async () => { - if (!publicWS) - return; - setUsePassword((await messageAndResponse(publicWS, { name: 'requirePassword', data: undefined })).data ? 'yes' : 'no'); - setIsSetup((await messageAndResponse(publicWS, { name: 'isSetup', data: undefined })).data ? 'yes' : 'no'); - })(); - }, [publicWS]); - - const connect = (ev?: React.FormEvent) => { - let search = new URLSearchParams(); - if (ev) { - ev.preventDefault(); - const formData = new FormData(ev.currentTarget); - const password = formData.get('password')?.toString(); - if (!password) - return enqueueSnackbar('Please provide both a username and password', { - variant: 'error' - }); - search = new URLSearchParams({ - password - }); - } - - const wws = new WebSocket(`${location.protocol == 'https:' ? 'wss' : 'ws'}://${process.env.NODE_ENV === 'development' ? 'localhost:3000' : window.location.host}/private?${search}`, ); - wws.addEventListener('open', () => { - console.log('[INFO] [WS] Connected'); - setSocket(wws); - }); - wws.addEventListener('error', (er) => { - console.error('[ERROR] [WS]', er); - enqueueSnackbar('Unable to connect to server. Please check the password and try again.', { - variant: 'error' - }); - }); - }; - - const setup = async (ev: React.FormEvent) => { - ev.preventDefault(); - if (!socket) - return enqueueSnackbar('Invalid state: socket not found', { variant: 'error' }); - const formData = new FormData(ev.currentTarget); - const password = formData.get('password'); - const data = { - port: parseInt(formData.get('port')?.toString() ?? '') ?? 3000, - password: password ? password.toString() : undefined - } as GUIConfig; - await messageAndResponse(socket, { name: 'setupServer', data }); - enqueueSnackbar(`The following settings have been set: Port=${data.port}, Password=${data.password ?? 'noPasswordRequired'}`, { - variant: 'success', - persist: true - }); - enqueueSnackbar('Please restart the server now.', { - variant: 'info', - persist: true - }); - }; - - const randomEventHandler = React.useMemo(() => new RandomEventHandler(), []); - - React.useEffect(() => { - (async () => { - if (!socket) - return; - const currentService = await messageAndResponse(socket, { name: 'type', data: undefined }); - if (currentService.data !== undefined) - return dispatch({ type: 'service', payload: currentService.data }); - if (store.service !== currentService.data) - messageAndResponse(socket, { name: 'setup', data: store.service }); - })(); - }, [store.service, dispatch, socket]); - - React.useEffect(() => { - if (!socket) - return; - /* finish is a placeholder */ - const listener = (initalData: MessageEvent) => { - const data = JSON.parse(initalData.data) as RandomEvent<'finish'>; - randomEventHandler.emit(data.name, data); - }; - socket.addEventListener('message', listener); - return () => { - socket.removeEventListener('message', listener); - }; - }, [ socket ]); - - if (usePassword === 'waiting') - return <>; - - if (socket === undefined) { - if (usePassword === 'no') { - connect(undefined); - return <>; - } - return - - - - - Login - - - - - - You need to login in order to use this tool. - - - ; - } - - if (isSetup === 'no') { - return - - - - - Confirm - - - - - - - Please enter data that will be set to use this tool. -
- Leave blank to use no password (NOT RECOMMENDED)! -
-
-
; - } - - const messageHandler: FrontEndMessages = { - name: 'default', - auth: async (data) => (await messageAndResponse(socket, { name: 'auth', data })).data, - version: async () => (await messageAndResponse(socket, { name: 'version', data: undefined })).data, - checkToken: async () => (await messageAndResponse(socket, { name: 'checkToken', data: undefined })).data, - search: async (data) => (await messageAndResponse(socket, { name: 'search', data })).data, - handleDefault: async (data) => (await messageAndResponse(socket, { name: 'default', data })).data, - availableDubCodes: async () => (await messageAndResponse(socket, { name: 'availableDubCodes', data: undefined})).data, - availableSubCodes: async () => (await messageAndResponse(socket, { name: 'availableSubCodes', data: undefined })).data, - resolveItems: async (data) => (await messageAndResponse(socket, { name: 'resolveItems', data })).data, - listEpisodes: async (data) => (await messageAndResponse(socket, { name: 'listEpisodes', data })).data, - randomEvents: randomEventHandler, - downloadItem: (data) => messageAndResponse(socket, { name: 'downloadItem', data }), - isDownloading: async () => (await messageAndResponse(socket, { name: 'isDownloading', data: undefined })).data, - openFolder: async (data) => messageAndResponse(socket, { name: 'openFolder', data }), - logout: async () => (await messageAndResponse(socket, { name: 'changeProvider', data: undefined })).data, - openFile: async (data) => await messageAndResponse(socket, { name: 'openFile', data }), - openURL: async (data) => await messageAndResponse(socket, { name: 'openURL', data }), - getQueue: async () => (await messageAndResponse(socket, { name: 'getQueue', data: undefined })).data, - removeFromQueue: async (data) => await messageAndResponse(socket, { name: 'removeFromQueue', data }), - clearQueue: async () => await messageAndResponse(socket, { name: 'clearQueue', data: undefined }), - setDownloadQueue: async (data) => await messageAndResponse(socket, { name: 'setDownloadQueue', data }), - getDownloadQueue: async () => (await messageAndResponse(socket, { name: 'getDownloadQueue', data: undefined })).data, - }; - - return - {children} - ; -}; - -export default MessageChannelProvider; diff --git a/gui/react/src/provider/QueueProvider.tsx b/gui/react/src/provider/QueueProvider.tsx deleted file mode 100644 index dc31db9..0000000 --- a/gui/react/src/provider/QueueProvider.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import React from 'react'; -import { QueueItem } from '../../../../@types/messageHandler'; -import { messageChannelContext } from './MessageChannel'; -import { RandomEvent } from '../../../../@types/randomEvents'; - -export const queueContext = React.createContext([]); - -const QueueProvider: FCWithChildren = ({ children }) => { - const msg = React.useContext(messageChannelContext); - - const [ready, setReady] = React.useState(false); - const [queue, setQueue] = React.useState([]); - - React.useEffect(() => { - if (msg && !ready) { - msg.getQueue().then(data => { - setQueue(data); - setReady(true); - }); - } - const listener = (ev: RandomEvent<'queueChange'>) => { - setQueue(ev.data); - }; - msg?.randomEvents.on('queueChange', listener); - return () => { - msg?.randomEvents.removeListener('queueChange', listener); - }; - }, [ msg ]); - - return - {children} - ; -}; - -export default QueueProvider; \ No newline at end of file diff --git a/gui/react/src/provider/ServiceProvider.tsx b/gui/react/src/provider/ServiceProvider.tsx deleted file mode 100644 index 876bda9..0000000 --- a/gui/react/src/provider/ServiceProvider.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import React from 'react'; -import {Divider, Box, Button, Typography, Avatar} from '@mui/material'; -import useStore from '../hooks/useStore'; -import { StoreState } from './Store'; - -type Services = 'crunchy'|'hidive'|'ao'|'adn'; - -export const serviceContext = React.createContext(undefined); - -const ServiceProvider: FCWithChildren = ({ children }) => { - const [ { service }, dispatch ] = useStore(); - - const setService = (s: StoreState['service']) => { - dispatch({ - type: 'service', - payload: s - }); - }; - - return service === undefined ? - - Please select your service - - - - - - - - : - {children} - ; -}; - -export default ServiceProvider; \ No newline at end of file diff --git a/gui/react/src/provider/Store.tsx b/gui/react/src/provider/Store.tsx deleted file mode 100644 index 15d50ec..0000000 --- a/gui/react/src/provider/Store.tsx +++ /dev/null @@ -1,91 +0,0 @@ -import React from 'react'; -import { Episode } from '../../../../@types/messageHandler'; -import { dubLanguageCodes } from '../../../../modules/module.langsData'; - -export type DownloadOptions = { - q: number, - id: string, - e: string, - dubLang: typeof dubLanguageCodes, - dlsubs: string[], - fileName: string, - dlVideoOnce: boolean, - all: boolean, - but: boolean, - novids: boolean, - hslang?: string, - simul: boolean, - noaudio: boolean -} - -export type StoreState = { - episodeListing: Episode[]; - downloadOptions: DownloadOptions, - service: 'crunchy'|'hidive'|'ao'|'adn'|undefined, - version: string, -} - -export type StoreAction = { - type: T, - payload: StoreState[T], - extraInfo?: Record -} - -const Reducer = (state: StoreState, action: StoreAction): StoreState => { - switch(action.type) { - default: - return { ...state, [action.type]: action.payload }; - } -}; - -const initialState: StoreState = { - downloadOptions: { - id: '', - q: 0, - e: '', - dubLang: [ 'jpn' ], - dlsubs: [ 'all' ], - fileName: '', - dlVideoOnce: false, - all: false, - but: false, - noaudio: false, - novids: false, - simul: false - }, - service: undefined, - episodeListing: [], - version: '', -}; - -const Store: FCWithChildren = ({children}) => { - const [state, dispatch] = React.useReducer(Reducer, initialState); - /*React.useEffect(() => { - if (!state.unsavedChanges.has) - return; - const unsavedChanges = (ev: BeforeUnloadEvent, lang: LanguageContextType) => { - ev.preventDefault(); - ev.returnValue = lang.getLang('unsaved_changes'); - return lang.getLang('unsaved_changes'); - }; - - - const windowListener = (ev: BeforeUnloadEvent) => { - return unsavedChanges(ev, state.lang); - }; - - window.addEventListener('beforeunload', windowListener); - - return () => window.removeEventListener('beforeunload', windowListener); - }, [state.unsavedChanges.has]);*/ - - return ( - - {children} - - ); -}; - -/* Importent Notice -- The 'queue' generic will be overriden */ -export const StoreContext = React.createContext<[StoreState, React.Dispatch>]>([initialState, undefined as any]); -export default Store; \ No newline at end of file diff --git a/gui/react/tsconfig.json b/gui/react/tsconfig.json deleted file mode 100644 index b13020e..0000000 --- a/gui/react/tsconfig.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "compilerOptions": { - "outDir": "./build", - "target": "es5", - "lib": [ - "dom", - "dom.iterable", - "esnext" - ], - "allowJs": true, - "skipLibCheck": true, - "esModuleInterop": true, - "allowSyntheticDefaultImports": true, - "strict": true, - "forceConsistentCasingInFileNames": true, - "noFallthroughCasesInSwitch": true, - "module": "CommonJS", - "moduleResolution": "node", - "resolveJsonModule": true, - "isolatedModules": true, - //"noEmit": true, - "jsx": "react-jsx", - "downlevelIteration": true - }, - "include": [ - "./src", - "./webpack.config.ts" - ] -} \ No newline at end of file diff --git a/gui/react/webpack.config.ts b/gui/react/webpack.config.ts deleted file mode 100644 index 0c654d4..0000000 --- a/gui/react/webpack.config.ts +++ /dev/null @@ -1,58 +0,0 @@ -import type { Configuration } from 'webpack'; -import HtmlWebpackPlugin from 'html-webpack-plugin'; -import path from 'path'; -import type { Configuration as DevServerConfig } from 'webpack-dev-server'; - -const config: Configuration & DevServerConfig = { - devServer: { - proxy: [ - { - target: 'http://localhost:3000', - context: ['/public', '/private'], - ws: true - } - ], - }, - entry: './src/index.tsx', - mode: 'production', - output: { - path: path.resolve(__dirname, './build'), - filename: 'index.js', - }, - target: 'web', - resolve: { - extensions: ['.js', '.jsx', '.ts', '.tsx', '.json'], - }, - performance: false, - module: { - rules: [ - { - test: /\.(ts|tsx)$/, - exclude: /node_modules/, - use: { - 'loader': 'babel-loader', - options: { - presets: [ - '@babel/typescript', - '@babel/preset-react', - ['@babel/preset-env', { - targets: 'defaults' - }] - ] - } - }, - }, - { - test: /\.css$/i, - use: ['style-loader', 'css-loader'], - }, - ], - }, - plugins: [ - new HtmlWebpackPlugin({ - template: path.join(__dirname, 'public', 'index.html') - }) - ] -}; - -export default config; diff --git a/gui/server/index.ts b/gui/server/index.ts deleted file mode 100644 index 2229d78..0000000 --- a/gui/server/index.ts +++ /dev/null @@ -1,34 +0,0 @@ -import express from 'express'; -import { ensureConfig, loadCfg, workingDir } from '../../modules/module.cfg-loader'; -import cors from 'cors'; -import ServiceHandler from './serviceHandler'; -import open from 'open'; -import path from 'path'; -import { PublicWebSocket } from './websocket'; -import { console } from '../../modules/log'; -import packageJson from '../../package.json'; - -process.title = 'AniDL'; - -ensureConfig(); - -const cfg = loadCfg(); - -const app = express(); - -export { app, cfg }; - -app.use(express.json()); -app.use(cors()); -app.use(express.static(path.join(workingDir, 'gui', 'server', 'build'), { maxAge: 1000 * 60 * 20 })); - -console.info(`\n=== Multi Downloader NX GUI ${packageJson.version} ===\n`); - -const server = app.listen(cfg.gui.port, () => { - console.info(`GUI server started on port ${cfg.gui.port}`); -}); - -new PublicWebSocket(server); -new ServiceHandler(server); - -open(`http://localhost:${cfg.gui.port}`); \ No newline at end of file diff --git a/gui/server/serviceHandler.ts b/gui/server/serviceHandler.ts deleted file mode 100644 index db8618e..0000000 --- a/gui/server/serviceHandler.ts +++ /dev/null @@ -1,134 +0,0 @@ -import { ServerResponse } from 'http'; -import { Server } from 'http'; -import { IncomingMessage } from 'http'; -import { MessageHandler, GuiState } from '../../@types/messageHandler'; -import { setState, getState, writeYamlCfgFile } from '../../modules/module.cfg-loader'; -import CrunchyHandler from './services/crunchyroll'; -import HidiveHandler from './services/hidive'; -import AnimeOnegaiHandler from './services/animeonegai'; -import ADNHandler from './services/adn'; -import WebSocketHandler from './websocket'; -import packageJson from '../../package.json'; - -export default class ServiceHandler { - - private service: MessageHandler|undefined = undefined; - private ws: WebSocketHandler; - private state: GuiState; - - constructor(server: Server) { - this.ws = new WebSocketHandler(server); - this.handleMessages(); - this.state = getState(); - } - - private handleMessages() { - this.ws.events.on('setupServer', ({ data }, respond) => { - writeYamlCfgFile('gui', data); - this.state.setup = true; - setState(this.state); - respond(true); - process.exit(0); - }); - - this.ws.events.on('setup', ({ data }) => { - if (data === 'crunchy') { - this.service = new CrunchyHandler(this.ws); - } else if (data === 'hidive') { - this.service = new HidiveHandler(this.ws); - } else if (data === 'ao') { - this.service = new AnimeOnegaiHandler(this.ws); - } else if (data === 'adn') { - this.service = new ADNHandler(this.ws); - } - }); - - this.ws.events.on('changeProvider', async (_, respond) => { - if (await this.service?.isDownloading()) - return respond(false); - this.service = undefined; - respond(true); - }); - - this.ws.events.on('auth', async ({ data }, respond) => { - if (this.service === undefined) - return respond({ isOk: false, reason: new Error('No service selected') }); - respond(await this.service.auth(data)); - }); - this.ws.events.on('version', async (_, respond) => { - respond(packageJson.version); - }); - this.ws.events.on('type', async (_, respond) => respond(this.service === undefined ? undefined : this.service.name as 'hidive'|'crunchy'|'ao'|'adn')); - this.ws.events.on('checkToken', async (_, respond) => { - if (this.service === undefined) - return respond({ isOk: false, reason: new Error('No service selected') }); - respond(await this.service.checkToken()); - }); - this.ws.events.on('search', async ({ data }, respond) => { - if (this.service === undefined) - return respond({ isOk: false, reason: new Error('No service selected') }); - respond(await this.service.search(data)); - }); - this.ws.events.on('default', async ({ data }, respond) => { - if (this.service === undefined) - return respond({ isOk: false, reason: new Error('No service selected') }); - respond(await this.service.handleDefault(data)); - }); - this.ws.events.on('availableDubCodes', async (_, respond) => { - if (this.service === undefined) - return respond([]); - respond(await this.service.availableDubCodes()); - }); - this.ws.events.on('availableSubCodes', async (_, respond) => { - if (this.service === undefined) - return respond([]); - respond(await this.service.availableSubCodes()); - }); - this.ws.events.on('resolveItems', async ({ data }, respond) => { - if (this.service === undefined) - return respond(false); - respond(await this.service.resolveItems(data)); - }); - this.ws.events.on('listEpisodes', async ({ data }, respond) => { - if (this.service === undefined) - return respond({ isOk: false, reason: new Error('No service selected') }); - respond(await this.service.listEpisodes(data)); - }); - this.ws.events.on('downloadItem', async ({ data }, respond) => { - this.service?.downloadItem(data); - respond(undefined); - }); - this.ws.events.on('openFolder', async ({ data }, respond) => { - this.service?.openFolder(data); - respond(undefined); - }); - this.ws.events.on('openFile', async ({ data }, respond) => { - this.service?.openFile(data); - respond(undefined); - }); - this.ws.events.on('openURL', async ({ data }, respond) => { - this.service?.openURL(data); - respond(undefined); - }); - this.ws.events.on('getQueue', async (_, respond) => { - respond(await this.service?.getQueue() ?? []); - }); - this.ws.events.on('removeFromQueue', async ({ data }, respond) => { - this.service?.removeFromQueue(data); - respond(undefined); - }); - this.ws.events.on('clearQueue', async (_, respond) => { - this.service?.clearQueue(); - respond(undefined); - }); - this.ws.events.on('setDownloadQueue', async ({ data }, respond) => { - this.service?.setDownloadQueue(data); - respond(undefined); - }); - this.ws.events.on('getDownloadQueue', async (_, respond) => { - respond(await this.service?.getDownloadQueue() ?? false); - }); - this.ws.events.on('isDownloading', async (_, respond) => respond(await this.service?.isDownloading() ?? false)); - } - -} \ No newline at end of file diff --git a/gui/server/services/adn.ts b/gui/server/services/adn.ts deleted file mode 100644 index 88bbe2d..0000000 --- a/gui/server/services/adn.ts +++ /dev/null @@ -1,139 +0,0 @@ -import { AuthData, CheckTokenResponse, DownloadData, EpisodeListResponse, MessageHandler, ResolveItemsData, SearchData, SearchResponse } from '../../../@types/messageHandler'; -import AnimationDigitalNetwork from '../../../adn'; -import { getDefault } from '../../../modules/module.args'; -import { languages } from '../../../modules/module.langsData'; -import WebSocketHandler from '../websocket'; -import Base from './base'; -import { console } from '../../../modules/log'; -import * as yargs from '../../../modules/module.app-args'; - -class ADNHandler extends Base implements MessageHandler { - private adn: AnimationDigitalNetwork; - public name = 'adn'; - constructor(ws: WebSocketHandler) { - super(ws); - this.adn = new AnimationDigitalNetwork(); - this.initState(); - this.getDefaults(); - } - - public getDefaults() { - const _default = yargs.appArgv(this.adn.cfg.cli, true); - if (['fr', 'de'].includes(_default.locale)) - this.adn.locale = _default.locale; - } - - public async auth(data: AuthData) { - return this.adn.doAuth(data); - } - - public async checkToken(): Promise { - //TODO: implement proper method to check token - return { isOk: true, value: undefined }; - } - - public async search(data: SearchData): Promise { - console.debug(`Got search options: ${JSON.stringify(data)}`); - const search = await this.adn.doSearch(data); - if (!search.isOk) { - return search; - } - return { isOk: true, value: search.value }; - } - - public async handleDefault(name: string) { - return getDefault(name, this.adn.cfg.cli); - } - - public async availableDubCodes(): Promise { - const dubLanguageCodesArray: string[] = []; - for(const language of languages){ - if (language.adn_locale) - dubLanguageCodesArray.push(language.code); - } - return [...new Set(dubLanguageCodesArray)]; - } - - public async availableSubCodes(): Promise { - const subLanguageCodesArray: string[] = []; - for(const language of languages){ - if (language.adn_locale) - subLanguageCodesArray.push(language.locale); - } - return ['all', 'none', ...new Set(subLanguageCodesArray)]; - } - - public async resolveItems(data: ResolveItemsData): Promise { - const parse = parseInt(data.id); - if (isNaN(parse) || parse <= 0) - return false; - console.debug(`Got resolve options: ${JSON.stringify(data)}`); - const res = await this.adn.selectShow(parseInt(data.id), data.e, data.but, data.all); - if (!res.isOk || !res.value) - return res.isOk; - this.addToQueue(res.value.map(a => { - return { - ...data, - ids: [a.id], - title: a.title, - parent: { - title: a.show.shortTitle, - season: a.season - }, - e: a.shortNumber, - image: a.image, - episode: a.shortNumber - }; - })); - return true; - } - - public async listEpisodes(id: string): Promise { - const parse = parseInt(id); - if (isNaN(parse) || parse <= 0) - return { isOk: false, reason: new Error('The ID is invalid') }; - - const request = await this.adn.listShow(parse); - if (!request.isOk || !request.value) - return {isOk: false, reason: new Error('Unknown upstream error, check for additional logs')}; - - return { isOk: true, value: request.value.videos.map(function(item) { - return { - e: item.shortNumber, - lang: [], - name: item.title, - season: item.season, - seasonTitle: item.show.title, - episode: item.shortNumber, - id: item.id+'', - img: item.image, - description: item.summary, - time: item.duration+'' - }; - })}; - } - - public async downloadItem(data: DownloadData) { - this.setDownloading(true); - console.debug(`Got download options: ${JSON.stringify(data)}`); - const _default = yargs.appArgv(this.adn.cfg.cli, true); - const res = await this.adn.selectShow(parseInt(data.id), data.e, false, false); - if (res.isOk) { - for (const select of res.value) { - if (!(await this.adn.getEpisode(select, {..._default, skipsubs: false, callbackMaker: this.makeProgressHandler.bind(this), q: data.q, fileName: data.fileName, dlsubs: data.dlsubs, dlVideoOnce: data.dlVideoOnce, force: 'y', - novids: data.novids, noaudio: data.noaudio, hslang: data.hslang || 'none', dubLang: data.dubLang }))) { - const er = new Error(`Unable to download episode ${data.e} from ${data.id}`); - er.name = 'Download error'; - this.alertError(er); - } - } - } else { - this.alertError(new Error('Failed to download episode, check for additional logs.')); - } - this.sendMessage({ name: 'finish', data: undefined }); - this.setDownloading(false); - this.onFinish(); - } -} - -export default ADNHandler; \ No newline at end of file diff --git a/gui/server/services/animeonegai.ts b/gui/server/services/animeonegai.ts deleted file mode 100644 index ef413bf..0000000 --- a/gui/server/services/animeonegai.ts +++ /dev/null @@ -1,151 +0,0 @@ -import { AuthData, CheckTokenResponse, DownloadData, Episode, EpisodeListResponse, MessageHandler, ResolveItemsData, SearchData, SearchResponse } from '../../../@types/messageHandler'; -import AnimeOnegai from '../../../ao'; -import { getDefault } from '../../../modules/module.args'; -import { languages } from '../../../modules/module.langsData'; -import WebSocketHandler from '../websocket'; -import Base from './base'; -import { console } from '../../../modules/log'; -import * as yargs from '../../../modules/module.app-args'; - -class AnimeOnegaiHandler extends Base implements MessageHandler { - private ao: AnimeOnegai; - public name = 'ao'; - constructor(ws: WebSocketHandler) { - super(ws); - this.ao = new AnimeOnegai(); - this.initState(); - this.getDefaults(); - } - - public getDefaults() { - const _default = yargs.appArgv(this.ao.cfg.cli, true); - if (['es', 'pt'].includes(_default.locale)) - this.ao.locale = _default.locale; - } - - public async auth(data: AuthData) { - return this.ao.doAuth(data); - } - - public async checkToken(): Promise { - //TODO: implement proper method to check token - return { isOk: true, value: undefined }; - } - - public async search(data: SearchData): Promise { - console.debug(`Got search options: ${JSON.stringify(data)}`); - const search = await this.ao.doSearch(data); - if (!search.isOk) { - return search; - } - return { isOk: true, value: search.value }; - } - - public async handleDefault(name: string) { - return getDefault(name, this.ao.cfg.cli); - } - - public async availableDubCodes(): Promise { - const dubLanguageCodesArray: string[] = []; - for(const language of languages){ - if (language.ao_locale) - dubLanguageCodesArray.push(language.code); - } - return [...new Set(dubLanguageCodesArray)]; - } - - public async availableSubCodes(): Promise { - const subLanguageCodesArray: string[] = []; - for(const language of languages){ - if (language.ao_locale) - subLanguageCodesArray.push(language.locale); - } - return ['all', 'none', ...new Set(subLanguageCodesArray)]; - } - - public async resolveItems(data: ResolveItemsData): Promise { - const parse = parseInt(data.id); - if (isNaN(parse) || parse <= 0) - return false; - console.debug(`Got resolve options: ${JSON.stringify(data)}`); - const _default = yargs.appArgv(this.ao.cfg.cli, true); - const res = await this.ao.selectShow(parseInt(data.id), data.e, data.but, data.all, _default); - if (!res.isOk || !res.value) - return res.isOk; - this.addToQueue(res.value.map(a => { - return { - ...data, - ids: a.data.map(a => a.videoId), - title: a.episodeTitle, - parent: { - title: a.seasonTitle, - season: a.seasonTitle - }, - e: a.episodeNumber+'', - image: a.image, - episode: a.episodeNumber+'' - }; - })); - return true; - } - - public async listEpisodes(id: string): Promise { - const parse = parseInt(id); - if (isNaN(parse) || parse <= 0) - return { isOk: false, reason: new Error('The ID is invalid') }; - - const request = await this.ao.listShow(parse); - if (!request.isOk || !request.value) - return {isOk: false, reason: new Error('Unknown upstream error, check for additional logs')}; - - const episodes: Episode[] = []; - const seasonNumberTitleParse = request.series.data.title.match(/\d+$/); - const seasonNumber = seasonNumberTitleParse ? parseInt(seasonNumberTitleParse[0]) : 1; - //request.value - for (const episodeKey in request.value) { - const episode = request.value[episodeKey][0]; - const langs = Array.from(new Set(request.value[episodeKey].map(a=>a.lang))); - episodes.push({ - e: episode.number+'', - lang: langs as string[], - name: episode.name, - season: seasonNumber+'', - seasonTitle: '', - episode: episode.number+'', - id: episode.video_entry+'', - img: episode.thumbnail, - description: episode.description, - time: '' - }); - } - return { isOk: true, value: episodes }; - } - - public async downloadItem(data: DownloadData) { - this.setDownloading(true); - console.debug(`Got download options: ${JSON.stringify(data)}`); - const _default = yargs.appArgv(this.ao.cfg.cli, true); - const res = await this.ao.selectShow(parseInt(data.id), data.e, false, false, { - ..._default, - dubLang: data.dubLang, - e: data.e - }); - if (res.isOk) { - for (const select of res.value) { - if (!(await this.ao.downloadEpisode(select, {..._default, skipsubs: false, callbackMaker: this.makeProgressHandler.bind(this), q: data.q, fileName: data.fileName, dlsubs: data.dlsubs, dlVideoOnce: data.dlVideoOnce, force: 'y', - novids: data.novids, noaudio: data.noaudio, hslang: data.hslang || 'none', dubLang: data.dubLang }))) { - const er = new Error(`Unable to download episode ${data.e} from ${data.id}`); - er.name = 'Download error'; - this.alertError(er); - } - } - } else { - this.alertError(new Error('Failed to download episode, check for additional logs.')); - } - this.sendMessage({ name: 'finish', data: undefined }); - this.setDownloading(false); - this.onFinish(); - } -} - -export default AnimeOnegaiHandler; \ No newline at end of file diff --git a/gui/server/services/base.ts b/gui/server/services/base.ts deleted file mode 100644 index a192d18..0000000 --- a/gui/server/services/base.ts +++ /dev/null @@ -1,148 +0,0 @@ -import { DownloadInfo, FolderTypes, GuiState, ProgressData, QueueItem } from '../../../@types/messageHandler'; -import { RandomEvent, RandomEvents } from '../../../@types/randomEvents'; -import WebSocketHandler from '../websocket'; -import open from 'open'; -import { cfg } from '..'; -import path from 'path'; -import { console } from '../../../modules/log'; -import { getState, setState } from '../../../modules/module.cfg-loader'; -import packageJson from '../../../package.json'; - -export default class Base { - private state: GuiState; - public name = 'default'; - constructor(private ws: WebSocketHandler) { - this.state = getState(); - } - - private downloading = false; - - private queue: QueueItem[] = []; - private workOnQueue = false; - - version(): Promise { - return new Promise(() => { - return packageJson.version; - }); - } - - initState() { - if (this.state.services[this.name]) { - this.queue = this.state.services[this.name].queue; - this.queueChange(); - } else { - this.state.services[this.name] = { - 'queue': [] - }; - } - } - - setDownloading(downloading: boolean) { - this.downloading = downloading; - } - - getDownloading() { - return this.downloading; - } - - alertError(error: Error) { - console.error(`${error}`); - } - - makeProgressHandler(videoInfo: DownloadInfo) { - return ((data: ProgressData) => { - this.sendMessage({ - name: 'progress', - data: { - downloadInfo: videoInfo, - progress: data - } - }); - }); - } - - sendMessage(data: RandomEvent) { - this.ws.sendMessage(data); - } - - async isDownloading() { - return this.downloading; - } - - async openFolder(folderType: FolderTypes) { - switch (folderType) { - case 'content': - open(cfg.dir.content); - break; - case 'config': - open(cfg.dir.config); - break; - } - } - - async openFile(data: [FolderTypes, string]) { - switch (data[0]) { - case 'config': - open(path.join(cfg.dir.config, data[1])); - break; - case 'content': - throw new Error('No subfolders'); - } - } - - async openURL(data: string) { - open(data); - } - - public async getQueue(): Promise { - return this.queue; - } - - public async removeFromQueue(index: number) { - this.queue.splice(index, 1); - this.queueChange(); - } - - public async clearQueue() { - this.queue = []; - this.queueChange(); - } - - public addToQueue(data: QueueItem[]) { - this.queue = this.queue.concat(...data); - this.queueChange(); - } - - public setDownloadQueue(data: boolean) { - this.workOnQueue = data; - this.queueChange(); - } - - public async getDownloadQueue(): Promise { - return this.workOnQueue; - } - - private async queueChange() { - this.sendMessage({ name: 'queueChange', data: this.queue }); - if (this.workOnQueue && this.queue.length > 0 && !await this.isDownloading()) { - this.setDownloading(true); - this.sendMessage({ name: 'current', data: this.queue[0] }); - this.downloadItem(this.queue[0]); - this.queue = this.queue.slice(1); - this.queueChange(); - } - this.state.services[this.name].queue = this.queue; - setState(this.state); - } - - public async onFinish() { - this.sendMessage({ name: 'current', data: undefined }); - this.queueChange(); - } - - //Overriten - // eslint-disable-next-line - public async downloadItem(_: QueueItem) { - throw new Error('downloadItem not overriden'); - } -} \ No newline at end of file diff --git a/gui/server/services/crunchyroll.ts b/gui/server/services/crunchyroll.ts deleted file mode 100644 index da09adb..0000000 --- a/gui/server/services/crunchyroll.ts +++ /dev/null @@ -1,129 +0,0 @@ -import { AuthData, CheckTokenResponse, DownloadData, EpisodeListResponse, MessageHandler, ResolveItemsData, SearchData, SearchResponse } from '../../../@types/messageHandler'; -import Crunchy from '../../../crunchy'; -import { getDefault } from '../../../modules/module.args'; -import { languages, subtitleLanguagesFilter } from '../../../modules/module.langsData'; -import WebSocketHandler from '../websocket'; -import Base from './base'; -import { console } from '../../../modules/log'; -import * as yargs from '../../../modules/module.app-args'; - -class CrunchyHandler extends Base implements MessageHandler { - private crunchy: Crunchy; - public name = 'crunchy'; - constructor(ws: WebSocketHandler) { - super(ws); - this.crunchy = new Crunchy(); - this.crunchy.refreshToken(); - this.initState(); - this.getDefaults(); - } - - public getDefaults() { - const _default = yargs.appArgv(this.crunchy.cfg.cli, true); - this.crunchy.api = _default.crapi; - this.crunchy.locale = _default.locale; - } - - public async listEpisodes (id: string): Promise { - this.getDefaults(); - await this.crunchy.refreshToken(true); - return { isOk: true, value: (await this.crunchy.listSeriesID(id)).list }; - } - - public async handleDefault(name: string) { - return getDefault(name, this.crunchy.cfg.cli); - } - - public async availableDubCodes(): Promise { - const dubLanguageCodesArray: string[] = []; - for(const language of languages){ - if (language.cr_locale) - dubLanguageCodesArray.push(language.code); - } - return [...new Set(dubLanguageCodesArray)]; - } - - public async availableSubCodes(): Promise { - return subtitleLanguagesFilter; - } - - public async resolveItems(data: ResolveItemsData): Promise { - this.getDefaults(); - await this.crunchy.refreshToken(true); - console.debug(`Got resolve options: ${JSON.stringify(data)}`); - const res = await this.crunchy.downloadFromSeriesID(data.id, data); - if (!res.isOk) - return res.isOk; - this.addToQueue(res.value.map(a => { - return { - ...data, - - ids: a.data.map(a => a.mediaId), - title: a.episodeTitle, - parent: { - title: a.seasonTitle, - season: a.season.toString() - }, - e: a.e, - image: a.image, - episode: a.episodeNumber - }; - })); - return true; - } - - public async search(data: SearchData): Promise { - this.getDefaults(); - await this.crunchy.refreshToken(true); - if (!data['search-type']) data['search-type'] = 'series'; - console.debug(`Got search options: ${JSON.stringify(data)}`); - const crunchySearch = await this.crunchy.doSearch(data); - if (!crunchySearch.isOk) { - this.crunchy.refreshToken(); - return crunchySearch; - } - return { isOk: true, value: crunchySearch.value }; - } - - public async checkToken(): Promise { - if (await this.crunchy.getProfile()) { - return { isOk: true, value: undefined }; - } else { - return { isOk: false, reason: new Error('') }; - } - } - - public auth(data: AuthData) { - return this.crunchy.doAuth(data); - } - - public async downloadItem(data: DownloadData) { - this.getDefaults(); - await this.crunchy.refreshToken(true); - console.debug(`Got download options: ${JSON.stringify(data)}`); - this.setDownloading(true); - const _default = yargs.appArgv(this.crunchy.cfg.cli, true); - this.crunchy.api = _default.crapi; - const res = await this.crunchy.downloadFromSeriesID(data.id, { - dubLang: data.dubLang, - e: data.e - }); - if (res.isOk) { - for (const select of res.value) { - if (!(await this.crunchy.downloadEpisode(select, {..._default, skipsubs: false, callbackMaker: this.makeProgressHandler.bind(this), q: data.q, fileName: data.fileName, dlsubs: data.dlsubs, dlVideoOnce: data.dlVideoOnce, force: 'y', - novids: data.novids, noaudio: data.noaudio, hslang: data.hslang || 'none' }))) { - const er = new Error(`Unable to download episode ${data.e} from ${data.id}`); - er.name = 'Download error'; - this.alertError(er); - } - } - } else { - this.alertError(res.reason); - } - this.sendMessage({ name: 'finish', data: undefined }); - this.setDownloading(false); - this.onFinish(); - } -} - -export default CrunchyHandler; \ No newline at end of file diff --git a/gui/server/services/hidive.ts b/gui/server/services/hidive.ts deleted file mode 100644 index ee98426..0000000 --- a/gui/server/services/hidive.ts +++ /dev/null @@ -1,127 +0,0 @@ -import { AuthData, CheckTokenResponse, DownloadData, EpisodeListResponse, MessageHandler, ResolveItemsData, SearchData, SearchResponse } from '../../../@types/messageHandler'; -import Hidive from '../../../hidive'; -import { getDefault } from '../../../modules/module.args'; -import { languages } from '../../../modules/module.langsData'; -import WebSocketHandler from '../websocket'; -import Base from './base'; -import { console } from '../../../modules/log'; -import * as yargs from '../../../modules/module.app-args'; - -class HidiveHandler extends Base implements MessageHandler { - private hidive: Hidive; - public name = 'hidive'; - constructor(ws: WebSocketHandler) { - super(ws); - this.hidive = new Hidive(); - this.initState(); - } - - public async auth(data: AuthData) { - return this.hidive.doAuth(data); - } - - public async checkToken(): Promise { - //TODO: implement proper method to check token - return { isOk: true, value: undefined }; - } - - public async search(data: SearchData): Promise { - console.debug(`Got search options: ${JSON.stringify(data)}`); - const hidiveSearch = await this.hidive.doSearch(data); - if (!hidiveSearch.isOk) { - return hidiveSearch; - } - return { isOk: true, value: hidiveSearch.value }; - } - - public async handleDefault(name: string) { - return getDefault(name, this.hidive.cfg.cli); - } - - public async availableDubCodes(): Promise { - const dubLanguageCodesArray: string[] = []; - for(const language of languages){ - if (language.new_hd_locale) - dubLanguageCodesArray.push(language.code); - } - return [...new Set(dubLanguageCodesArray)]; - } - - public async availableSubCodes(): Promise { - const subLanguageCodesArray: string[] = []; - for(const language of languages){ - if (language.new_hd_locale) - subLanguageCodesArray.push(language.locale); - } - return ['all', 'none', ...new Set(subLanguageCodesArray)]; - } - - public async resolveItems(data: ResolveItemsData): Promise { - const parse = parseInt(data.id); - if (isNaN(parse) || parse <= 0) - return false; - console.debug(`Got resolve options: ${JSON.stringify(data)}`); - const res = await this.hidive.selectSeries(parseInt(data.id), data.e, data.but, data.all); - if (!res.isOk || !res.value) - return res.isOk; - this.addToQueue(res.value.map(item => { - return { - ...data, - ids: [item.id], - title: item.title, - parent: { - title: item.seriesTitle, - season: item.episodeInformation.seasonNumber+'' - }, - image: item.thumbnailUrl, - e: item.episodeInformation.episodeNumber+'', - episode: item.episodeInformation.episodeNumber+'', - }; - })); - return true; - } - - public async listEpisodes(id: string): Promise { - const parse = parseInt(id); - if (isNaN(parse) || parse <= 0) - return { isOk: false, reason: new Error('The ID is invalid') }; - - const request = await this.hidive.listSeries(parse); - if (!request.isOk || !request.value) - return {isOk: false, reason: new Error('Unknown upstream error, check for additional logs')}; - - return { isOk: true, value: request.value.map(function(item) { - const description = item.description.split('\r\n'); - return { - e: item.episodeInformation.episodeNumber+'', - lang: [], - name: item.title, - season: item.episodeInformation.seasonNumber+'', - seasonTitle: request.series.seasons[item.episodeInformation.seasonNumber-1]?.title ?? request.series.title, - episode: item.episodeInformation.episodeNumber+'', - id: item.id+'', - img: item.thumbnailUrl, - description: description ? description[0] : '', - time: '' - }; - })}; - } - - public async downloadItem(data: DownloadData) { - this.setDownloading(true); - console.debug(`Got download options: ${JSON.stringify(data)}`); - const _default = yargs.appArgv(this.hidive.cfg.cli, true); - const res = await this.hidive.selectSeries(parseInt(data.id), data.e, false, false); - if (!res.isOk || !res.showData) - return this.alertError(new Error('Download failed upstream, check for additional logs')); - - for (const ep of res.value) { - await this.hidive.downloadEpisode(ep, {..._default, callbackMaker: this.makeProgressHandler.bind(this), dubLang: data.dubLang, dlsubs: data.dlsubs, fileName: data.fileName, q: data.q, force: 'y', noaudio: data.noaudio, novids: data.novids }); - } - this.sendMessage({ name: 'finish', data: undefined }); - this.setDownloading(false); - this.onFinish(); - } -} - -export default HidiveHandler; \ No newline at end of file diff --git a/gui/server/websocket.ts b/gui/server/websocket.ts deleted file mode 100644 index 88044c2..0000000 --- a/gui/server/websocket.ts +++ /dev/null @@ -1,123 +0,0 @@ -import { IncomingMessage, Server } from 'http'; -import ws, { WebSocket } from 'ws'; -import { RandomEvent, RandomEvents } from '../../@types/randomEvents'; -import { MessageTypes, UnknownWSMessage, WSMessage } from '../../@types/ws'; -import { EventEmitter } from 'events'; -import { cfg } from '.'; -import { getState } from '../../modules/module.cfg-loader'; -import { console } from '../../modules/log'; - -declare interface ExternalEvent { - on(event: T, listener: (msg: WSMessage, respond: (data: MessageTypes[T][1]) => void) => void): this; - emit(event: T, msg: WSMessage, respond: (data: MessageTypes[T][1]) => void): boolean; -} - -class ExternalEvent extends EventEmitter {} - -export default class WebSocketHandler { - - private wsServer: ws.Server; - - public events: ExternalEvent = new ExternalEvent(); - - constructor(server: Server) { - this.wsServer = new ws.WebSocketServer({ noServer: true, path: '/private' }); - - this.wsServer.on('connection', (socket, req) => { - console.info(`[WS] Connection from '${req.socket.remoteAddress}'`); - socket.on('error', (er) => console.error(`[WS] ${er}`)); - socket.on('message', (data) => { - const json = JSON.parse(data.toString()) as UnknownWSMessage; - this.events.emit(json.name, json as any, (data) => { - this.wsServer.clients.forEach(client => { - if (client.readyState !== WebSocket.OPEN) - return; - client.send(JSON.stringify({ - data, - id: json.id, - name: json.name - }), (er) => { - if (er) - console.error(`[WS] ${er}`); - }); - }); - }); - }); - }); - - server.on('upgrade', (request, socket, head) => { - if (!this.wsServer.shouldHandle(request)) - return; - if (!this.authenticate(request)) { - socket.write('HTTP/1.1 401 Unauthorized\r\n\r\n'); - socket.destroy(); - console.info(`[WS] ${request.socket.remoteAddress} tried to connect but used a wrong password.`); - return; - } - this.wsServer.handleUpgrade(request, socket, head, socket => { - this.wsServer.emit('connection', socket, request); - }); - }); - } - - public sendMessage(data: RandomEvent) { - this.wsServer.clients.forEach(client => { - if (client.readyState !== WebSocket.OPEN) - return; - client.send(JSON.stringify(data), (er) => { - if (er) - console.error(`[WS] ${er}`); - }); - }); - } - - private authenticate(request: IncomingMessage): boolean { - const search = new URL(`http://${request.headers.host}${request.url}`).searchParams; - return cfg.gui.password === (search.get('password') ?? undefined); - } - -} - -export class PublicWebSocket { - private wsServer: ws.Server; - - private state = getState(); - constructor(server: Server) { - this.wsServer = new ws.WebSocketServer({ noServer: true, path: '/public' }); - - this.wsServer.on('connection', (socket, req) => { - console.info(`[WS] Connection to public ws from '${req.socket.remoteAddress}'`); - socket.on('error', (er) => console.error(`[WS] ${er}`)); - socket.on('message', (msg) => { - const data = JSON.parse(msg.toString()) as UnknownWSMessage; - switch (data.name) { - case 'isSetup': - this.send(socket, data.id, data.name, this.state.setup); - break; - case 'requirePassword': - this.send(socket, data.id, data.name, cfg.gui.password !== undefined); - break; - } - }); - }); - - server.on('upgrade', (request, socket, head) => { - if (!this.wsServer.shouldHandle(request)) - return; - this.wsServer.handleUpgrade(request, socket, head, socket => { - this.wsServer.emit('connection', socket, request); - }); - }); - } - - private send(client: ws.WebSocket, id: string, name: string, data: any) { - client.send(JSON.stringify({ - data, - id, - name - }), (er) => { - if (er) - console.error(`[WS] ${er}`); - }); - } -} diff --git a/hidive.ts b/hidive.ts deleted file mode 100644 index 6c35fe0..0000000 --- a/hidive.ts +++ /dev/null @@ -1,1082 +0,0 @@ -// build-in -import path from 'path'; -import fs from 'fs-extra'; - -// package program -import packageJson from './package.json'; - -// plugins -import { console } from './modules/log'; -import shlp from 'sei-helper'; -import streamdl, { M3U8Json } from './modules/hls-download'; - -// custom modules -import * as fontsData from './modules/module.fontsData'; -import * as langsData from './modules/module.langsData'; -import * as yamlCfg from './modules/module.cfg-loader'; -import * as yargs from './modules/module.app-args'; -import Merger, { Font, MergerInput, SubtitleInput } from './modules/module.merger'; -import vtt2ass from './modules/module.vtt2ass'; - -// load req -import { domain, api } from './modules/module.api-urls'; -import * as reqModule from './modules/module.req'; -import { DownloadedMedia } from './@types/hidiveTypes'; -import parseFileName, { Variable } from './modules/module.filename'; -import { downloaded } from './modules/module.downloadArchive'; -import parseSelect from './modules/module.parseSelect'; -import { AvailableFilenameVars } from './modules/module.args'; -import { AuthData, AuthResponse, SearchData, SearchResponse, SearchResponseItem } from './@types/messageHandler'; -import { ServiceClass } from './@types/serviceClassInterface'; -import { sxItem } from './crunchy'; -import { Hit, NewHidiveSearch } from './@types/newHidiveSearch'; -import { NewHidiveSeries } from './@types/newHidiveSeries'; -import { Episode, NewHidiveEpisodeExtra, NewHidiveSeason, NewHidiveSeriesExtra } from './@types/newHidiveSeason'; -import { NewHidiveEpisode } from './@types/newHidiveEpisode'; -import { NewHidivePlayback, Subtitle } from './@types/newHidivePlayback'; -import { MPDParsed, parse } from './modules/module.transform-mpd'; -import getKeys, { canDecrypt } from './modules/widevine'; -import { exec } from './modules/sei-helper-fixes'; -import { KeyContainer } from './modules/license'; - -export default class Hidive implements ServiceClass { - public cfg: yamlCfg.ConfigObject; - private token: Record; - private req: reqModule.Req; - - constructor(private debug = false) { - this.cfg = yamlCfg.loadCfg(); - this.token = yamlCfg.loadNewHDToken(); - this.req = new reqModule.Req(domain, debug, false, 'hd'); - } - - public async cli() { - console.info(`\n=== Multi Downloader NX ${packageJson.version} ===\n`); - const argv = yargs.appArgv(this.cfg.cli); - if (argv.debug) - this.debug = true; - - //below is for quickly testing API calls - /*const apiTest = await this.apiReq('/v4/season/18871', '', 'auth', 'GET'); - if(!apiTest.ok || !apiTest.res){return;} - console.info(apiTest.res.body); - fs.writeFileSync('apitest.json', JSON.stringify(JSON.parse(apiTest.res.body), null, 2)); - return console.info('test done');*/ - - // load binaries - this.cfg.bin = await yamlCfg.loadBinCfg(); - if (argv.allDubs) { - argv.dubLang = langsData.dubLanguageCodes; - } - if (argv.auth) { - //Authenticate - await this.doAuth({ - username: argv.username ?? await shlp.question('[Q] LOGIN/EMAIL'), - password: argv.password ?? await shlp.question('[Q] PASSWORD ') - }); - } else if (argv.search && argv.search.length > 2){ - await this.doSearch({ ...argv, search: argv.search as string }); - } else if (argv.s && !isNaN(parseInt(argv.s,10)) && parseInt(argv.s,10) > 0) { - const selected = await this.selectSeason(parseInt(argv.s), argv.e, argv.but, argv.all); - if (selected.isOk && selected.showData) { - for (const select of selected.value) { - //download episode - if (!(await this.downloadEpisode(select, {...argv}))) { - console.error(`Unable to download selected episode ${select.episodeInformation.episodeNumber}`); - return false; - } - } - } - return true; - } else if (argv.srz && !isNaN(parseInt(argv.srz,10)) && parseInt(argv.srz,10) > 0) { - const selected = await this.selectSeries(parseInt(argv.srz), argv.e, argv.but, argv.all); - if (selected.isOk && selected.showData) { - for (const select of selected.value) { - //download episode - if (!(await this.downloadEpisode(select, {...argv}))) { - console.error(`Unable to download selected episode ${select.episodeInformation.episodeNumber}`); - return false; - } - } - } - } else if (argv.new) { - console.error('--new is not yet implemented in the new API'); - } else if(argv.e) { - if (!(await this.downloadSingleEpisode(parseInt(argv.e), {...argv}))) { - console.error(`Unable to download selected episode ${argv.e}`); - return false; - } - } else { - console.info('No option selected or invalid value entered. Try --help.'); - } - } - - - public async apiReq(endpoint: string, body: string | object = '', authType: 'refresh' | 'auth' | 'both' | 'other' | 'none' = 'none', method: 'GET' | 'POST' = 'POST', authHeader?: string) { - const options = { - headers: { - 'X-Api-Key': api.hd_new_apiKey, - 'X-App-Var': api.hd_new_version, - 'realm': 'dce.hidive', - 'Referer': 'https://www.hidive.com/', - 'Origin': 'https://www.hidive.com' - } as Record, - method: method as 'GET'|'POST', - url: api.hd_new_api+endpoint as string, - body: body, - useProxy: true - }; - // get request type - const isGet = method == 'GET'; - if(!isGet){ - options.body = body == '' ? body : JSON.stringify(body); - options.headers['Content-Type'] = 'application/json'; - } - if (authType == 'other') { - options.headers['Authorization'] = authHeader; - } else if (authType == 'auth') { - options.headers['Authorization'] = `Bearer ${this.token.authorisationToken}`; - } else if (authType == 'refresh') { - options.headers['Authorization'] = `Bearer ${this.token.refreshToken}`; - } else if (authType == 'both') { - options.headers['Authorization'] = `Mixed ${this.token.authorisationToken} ${this.token.refreshToken}`; - } - if (this.debug) { - console.debug('[DEBUG] Request params:'); - console.debug(options); - } - const apiReqOpts: reqModule.Params = { - method: options.method, - headers: options.headers as Record, - body: options.body as string - }; - let apiReq = await this.req.getData(options.url, apiReqOpts); - if(!apiReq.ok || !apiReq.res){ - if (apiReq.error && apiReq.error.res?.statusCode == 401) { - console.warn('Token expired, refreshing token and retrying.'); - if (await this.refreshToken()) { - if (authType == 'other') { - options.headers['Authorization'] = authHeader; - } else if (authType == 'auth') { - options.headers['Authorization'] = `Bearer ${this.token.authorisationToken}`; - } else if (authType == 'refresh') { - options.headers['Authorization'] = `Bearer ${this.token.refreshToken}`; - } else if (authType == 'both') { - options.headers['Authorization'] = `Mixed ${this.token.authorisationToken} ${this.token.refreshToken}`; - } - apiReq = await this.req.getData(options.url, apiReqOpts); - if(!apiReq.ok || !apiReq.res) { - console.error('API Request Failed!'); - return { - ok: false, - res: apiReq.res, - error: apiReq.error - }; - } - } else { - console.error('Failed to refresh token...'); - return { - ok: false, - res: apiReq.res, - error: apiReq.error - }; - } - } else { - console.error('API Request Failed!'); - return { - ok: false, - res: apiReq.res, - error: apiReq.error - }; - } - } - return { - ok: true, - res: apiReq.res, - }; - } - - public async doAuth(data: AuthData): Promise { - if (!this.token.refreshToken || !this.token.authorisationToken) { - await this.doAnonymousAuth(); - } - const authReq = await this.apiReq('/v2/login', { - id: data.username, - secret: data.password - }, 'auth'); - if(!authReq.ok || !authReq.res){ - console.error('Authentication failed!'); - return { isOk: false, reason: new Error('Authentication failed') }; - } - const tokens: Record = JSON.parse(authReq.res.body); - for (const token in tokens) { - this.token[token] = tokens[token]; - } - this.token.guest = false; - yamlCfg.saveNewHDToken(this.token); - console.info('Auth complete!'); - return { isOk: true, value: undefined }; - } - - public async doAnonymousAuth() { - const authReq = await this.apiReq('/v2/login/guest/checkin'); - if(!authReq.ok || !authReq.res){ - console.error('Authentication failed!'); - return false; - } - const tokens: Record = JSON.parse(authReq.res.body); - for (const token in tokens) { - this.token[token] = tokens[token]; - } - //this.token.expires = new Date(Date.now() + 300); - this.token.guest = true; - yamlCfg.saveNewHDToken(this.token); - return true; - } - - public async refreshToken() { - if (!this.token.refreshToken || !this.token.authorisationToken) { - return await this.doAnonymousAuth(); - } else { - const authReq = await this.apiReq('/v2/token/refresh', { - 'refreshToken': this.token.refreshToken - }, 'auth'); - if(!authReq.ok || !authReq.res){ - console.error('Token refresh failed, reinitializing session...'); - return this.initSession(); - } - const tokens: Record = JSON.parse(authReq.res.body); - for (const token in tokens) { - this.token[token] = tokens[token]; - } - yamlCfg.saveNewHDToken(this.token); - return true; - } - } - - public async initSession() { - const authReq = await this.apiReq('/v1/init/', '', 'both', 'GET'); - if(!authReq.ok || !authReq.res){ - console.error('Failed to initialize session.'); - return false; - } - const tokens: Record = JSON.parse(authReq.res.body).authentication; - for (const token in tokens) { - this.token[token] = tokens[token]; - } - yamlCfg.saveNewHDToken(this.token); - return true; - } - - public async doSearch(data: SearchData): Promise { - const searchReq = await this.req.getData('https://h99xldr8mj-dsn.algolia.net/1/indexes/*/queries?x-algolia-agent=Algolia%20for%20JavaScript%20(3.35.1)%3B%20Browser&x-algolia-application-id=H99XLDR8MJ&x-algolia-api-key=e55ccb3db0399eabe2bfc37a0314c346', { - method: 'POST', - body: JSON.stringify({'requests': - [ - {'indexName':'prod-dce.hidive-livestreaming-events','params':'query='+encodeURIComponent(data.search)+'&facetFilters=%5B%22type%3ALIVE_EVENT%22%5D&hitsPerPage=25'+(data.page ? '&page='+(data.page-1) : '')}, - {'indexName':'prod-dce.hidive-livestreaming-events','params':'query='+encodeURIComponent(data.search)+'&facetFilters=%5B%22type%3AVOD_VIDEO%22%5D&hitsPerPage=25'+(data.page ? '&page='+(data.page-1) : '')}, - {'indexName':'prod-dce.hidive-livestreaming-events','params':'query='+encodeURIComponent(data.search)+'&facetFilters=%5B%22type%3AVOD_PLAYLIST%22%5D&hitsPerPage=25'+(data.page ? '&page='+(data.page-1) : '')}, - {'indexName':'prod-dce.hidive-livestreaming-events','params':'query='+encodeURIComponent(data.search)+'&facetFilters=%5B%22type%3AVOD_SERIES%22%5D&hitsPerPage=25'+(data.page ? '&page='+(data.page-1) : '')} - ] - }) - }); - if(!searchReq.ok || !searchReq.res){ - console.error('Search FAILED!'); - return { isOk: false, reason: new Error('Search failed. No more information provided') }; - } - const searchData = JSON.parse(searchReq.res.body) as NewHidiveSearch; - const searchItems: Hit[] = []; - console.info('Search Results:'); - for (const category of searchData.results) { - for (const hit of category.hits) { - searchItems.push(hit); - let fullType: string; - if (hit.type == 'VOD_SERIES') { - fullType = `Z.${hit.id}`; - } else if (hit.type == 'VOD_VIDEO') { - fullType = `E.${hit.id}`; - } else { - fullType = `${hit.type} #${hit.id}`; - } - console.log(`[${fullType}] ${hit.name} ${hit.seasonsCount ? '('+hit.seasonsCount+' Seasons)' : ''}`); - } - } - return { isOk: true, value: searchItems.filter(a => a.type == 'VOD_SERIES').flatMap((a): SearchResponseItem => { - return { - id: a.id+'', - image: a.coverUrl ?? '/notFound.png', - name: a.name, - rating: -1, - desc: a.description - }; - })}; - } - - public async getSeries(id: number) { - const getSeriesData = await this.apiReq(`/v4/series/${id}?rpp=20`, '', 'auth', 'GET'); - if (!getSeriesData.ok || !getSeriesData.res) { - console.error('Failed to get Series Data'); - return { isOk: false }; - } - const seriesData = JSON.parse(getSeriesData.res.body) as NewHidiveSeries; - return { isOk: true, value: seriesData }; - } - - /** - * Function to get the season data from the API - * @param id ID of the season - * @param lastSeen Last episode ID seen, used for paging - * @returns - */ - public async getSeason(id: number, lastSeen?: number) { - const getSeasonData = await this.apiReq(`/v4/season/${id}?rpp=20${lastSeen ? '&lastSeen='+lastSeen : ''}`, '', 'auth', 'GET'); - if (!getSeasonData.ok || !getSeasonData.res) { - console.error('Failed to get Season Data'); - return { isOk: false }; - } - const seasonData = JSON.parse(getSeasonData.res.body) as NewHidiveSeason; - return { isOk: true, value: seasonData }; - } - - public async listSeries(id: number) { - const series = await this.getSeries(id); - if (!series.isOk || !series.value) { - console.error('Failed to list series data: Failed to get series'); - return { isOk: false }; - } - console.info(`[Z.${series.value.id}] ${series.value.title} (${series.value.seasons.length} Seasons)`); - if (series.value.seasons.length === 0) { - console.info(' No Seasons found!'); - return { isOk: false }; - } - const episodes: Episode[] = []; - for (const seasonData of series.value.seasons) { - const season = await this.getSeason(seasonData.id); - if (!season.isOk || !season.value) { - console.error('Failed to list series data: Failed to get season '+seasonData.id); - return { isOk: false }; - } - console.info(` [S.${season.value.id}] ${season.value.title} (${season.value.episodeCount} Episodes)`); - while (season.value.paging.moreDataAvailable) { - const seasonPage = await this.getSeason(seasonData.id, season.value.paging.lastSeen); - if (!seasonPage.isOk || !seasonPage.value) break; - season.value.episodes = season.value.episodes.concat(seasonPage.value.episodes); - season.value.paging.lastSeen = seasonPage.value.paging.lastSeen; - season.value.paging.moreDataAvailable = seasonPage.value.paging.moreDataAvailable; - } - for (const episode of season.value.episodes) { - const datePattern = /\d{1,2}\/\d{1,2}\/\d{2,4} \d{1,2}:\d{2} UTC/; - if (episode.title.includes(' - ')) { - episode.episodeInformation.episodeNumber = parseFloat(episode.title.split(' - ')[0].replace('E', '')); - episode.title = episode.title.split(' - ')[1]; - } - //S${episode.episodeInformation.seasonNumber}E${episode.episodeInformation.episodeNumber} - - if (!datePattern.test(episode.title) && episode.duration !== 10) { - episodes.push(episode); - } - console.info(` [E.${episode.id}] ${episode.title}`); - } - } - return { isOk: true, value: episodes, series: series.value }; - } - - public async listSeason(id: number) { - const season = await this.getSeason(id); - if (!season.isOk || !season.value) { - console.error('Failed to list series data: Failed to get season '+id); - return { isOk: false }; - } - console.info(` [S.${season.value.id}] ${season.value.title} (${season.value.episodeCount} Episodes)`); - while (season.value.paging.moreDataAvailable) { - const seasonPage = await this.getSeason(id, season.value.paging.lastSeen); - if (!seasonPage.isOk || !seasonPage.value) break; - season.value.episodes = season.value.episodes.concat(seasonPage.value.episodes); - season.value.paging.lastSeen = seasonPage.value.paging.lastSeen; - season.value.paging.moreDataAvailable = seasonPage.value.paging.moreDataAvailable; - } - const episodes: Episode[] = []; - for (const episode of season.value.episodes) { - const datePattern = /\d{1,2}\/\d{1,2}\/\d{2,4} \d{1,2}:\d{2} UTC/; - if (episode.title.includes(' - ')) { - episode.episodeInformation.episodeNumber = parseFloat(episode.title.split(' - ')[0].replace('E', '')); - episode.title = episode.title.split(' - ')[1]; - } - //S${episode.episodeInformation.seasonNumber}E${episode.episodeInformation.episodeNumber} - - if (!datePattern.test(episode.title) && episode.duration !== 10) { - episodes.push(episode); - } - console.info(` [E.${episode.id}] ${episode.title}`); - } - const series: NewHidiveSeriesExtra = {...season.value.series, season: season.value}; - return { isOk: true, value: episodes, series: series }; - } - - /** - * Lists the requested series, and returns the selected episodes - * @param id Series ID - * @param e Selector - * @param but Download all but selected videos - * @param all Whether to download all available videos - * @returns - */ - public async selectSeries(id: number, e: string | undefined, but: boolean, all: boolean) { - const getShowData = await this.listSeries(id); - if (!getShowData.isOk || !getShowData.value) { - return { isOk: false, value: [] }; - } - const showData = getShowData.value; - const doEpsFilter = parseSelect(e as string); - // build selected episodes - const selEpsArr: NewHidiveEpisodeExtra[] = []; let ovaSeq = 1; let movieSeq = 1; - for (let i = 0; i < showData.length; i++) { - const titleId = showData[i].id; - const seriesTitle = getShowData.series.title; - const seasonTitle = getShowData.series.seasons[showData[i].episodeInformation.seasonNumber-1]?.title ?? seriesTitle; - let nameLong = showData[i].title; - if (nameLong.match(/OVA/i)) { - nameLong = 'ova' + (('0' + ovaSeq).slice(-2)); ovaSeq++; - } else if (nameLong.match(/Theatrical/i)) { - nameLong = 'movie' + (('0' + movieSeq).slice(-2)); movieSeq++; - } - let selMark = ''; - if (all || - but && !doEpsFilter.isSelected([parseFloat(showData[i].episodeInformation.episodeNumber+'')+'', showData[i].id+'']) || - !but && doEpsFilter.isSelected([parseFloat(showData[i].episodeInformation.episodeNumber+'')+'', showData[i].id+'']) - ) { - selEpsArr.push({ isSelected: true, titleId, nameLong, seasonTitle, seriesTitle, ...showData[i] }); - selMark = '✓ '; - } - console.info('%s[%s] %s', - selMark, - 'S'+parseFloat(showData[i].episodeInformation.seasonNumber+'')+'E'+parseFloat(showData[i].episodeInformation.episodeNumber+''), - showData[i].title, - ); - } - return { isOk: true, value: selEpsArr, showData: getShowData.series }; - } - - /** - * Lists the requested season, and returns the selected episodes - * @param id Season ID - * @param e Selector - * @param but Download all but selected videos - * @param all Whether to download all available videos - * @returns - */ - public async selectSeason(id: number, e: string | undefined, but: boolean, all: boolean) { - const getShowData = await this.listSeason(id); - if (!getShowData.isOk || !getShowData.value) { - return { isOk: false, value: [] }; - } - const showData = getShowData.value; - const doEpsFilter = parseSelect(e as string); - // build selected episodes - const selEpsArr: NewHidiveEpisodeExtra[] = []; let ovaSeq = 1; let movieSeq = 1; - for (let i = 0; i < showData.length; i++) { - const titleId = showData[i].id; - const seriesTitle = getShowData.series.title; - const seasonTitle = getShowData.series.season.title; - let nameLong = showData[i].title; - if (nameLong.match(/OVA/i)) { - nameLong = 'ova' + (('0' + ovaSeq).slice(-2)); ovaSeq++; - } else if (nameLong.match(/Theatrical/i)) { - nameLong = 'movie' + (('0' + movieSeq).slice(-2)); movieSeq++; - } - let selMark = ''; - if (all || - but && !doEpsFilter.isSelected([parseFloat(showData[i].episodeInformation.episodeNumber+'')+'', showData[i].id+'']) || - !but && doEpsFilter.isSelected([parseFloat(showData[i].episodeInformation.episodeNumber+'')+'', showData[i].id+'']) - ) { - selEpsArr.push({ isSelected: true, titleId, nameLong, seasonTitle, seriesTitle, ...showData[i] }); - selMark = '✓ '; - } - console.info('%s[%s] %s', - selMark, - 'S'+parseFloat(showData[i].episodeInformation.seasonNumber+'')+'E'+parseFloat(showData[i].episodeInformation.episodeNumber+''), - showData[i].title, - ); - } - return { isOk: true, value: selEpsArr, showData: getShowData.series }; - } - - public async downloadEpisode(selectedEpisode: NewHidiveEpisodeExtra, options: Record) { - //Get Episode data - const episodeDataReq = await this.apiReq(`/v4/vod/${selectedEpisode.id}?includePlaybackDetails=URL`, '', 'auth', 'GET'); - if (!episodeDataReq.ok || !episodeDataReq.res) { - console.error('Failed to get episode data'); - return { isOk: false, reason: new Error('Failed to get Episode Data') }; - } - const episodeData = JSON.parse(episodeDataReq.res.body) as NewHidiveEpisode; - - if (!episodeData.playerUrlCallback) { - console.error('Failed to download episode: You do not have access to this'); - return { isOk: false, reason: new Error('You do not have access to this') }; - } - - //Get Playback data - const playbackReq = await this.req.getData(episodeData.playerUrlCallback); - if(!playbackReq.ok || !playbackReq.res){ - console.error('Playback Request Failed'); - return { isOk: false, reason: new Error('Playback request failed') }; - } - const playbackData = JSON.parse(playbackReq.res.body) as NewHidivePlayback; - - //Get actual MPD - const mpdRequest = await this.req.getData(playbackData.dash[0].url); - if(!mpdRequest.ok || !mpdRequest.res){ - console.error('MPD Request Failed'); - return { isOk: false, reason: new Error('MPD request failed') }; - } - const mpd = mpdRequest.res.body as string; - - selectedEpisode.jwtToken = playbackData.dash[0].drm.jwtToken; - - //Output metadata and prepare for download - const availableSubs = playbackData.dash[0].subtitles.filter(a => a.format === 'vtt'); - const showTitle = `${selectedEpisode.seriesTitle} S${selectedEpisode.episodeInformation.seasonNumber}`; - console.info(`[INFO] ${showTitle} - ${selectedEpisode.episodeInformation.episodeNumber}`); - console.info('[INFO] Available dubs and subtitles:'); - console.info('\tAudios: ' + episodeData.offlinePlaybackLanguages.map(a => langsData.languages.find(b => b.code == a)?.name).join('\n\t\t')); - console.info('\tSubs : ' + availableSubs.map(a => langsData.languages.find(b => b.new_hd_locale == a.language)?.name).join('\n\t\t')); - console.info(`[INFO] Selected dub(s): ${options.dubLang.join(', ')}`); - const baseUrl = playbackData.dash[0].url.split('master')[0]; - const parsedmpd = await parse(mpd, undefined, baseUrl); - const res = await this.downloadMPD(parsedmpd, availableSubs, selectedEpisode, options); - if (res === undefined || res.error) { - console.error('Failed to download media list'); - return { isOk: false, reason: new Error('Failed to download media list') }; - } else { - if (!options.skipmux) { - await this.muxStreams(res.data, { ...options, output: res.fileName }, false); - } else { - console.info('Skipping mux'); - } - downloaded({ - service: 'hidive', - type: 's' - }, selectedEpisode.titleId+'', [selectedEpisode.episodeInformation.episodeNumber+'']); - return { isOk: res, value: undefined }; - } - } - - public async downloadSingleEpisode(id: number, options: Record) { - //Get Episode data - const episodeDataReq = await this.apiReq(`/v4/vod/${id}?includePlaybackDetails=URL`, '', 'auth', 'GET'); - if (!episodeDataReq.ok || !episodeDataReq.res) { - console.error('Failed to get episode data'); - return { isOk: false, reason: new Error('Failed to get Episode Data') }; - } - const episodeData = JSON.parse(episodeDataReq.res.body) as NewHidiveEpisode; - - if (episodeData.title.includes(' - ') && episodeData.episodeInformation) { - episodeData.episodeInformation.episodeNumber = parseFloat(episodeData.title.split(' - ')[0].replace('E', '')); - episodeData.title = episodeData.title.split(' - ')[1]; - } - - if (!episodeData.playerUrlCallback) { - console.error('Failed to download episode: You do not have access to this'); - return { isOk: false, reason: new Error('You do not have access to this') }; - } - - let seasonData: Awaited> | undefined = undefined; - if (episodeData.episodeInformation) { - seasonData = await this.getSeason(episodeData.episodeInformation.season); - if (!seasonData.isOk || !seasonData.value) { - console.error('Failed to get season data'); - return { isOk: false, reason: new Error('Failed to get season data') }; - } - } else { - episodeData.episodeInformation = { - season: 0, - seasonNumber: 0, - episodeNumber: 0, - }; - } - - //Get Playback data - const playbackReq = await this.req.getData(episodeData.playerUrlCallback); - if(!playbackReq.ok || !playbackReq.res){ - console.error('Playback Request Failed'); - return { isOk: false, reason: new Error('Playback request failed') }; - } - const playbackData = JSON.parse(playbackReq.res.body) as NewHidivePlayback; - - //Get actual MPD - const mpdRequest = await this.req.getData(playbackData.dash[0].url); - if(!mpdRequest.ok || !mpdRequest.res){ - console.error('MPD Request Failed'); - return { isOk: false, reason: new Error('MPD request failed') }; - } - const mpd = mpdRequest.res.body as string; - - const selectedEpisode: NewHidiveEpisodeExtra = { - ...episodeData, - nameLong: episodeData.title, - titleId: episodeData.id, - seasonTitle: seasonData?.value.title ?? episodeData.title, - seriesTitle: seasonData?.value.series.title ?? episodeData.title, - isSelected: true - }; - - selectedEpisode.jwtToken = playbackData.dash[0].drm.jwtToken; - - //Output metadata and prepare for download - const availableSubs = playbackData.dash[0].subtitles.filter(a => a.format === 'vtt'); - const showTitle = `${selectedEpisode.seriesTitle} S${selectedEpisode.episodeInformation.seasonNumber}`; - console.info(`[INFO] ${showTitle} - ${selectedEpisode.episodeInformation.episodeNumber}`); - console.info('[INFO] Available dubs and subtitles:'); - console.info('\tAudios: ' + episodeData.offlinePlaybackLanguages.map(a => langsData.languages.find(b => b.code == a)?.name).join('\n\t\t')); - console.info('\tSubs : ' + availableSubs.map(a => langsData.languages.find(b => b.new_hd_locale == a.language)?.name).join('\n\t\t')); - console.info(`[INFO] Selected dub(s): ${options.dubLang.join(', ')}`); - const baseUrl = playbackData.dash[0].url.split('master')[0]; - const parsedmpd = await parse(mpd, undefined, baseUrl); - const res = await this.downloadMPD(parsedmpd, availableSubs, selectedEpisode, options); - if (res === undefined || res.error) { - console.error('Failed to download media list'); - return { isOk: false, reason: new Error('Failed to download media list') }; - } else { - if (!options.skipmux) { - await this.muxStreams(res.data, { ...options, output: res.fileName }, false); - } else { - console.info('Skipping mux'); - } - downloaded({ - service: 'hidive', - type: 's' - }, selectedEpisode.titleId+'', [selectedEpisode.episodeInformation.episodeNumber+'']); - return { isOk: res, value: undefined }; - } - } - - public async downloadMPD(streamPlaylists: MPDParsed, subs: Subtitle[], selectedEpisode: NewHidiveEpisodeExtra, options: Record) { - //let fileName: string; - const files: DownloadedMedia[] = []; - const variables: Variable[] = []; - let dlFailed = false; - const subsMargin = 0; - const chosenFontSize = options.originalFontSize ? undefined : options.fontSize; - let encryptionKeys: KeyContainer[] = []; - if (!canDecrypt) console.warn('Decryption not enabled!'); - - if (!this.cfg.bin.ffmpeg) - this.cfg.bin = await yamlCfg.loadBinCfg(); - - variables.push(...([ - ['title', selectedEpisode.title, true], - ['episode', selectedEpisode.episodeInformation.episodeNumber, false], - ['service', 'HD', false], - ['seriesTitle', selectedEpisode.seasonTitle, true], - ['showTitle', selectedEpisode.seriesTitle, true], - ['season', selectedEpisode.episodeInformation.seasonNumber, false] - ] as [AvailableFilenameVars, string|number, boolean][]).map((a): Variable => { - return { - name: a[0], - replaceWith: a[1], - type: typeof a[1], - sanitize: a[2] - } as Variable; - })); - - //Get name of CDNs/Servers - const streamServers = Object.keys(streamPlaylists); - - options.x = options.x > streamServers.length ? 1 : options.x; - - const selectedServer = streamServers[options.x - 1]; - const selectedList = streamPlaylists[selectedServer]; - - //set Video Qualities - const videos = selectedList.video.map(item => { - return { - ...item, - resolutionText: `${item.quality.width}x${item.quality.height} (${Math.round(item.bandwidth/1024)}KiB/s)` - }; - }); - - const audios = selectedList.audio.map(item => { - return { - ...item, - resolutionText: `${Math.round(item.bandwidth/1000)}kB/s` - }; - }); - - - videos.sort((a, b) => { - return a.bandwidth - b.bandwidth; - }); - - videos.sort((a, b) => { - return a.quality.width - b.quality.width; - }); - - audios.sort((a, b) => { - return a.bandwidth - b.bandwidth; - }); - - let chosenVideoQuality = options.q === 0 ? videos.length : options.q; - if(chosenVideoQuality > videos.length) { - console.warn(`The requested quality of ${options.q} is greater than the maximum ${videos.length}.\n[WARN] Therefor the maximum will be capped at ${videos.length}.`); - chosenVideoQuality = videos.length; - } - chosenVideoQuality--; - - const chosenVideoSegments = videos[chosenVideoQuality]; - - console.info(`Servers available:\n\t${streamServers.join('\n\t')}`); - console.info(`Available Video Qualities:\n\t${videos.map((a, ind) => `[${ind+1}] ${a.resolutionText}`).join('\n\t')}`); - console.info(`Available Audio Qualities:\n\t${audios.map((a, ind) => `[${ind+1}] ${a.resolutionText}`).join('\n\t')}`); - - variables.push({ - name: 'height', - type: 'number', - replaceWith: chosenVideoSegments.quality.height - }, { - name: 'width', - type: 'number', - replaceWith: chosenVideoSegments.quality.width - }); - - const chosenAudios: typeof audios[0][] = []; - const audioByLanguage: Record = {}; - for (const audio of audios) { - if (!audioByLanguage[audio.language.code]) audioByLanguage[audio.language.code] = []; - audioByLanguage[audio.language.code].push(audio); - } - for (const dubLang of options.dubLang as string[]) { - if (audioByLanguage[dubLang]) { - let chosenAudioQuality = options.q === 0 ? audios.length : options.q; - if(chosenAudioQuality > audioByLanguage[dubLang].length) { - chosenAudioQuality = audioByLanguage[dubLang].length; - } - chosenAudioQuality--; - chosenAudios.push(audioByLanguage[dubLang][chosenAudioQuality]); - } - } - if (chosenAudios.length == 0) { - console.error(`Chosen audio language(s) does not exist for episode ${selectedEpisode.episodeInformation.episodeNumber}`); - return undefined; - } - - const fileName = parseFileName(options.fileName, variables, options.numbers, options.override).join(path.sep); - - console.info(`Selected quality: \n\tVideo: ${chosenVideoSegments.resolutionText}\n\tAudio: ${chosenAudios[0].resolutionText}\n\tServer: ${selectedServer}`); - console.info(`Selected (Available) Audio Languages: ${chosenAudios.map(a => a.language.name).join(', ')}`); - console.info('Stream URL:', chosenVideoSegments.segments[0].map.uri.split('/init.mp4')[0]); - - if (chosenAudios[0].pssh || chosenVideoSegments.pssh) { - encryptionKeys = await getKeys(chosenVideoSegments.pssh, 'https://shield-drm.imggaming.com/api/v2/license', { - 'Authorization': `Bearer ${selectedEpisode.jwtToken}`, - 'X-Drm-Info': 'eyJzeXN0ZW0iOiJjb20ud2lkZXZpbmUuYWxwaGEifQ==', - }); - } - - if (!options.novids) { - //Download Video - const totalParts = chosenVideoSegments.segments.length; - const mathParts = Math.ceil(totalParts / options.partsize); - const mathMsg = `(${mathParts}*${options.partsize})`; - console.info('Total parts in video stream:', totalParts, mathMsg); - const tsFile = path.isAbsolute(fileName) ? fileName : path.join(this.cfg.dir.content, fileName); - const tempFile = parseFileName(`temp-${selectedEpisode.id}`, variables, options.numbers, options.override).join(path.sep); - const tempTsFile = path.isAbsolute(tempFile as string) ? tempFile : path.join(this.cfg.dir.content, tempFile); - const split = fileName.split(path.sep).slice(0, -1); - split.forEach((val, ind, arr) => { - const isAbsolut = path.isAbsolute(fileName); - if (!fs.existsSync(path.join(isAbsolut ? '' : this.cfg.dir.content, ...arr.slice(0, ind), val))) - fs.mkdirSync(path.join(isAbsolut ? '' : this.cfg.dir.content, ...arr.slice(0, ind), val)); - }); - const videoJson: M3U8Json = { - segments: chosenVideoSegments.segments - }; - const videoDownload = await new streamdl({ - output: `${tempTsFile}.video.enc.m4s`, - timeout: options.timeout, - m3u8json: videoJson, - // baseurl: chunkPlaylist.baseUrl, - threads: options.partsize, - fsRetryTime: options.fsRetryTime * 1000, - override: options.force, - callback: options.callbackMaker ? options.callbackMaker({ - fileName: `${path.isAbsolute(fileName) ? fileName.slice(this.cfg.dir.content.length) : fileName}`, - image: selectedEpisode.thumbnailUrl, - parent: { - title: selectedEpisode.seriesTitle - }, - title: selectedEpisode.title, - language: chosenAudios[0].language - }) : undefined - }).download(); - if(!videoDownload.ok){ - console.error(`DL Stats: ${JSON.stringify(videoDownload.parts)}\n`); - dlFailed = true; - } else { - if (chosenVideoSegments.pssh) { - console.info('Decryption Needed, attempting to decrypt'); - if (encryptionKeys.length == 0) { - console.error('Failed to get encryption keys'); - return undefined; - } - if (this.cfg.bin.mp4decrypt) { - const commandBase = `--show-progress --key ${encryptionKeys[1].kid}:${encryptionKeys[1].key} `; - const commandVideo = commandBase+`"${tempTsFile}.video.enc.m4s" "${tempTsFile}.video.m4s"`; - - console.info('Started decrypting video'); - const decryptVideo = exec('mp4decrypt', `"${this.cfg.bin.mp4decrypt}"`, commandVideo); - if (!decryptVideo.isOk) { - console.error(decryptVideo.err); - console.error(`Decryption failed with exit code ${decryptVideo.err.code}`); - fs.renameSync(`${tempTsFile}.video.enc.m4s`, `${tsFile}.video.enc.m4s`); - return undefined; - } else { - console.info('Decryption done for video'); - if (!options.nocleanup) { - fs.removeSync(`${tempTsFile}.video.enc.m4s`); - } - fs.renameSync(`${tempTsFile}.video.m4s`, `${tsFile}.video.m4s`); - files.push({ - type: 'Video', - path: `${tsFile}.video.m4s`, - lang: chosenAudios[0].language, - isPrimary: true - }); - } - } else { - console.warn('mp4decrypt not found, files need decryption. Decryption Keys:', encryptionKeys); - } - } - } - } else { - console.info('Skipping Video'); - } - - if (!options.noaudio) { - for (const audio of chosenAudios) { - const chosenAudioSegments = audio; - //Download Audio (if available) - const totalParts = chosenAudioSegments.segments.length; - const mathParts = Math.ceil(totalParts / options.partsize); - const mathMsg = `(${mathParts}*${options.partsize})`; - console.info('Total parts in audio stream:', totalParts, mathMsg); - const tempFile = parseFileName(`temp-${selectedEpisode.id}.${chosenAudioSegments.language.name}`, variables, options.numbers, options.override).join(path.sep); - const tempTsFile = path.isAbsolute(tempFile as string) ? tempFile : path.join(this.cfg.dir.content, tempFile); - const outFile = parseFileName(options.fileName + '.' + (chosenAudioSegments.language.name), variables, options.numbers, options.override).join(path.sep); - const tsFile = path.isAbsolute(outFile as string) ? outFile : path.join(this.cfg.dir.content, outFile); - const split = outFile.split(path.sep).slice(0, -1); - split.forEach((val, ind, arr) => { - const isAbsolut = path.isAbsolute(outFile as string); - if (!fs.existsSync(path.join(isAbsolut ? '' : this.cfg.dir.content, ...arr.slice(0, ind), val))) - fs.mkdirSync(path.join(isAbsolut ? '' : this.cfg.dir.content, ...arr.slice(0, ind), val)); - }); - const audioJson: M3U8Json = { - segments: chosenAudioSegments.segments - }; - const audioDownload = await new streamdl({ - output: `${tempTsFile}.audio.enc.m4s`, - timeout: options.timeout, - m3u8json: audioJson, - // baseurl: chunkPlaylist.baseUrl, - threads: options.partsize, - fsRetryTime: options.fsRetryTime * 1000, - override: options.force, - callback: options.callbackMaker ? options.callbackMaker({ - fileName: `${path.isAbsolute(outFile) ? outFile.slice(this.cfg.dir.content.length) : outFile}`, - image: selectedEpisode.thumbnailUrl, - parent: { - title: selectedEpisode.seriesTitle - }, - title: selectedEpisode.title, - language: chosenAudioSegments.language - }) : undefined - }).download(); - if(!audioDownload.ok){ - console.error(`DL Stats: ${JSON.stringify(audioDownload.parts)}\n`); - dlFailed = true; - } - if (chosenAudioSegments.pssh) { - console.info('Decryption Needed, attempting to decrypt'); - if (encryptionKeys.length == 0) { - console.error('Failed to get encryption keys'); - return undefined; - } - if (this.cfg.bin.mp4decrypt) { - const commandBase = `--show-progress --key ${encryptionKeys[1].kid}:${encryptionKeys[1].key} `; - const commandAudio = commandBase+`"${tempTsFile}.audio.enc.m4s" "${tempTsFile}.audio.m4s"`; - - console.info('Started decrypting audio'); - const decryptAudio = exec('mp4decrypt', `"${this.cfg.bin.mp4decrypt}"`, commandAudio); - if (!decryptAudio.isOk) { - console.error(decryptAudio.err); - console.error(`Decryption failed with exit code ${decryptAudio.err.code}`); - fs.renameSync(`${tempTsFile}.audio.enc.m4s`, `${tsFile}.audio.enc.m4s`); - return undefined; - } else { - if (!options.nocleanup) { - fs.removeSync(`${tempTsFile}.audio.enc.m4s`); - } - fs.renameSync(`${tempTsFile}.audio.m4s`, `${tsFile}.audio.m4s`); - files.push({ - type: 'Audio', - path: `${tsFile}.audio.m4s`, - lang: chosenAudioSegments.language, - isPrimary: chosenAudioSegments.default - }); - console.info('Decryption done for audio'); - } - } else { - console.warn('mp4decrypt not found, files need decryption. Decryption Keys:', encryptionKeys); - } - } - } - } else { - console.info('Skipping Audio'); - } - - if(options.dlsubs.indexOf('all') > -1){ - options.dlsubs = ['all']; - } - - if (options.nosubs) { - console.info('Subtitles downloading disabled from nosubs flag.'); - options.skipsubs = true; - } - - if(!options.skipsubs && options.dlsubs.indexOf('none') == -1) { - if(subs.length > 0) { - let subIndex = 0; - for(const sub of subs) { - const subLang = langsData.languages.find(a => a.new_hd_locale === sub.language); - if (!subLang) { - console.warn(`Language not found for subtitle language: ${sub.language}, Skipping`); - continue; - } - const sxData: Partial = {}; - sxData.file = langsData.subsFile(fileName as string, subIndex+'', subLang, false, options.ccTag); - sxData.path = path.join(this.cfg.dir.content, sxData.file); - sxData.language = subLang; - if(options.dlsubs.includes('all') || options.dlsubs.includes(subLang.locale)) { - const getVttContent = await this.req.getData(sub.url); - if (getVttContent.ok && getVttContent.res) { - console.info(`Subtitle Downloaded: ${sub.url}`); - //vttConvert(getVttContent.res.body, false, subLang.name, fontSize); - const sBody = vtt2ass(undefined, chosenFontSize, getVttContent.res.body, '', subsMargin, options.fontName, options.combineLines); - sxData.title = `${subLang.language} / ${sxData.title}`; - sxData.fonts = fontsData.assFonts(sBody) as Font[]; - fs.writeFileSync(sxData.path, sBody); - console.info(`Subtitle converted: ${sxData.file}`); - files.push({ - type: 'Subtitle', - ...sxData as sxItem, - cc: false - }); - } else{ - console.warn(`Failed to download subtitle: ${sxData.file}`); - } - } - subIndex++; - } - } else{ - console.warn('Can\'t find urls for subtitles!'); - } - } else{ - console.info('Subtitles downloading skipped!'); - } - - return { - error: dlFailed, - data: files, - fileName: fileName ? (path.isAbsolute(fileName) ? fileName : path.join(this.cfg.dir.content, fileName)) || './unknown' : './unknown' - }; - } - - public async muxStreams(data: DownloadedMedia[], options: Record, inverseTrackOrder: boolean = true) { - this.cfg.bin = await yamlCfg.loadBinCfg(); - let hasAudioStreams = false; - if (options.novids || data.filter(a => a.type === 'Video').length === 0) - return console.info('Skip muxing since no vids are downloaded'); - if (data.some(a => a.type === 'Audio')) { - hasAudioStreams = true; - } - const merger = new Merger({ - onlyVid: hasAudioStreams ? data.filter(a => a.type === 'Video').map((a) : MergerInput => { - if (a.type === 'Subtitle') - throw new Error('Never'); - return { - lang: a.lang, - path: a.path, - }; - }) : [], - skipSubMux: options.skipSubMux, - inverseTrackOrder: inverseTrackOrder, - keepAllVideos: options.keepAllVideos, - onlyAudio: hasAudioStreams ? data.filter(a => a.type === 'Audio').map((a) : MergerInput => { - if (a.type === 'Subtitle') - throw new Error('Never'); - return { - lang: a.lang, - path: a.path, - }; - }) : [], - output: `${options.output}.${options.mp4 ? 'mp4' : 'mkv'}`, - subtitles: data.filter(a => a.type === 'Subtitle').map((a) : SubtitleInput => { - if (a.type === 'Video') - throw new Error('Never'); - if (a.type === 'Audio') - throw new Error('Never'); - return { - file: a.path, - language: a.language, - closedCaption: a.cc - }; - }), - simul: data.filter(a => a.type === 'Video').map((a) : boolean => { - if (a.type === 'Subtitle') - throw new Error('Never'); - return !a.uncut as boolean; - })[0], - fonts: Merger.makeFontsList(this.cfg.dir.fonts, data.filter(a => a.type === 'Subtitle') as sxItem[]), - videoAndAudio: hasAudioStreams ? [] : data.filter(a => a.type === 'Video').map((a) : MergerInput => { - if (a.type === 'Subtitle') - throw new Error('Never'); - return { - lang: a.lang, - path: a.path, - }; - }), - videoTitle: options.videoTitle, - options: { - ffmpeg: options.ffmpegOptions, - mkvmerge: options.mkvmergeOptions - }, - defaults: { - audio: options.defaultAudio, - sub: options.defaultSub - }, - ccTag: options.ccTag - }); - const bin = Merger.checkMerger(this.cfg.bin, options.mp4, options.forceMuxer); - // collect fonts info - // mergers - let isMuxed = false; - if (options.syncTiming) { - await merger.createDelays(); - } - if (bin.MKVmerge) { - await merger.merge('mkvmerge', bin.MKVmerge); - isMuxed = true; - } else if (bin.FFmpeg) { - await merger.merge('ffmpeg', bin.FFmpeg); - isMuxed = true; - } else{ - console.info('\nDone!\n'); - return; - } - if (isMuxed && !options.nocleanup) - merger.cleanUp(); - } - - public sleep(ms: number) { - return new Promise((resolve) => { - setTimeout(resolve, ms); - }); - } -} diff --git a/index.ts b/index.ts deleted file mode 100644 index 7ef4cf7..0000000 --- a/index.ts +++ /dev/null @@ -1,100 +0,0 @@ -import { console } from './modules/log'; -import { ServiceClass } from './@types/serviceClassInterface'; -import { appArgv, overrideArguments } from './modules/module.app-args'; -import * as yamlCfg from './modules/module.cfg-loader'; -import { makeCommand, addToArchive } from './modules/module.downloadArchive'; - -import update from './modules/module.updater'; - -(async () => { - const cfg = yamlCfg.loadCfg(); - const argv = appArgv(cfg.cli); - if (!argv.skipUpdate) - await update(argv.update); - - if (argv.all && argv.but) { - console.error('--all and --but exclude each other!'); - return; - } - - if (argv.addArchive) { - if (argv.service === 'crunchy') { - if (argv.s === undefined && argv.series === undefined) - return console.error('`-s` or `--srz` not found'); - if (argv.s && argv.series) - return console.error('Both `-s` and `--srz` found'); - addToArchive({ - service: 'crunchy', - type: argv.s === undefined ? 'srz' : 's' - }, (argv.s === undefined ? argv.series : argv.s) as string); - console.info('Added %s to the downloadArchive list', (argv.s === undefined ? argv.series : argv.s)); - } else if (argv.service === 'hidive') { - if (argv.s === undefined) - return console.error('`-s` not found'); - addToArchive({ - service: 'hidive', - //type: argv.s === undefined ? 'srz' : 's' - type: 's' - }, (argv.s === undefined ? argv.series : argv.s) as string); - console.info('Added %s to the downloadArchive list', (argv.s === undefined ? argv.series : argv.s)); - } else if (argv.service === 'ao') { - if (argv.s === undefined) - return console.error('`-s` not found'); - addToArchive({ - service: 'hidive', - //type: argv.s === undefined ? 'srz' : 's' - type: 's' - }, (argv.s === undefined ? argv.series : argv.s) as string); - console.info('Added %s to the downloadArchive list', (argv.s === undefined ? argv.series : argv.s)); - } - } else if (argv.downloadArchive) { - const ids = makeCommand(argv.service); - for (const id of ids) { - overrideArguments(cfg.cli, id); - /* Reimport module to override appArgv */ - Object.keys(require.cache).forEach(key => { - if (key.endsWith('crunchy.js') || key.endsWith('hidive.js') || key.endsWith('ao.js')) - delete require.cache[key]; - }); - let service: ServiceClass; - switch(argv.service) { - case 'crunchy': - service = new (await import('./crunchy')).default; - break; - case 'hidive': - service = new (await import('./hidive')).default; - break; - case 'ao': - service = new (await import('./ao')).default; - break; - case 'adn': - service = new (await import('./adn')).default; - break; - default: - service = new (await import(`./${argv.service}`)).default; - break; - } - await service.cli(); - } - } else { - let service: ServiceClass; - switch(argv.service) { - case 'crunchy': - service = new (await import('./crunchy')).default; - break; - case 'hidive': - service = new (await import('./hidive')).default; - break; - case 'ao': - service = new (await import('./ao')).default; - break; - case 'adn': - service = new (await import('./adn')).default; - break; - default: - service = new (await import(`./${argv.service}`)).default; - break; - } - await service.cli(); - } -})(); \ No newline at end of file diff --git a/modules/build-docs.ts b/modules/build-docs.ts deleted file mode 100644 index 432c6c9..0000000 --- a/modules/build-docs.ts +++ /dev/null @@ -1,76 +0,0 @@ -import packageJSON from '../package.json'; -import fs from 'fs'; -import path from 'path'; -import { args, groups } from './module.args'; - -const transformService = (str: Array<'crunchy'|'hidive'|'ao'|'adn'|'all'>) => { - const services: string[] = []; - str.forEach(function(part) { - switch(part) { - case 'crunchy': - services.push('Crunchyroll'); - break; - case 'hidive': - services.push('Hidive'); - break; - case 'ao': - services.push('AnimeOnegai'); - break; - case 'adn': - services.push('AnimationDigitalNetwork'); - break; - case 'all': - services.push('All'); - break; - } - }); - return services.join(', '); -}; - -let docs = `# ${packageJSON.name} (${packageJSON.version}v) - -If you find any bugs in this documentation or in the program itself please report it [over on GitHub](${packageJSON.bugs.url}). - -## Legal Warning - -This application is not endorsed by or affiliated with *Crunchyroll*, *Hidive*, *AnimeOnegai*, or *AnimationDigitalNetwork*. -This application enables you to download videos for offline viewing which may be forbidden by law in your country. -The usage of this application may also cause a violation of the *Terms of Service* between you and the stream provider. -This tool is not responsible for your actions; please make an informed decision before using this application. - -## CLI Options -### Legend - - \`\${someText}\` shows that you should replace this text with your own - - e.g. \`--username \${someText}\` -> \`--username Izuco\` -`; - -Object.entries(groups).forEach(([key, value]) => { - docs += `\n### ${value.slice(0, -1)}\n`; - - docs += args.filter(a => a.group === key).map(argument => { - return [`#### \`${argument.name.length > 1 ? '--' : '-'}${argument.name}\``, - `| **Service** | **Usage** | **Type** | **Required** | **Alias** | ${argument.choices ? '**Choices** |' : ''} ${argument.default ? '**Default** |' : ''}**cli-default Entry**`, - `| --- | --- | --- | --- | --- | ${argument.choices ? '--- | ' : ''}${argument.default ? '--- | ' : ''}---| `, - `| ${transformService(argument.service)} | \`${argument.name.length > 1 ? '--' : '-'}${argument.name} ${argument.usage}\` | \`${argument.type}\` | \`${argument.demandOption ? 'Yes' : 'No'}\`|` - + ` \`${(argument.alias ? `${argument.alias.length > 1 ? '--' : '-'}${argument.alias}` : undefined) ?? 'NaN'}\` |` - + `${argument.choices ? ` [${argument.choices.map(a => `\`${a || '\'\''}\``).join(', ')}] |` : ''}` - + `${argument.default ? ` \`${ - typeof argument.default === 'object' - ? Array.isArray(argument.default) - ? JSON.stringify(argument.default) - : (argument.default as any).default - : argument.default - }\`|` : ''}` - + ` ${typeof argument.default === 'object' && !Array.isArray(argument.default) - ? `\`${argument.default.name || argument.name}: \`` - : '`NaN`' - } |`, - '', - argument.docDescribe === true ? argument.describe : argument.docDescribe - ].join('\n'); - }).join('\n'); -}); - - - -fs.writeFileSync(path.resolve(__dirname, '..', 'docs', 'DOCUMENTATION.md'), docs); \ No newline at end of file diff --git a/modules/build.js b/modules/build.js new file mode 100644 index 0000000..3a1113c --- /dev/null +++ b/modules/build.js @@ -0,0 +1,73 @@ +#!/usr/bin/env node + +// build requirements +const pkg = require('../package.json'); +const fs = require('fs-extra'); +const modulesCleanup = require('removeNPMAbsolutePaths'); +const { exec } = require('pkg'); + +const buildsDir = './_builds'; +const nodeVer = 'node14-'; + +// main +(async function(){ + const buildStr = `${pkg.name}-${pkg.version}`; + const acceptableBuilds = ['win64','linux64','macos64']; + const buildType = process.argv[2]; + if(!acceptableBuilds.includes(buildType)){ + console.error('[ERROR] unknown build type!'); + process.exit(1); + } + await modulesCleanup('.'); + if(!fs.existsSync(buildsDir)){ + fs.mkdirSync(buildsDir); + } + const buildFull = `${buildStr}-${buildType}`; + const buildDir = `${buildsDir}/${buildFull}`; + if(fs.existsSync(buildDir)){ + fs.removeSync(buildDir); + } + fs.mkdirSync(buildDir); + const buildConfig = [ + pkg.main, + '--target', nodeVer + getTarget(buildType), + '--output', `${buildDir}/${pkg.short_name}`, + ]; + console.log(`[Build] Build configuration: ${buildFull}`); + try { + await exec(buildConfig); + } + catch(e){ + console.log(e); + process.exit(1); + } + fs.mkdirSync(`${buildDir}/bin`); + fs.mkdirSync(`${buildDir}/config`); + fs.mkdirSync(`${buildDir}/videos`); + fs.mkdirSync(`${buildDir}/videos/_trash`); + fs.copySync('./bin/', `${buildDir}/bin/`); + fs.copySync('./config/bin-path.yml', `${buildDir}/config/bin-path.yml`); + fs.copySync('./config/cli-defaults.yml', `${buildDir}/config/cli-defaults.yml`); + fs.copySync('./config/dir-path.yml', `${buildDir}/config/dir-path.yml`); + fs.copySync('./modules/cmd-here.bat', `${buildDir}/cmd-here.bat`); + fs.copySync('./modules/NotoSans-Regular.ttf', `${buildDir}/NotoSans-Regular.ttf`); + fs.copySync('./docs/', `${buildDir}/docs/`); + fs.copySync('./LICENSE.md', `${buildDir}/docs/LICENSE.md`); + if(fs.existsSync(`${buildsDir}/${buildFull}.7z`)){ + fs.removeSync(`${buildsDir}/${buildFull}.7z`); + } + require('child_process').execSync(`7z a -t7z "${buildsDir}/${buildFull}.7z" "${buildDir}"`,{stdio:[0,1,2]}); +}()); + +function getTarget(bt){ + switch(bt){ + case 'win64': + return 'windows-x64'; + case 'linux64': + return 'linux-x64'; + case 'macos64': + return 'macos-x64'; + default: + return 'windows-x64'; + } +} diff --git a/modules/build.ts b/modules/build.ts deleted file mode 100644 index 73ffccc..0000000 --- a/modules/build.ts +++ /dev/null @@ -1,116 +0,0 @@ -// build requirements -import fs from 'fs-extra'; -import pkg from '../package.json'; -import modulesCleanup from 'removeNPMAbsolutePaths'; -import { exec } from '@yao-pkg/pkg'; -import { execSync } from 'child_process'; -import { console } from './log'; -import esbuild from 'esbuild'; -import path from 'path'; - -const buildsDir = './_builds'; -const nodeVer = 'node20-'; - -type BuildTypes = `${'windows'|'macos'|'linux'|'linuxstatic'|'alpine'}-${'x64'|'arm64'}`|'linuxstatic-armv7' - -(async () => { - const buildType = process.argv[2] as BuildTypes; - const isGUI = process.argv[3] === 'true'; - - buildBinary(buildType, isGUI); -})(); - -// main -async function buildBinary(buildType: BuildTypes, gui: boolean) { - const buildStr = 'multi-downloader-nx'; - const acceptablePlatforms = ['windows','linux','linuxstatic','macos','alpine']; - const acceptableArchs = ['x64','arm64']; - const acceptableBuilds: string[] = ['linuxstatic-armv7']; - for (const platform of acceptablePlatforms) { - for (const arch of acceptableArchs) { - acceptableBuilds.push(platform+'-'+arch); - } - } - if(!acceptableBuilds.includes(buildType)){ - console.error('Unknown build type!'); - process.exit(1); - } - await modulesCleanup('.'); - if(!fs.existsSync(buildsDir)){ - fs.mkdirSync(buildsDir); - } - const buildFull = `${buildStr}-${getFriendlyName(buildType)}-${gui ? 'gui' : 'cli'}`; - const buildDir = `${buildsDir}/${buildFull}`; - if(fs.existsSync(buildDir)){ - fs.removeSync(buildDir); - } - fs.mkdirSync(buildDir); - console.info('Running esbuild'); - - const build = await esbuild.build({ - entryPoints: [ - gui ? 'gui.js' : 'index.js', - ], - sourceRoot: './', - bundle: true, - platform: 'node', - format: 'cjs', - treeShaking: true, - // External source map for debugging - sourcemap: true, - // Minify and keep the original names - minify: true, - keepNames: true, - outfile: path.join(buildsDir, 'index.cjs'), - metafile: true, - external: ['cheerio'] - }); - - if (build.errors?.length > 0) console.error(build.errors); - if (build.warnings?.length > 0) console.warn(build.warnings); - - const buildConfig = [ - `${buildsDir}/index.cjs`, - '--target', nodeVer + buildType, - '--output', `${buildDir}/${pkg.short_name}`, - '--compress', 'GZip' - ]; - console.info(`[Build] Build configuration: ${buildFull}`); - try { - await exec(buildConfig); - } - catch(e){ - console.info(e); - process.exit(1); - } - fs.mkdirSync(`${buildDir}/config`); - fs.mkdirSync(`${buildDir}/videos`); - fs.mkdirSync(`${buildDir}/widevine`); - fs.copySync('./config/bin-path.yml', `${buildDir}/config/bin-path.yml`); - fs.copySync('./config/cli-defaults.yml', `${buildDir}/config/cli-defaults.yml`); - fs.copySync('./config/dir-path.yml', `${buildDir}/config/dir-path.yml`); - fs.copySync('./config/gui.yml', `${buildDir}/config/gui.yml`); - fs.copySync('./modules/cmd-here.bat', `${buildDir}/cmd-here.bat`); - fs.copySync('./modules/NotoSans-Regular.ttf', `${buildDir}/NotoSans-Regular.ttf`); - fs.copySync('./package.json', `${buildDir}/package.json`); - fs.copySync('./docs/', `${buildDir}/docs/`); - fs.copySync('./LICENSE.md', `${buildDir}/docs/LICENSE.md`); - if (gui) { - fs.copySync('./gui', `${buildDir}/gui`); - fs.copySync('./node_modules/open/xdg-open', `${buildDir}/xdg-open`); - } - if(fs.existsSync(`${buildsDir}/${buildFull}.7z`)){ - fs.removeSync(`${buildsDir}/${buildFull}.7z`); - } - execSync(`7z a -t7z "${buildsDir}/${buildFull}.7z" "${buildDir}"`,{stdio:[0,1,2]}); -} - -function getFriendlyName(buildString: string): string { - if (buildString.includes('armv7')) { - return 'android'; - } - if (buildString.includes('linuxstatic')) { - buildString = buildString.replace('linuxstatic', 'linux'); - } - return buildString; -} \ No newline at end of file diff --git a/modules/cmac.ts b/modules/cmac.ts deleted file mode 100644 index 87d94db..0000000 --- a/modules/cmac.ts +++ /dev/null @@ -1,114 +0,0 @@ -//Originally from https://github.com/Frooastside/node-widevine/blob/main/src/cmac.ts - -import crypto from 'crypto'; - -export class AES_CMAC { - private readonly BLOCK_SIZE = 16; - private readonly XOR_RIGHT = Buffer.from([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87]); - private readonly EMPTY_BLOCK_SIZE_BUFFER = Buffer.alloc(this.BLOCK_SIZE); - - private _key: Buffer; - private _subkeys: { first: Buffer; second: Buffer }; - - public constructor(key: Buffer) { - if (![16, 24, 32].includes(key.length)) { - throw new Error('Key size must be 128, 192, or 256 bits.'); - } - this._key = key; - this._subkeys = this._generateSubkeys(); - } - - public calculate(message: Buffer): Buffer { - const blockCount = this._getBlockCount(message); - - let x = this.EMPTY_BLOCK_SIZE_BUFFER; - let y; - - for (let i = 0; i < blockCount - 1; i++) { - const from = i * this.BLOCK_SIZE; - const block = message.subarray(from, from + this.BLOCK_SIZE); - y = this._xor(x, block); - x = this._aes(y); - } - - y = this._xor(x, this._getLastBlock(message)); - x = this._aes(y); - - return x; - } - - private _generateSubkeys(): { first: Buffer; second: Buffer } { - const l = this._aes(this.EMPTY_BLOCK_SIZE_BUFFER); - - let first = this._bitShiftLeft(l); - if (l[0] & 0x80) { - first = this._xor(first, this.XOR_RIGHT); - } - - let second = this._bitShiftLeft(first); - if (first[0] & 0x80) { - second = this._xor(second, this.XOR_RIGHT); - } - - return { first: first, second: second }; - } - - private _getBlockCount(message: Buffer): number { - const blockCount = Math.ceil(message.length / this.BLOCK_SIZE); - return blockCount === 0 ? 1 : blockCount; - } - - private _aes(message: Buffer): Buffer { - const cipher = crypto.createCipheriv(`aes-${this._key.length * 8}-cbc`, this._key, Buffer.alloc(this.BLOCK_SIZE)); - const result = cipher.update(message).subarray(0, 16); - cipher.destroy(); - return result; - } - - private _getLastBlock(message: Buffer): Buffer { - const blockCount = this._getBlockCount(message); - const paddedBlock = this._padding(message, blockCount - 1); - - let complete = false; - if (message.length > 0) { - complete = message.length % this.BLOCK_SIZE === 0; - } - - const key = complete ? this._subkeys.first : this._subkeys.second; - return this._xor(paddedBlock, key); - } - - private _padding(message: Buffer, blockIndex: number): Buffer { - const block = Buffer.alloc(this.BLOCK_SIZE); - - const from = blockIndex * this.BLOCK_SIZE; - - const slice = message.subarray(from, from + this.BLOCK_SIZE); - block.set(slice); - - if (slice.length !== this.BLOCK_SIZE) { - block[slice.length] = 0x80; - } - - return block; - } - - private _bitShiftLeft(input: Buffer): Buffer { - const output = Buffer.alloc(input.length); - let overflow = 0; - for (let i = input.length - 1; i >= 0; i--) { - output[i] = (input[i] << 1) | overflow; - overflow = input[i] & 0x80 ? 1 : 0; - } - return output; - } - - private _xor(a: Buffer, b: Buffer): Buffer { - const length = Math.min(a.length, b.length); - const output = Buffer.alloc(length); - for (let i = 0; i < length; i++) { - output[i] = a[i] ^ b[i]; - } - return output; - } -} \ No newline at end of file diff --git a/modules/hls-download.ts b/modules/hls-download.ts deleted file mode 100644 index a8a7b7b..0000000 --- a/modules/hls-download.ts +++ /dev/null @@ -1,453 +0,0 @@ -// build-in -import crypto from 'crypto'; -import fs from 'fs'; -import url from 'url'; - -// extra -import shlp from 'sei-helper'; -import got, { Response } from 'got'; - -import { console } from './log'; -import { ProgressData } from '../@types/messageHandler'; - -// The following function should fix an issue with downloading. For more information see https://github.com/sindresorhus/got/issues/1489 -const fixMiddleWare = (res: Response) => { - const isResponseOk = (response: Response) => { - const {statusCode} = response; - const limitStatusCode = response.request.options.followRedirect ? 299 : 399; - - return (statusCode >= 200 && statusCode <= limitStatusCode) || statusCode === 304; - }; - if (isResponseOk(res)) { - res.request.destroy(); - } - return res; -}; - -export type HLSCallback = (data: ProgressData) => unknown; - -export type M3U8Json = { - segments: Record[], - mediaSequence?: number, -} - -type Segment = { - uri: string - key: Key, - byterange?: { - offset: number, - length: number - } -} - -type Key = { - uri: string, - iv: number[] -} - -export type HLSOptions = { - m3u8json: M3U8Json, - output?: string, - threads?: number, - retries?: number, - offset?: number, - baseurl?: string, - skipInit?: boolean, - timeout?: number, - fsRetryTime?: number, - override?: 'Y'|'y'|'N'|'n'|'C'|'c' - callback?: HLSCallback -} - -type Data = { - parts: { - first: number, - total: number, - completed: number - }, - m3u8json: M3U8Json, - outputFile: string, - threads: number, - retries: number, - offset: number, - baseurl?: string - skipInit?: boolean, - keys: { - [uri: string]: Buffer|string - }, - timeout: number, - checkPartLength: boolean, - isResume: boolean, - bytesDownloaded: number, - waitTime: number, - callback?: HLSCallback, - override?: string, - dateStart: number -} - -// hls class -class hlsDownload { - private data: Data; - constructor(options: HLSOptions){ - // check playlist - if( - !options - || !options.m3u8json - || !options.m3u8json.segments - || options.m3u8json.segments.length === 0 - ){ - throw new Error('Playlist is empty!'); - } - // init options - this.data = { - parts: { - first: options.m3u8json.mediaSequence || 0, - total: options.m3u8json.segments.length, - completed: 0, - }, - m3u8json: options.m3u8json, - outputFile: options.output || 'stream.ts', - threads: options.threads || 5, - retries: options.retries || 4, - offset: options.offset || 0, - baseurl: options.baseurl, - skipInit: options.skipInit, - keys: {}, - timeout: options.timeout ? options.timeout : 60 * 1000, - checkPartLength: true, - isResume: options.offset ? options.offset > 0 : false, - bytesDownloaded: 0, - waitTime: options.fsRetryTime ?? 1000 * 5, - callback: options.callback, - override: options.override, - dateStart: 0 - }; - } - async download(){ - // set output - const fn = this.data.outputFile; - // try load resume file - if(fs.existsSync(fn) && fs.existsSync(`${fn}.resume`) && this.data.offset < 1){ - try{ - console.info('Resume data found! Trying to resume...'); - const resumeData = JSON.parse(fs.readFileSync(`${fn}.resume`, 'utf-8')); - if( - resumeData.total == this.data.m3u8json.segments.length - && resumeData.completed != resumeData.total - && !isNaN(resumeData.completed) - ){ - console.info('Resume data is ok!'); - this.data.offset = resumeData.completed; - this.data.isResume = true; - } - else{ - console.warn(' Resume data is wrong!'); - console.warn({ - resume: { total: resumeData.total, dled: resumeData.completed }, - current: { total: this.data.m3u8json.segments.length }, - }); - } - } - catch(e){ - console.error('Resume failed, downloading will be not resumed!'); - console.error(e); - } - } - // ask before rewrite file - if (fs.existsSync(`${fn}`) && !this.data.isResume) { - let rwts = this.data.override ?? await shlp.question(`[Q] File «${fn}» already exists! Rewrite? ([y]es/[N]o/[c]ontinue)`); - rwts = rwts || 'N'; - if (['Y', 'y'].includes(rwts[0])) { - console.info(`Deleting «${fn}»...`); - fs.unlinkSync(fn); - } - else if (['C', 'c'].includes(rwts[0])) { - return { ok: true, parts: this.data.parts }; - } - else { - return { ok: false, parts: this.data.parts }; - } - } - // show output filename - if (fs.existsSync(fn) && this.data.isResume) { - console.info(`Adding content to «${fn}»...`); - } - else{ - console.info(`Saving stream to «${fn}»...`); - } - // start time - this.data.dateStart = Date.now(); - let segments = this.data.m3u8json.segments; - // download init part - if (segments[0].map && this.data.offset === 0 && !this.data.skipInit) { - console.info('Download and save init part...'); - const initSeg = segments[0].map as Segment; - if(segments[0].key){ - initSeg.key = segments[0].key as Key; - } - try{ - const initDl = await this.downloadPart(initSeg, 0, 0); - fs.writeFileSync(fn, initDl.dec, { flag: 'a' }); - fs.writeFileSync(`${fn}.resume`, JSON.stringify({ - completed: 0, - total: this.data.m3u8json.segments.length - })); - console.info('Init part downloaded.'); - } - catch(e: any){ - console.error(`Part init download error:\n\t${e.message}`); - return { ok: false, parts: this.data.parts }; - } - } - else if(segments[0].map && this.data.offset === 0 && this.data.skipInit){ - console.warn('Skipping init part can lead to broken video!'); - } - // resuming ... - if(this.data.offset > 0){ - segments = segments.slice(this.data.offset); - console.info(`Resuming download from part ${this.data.offset+1}...`); - this.data.parts.completed = this.data.offset; - } - // dl process - for (let p = 0; p < segments.length / this.data.threads; p++) { - // set offsets - const offset = p * this.data.threads; - const dlOffset = offset + this.data.threads; - // map download threads - const krq = new Map(), prq = new Map(); - const res = []; - let errcnt = 0; - for (let px = offset; px < dlOffset && px < segments.length; px++){ - const curp = segments[px]; - const key = curp.key as Key; - if(key && !krq.has(key.uri) && !this.data.keys[key.uri as string]){ - krq.set(key.uri, this.downloadKey(key, px, this.data.offset)); - } - } - try { - await Promise.all(krq.values()); - } catch (er: any) { - console.error(`Key ${er.p + 1} download error:\n\t${er.message}`); - return { ok: false, parts: this.data.parts }; - } - for (let px = offset; px < dlOffset && px < segments.length; px++){ - const curp = segments[px] as Segment; - prq.set(px, this.downloadPart(curp, px, this.data.offset)); - } - for (let i = prq.size; i--;) { - try { - const r = await Promise.race(prq.values()); - prq.delete(r.p); - res[r.p - offset] = r.dec; - } - catch (error: any) { - console.error('Part %s download error:\n\t%s', - error.p + 1 + this.data.offset, error.message); - prq.delete(error.p); - errcnt++; - } - } - // catch error - if (errcnt > 0) { - console.error(`${errcnt} parts not downloaded`); - return { ok: false, parts: this.data.parts }; - } - // write downloaded - for (const r of res) { - let error = 0; - while (error < 3) { - try { - fs.writeFileSync(fn, r, { flag: 'a' }); - break; - } catch (err) { - console.error(err); - console.error(`Unable to write to file '${fn}' (Attempt ${error+1}/3)`); - console.info(`Waiting ${Math.round(this.data.waitTime / 1000)}s before retrying`); - await new Promise((resolve) => setTimeout(() => resolve(), this.data.waitTime)); - } - error++; - } - if (error === 3) { - console.error(`Unable to write content to '${fn}'.`); - return { ok: false, parts: this.data.parts }; - } - } - // log downloaded - const totalSeg = segments.length + this.data.offset; // Add the sliced lenght back so the resume data will be correct even if an resumed download fails - const downloadedSeg = dlOffset < totalSeg ? dlOffset : totalSeg; - this.data.parts.completed = downloadedSeg + this.data.offset; - const data = extFn.getDownloadInfo( - this.data.dateStart, downloadedSeg, totalSeg, - this.data.bytesDownloaded - ); - fs.writeFileSync(`${fn}.resume`, JSON.stringify({ - completed: this.data.parts.completed, - total: totalSeg - })); - console.info(`${downloadedSeg} of ${totalSeg} parts downloaded [${data.percent}%] (${shlp.formatTime(parseInt((data.time / 1000).toFixed(0)))} | ${(data.downloadSpeed / 1000000).toPrecision(2)}Mb/s)`); - if (this.data.callback) - this.data.callback({ total: this.data.parts.total, cur: this.data.parts.completed, bytes: this.data.bytesDownloaded, percent: data.percent, time: data.time, downloadSpeed: data.downloadSpeed }); - } - // return result - fs.unlinkSync(`${fn}.resume`); - return { ok: true, parts: this.data.parts }; - } - async downloadPart(seg: Segment, segIndex: number, segOffset: number){ - const sURI = extFn.getURI(seg.uri, this.data.baseurl); - let decipher, part, dec; - const p = segIndex; - try { - if (seg.key != undefined) { - decipher = await this.getKey(seg.key, p, segOffset); - } - part = await extFn.getData(p, sURI, { - ...(seg.byterange ? { - Range: `bytes=${seg.byterange.offset}-${seg.byterange.offset+seg.byterange.length-1}` - } : {}) - }, segOffset, false, this.data.timeout, this.data.retries, [ - (res, retryWithMergedOptions) => { - if(this.data.checkPartLength && res.headers['content-length']){ - if(!res.body || (res.body as any).length != res.headers['content-length']){ - // 'Part not fully downloaded' - return retryWithMergedOptions(); - } - } - return res; - } - ]); - if(this.data.checkPartLength && !(part as any).headers['content-length']){ - this.data.checkPartLength = false; - console.warn(`Part ${segIndex+segOffset+1}: can't check parts size!`); - } - if (decipher == undefined) { - this.data.bytesDownloaded += (part.body as Buffer).byteLength; - return { dec: part.body, p }; - } - dec = decipher.update(part.body as Buffer); - dec = Buffer.concat([dec, decipher.final()]); - this.data.bytesDownloaded += dec.byteLength; - } - catch (error: any) { - error.p = p; - throw error; - } - return { dec, p }; - } - async downloadKey(key: Key, segIndex: number, segOffset: number){ - const kURI = extFn.getURI(key.uri, this.data.baseurl); - if (!this.data.keys[kURI]) { - try { - const rkey = await extFn.getData(segIndex, kURI, {}, segOffset, true, this.data.timeout, this.data.retries, [ - (res, retryWithMergedOptions) => { - if (!res || !res.body) { - // 'Key get error' - return retryWithMergedOptions(); - } - if((res.body as any).length != 16){ - // 'Key not fully downloaded' - return retryWithMergedOptions(); - } - return res; - } - ]); - return rkey; - } - catch (error: any) { - error.p = segIndex; - throw error; - } - } - } - async getKey(key: Key, segIndex: number, segOffset: number){ - const kURI = extFn.getURI(key.uri, this.data.baseurl); - const p = segIndex; - if (!this.data.keys[kURI]) { - try{ - const rkey = await this.downloadKey(key, segIndex, segOffset); - if (!rkey) - throw new Error(); - this.data.keys[kURI] = rkey.body; - } - catch (error: any) { - error.p = p; - throw error; - } - } - // get ivs - const iv = Buffer.alloc(16); - const ivs = key.iv ? key.iv : [0, 0, 0, p + 1]; - for (let i = 0; i < ivs.length; i++) { - iv.writeUInt32BE(ivs[i], i * 4); - } - return crypto.createDecipheriv('aes-128-cbc', this.data.keys[kURI], iv); - } -} - -const extFn = { - getURI: (uri: string, baseurl?: string) => { - const httpURI = /^https{0,1}:/.test(uri); - if (!baseurl && !httpURI) { - throw new Error('No base and not http(s) uri'); - } - else if (httpURI) { - return uri; - } - return baseurl + uri; - }, - getDownloadInfo: (dateStart: number, partsDL: number, partsTotal: number, downloadedBytes: number) => { - const dateElapsed = Date.now() - dateStart; - const percentFxd = parseInt((partsDL / partsTotal * 100).toFixed()); - const percent = percentFxd < 100 ? percentFxd : (partsTotal == partsDL ? 100 : 99); - const revParts = dateElapsed * (partsTotal / partsDL - 1); - const downloadSpeed = downloadedBytes / (dateElapsed / 1000); //Bytes per second - return { percent, time: revParts, downloadSpeed }; - }, - getData: (partIndex: number, uri: string, headers: Record, segOffset: number, isKey: boolean, timeout: number, retry: number, afterResponse: ((res: Response, retryWithMergedOptions: () => Response) => Response)[]) => { - // get file if uri is local - if (uri.startsWith('file://')) { - return { - body: fs.readFileSync(url.fileURLToPath(uri)), - }; - } - // base options - headers = headers && typeof headers == 'object' ? headers : {}; - const options = { headers, retry, responseType: 'buffer', hooks: { - beforeRequest: [ - (options: Record>) => { - if(!options.headers['user-agent']){ - options.headers['user-agent'] = 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:70.0) Gecko/20100101 Firefox/70.0'; - } - //TODO: implement fix for hidive properly - if ((options.url.hostname as string).match('hidive')) { - options.headers['referrer'] = 'https://www.hidive.com/'; - options.headers['origin'] = 'https://www.hidive.com'; - } else if ((options.url.hostname as string).includes('animecdn')) { - options.headers = { - origin: 'https://www.animeonegai.com', - referer: 'https://www.animeonegai.com/', - range: options.headers['range'] - }; - } - // console.log(' - Req:', options.url.pathname); - } - ], - afterResponse: [(fixMiddleWare as (r: Response, s: () => Response) => Response)].concat(afterResponse || []), - beforeRetry: [ - (_: any, error: Error, retryCount: number) => { - if(error){ - const partType = isKey ? 'Key': 'Part'; - const partIndx = partIndex + 1 + segOffset; - console.warn('%s %s: %d attempt to retrieve data', partType, partIndx, retryCount + 1); - console.error(`\t${error.message}`); - } - } - ] - }} as Record; - // proxy - options.timeout = timeout; - // do request - return got(uri, options); - } -}; - -export default hlsDownload; \ No newline at end of file diff --git a/modules/license.ts b/modules/license.ts deleted file mode 100644 index e2a92ea..0000000 --- a/modules/license.ts +++ /dev/null @@ -1,161 +0,0 @@ -//Originaly from https://github.com/Frooastside/node-widevine/blob/main/src/license.ts - -import crypto from 'crypto'; -import Long from 'long'; -import { AES_CMAC } from './cmac'; -import { - ClientIdentification, - License, - LicenseRequest, - LicenseRequest_RequestType, - LicenseType, - ProtocolVersion, - SignedMessage, - SignedMessage_MessageType, - SignedMessage_SessionKeyType, - WidevinePsshData -} from './license_protocol'; - -const WIDEVINE_SYSTEM_ID = new Uint8Array([237, 239, 139, 169, 121, 214, 74, 206, 163, 200, 39, 220, 213, 29, 33, 237]); - -export type KeyContainer = { - kid: string; - key: string; -}; - -export type ContentDecryptionModule = { - privateKey: Buffer; - identifierBlob: Buffer; -}; - -export class Session { - private _devicePrivateKey: crypto.KeyObject; - private _identifierBlob: ClientIdentification; - private _identifier: Buffer; - private _pssh: Buffer; - private _rawLicenseRequest?: Buffer; - - constructor(contentDecryptionModule: ContentDecryptionModule, pssh: Buffer) { - this._devicePrivateKey = crypto.createPrivateKey(contentDecryptionModule.privateKey); - this._identifierBlob = ClientIdentification.decode(contentDecryptionModule.identifierBlob); - this._identifier = this._generateIdentifier(); - this._pssh = pssh; - } - - createLicenseRequest(): Buffer { - if (!this._pssh.subarray(12, 28).equals(Buffer.from(WIDEVINE_SYSTEM_ID))) { - throw new Error('the pssh is not an actuall pssh'); - } - const pssh = this._parsePSSH(this._pssh); - if (!pssh) { - throw new Error('pssh is invalid'); - } - - const licenseRequest: LicenseRequest = { - type: LicenseRequest_RequestType.NEW, - clientId: this._identifierBlob, - contentId: { - widevinePsshData: { - psshData: [this._pssh.subarray(32)], - licenseType: LicenseType.STREAMING, - requestId: this._identifier - } - }, - requestTime: Long.fromNumber(Date.now()).divide(1000), - protocolVersion: ProtocolVersion.VERSION_2_1, - keyControlNonce: crypto.randomInt(2 ** 31), - keyControlNonceDeprecated: Buffer.alloc(0), - encryptedClientId: undefined - }; - - this._rawLicenseRequest = Buffer.from(LicenseRequest.encode(licenseRequest).finish()); - - const signature = crypto - .createSign('sha1') - .update(this._rawLicenseRequest) - .sign({ key: this._devicePrivateKey, padding: crypto.constants.RSA_PKCS1_PSS_PADDING, saltLength: 20 }); - - const signedLicenseRequest: SignedMessage = { - type: SignedMessage_MessageType.LICENSE_REQUEST, - msg: this._rawLicenseRequest, - signature: Buffer.from(signature), - sessionKey: Buffer.alloc(0), - remoteAttestation: Buffer.alloc(0), - metricData: [], - serviceVersionInfo: undefined, - sessionKeyType: SignedMessage_SessionKeyType.UNDEFINED, - oemcryptoCoreMessage: Buffer.alloc(0) - }; - - return Buffer.from(SignedMessage.encode(signedLicenseRequest).finish()); - } - - parseLicense(rawLicense: Buffer) { - if (!this._rawLicenseRequest) { - throw new Error('please request a license first'); - } - const signedLicense = SignedMessage.decode(rawLicense); - const sessionKey = crypto.privateDecrypt(this._devicePrivateKey, signedLicense.sessionKey); - - const cmac = new AES_CMAC(Buffer.from(sessionKey)); - - const encKeyBase = Buffer.concat([ - Buffer.from('ENCRYPTION'), - Buffer.from('\x00', 'ascii'), - this._rawLicenseRequest, - Buffer.from('\x00\x00\x00\x80', 'ascii') - ]); - const authKeyBase = Buffer.concat([ - Buffer.from('AUTHENTICATION'), - Buffer.from('\x00', 'ascii'), - this._rawLicenseRequest, - Buffer.from('\x00\x00\x02\x00', 'ascii') - ]); - - const encKey = cmac.calculate(Buffer.concat([Buffer.from('\x01'), encKeyBase])); - const serverKey = Buffer.concat([ - cmac.calculate(Buffer.concat([Buffer.from('\x01'), authKeyBase])), - cmac.calculate(Buffer.concat([Buffer.from('\x02'), authKeyBase])) - ]); - /*const clientKey = Buffer.concat([ - cmac.calculate(Buffer.concat([Buffer.from("\x03"), authKeyBase])), - cmac.calculate(Buffer.concat([Buffer.from("\x04"), authKeyBase])) - ]);*/ - - const calculatedSignature = crypto.createHmac('sha256', serverKey).update(signedLicense.msg).digest(); - - if (!calculatedSignature.equals(signedLicense.signature)) { - throw new Error('signatures do not match'); - } - - const license = License.decode(signedLicense.msg); - - return license.key.map((keyContainer) => { - const keyId = keyContainer.id.length ? keyContainer.id.toString('hex') : keyContainer.type.toString(); - const decipher = crypto.createDecipheriv(`aes-${encKey.length * 8}-cbc`, encKey, keyContainer.iv); - const decryptedKey = decipher.update(keyContainer.key); - decipher.destroy(); - const key: KeyContainer = { - kid: keyId, - key: decryptedKey.toString('hex') - }; - return key; - }); - } - - private _parsePSSH(pssh: Buffer): WidevinePsshData | null { - try { - return WidevinePsshData.decode(pssh.subarray(32)); - } catch { - return null; - } - } - - private _generateIdentifier(): Buffer { - return Buffer.from(`${crypto.randomBytes(8).toString('hex')}${'01'}${'00000000000000'}`); - } - - get pssh(): Buffer { - return this._pssh; - } -} \ No newline at end of file diff --git a/modules/license_protocol.proto b/modules/license_protocol.proto deleted file mode 100644 index 7a9099c..0000000 --- a/modules/license_protocol.proto +++ /dev/null @@ -1,749 +0,0 @@ -//Originally from https://github.com/Frooastside/node-widevine/blob/main/src/license_protocol.proto - -syntax = "proto2"; - -package license_protocol; - -enum LicenseType { - STREAMING = 1; - OFFLINE = 2; - // License type decision is left to provider. - AUTOMATIC = 3; -} - -enum PlatformVerificationStatus { - // The platform is not verified. - PLATFORM_UNVERIFIED = 0; - // Tampering detected on the platform. - PLATFORM_TAMPERED = 1; - // The platform has been verified by means of software. - PLATFORM_SOFTWARE_VERIFIED = 2; - // The platform has been verified by means of hardware (e.g. secure boot). - PLATFORM_HARDWARE_VERIFIED = 3; - // Platform verification was not performed. - PLATFORM_NO_VERIFICATION = 4; - // Platform and secure storage capability have been verified by means of - // software. - PLATFORM_SECURE_STORAGE_SOFTWARE_VERIFIED = 5; -} - -// LicenseIdentification is propagated from LicenseRequest to License, -// incrementing version with each iteration. -message LicenseIdentification { - optional bytes request_id = 1; - optional bytes session_id = 2; - optional bytes purchase_id = 3; - optional LicenseType type = 4; - optional int32 version = 5; - optional bytes provider_session_token = 6; -} - -message License { - message Policy { - // Indicates that playback of the content is allowed. - optional bool can_play = 1 [default = false]; - - // Indicates that the license may be persisted to non-volatile - // storage for offline use. - optional bool can_persist = 2 [default = false]; - - // Indicates that renewal of this license is allowed. - optional bool can_renew = 3 [default = false]; - - // For the |*duration*| fields, playback must halt when - // license_start_time (seconds since the epoch (UTC)) + - // license_duration_seconds is exceeded. A value of 0 - // indicates that there is no limit to the duration. - - // Indicates the rental window. - optional int64 rental_duration_seconds = 4 [default = 0]; - - // Indicates the viewing window, once playback has begun. - optional int64 playback_duration_seconds = 5 [default = 0]; - - // Indicates the time window for this specific license. - optional int64 license_duration_seconds = 6 [default = 0]; - - // The |renewal*| fields only apply if |can_renew| is true. - - // The window of time, in which playback is allowed to continue while - // renewal is attempted, yet unsuccessful due to backend problems with - // the license server. - optional int64 renewal_recovery_duration_seconds = 7 [default = 0]; - - // All renewal requests for this license shall be directed to the - // specified URL. - optional string renewal_server_url = 8; - - // How many seconds after license_start_time, before renewal is first - // attempted. - optional int64 renewal_delay_seconds = 9 [default = 0]; - - // Specifies the delay in seconds between subsequent license - // renewal requests, in case of failure. - optional int64 renewal_retry_interval_seconds = 10 [default = 0]; - - // Indicates that the license shall be sent for renewal when usage is - // started. - optional bool renew_with_usage = 11 [default = false]; - - // Indicates to client that license renewal and release requests ought to - // include ClientIdentification (client_id). - optional bool always_include_client_id = 12 [default = false]; - - // Duration of grace period before playback_duration_seconds (short window) - // goes into effect. Optional. - optional int64 play_start_grace_period_seconds = 13 [default = 0]; - - // Enables "soft enforcement" of playback_duration_seconds, letting the user - // finish playback even if short window expires. Optional. - optional bool soft_enforce_playback_duration = 14 [default = false]; - - // Enables "soft enforcement" of rental_duration_seconds. Initial playback - // must always start before rental duration expires. In order to allow - // subsequent playbacks to start after the rental duration expires, - // soft_enforce_playback_duration must be true. Otherwise, subsequent - // playbacks will not be allowed once rental duration expires. Optional. - optional bool soft_enforce_rental_duration = 15 [default = true]; - } - - message KeyContainer { - enum KeyType { - SIGNING = 1; // Exactly one key of this type must appear. - CONTENT = 2; // Content key. - KEY_CONTROL = 3; // Key control block for license renewals. No key. - OPERATOR_SESSION = 4; // wrapped keys for auxiliary crypto operations. - ENTITLEMENT = 5; // Entitlement keys. - OEM_CONTENT = 6; // Partner-specific content key. - } - - // The SecurityLevel enumeration allows the server to communicate the level - // of robustness required by the client, in order to use the key. - enum SecurityLevel { - // Software-based whitebox crypto is required. - SW_SECURE_CRYPTO = 1; - - // Software crypto and an obfuscated decoder is required. - SW_SECURE_DECODE = 2; - - // The key material and crypto operations must be performed within a - // hardware backed trusted execution environment. - HW_SECURE_CRYPTO = 3; - - // The crypto and decoding of content must be performed within a hardware - // backed trusted execution environment. - HW_SECURE_DECODE = 4; - - // The crypto, decoding and all handling of the media (compressed and - // uncompressed) must be handled within a hardware backed trusted - // execution environment. - HW_SECURE_ALL = 5; - } - - message KeyControl { - // |key_control| is documented in: - // Widevine Modular DRM Security Integration Guide for CENC - // If present, the key control must be communicated to the secure - // environment prior to any usage. This message is automatically generated - // by the Widevine License Server SDK. - optional bytes key_control_block = 1; - optional bytes iv = 2; - } - - message OutputProtection { - // Indicates whether HDCP is required on digital outputs, and which - // version should be used. - enum HDCP { - HDCP_NONE = 0; - HDCP_V1 = 1; - HDCP_V2 = 2; - HDCP_V2_1 = 3; - HDCP_V2_2 = 4; - HDCP_V2_3 = 5; - HDCP_NO_DIGITAL_OUTPUT = 0xff; - } - optional HDCP hdcp = 1 [default = HDCP_NONE]; - - // Indicate the CGMS setting to be inserted on analog output. - enum CGMS { - CGMS_NONE = 42; - COPY_FREE = 0; - COPY_ONCE = 2; - COPY_NEVER = 3; - } - optional CGMS cgms_flags = 2 [default = CGMS_NONE]; - - enum HdcpSrmRule { - HDCP_SRM_RULE_NONE = 0; - // In 'required_protection', this means most current SRM is required. - // Update the SRM on the device. If update cannot happen, - // do not allow the key. - // In 'requested_protection', this means most current SRM is requested. - // Update the SRM on the device. If update cannot happen, - // allow use of the key anyway. - CURRENT_SRM = 1; - } - optional HdcpSrmRule hdcp_srm_rule = 3 [default = HDCP_SRM_RULE_NONE]; - // Optional requirement to indicate analog output is not allowed. - optional bool disable_analog_output = 4 [default = false]; - // Optional requirement to indicate digital output is not allowed. - optional bool disable_digital_output = 5 [default = false]; - } - - message VideoResolutionConstraint { - // Minimum and maximum video resolutions in the range (height x width). - optional uint32 min_resolution_pixels = 1; - optional uint32 max_resolution_pixels = 2; - // Optional output protection requirements for this range. If not - // specified, the OutputProtection in the KeyContainer applies. - optional OutputProtection required_protection = 3; - } - - message OperatorSessionKeyPermissions { - // Permissions/key usage flags for operator service keys - // (type = OPERATOR_SESSION). - optional bool allow_encrypt = 1 [default = false]; - optional bool allow_decrypt = 2 [default = false]; - optional bool allow_sign = 3 [default = false]; - optional bool allow_signature_verify = 4 [default = false]; - } - - optional bytes id = 1; - optional bytes iv = 2; - optional bytes key = 3; - optional KeyType type = 4; - optional SecurityLevel level = 5 [default = SW_SECURE_CRYPTO]; - optional OutputProtection required_protection = 6; - // NOTE: Use of requested_protection is not recommended as it is only - // supported on a small number of platforms. - optional OutputProtection requested_protection = 7; - optional KeyControl key_control = 8; - optional OperatorSessionKeyPermissions operator_session_key_permissions = 9; - // Optional video resolution constraints. If the video resolution of the - // content being decrypted/decoded falls within one of the specified ranges, - // the optional required_protections may be applied. Otherwise an error will - // be reported. - // NOTE: Use of this feature is not recommended, as it is only supported on - // a small number of platforms. - repeated VideoResolutionConstraint video_resolution_constraints = 10; - // Optional flag to indicate the key must only be used if the client - // supports anti rollback of the user table. Content provider can query the - // client capabilities to determine if the client support this feature. - optional bool anti_rollback_usage_table = 11 [default = false]; - // Optional not limited to commonly known track types such as SD, HD. - // It can be some provider defined label to identify the track. - optional string track_label = 12; - } - - optional LicenseIdentification id = 1; - optional Policy policy = 2; - repeated KeyContainer key = 3; - // Time of the request in seconds (UTC) as set in - // LicenseRequest.request_time. If this time is not set in the request, - // the local time at the license service is used in this field. - optional int64 license_start_time = 4; - optional bool remote_attestation_verified = 5 [default = false]; - // Client token generated by the content provider. Optional. - optional bytes provider_client_token = 6; - // 4cc code specifying the CENC protection scheme as defined in the CENC 3.0 - // specification. Propagated from Widevine PSSH box. Optional. - optional uint32 protection_scheme = 7; - // 8 byte verification field "HDCPDATA" followed by unsigned 32 bit minimum - // HDCP SRM version (whether the version is for HDCP1 SRM or HDCP2 SRM - // depends on client max_hdcp_version). - // Additional details can be found in Widevine Modular DRM Security - // Integration Guide for CENC. - optional bytes srm_requirement = 8; - // If present this contains a signed SRM file (either HDCP1 SRM or HDCP2 SRM - // depending on client max_hdcp_version) that should be installed on the - // client device. - optional bytes srm_update = 9; - // Indicates the status of any type of platform verification performed by the - // server. - optional PlatformVerificationStatus platform_verification_status = 10 - [default = PLATFORM_NO_VERIFICATION]; - // IDs of the groups for which keys are delivered in this license, if any. - repeated bytes group_ids = 11; -} - -enum ProtocolVersion { - VERSION_2_0 = 20; - VERSION_2_1 = 21; - VERSION_2_2 = 22; -} - -message LicenseRequest { - message ContentIdentification { - message WidevinePsshData { - repeated bytes pssh_data = 1; - optional LicenseType license_type = 2; - optional bytes request_id = 3; // Opaque, client-specified. - } - - message WebmKeyId { - optional bytes header = 1; - optional LicenseType license_type = 2; - optional bytes request_id = 3; // Opaque, client-specified. - } - - message ExistingLicense { - optional LicenseIdentification license_id = 1; - optional int64 seconds_since_started = 2; - optional int64 seconds_since_last_played = 3; - optional bytes session_usage_table_entry = 4; - } - - message InitData { - enum InitDataType { - CENC = 1; - WEBM = 2; - } - - optional InitDataType init_data_type = 1 [default = CENC]; - optional bytes init_data = 2; - optional LicenseType license_type = 3; - optional bytes request_id = 4; - } - - oneof content_id_variant { - // Exactly one of these must be present. - WidevinePsshData widevine_pssh_data = 1; - WebmKeyId webm_key_id = 2; - ExistingLicense existing_license = 3; - InitData init_data = 4; - } - } - - enum RequestType { - NEW = 1; - RENEWAL = 2; - RELEASE = 3; - } - - // The client_id provides information authenticating the calling device. It - // contains the Widevine keybox token that was installed on the device at the - // factory. This field or encrypted_client_id below is required for a valid - // license request, but both should never be present in the same request. - optional ClientIdentification client_id = 1; - optional ContentIdentification content_id = 2; - optional RequestType type = 3; - // Time of the request in seconds (UTC) as set by the client. - optional int64 request_time = 4; - // Old-style decimal-encoded string key control nonce. - optional bytes key_control_nonce_deprecated = 5; - optional ProtocolVersion protocol_version = 6 [default = VERSION_2_0]; - // New-style uint32 key control nonce, please use instead of - // key_control_nonce_deprecated. - optional uint32 key_control_nonce = 7; - // Encrypted ClientIdentification message, used for privacy purposes. - optional EncryptedClientIdentification encrypted_client_id = 8; -} - -message MetricData { - enum MetricType { - // The time spent in the 'stage', specified in microseconds. - LATENCY = 1; - // The UNIX epoch timestamp at which the 'stage' was first accessed in - // microseconds. - TIMESTAMP = 2; - } - - message TypeValue { - optional MetricType type = 1; - // The value associated with 'type'. For example if type == LATENCY, the - // value would be the time in microseconds spent in this 'stage'. - optional int64 value = 2 [default = 0]; - } - - // 'stage' that is currently processing the SignedMessage. Required. - optional string stage_name = 1; - // metric and associated value. - repeated TypeValue metric_data = 2; -} - -message VersionInfo { - // License SDK version reported by the Widevine License SDK. This field - // is populated automatically by the SDK. - optional string license_sdk_version = 1; - // Version of the service hosting the license SDK. This field is optional. - // It may be provided by the hosting service. - optional string license_service_version = 2; -} - -message SignedMessage { - enum MessageType { - LICENSE_REQUEST = 1; - LICENSE = 2; - ERROR_RESPONSE = 3; - SERVICE_CERTIFICATE_REQUEST = 4; - SERVICE_CERTIFICATE = 5; - SUB_LICENSE = 6; - CAS_LICENSE_REQUEST = 7; - CAS_LICENSE = 8; - EXTERNAL_LICENSE_REQUEST = 9; - EXTERNAL_LICENSE = 10; - } - - enum SessionKeyType { - UNDEFINED = 0; - WRAPPED_AES_KEY = 1; - EPHERMERAL_ECC_PUBLIC_KEY = 2; - } - optional MessageType type = 1; - optional bytes msg = 2; - // Required field that contains the signature of the bytes of msg. - // For license requests, the signing algorithm is determined by the - // certificate contained in the request. - // For license responses, the signing algorithm is HMAC with signing key based - // on |session_key|. - optional bytes signature = 3; - // If populated, the contents of this field will be signaled by the - // |session_key_type| type. If the |session_key_type| is WRAPPED_AES_KEY the - // key is the bytes of an encrypted AES key. If the |session_key_type| is - // EPHERMERAL_ECC_PUBLIC_KEY the field contains the bytes of an RFC5208 ASN1 - // serialized ECC public key. - optional bytes session_key = 4; - // Remote attestation data which will be present in the initial license - // request for ChromeOS client devices operating in verified mode. Remote - // attestation challenge data is |msg| field above. Optional. - optional bytes remote_attestation = 5; - - repeated MetricData metric_data = 6; - // Version information from the SDK and license service. This information is - // provided in the license response. - optional VersionInfo service_version_info = 7; - // Optional field that contains the algorithm type used to generate the - // session_key and signature in a LICENSE message. - optional SessionKeyType session_key_type = 8 [default = WRAPPED_AES_KEY]; - // The core message is the simple serialization of fields used by OEMCrypto. - // This field was introduced in OEMCrypto API v16. - optional bytes oemcrypto_core_message = 9; -} - -enum HashAlgorithmProto { - // Unspecified hash algorithm: SHA_256 shall be used for ECC based algorithms - // and SHA_1 shall be used otherwise. - HASH_ALGORITHM_UNSPECIFIED = 0; - HASH_ALGORITHM_SHA_1 = 1; - HASH_ALGORITHM_SHA_256 = 2; - HASH_ALGORITHM_SHA_384 = 3; -} - -// ClientIdentification message used to authenticate the client device. -message ClientIdentification { - enum TokenType { - KEYBOX = 0; - DRM_DEVICE_CERTIFICATE = 1; - REMOTE_ATTESTATION_CERTIFICATE = 2; - OEM_DEVICE_CERTIFICATE = 3; - } - - message NameValue { - optional string name = 1; - optional string value = 2; - } - - // Capabilities which not all clients may support. Used for the license - // exchange protocol only. - message ClientCapabilities { - enum HdcpVersion { - HDCP_NONE = 0; - HDCP_V1 = 1; - HDCP_V2 = 2; - HDCP_V2_1 = 3; - HDCP_V2_2 = 4; - HDCP_V2_3 = 5; - HDCP_NO_DIGITAL_OUTPUT = 0xff; - } - - enum CertificateKeyType { - RSA_2048 = 0; - RSA_3072 = 1; - ECC_SECP256R1 = 2; - ECC_SECP384R1 = 3; - ECC_SECP521R1 = 4; - } - - enum AnalogOutputCapabilities { - ANALOG_OUTPUT_UNKNOWN = 0; - ANALOG_OUTPUT_NONE = 1; - ANALOG_OUTPUT_SUPPORTED = 2; - ANALOG_OUTPUT_SUPPORTS_CGMS_A = 3; - } - - optional bool client_token = 1 [default = false]; - optional bool session_token = 2 [default = false]; - optional bool video_resolution_constraints = 3 [default = false]; - optional HdcpVersion max_hdcp_version = 4 [default = HDCP_NONE]; - optional uint32 oem_crypto_api_version = 5; - // Client has hardware support for protecting the usage table, such as - // storing the generation number in secure memory. For Details, see: - // Widevine Modular DRM Security Integration Guide for CENC - optional bool anti_rollback_usage_table = 6 [default = false]; - // The client shall report |srm_version| if available. - optional uint32 srm_version = 7; - // A device may have SRM data, and report a version, but may not be capable - // of updating SRM data. - optional bool can_update_srm = 8 [default = false]; - repeated CertificateKeyType supported_certificate_key_type = 9; - optional AnalogOutputCapabilities analog_output_capabilities = 10 - [default = ANALOG_OUTPUT_UNKNOWN]; - optional bool can_disable_analog_output = 11 [default = false]; - // Clients can indicate a performance level supported by OEMCrypto. - // This will allow applications and providers to choose an appropriate - // quality of content to serve. Currently defined tiers are - // 1 (low), 2 (medium) and 3 (high). Any other value indicates that - // the resource rating is unavailable or reporting erroneous values - // for that device. For details see, - // Widevine Modular DRM Security Integration Guide for CENC - optional uint32 resource_rating_tier = 12 [default = 0]; - } - - message ClientCredentials { - optional TokenType type = 1 [default = KEYBOX]; - optional bytes token = 2; - } - - // Type of factory-provisioned device root of trust. Optional. - optional TokenType type = 1 [default = KEYBOX]; - // Factory-provisioned device root of trust. Required. - optional bytes token = 2; - // Optional client information name/value pairs. - repeated NameValue client_info = 3; - // Client token generated by the content provider. Optional. - optional bytes provider_client_token = 4; - // Number of licenses received by the client to which the token above belongs. - // Only present if client_token is specified. - optional uint32 license_counter = 5; - // List of non-baseline client capabilities. - optional ClientCapabilities client_capabilities = 6; - // Serialized VmpData message. Optional. - optional bytes vmp_data = 7; - // Optional field that may contain additional provisioning credentials. - repeated ClientCredentials device_credentials = 8; -} - -// EncryptedClientIdentification message used to hold ClientIdentification -// messages encrypted for privacy purposes. -message EncryptedClientIdentification { - // Provider ID for which the ClientIdentifcation is encrypted (owner of - // service certificate). - optional string provider_id = 1; - // Serial number for the service certificate for which ClientIdentification is - // encrypted. - optional bytes service_certificate_serial_number = 2; - // Serialized ClientIdentification message, encrypted with the privacy key - // using AES-128-CBC with PKCS#5 padding. - optional bytes encrypted_client_id = 3; - // Initialization vector needed to decrypt encrypted_client_id. - optional bytes encrypted_client_id_iv = 4; - // AES-128 privacy key, encrypted with the service public key using RSA-OAEP. - optional bytes encrypted_privacy_key = 5; -} - -// DRM certificate definition for user devices, intermediate, service, and root -// certificates. -message DrmCertificate { - enum Type { - ROOT = 0; // ProtoBestPractices: ignore. - DEVICE_MODEL = 1; - DEVICE = 2; - SERVICE = 3; - PROVISIONER = 4; - } - enum ServiceType { - UNKNOWN_SERVICE_TYPE = 0; - LICENSE_SERVER_SDK = 1; - LICENSE_SERVER_PROXY_SDK = 2; - PROVISIONING_SDK = 3; - CAS_PROXY_SDK = 4; - } - enum Algorithm { - UNKNOWN_ALGORITHM = 0; - RSA = 1; - ECC_SECP256R1 = 2; - ECC_SECP384R1 = 3; - ECC_SECP521R1 = 4; - } - - message EncryptionKey { - // Device public key. PKCS#1 ASN.1 DER-encoded. Required. - optional bytes public_key = 1; - // Required. The algorithm field contains the curve used to create the - // |public_key| if algorithm is one of the ECC types. - // The |algorithm| is used for both to determine the if the certificate is - // ECC or RSA. The |algorithm| also specifies the parameters that were used - // to create |public_key| and are used to create an ephemeral session key. - optional Algorithm algorithm = 2 [default = RSA]; - } - - // Type of certificate. Required. - optional Type type = 1; - // 128-bit globally unique serial number of certificate. - // Value is 0 for root certificate. Required. - optional bytes serial_number = 2; - // POSIX time, in seconds, when the certificate was created. Required. - optional uint32 creation_time_seconds = 3; - // POSIX time, in seconds, when the certificate should expire. Value of zero - // denotes indefinite expiry time. For more information on limited lifespan - // DRM certificates see (go/limited-lifespan-drm-certificates). - optional uint32 expiration_time_seconds = 12; - // Device public key. PKCS#1 ASN.1 DER-encoded. Required. - optional bytes public_key = 4; - // Widevine system ID for the device. Required for intermediate and - // user device certificates. - optional uint32 system_id = 5; - // Deprecated field, which used to indicate whether the device was a test - // (non-production) device. The test_device field in ProvisionedDeviceInfo - // below should be observed instead. - optional bool test_device_deprecated = 6 [deprecated = true]; - // Service identifier (web origin) for the provider which owns the - // certificate. Required for service and provisioner certificates. - optional string provider_id = 7; - // This field is used only when type = SERVICE to specify which SDK uses - // service certificate. This repeated field is treated as a set. A certificate - // may be used for the specified service SDK if the appropriate ServiceType - // is specified in this field. - repeated ServiceType service_types = 8; - // Required. The algorithm field contains the curve used to create the - // |public_key| if algorithm is one of the ECC types. - // The |algorithm| is used for both to determine the if the certificate is ECC - // or RSA. The |algorithm| also specifies the parameters that were used to - // create |public_key| and are used to create an ephemeral session key. - optional Algorithm algorithm = 9 [default = RSA]; - // Optional. May be present in DEVICE certificate types. This is the root - // of trust identifier that holds an encrypted value that identifies the - // keybox or other root of trust that was used to provision a DEVICE drm - // certificate. - optional bytes rot_id = 10; - // Optional. May be present in devices that explicitly support dual keys. When - // present the |public_key| is used for verification of received license - // request messages. - optional EncryptionKey encryption_key = 11; -} - -// DrmCertificate signed by a higher (CA) DRM certificate. -message SignedDrmCertificate { - // Serialized certificate. Required. - optional bytes drm_certificate = 1; - // Signature of certificate. Signed with root or intermediate - // certificate specified below. Required. - optional bytes signature = 2; - // SignedDrmCertificate used to sign this certificate. - optional SignedDrmCertificate signer = 3; - // Optional field that indicates the hash algorithm used in signature scheme. - optional HashAlgorithmProto hash_algorithm = 4; -} - -message WidevinePsshData { - enum Type { - SINGLE = 0; // Single PSSH to be used to retrieve content keys. - ENTITLEMENT = 1; // Primary PSSH used to retrieve entitlement keys. - ENTITLED_KEY = 2; // Secondary PSSH containing entitled key(s). - } - - message EntitledKey { - // ID of entitlement key used for wrapping |key|. - optional bytes entitlement_key_id = 1; - // ID of the entitled key. - optional bytes key_id = 2; - // Wrapped key. Required. - optional bytes key = 3; - // IV used for wrapping |key|. Required. - optional bytes iv = 4; - // Size of entitlement key used for wrapping |key|. - optional uint32 entitlement_key_size_bytes = 5 [default = 32]; - } - - // Entitlement or content key IDs. Can onnly present in SINGLE or ENTITLEMENT - // PSSHs. May be repeated to facilitate delivery of multiple keys in a - // single license. Cannot be used in conjunction with content_id or - // group_ids, which are the preferred mechanism. - repeated bytes key_ids = 2; - - // Content identifier which may map to multiple entitlement or content key - // IDs to facilitate the delivery of multiple keys in a single license. - // Cannot be present in conjunction with key_ids, but if used must be in all - // PSSHs. - optional bytes content_id = 4; - - // Crypto period index, for media using key rotation. Always corresponds to - // The content key period. This means that if using entitlement licensing - // the ENTITLED_KEY PSSHs will have sequential crypto_period_index's, whereas - // the ENTITELEMENT PSSHs will have gaps in the sequence. Required if doing - // key rotation. - optional uint32 crypto_period_index = 7; - - // Protection scheme identifying the encryption algorithm. The protection - // scheme is represented as a uint32 value. The uint32 contains 4 bytes each - // representing a single ascii character in one of the 4CC protection scheme - // values. To be deprecated in favor of signaling from content. - // 'cenc' (AES-CTR) protection_scheme = 0x63656E63, - // 'cbc1' (AES-CBC) protection_scheme = 0x63626331, - // 'cens' (AES-CTR pattern encryption) protection_scheme = 0x63656E73, - // 'cbcs' (AES-CBC pattern encryption) protection_scheme = 0x63626373. - optional uint32 protection_scheme = 9; - - // Optional. For media using key rotation, this represents the duration - // of each crypto period in seconds. - optional uint32 crypto_period_seconds = 10; - - // Type of PSSH. Required if not SINGLE. - optional Type type = 11 [default = SINGLE]; - - // Key sequence for Widevine-managed keys. Optional. - optional uint32 key_sequence = 12; - - // Group identifiers for all groups to which the content belongs. This can - // be used to deliver licenses to unlock multiple titles / channels. - // Optional, and may only be present in ENTITLEMENT and ENTITLED_KEY PSSHs, and - // not in conjunction with key_ids. - repeated bytes group_ids = 13; - - // Copy/copies of the content key used to decrypt the media stream in which - // the PSSH box is embedded, each wrapped with a different entitlement key. - // May also contain sub-licenses to support devices with OEMCrypto 13 or - // older. May be repeated if using group entitlement keys. Present only in - // PSSHs of type ENTITLED_KEY. - repeated EntitledKey entitled_keys = 14; - - // Video feature identifier, which is used in conjunction with |content_id| - // to determine the set of keys to be returned in the license. Cannot be - // present in conjunction with |key_ids|. - // Current values are "HDR". - optional string video_feature = 15; - - //////////////////////////// Deprecated Fields //////////////////////////// - enum Algorithm { - UNENCRYPTED = 0; - AESCTR = 1; - }; - optional Algorithm algorithm = 1 [deprecated = true]; - - // Content provider name. - optional string provider = 3 [deprecated = true]; - - // Track type. Acceptable values are SD, HD and AUDIO. Used to - // differentiate content keys used by an asset. - optional string track_type = 5 [deprecated = true]; - - // The name of a registered policy to be used for this asset. - optional string policy = 6 [deprecated = true]; - - // Optional protected context for group content. The grouped_license is a - // serialized SignedMessage. - optional bytes grouped_license = 8 [deprecated = true]; -} - -// File Hashes for Verified Media Path (VMP) support. -message FileHashes { - message Signature { - optional string filename = 1; - optional bool test_signing = 2; //0 - release, 1 - testing - optional bytes SHA512Hash = 3; - optional bool main_exe = 4; //0 for dlls, 1 for exe, this is field 3 in file - optional bytes signature = 5; - } - optional bytes signer = 1; - repeated Signature signatures = 2; -} \ No newline at end of file diff --git a/modules/license_protocol.ts b/modules/license_protocol.ts deleted file mode 100644 index c7ef68c..0000000 --- a/modules/license_protocol.ts +++ /dev/null @@ -1,4996 +0,0 @@ -//Originally from https://github.com/Frooastside/node-widevine/blob/main/src/license_protocol.ts - -import Long from 'long'; -import _m0 from 'protobufjs/minimal'; - -export const protobufPackage = 'license_protocol'; - -export enum LicenseType { - STREAMING = 1, - OFFLINE = 2, - /** AUTOMATIC - License type decision is left to provider. */ - AUTOMATIC = 3, - UNRECOGNIZED = -1 -} - -export function licenseTypeFromJSON(object: any): LicenseType { - switch (object) { - case 1: - case 'STREAMING': - return LicenseType.STREAMING; - case 2: - case 'OFFLINE': - return LicenseType.OFFLINE; - case 3: - case 'AUTOMATIC': - return LicenseType.AUTOMATIC; - case -1: - case 'UNRECOGNIZED': - default: - return LicenseType.UNRECOGNIZED; - } -} - -export function licenseTypeToJSON(object: LicenseType): string { - switch (object) { - case LicenseType.STREAMING: - return 'STREAMING'; - case LicenseType.OFFLINE: - return 'OFFLINE'; - case LicenseType.AUTOMATIC: - return 'AUTOMATIC'; - case LicenseType.UNRECOGNIZED: - default: - return 'UNRECOGNIZED'; - } -} - -export enum PlatformVerificationStatus { - /** PLATFORM_UNVERIFIED - The platform is not verified. */ - PLATFORM_UNVERIFIED = 0, - /** PLATFORM_TAMPERED - Tampering detected on the platform. */ - PLATFORM_TAMPERED = 1, - /** PLATFORM_SOFTWARE_VERIFIED - The platform has been verified by means of software. */ - PLATFORM_SOFTWARE_VERIFIED = 2, - /** PLATFORM_HARDWARE_VERIFIED - The platform has been verified by means of hardware (e.g. secure boot). */ - PLATFORM_HARDWARE_VERIFIED = 3, - /** PLATFORM_NO_VERIFICATION - Platform verification was not performed. */ - PLATFORM_NO_VERIFICATION = 4, - /** - * PLATFORM_SECURE_STORAGE_SOFTWARE_VERIFIED - Platform and secure storage capability have been verified by means of - * software. - */ - PLATFORM_SECURE_STORAGE_SOFTWARE_VERIFIED = 5, - UNRECOGNIZED = -1 -} - -export function platformVerificationStatusFromJSON(object: any): PlatformVerificationStatus { - switch (object) { - case 0: - case 'PLATFORM_UNVERIFIED': - return PlatformVerificationStatus.PLATFORM_UNVERIFIED; - case 1: - case 'PLATFORM_TAMPERED': - return PlatformVerificationStatus.PLATFORM_TAMPERED; - case 2: - case 'PLATFORM_SOFTWARE_VERIFIED': - return PlatformVerificationStatus.PLATFORM_SOFTWARE_VERIFIED; - case 3: - case 'PLATFORM_HARDWARE_VERIFIED': - return PlatformVerificationStatus.PLATFORM_HARDWARE_VERIFIED; - case 4: - case 'PLATFORM_NO_VERIFICATION': - return PlatformVerificationStatus.PLATFORM_NO_VERIFICATION; - case 5: - case 'PLATFORM_SECURE_STORAGE_SOFTWARE_VERIFIED': - return PlatformVerificationStatus.PLATFORM_SECURE_STORAGE_SOFTWARE_VERIFIED; - case -1: - case 'UNRECOGNIZED': - default: - return PlatformVerificationStatus.UNRECOGNIZED; - } -} - -export function platformVerificationStatusToJSON(object: PlatformVerificationStatus): string { - switch (object) { - case PlatformVerificationStatus.PLATFORM_UNVERIFIED: - return 'PLATFORM_UNVERIFIED'; - case PlatformVerificationStatus.PLATFORM_TAMPERED: - return 'PLATFORM_TAMPERED'; - case PlatformVerificationStatus.PLATFORM_SOFTWARE_VERIFIED: - return 'PLATFORM_SOFTWARE_VERIFIED'; - case PlatformVerificationStatus.PLATFORM_HARDWARE_VERIFIED: - return 'PLATFORM_HARDWARE_VERIFIED'; - case PlatformVerificationStatus.PLATFORM_NO_VERIFICATION: - return 'PLATFORM_NO_VERIFICATION'; - case PlatformVerificationStatus.PLATFORM_SECURE_STORAGE_SOFTWARE_VERIFIED: - return 'PLATFORM_SECURE_STORAGE_SOFTWARE_VERIFIED'; - case PlatformVerificationStatus.UNRECOGNIZED: - default: - return 'UNRECOGNIZED'; - } -} - -export enum ProtocolVersion { - VERSION_2_0 = 20, - VERSION_2_1 = 21, - VERSION_2_2 = 22, - UNRECOGNIZED = -1 -} - -export function protocolVersionFromJSON(object: any): ProtocolVersion { - switch (object) { - case 20: - case 'VERSION_2_0': - return ProtocolVersion.VERSION_2_0; - case 21: - case 'VERSION_2_1': - return ProtocolVersion.VERSION_2_1; - case 22: - case 'VERSION_2_2': - return ProtocolVersion.VERSION_2_2; - case -1: - case 'UNRECOGNIZED': - default: - return ProtocolVersion.UNRECOGNIZED; - } -} - -export function protocolVersionToJSON(object: ProtocolVersion): string { - switch (object) { - case ProtocolVersion.VERSION_2_0: - return 'VERSION_2_0'; - case ProtocolVersion.VERSION_2_1: - return 'VERSION_2_1'; - case ProtocolVersion.VERSION_2_2: - return 'VERSION_2_2'; - case ProtocolVersion.UNRECOGNIZED: - default: - return 'UNRECOGNIZED'; - } -} - -export enum HashAlgorithmProto { - /** - * HASH_ALGORITHM_UNSPECIFIED - Unspecified hash algorithm: SHA_256 shall be used for ECC based algorithms - * and SHA_1 shall be used otherwise. - */ - HASH_ALGORITHM_UNSPECIFIED = 0, - HASH_ALGORITHM_SHA_1 = 1, - HASH_ALGORITHM_SHA_256 = 2, - HASH_ALGORITHM_SHA_384 = 3, - UNRECOGNIZED = -1 -} - -export function hashAlgorithmProtoFromJSON(object: any): HashAlgorithmProto { - switch (object) { - case 0: - case 'HASH_ALGORITHM_UNSPECIFIED': - return HashAlgorithmProto.HASH_ALGORITHM_UNSPECIFIED; - case 1: - case 'HASH_ALGORITHM_SHA_1': - return HashAlgorithmProto.HASH_ALGORITHM_SHA_1; - case 2: - case 'HASH_ALGORITHM_SHA_256': - return HashAlgorithmProto.HASH_ALGORITHM_SHA_256; - case 3: - case 'HASH_ALGORITHM_SHA_384': - return HashAlgorithmProto.HASH_ALGORITHM_SHA_384; - case -1: - case 'UNRECOGNIZED': - default: - return HashAlgorithmProto.UNRECOGNIZED; - } -} - -export function hashAlgorithmProtoToJSON(object: HashAlgorithmProto): string { - switch (object) { - case HashAlgorithmProto.HASH_ALGORITHM_UNSPECIFIED: - return 'HASH_ALGORITHM_UNSPECIFIED'; - case HashAlgorithmProto.HASH_ALGORITHM_SHA_1: - return 'HASH_ALGORITHM_SHA_1'; - case HashAlgorithmProto.HASH_ALGORITHM_SHA_256: - return 'HASH_ALGORITHM_SHA_256'; - case HashAlgorithmProto.HASH_ALGORITHM_SHA_384: - return 'HASH_ALGORITHM_SHA_384'; - case HashAlgorithmProto.UNRECOGNIZED: - default: - return 'UNRECOGNIZED'; - } -} - -/** - * LicenseIdentification is propagated from LicenseRequest to License, - * incrementing version with each iteration. - */ -export interface LicenseIdentification { - requestId: Buffer; - sessionId: Buffer; - purchaseId: Buffer; - type: LicenseType; - version: number; - providerSessionToken: Buffer; -} - -export interface License { - id: LicenseIdentification | undefined; - policy: License_Policy | undefined; - key: License_KeyContainer[]; - /** - * Time of the request in seconds (UTC) as set in - * LicenseRequest.request_time. If this time is not set in the request, - * the local time at the license service is used in this field. - */ - licenseStartTime: Long; - remoteAttestationVerified: boolean; - /** Client token generated by the content provider. Optional. */ - providerClientToken: Buffer; - /** - * 4cc code specifying the CENC protection scheme as defined in the CENC 3.0 - * specification. Propagated from Widevine PSSH box. Optional. - */ - protectionScheme: number; - /** - * 8 byte verification field "HDCPDATA" followed by unsigned 32 bit minimum - * HDCP SRM version (whether the version is for HDCP1 SRM or HDCP2 SRM - * depends on client max_hdcp_version). - * Additional details can be found in Widevine Modular DRM Security - * Integration Guide for CENC. - */ - srmRequirement: Buffer; - /** - * If present this contains a signed SRM file (either HDCP1 SRM or HDCP2 SRM - * depending on client max_hdcp_version) that should be installed on the - * client device. - */ - srmUpdate: Buffer; - /** - * Indicates the status of any type of platform verification performed by the - * server. - */ - platformVerificationStatus: PlatformVerificationStatus; - /** IDs of the groups for which keys are delivered in this license, if any. */ - groupIds: Buffer[]; -} - -export interface License_Policy { - /** Indicates that playback of the content is allowed. */ - canPlay: boolean; - /** - * Indicates that the license may be persisted to non-volatile - * storage for offline use. - */ - canPersist: boolean; - /** Indicates that renewal of this license is allowed. */ - canRenew: boolean; - /** Indicates the rental window. */ - rentalDurationSeconds: Long; - /** Indicates the viewing window, once playback has begun. */ - playbackDurationSeconds: Long; - /** Indicates the time window for this specific license. */ - licenseDurationSeconds: Long; - /** - * The window of time, in which playback is allowed to continue while - * renewal is attempted, yet unsuccessful due to backend problems with - * the license server. - */ - renewalRecoveryDurationSeconds: Long; - /** - * All renewal requests for this license shall be directed to the - * specified URL. - */ - renewalServerUrl: string; - /** - * How many seconds after license_start_time, before renewal is first - * attempted. - */ - renewalDelaySeconds: Long; - /** - * Specifies the delay in seconds between subsequent license - * renewal requests, in case of failure. - */ - renewalRetryIntervalSeconds: Long; - /** - * Indicates that the license shall be sent for renewal when usage is - * started. - */ - renewWithUsage: boolean; - /** - * Indicates to client that license renewal and release requests ought to - * include ClientIdentification (client_id). - */ - alwaysIncludeClientId: boolean; - /** - * Duration of grace period before playback_duration_seconds (short window) - * goes into effect. Optional. - */ - playStartGracePeriodSeconds: Long; - /** - * Enables "soft enforcement" of playback_duration_seconds, letting the user - * finish playback even if short window expires. Optional. - */ - softEnforcePlaybackDuration: boolean; - /** - * Enables "soft enforcement" of rental_duration_seconds. Initial playback - * must always start before rental duration expires. In order to allow - * subsequent playbacks to start after the rental duration expires, - * soft_enforce_playback_duration must be true. Otherwise, subsequent - * playbacks will not be allowed once rental duration expires. Optional. - */ - softEnforceRentalDuration: boolean; -} - -export interface License_KeyContainer { - id: Buffer; - iv: Buffer; - key: Buffer; - type: License_KeyContainer_KeyType; - level: License_KeyContainer_SecurityLevel; - requiredProtection: License_KeyContainer_OutputProtection | undefined; - /** - * NOTE: Use of requested_protection is not recommended as it is only - * supported on a small number of platforms. - */ - requestedProtection: License_KeyContainer_OutputProtection | undefined; - keyControl: License_KeyContainer_KeyControl | undefined; - operatorSessionKeyPermissions: License_KeyContainer_OperatorSessionKeyPermissions | undefined; - /** - * Optional video resolution constraints. If the video resolution of the - * content being decrypted/decoded falls within one of the specified ranges, - * the optional required_protections may be applied. Otherwise an error will - * be reported. - * NOTE: Use of this feature is not recommended, as it is only supported on - * a small number of platforms. - */ - videoResolutionConstraints: License_KeyContainer_VideoResolutionConstraint[]; - /** - * Optional flag to indicate the key must only be used if the client - * supports anti rollback of the user table. Content provider can query the - * client capabilities to determine if the client support this feature. - */ - antiRollbackUsageTable: boolean; - /** - * Optional not limited to commonly known track types such as SD, HD. - * It can be some provider defined label to identify the track. - */ - trackLabel: string; -} - -export enum License_KeyContainer_KeyType { - /** SIGNING - Exactly one key of this type must appear. */ - SIGNING = 1, - /** CONTENT - Content key. */ - CONTENT = 2, - /** KEY_CONTROL - Key control block for license renewals. No key. */ - KEY_CONTROL = 3, - /** OPERATOR_SESSION - wrapped keys for auxiliary crypto operations. */ - OPERATOR_SESSION = 4, - /** ENTITLEMENT - Entitlement keys. */ - ENTITLEMENT = 5, - /** OEM_CONTENT - Partner-specific content key. */ - OEM_CONTENT = 6, - UNRECOGNIZED = -1 -} - -export function license_KeyContainer_KeyTypeFromJSON(object: any): License_KeyContainer_KeyType { - switch (object) { - case 1: - case 'SIGNING': - return License_KeyContainer_KeyType.SIGNING; - case 2: - case 'CONTENT': - return License_KeyContainer_KeyType.CONTENT; - case 3: - case 'KEY_CONTROL': - return License_KeyContainer_KeyType.KEY_CONTROL; - case 4: - case 'OPERATOR_SESSION': - return License_KeyContainer_KeyType.OPERATOR_SESSION; - case 5: - case 'ENTITLEMENT': - return License_KeyContainer_KeyType.ENTITLEMENT; - case 6: - case 'OEM_CONTENT': - return License_KeyContainer_KeyType.OEM_CONTENT; - case -1: - case 'UNRECOGNIZED': - default: - return License_KeyContainer_KeyType.UNRECOGNIZED; - } -} - -export function license_KeyContainer_KeyTypeToJSON(object: License_KeyContainer_KeyType): string { - switch (object) { - case License_KeyContainer_KeyType.SIGNING: - return 'SIGNING'; - case License_KeyContainer_KeyType.CONTENT: - return 'CONTENT'; - case License_KeyContainer_KeyType.KEY_CONTROL: - return 'KEY_CONTROL'; - case License_KeyContainer_KeyType.OPERATOR_SESSION: - return 'OPERATOR_SESSION'; - case License_KeyContainer_KeyType.ENTITLEMENT: - return 'ENTITLEMENT'; - case License_KeyContainer_KeyType.OEM_CONTENT: - return 'OEM_CONTENT'; - case License_KeyContainer_KeyType.UNRECOGNIZED: - default: - return 'UNRECOGNIZED'; - } -} - -/** - * The SecurityLevel enumeration allows the server to communicate the level - * of robustness required by the client, in order to use the key. - */ -export enum License_KeyContainer_SecurityLevel { - /** SW_SECURE_CRYPTO - Software-based whitebox crypto is required. */ - SW_SECURE_CRYPTO = 1, - /** SW_SECURE_DECODE - Software crypto and an obfuscated decoder is required. */ - SW_SECURE_DECODE = 2, - /** - * HW_SECURE_CRYPTO - The key material and crypto operations must be performed within a - * hardware backed trusted execution environment. - */ - HW_SECURE_CRYPTO = 3, - /** - * HW_SECURE_DECODE - The crypto and decoding of content must be performed within a hardware - * backed trusted execution environment. - */ - HW_SECURE_DECODE = 4, - /** - * HW_SECURE_ALL - The crypto, decoding and all handling of the media (compressed and - * uncompressed) must be handled within a hardware backed trusted - * execution environment. - */ - HW_SECURE_ALL = 5, - UNRECOGNIZED = -1 -} - -export function license_KeyContainer_SecurityLevelFromJSON(object: any): License_KeyContainer_SecurityLevel { - switch (object) { - case 1: - case 'SW_SECURE_CRYPTO': - return License_KeyContainer_SecurityLevel.SW_SECURE_CRYPTO; - case 2: - case 'SW_SECURE_DECODE': - return License_KeyContainer_SecurityLevel.SW_SECURE_DECODE; - case 3: - case 'HW_SECURE_CRYPTO': - return License_KeyContainer_SecurityLevel.HW_SECURE_CRYPTO; - case 4: - case 'HW_SECURE_DECODE': - return License_KeyContainer_SecurityLevel.HW_SECURE_DECODE; - case 5: - case 'HW_SECURE_ALL': - return License_KeyContainer_SecurityLevel.HW_SECURE_ALL; - case -1: - case 'UNRECOGNIZED': - default: - return License_KeyContainer_SecurityLevel.UNRECOGNIZED; - } -} - -export function license_KeyContainer_SecurityLevelToJSON(object: License_KeyContainer_SecurityLevel): string { - switch (object) { - case License_KeyContainer_SecurityLevel.SW_SECURE_CRYPTO: - return 'SW_SECURE_CRYPTO'; - case License_KeyContainer_SecurityLevel.SW_SECURE_DECODE: - return 'SW_SECURE_DECODE'; - case License_KeyContainer_SecurityLevel.HW_SECURE_CRYPTO: - return 'HW_SECURE_CRYPTO'; - case License_KeyContainer_SecurityLevel.HW_SECURE_DECODE: - return 'HW_SECURE_DECODE'; - case License_KeyContainer_SecurityLevel.HW_SECURE_ALL: - return 'HW_SECURE_ALL'; - case License_KeyContainer_SecurityLevel.UNRECOGNIZED: - default: - return 'UNRECOGNIZED'; - } -} - -export interface License_KeyContainer_KeyControl { - /** - * |key_control| is documented in: - * Widevine Modular DRM Security Integration Guide for CENC - * If present, the key control must be communicated to the secure - * environment prior to any usage. This message is automatically generated - * by the Widevine License Server SDK. - */ - keyControlBlock: Buffer; - iv: Buffer; -} - -export interface License_KeyContainer_OutputProtection { - hdcp: License_KeyContainer_OutputProtection_HDCP; - cgmsFlags: License_KeyContainer_OutputProtection_CGMS; - hdcpSrmRule: License_KeyContainer_OutputProtection_HdcpSrmRule; - /** Optional requirement to indicate analog output is not allowed. */ - disableAnalogOutput: boolean; - /** Optional requirement to indicate digital output is not allowed. */ - disableDigitalOutput: boolean; -} - -/** - * Indicates whether HDCP is required on digital outputs, and which - * version should be used. - */ -export enum License_KeyContainer_OutputProtection_HDCP { - HDCP_NONE = 0, - HDCP_V1 = 1, - HDCP_V2 = 2, - HDCP_V2_1 = 3, - HDCP_V2_2 = 4, - HDCP_V2_3 = 5, - HDCP_NO_DIGITAL_OUTPUT = 255, - UNRECOGNIZED = -1 -} - -export function license_KeyContainer_OutputProtection_HDCPFromJSON(object: any): License_KeyContainer_OutputProtection_HDCP { - switch (object) { - case 0: - case 'HDCP_NONE': - return License_KeyContainer_OutputProtection_HDCP.HDCP_NONE; - case 1: - case 'HDCP_V1': - return License_KeyContainer_OutputProtection_HDCP.HDCP_V1; - case 2: - case 'HDCP_V2': - return License_KeyContainer_OutputProtection_HDCP.HDCP_V2; - case 3: - case 'HDCP_V2_1': - return License_KeyContainer_OutputProtection_HDCP.HDCP_V2_1; - case 4: - case 'HDCP_V2_2': - return License_KeyContainer_OutputProtection_HDCP.HDCP_V2_2; - case 5: - case 'HDCP_V2_3': - return License_KeyContainer_OutputProtection_HDCP.HDCP_V2_3; - case 255: - case 'HDCP_NO_DIGITAL_OUTPUT': - return License_KeyContainer_OutputProtection_HDCP.HDCP_NO_DIGITAL_OUTPUT; - case -1: - case 'UNRECOGNIZED': - default: - return License_KeyContainer_OutputProtection_HDCP.UNRECOGNIZED; - } -} - -export function license_KeyContainer_OutputProtection_HDCPToJSON(object: License_KeyContainer_OutputProtection_HDCP): string { - switch (object) { - case License_KeyContainer_OutputProtection_HDCP.HDCP_NONE: - return 'HDCP_NONE'; - case License_KeyContainer_OutputProtection_HDCP.HDCP_V1: - return 'HDCP_V1'; - case License_KeyContainer_OutputProtection_HDCP.HDCP_V2: - return 'HDCP_V2'; - case License_KeyContainer_OutputProtection_HDCP.HDCP_V2_1: - return 'HDCP_V2_1'; - case License_KeyContainer_OutputProtection_HDCP.HDCP_V2_2: - return 'HDCP_V2_2'; - case License_KeyContainer_OutputProtection_HDCP.HDCP_V2_3: - return 'HDCP_V2_3'; - case License_KeyContainer_OutputProtection_HDCP.HDCP_NO_DIGITAL_OUTPUT: - return 'HDCP_NO_DIGITAL_OUTPUT'; - case License_KeyContainer_OutputProtection_HDCP.UNRECOGNIZED: - default: - return 'UNRECOGNIZED'; - } -} - -/** Indicate the CGMS setting to be inserted on analog output. */ -export enum License_KeyContainer_OutputProtection_CGMS { - CGMS_NONE = 42, - COPY_FREE = 0, - COPY_ONCE = 2, - COPY_NEVER = 3, - UNRECOGNIZED = -1 -} - -export function license_KeyContainer_OutputProtection_CGMSFromJSON(object: any): License_KeyContainer_OutputProtection_CGMS { - switch (object) { - case 42: - case 'CGMS_NONE': - return License_KeyContainer_OutputProtection_CGMS.CGMS_NONE; - case 0: - case 'COPY_FREE': - return License_KeyContainer_OutputProtection_CGMS.COPY_FREE; - case 2: - case 'COPY_ONCE': - return License_KeyContainer_OutputProtection_CGMS.COPY_ONCE; - case 3: - case 'COPY_NEVER': - return License_KeyContainer_OutputProtection_CGMS.COPY_NEVER; - case -1: - case 'UNRECOGNIZED': - default: - return License_KeyContainer_OutputProtection_CGMS.UNRECOGNIZED; - } -} - -export function license_KeyContainer_OutputProtection_CGMSToJSON(object: License_KeyContainer_OutputProtection_CGMS): string { - switch (object) { - case License_KeyContainer_OutputProtection_CGMS.CGMS_NONE: - return 'CGMS_NONE'; - case License_KeyContainer_OutputProtection_CGMS.COPY_FREE: - return 'COPY_FREE'; - case License_KeyContainer_OutputProtection_CGMS.COPY_ONCE: - return 'COPY_ONCE'; - case License_KeyContainer_OutputProtection_CGMS.COPY_NEVER: - return 'COPY_NEVER'; - case License_KeyContainer_OutputProtection_CGMS.UNRECOGNIZED: - default: - return 'UNRECOGNIZED'; - } -} - -export enum License_KeyContainer_OutputProtection_HdcpSrmRule { - HDCP_SRM_RULE_NONE = 0, - /** - * CURRENT_SRM - In 'required_protection', this means most current SRM is required. - * Update the SRM on the device. If update cannot happen, - * do not allow the key. - * In 'requested_protection', this means most current SRM is requested. - * Update the SRM on the device. If update cannot happen, - * allow use of the key anyway. - */ - CURRENT_SRM = 1, - UNRECOGNIZED = -1 -} - -export function license_KeyContainer_OutputProtection_HdcpSrmRuleFromJSON(object: any): License_KeyContainer_OutputProtection_HdcpSrmRule { - switch (object) { - case 0: - case 'HDCP_SRM_RULE_NONE': - return License_KeyContainer_OutputProtection_HdcpSrmRule.HDCP_SRM_RULE_NONE; - case 1: - case 'CURRENT_SRM': - return License_KeyContainer_OutputProtection_HdcpSrmRule.CURRENT_SRM; - case -1: - case 'UNRECOGNIZED': - default: - return License_KeyContainer_OutputProtection_HdcpSrmRule.UNRECOGNIZED; - } -} - -export function license_KeyContainer_OutputProtection_HdcpSrmRuleToJSON(object: License_KeyContainer_OutputProtection_HdcpSrmRule): string { - switch (object) { - case License_KeyContainer_OutputProtection_HdcpSrmRule.HDCP_SRM_RULE_NONE: - return 'HDCP_SRM_RULE_NONE'; - case License_KeyContainer_OutputProtection_HdcpSrmRule.CURRENT_SRM: - return 'CURRENT_SRM'; - case License_KeyContainer_OutputProtection_HdcpSrmRule.UNRECOGNIZED: - default: - return 'UNRECOGNIZED'; - } -} - -export interface License_KeyContainer_VideoResolutionConstraint { - /** Minimum and maximum video resolutions in the range (height x width). */ - minResolutionPixels: number; - maxResolutionPixels: number; - /** - * Optional output protection requirements for this range. If not - * specified, the OutputProtection in the KeyContainer applies. - */ - requiredProtection: License_KeyContainer_OutputProtection | undefined; -} - -export interface License_KeyContainer_OperatorSessionKeyPermissions { - /** - * Permissions/key usage flags for operator service keys - * (type = OPERATOR_SESSION). - */ - allowEncrypt: boolean; - allowDecrypt: boolean; - allowSign: boolean; - allowSignatureVerify: boolean; -} - -export interface LicenseRequest { - /** - * The client_id provides information authenticating the calling device. It - * contains the Widevine keybox token that was installed on the device at the - * factory. This field or encrypted_client_id below is required for a valid - * license request, but both should never be present in the same request. - */ - clientId: ClientIdentification | undefined; - contentId: LicenseRequest_ContentIdentification | undefined; - type: LicenseRequest_RequestType; - /** Time of the request in seconds (UTC) as set by the client. */ - requestTime: Long; - /** Old-style decimal-encoded string key control nonce. */ - keyControlNonceDeprecated: Buffer; - protocolVersion: ProtocolVersion; - /** - * New-style uint32 key control nonce, please use instead of - * key_control_nonce_deprecated. - */ - keyControlNonce: number; - /** Encrypted ClientIdentification message, used for privacy purposes. */ - encryptedClientId: EncryptedClientIdentification | undefined; -} - -export enum LicenseRequest_RequestType { - NEW = 1, - RENEWAL = 2, - RELEASE = 3, - UNRECOGNIZED = -1 -} - -export function licenseRequest_RequestTypeFromJSON(object: any): LicenseRequest_RequestType { - switch (object) { - case 1: - case 'NEW': - return LicenseRequest_RequestType.NEW; - case 2: - case 'RENEWAL': - return LicenseRequest_RequestType.RENEWAL; - case 3: - case 'RELEASE': - return LicenseRequest_RequestType.RELEASE; - case -1: - case 'UNRECOGNIZED': - default: - return LicenseRequest_RequestType.UNRECOGNIZED; - } -} - -export function licenseRequest_RequestTypeToJSON(object: LicenseRequest_RequestType): string { - switch (object) { - case LicenseRequest_RequestType.NEW: - return 'NEW'; - case LicenseRequest_RequestType.RENEWAL: - return 'RENEWAL'; - case LicenseRequest_RequestType.RELEASE: - return 'RELEASE'; - case LicenseRequest_RequestType.UNRECOGNIZED: - default: - return 'UNRECOGNIZED'; - } -} - -export interface LicenseRequest_ContentIdentification { - /** Exactly one of these must be present. */ - widevinePsshData?: LicenseRequest_ContentIdentification_WidevinePsshData | undefined; - webmKeyId?: LicenseRequest_ContentIdentification_WebmKeyId | undefined; - existingLicense?: LicenseRequest_ContentIdentification_ExistingLicense | undefined; - initData?: LicenseRequest_ContentIdentification_InitData | undefined; -} - -export interface LicenseRequest_ContentIdentification_WidevinePsshData { - psshData: Buffer[]; - licenseType: LicenseType; - /** Opaque, client-specified. */ - requestId: Buffer; -} - -export interface LicenseRequest_ContentIdentification_WebmKeyId { - header: Buffer; - licenseType: LicenseType; - /** Opaque, client-specified. */ - requestId: Buffer; -} - -export interface LicenseRequest_ContentIdentification_ExistingLicense { - licenseId: LicenseIdentification | undefined; - secondsSinceStarted: Long; - secondsSinceLastPlayed: Long; - sessionUsageTableEntry: Buffer; -} - -export interface LicenseRequest_ContentIdentification_InitData { - initDataType: LicenseRequest_ContentIdentification_InitData_InitDataType; - initData: Buffer; - licenseType: LicenseType; - requestId: Buffer; -} - -export enum LicenseRequest_ContentIdentification_InitData_InitDataType { - CENC = 1, - WEBM = 2, - UNRECOGNIZED = -1 -} - -export function licenseRequest_ContentIdentification_InitData_InitDataTypeFromJSON( - object: any -): LicenseRequest_ContentIdentification_InitData_InitDataType { - switch (object) { - case 1: - case 'CENC': - return LicenseRequest_ContentIdentification_InitData_InitDataType.CENC; - case 2: - case 'WEBM': - return LicenseRequest_ContentIdentification_InitData_InitDataType.WEBM; - case -1: - case 'UNRECOGNIZED': - default: - return LicenseRequest_ContentIdentification_InitData_InitDataType.UNRECOGNIZED; - } -} - -export function licenseRequest_ContentIdentification_InitData_InitDataTypeToJSON( - object: LicenseRequest_ContentIdentification_InitData_InitDataType -): string { - switch (object) { - case LicenseRequest_ContentIdentification_InitData_InitDataType.CENC: - return 'CENC'; - case LicenseRequest_ContentIdentification_InitData_InitDataType.WEBM: - return 'WEBM'; - case LicenseRequest_ContentIdentification_InitData_InitDataType.UNRECOGNIZED: - default: - return 'UNRECOGNIZED'; - } -} - -export interface MetricData { - /** 'stage' that is currently processing the SignedMessage. Required. */ - stageName: string; - /** metric and associated value. */ - metricData: MetricData_TypeValue[]; -} - -export enum MetricData_MetricType { - /** LATENCY - The time spent in the 'stage', specified in microseconds. */ - LATENCY = 1, - /** - * TIMESTAMP - The UNIX epoch timestamp at which the 'stage' was first accessed in - * microseconds. - */ - TIMESTAMP = 2, - UNRECOGNIZED = -1 -} - -export function metricData_MetricTypeFromJSON(object: any): MetricData_MetricType { - switch (object) { - case 1: - case 'LATENCY': - return MetricData_MetricType.LATENCY; - case 2: - case 'TIMESTAMP': - return MetricData_MetricType.TIMESTAMP; - case -1: - case 'UNRECOGNIZED': - default: - return MetricData_MetricType.UNRECOGNIZED; - } -} - -export function metricData_MetricTypeToJSON(object: MetricData_MetricType): string { - switch (object) { - case MetricData_MetricType.LATENCY: - return 'LATENCY'; - case MetricData_MetricType.TIMESTAMP: - return 'TIMESTAMP'; - case MetricData_MetricType.UNRECOGNIZED: - default: - return 'UNRECOGNIZED'; - } -} - -export interface MetricData_TypeValue { - type: MetricData_MetricType; - /** - * The value associated with 'type'. For example if type == LATENCY, the - * value would be the time in microseconds spent in this 'stage'. - */ - value: Long; -} - -export interface VersionInfo { - /** - * License SDK version reported by the Widevine License SDK. This field - * is populated automatically by the SDK. - */ - licenseSdkVersion: string; - /** - * Version of the service hosting the license SDK. This field is optional. - * It may be provided by the hosting service. - */ - licenseServiceVersion: string; -} - -export interface SignedMessage { - type: SignedMessage_MessageType; - msg: Buffer; - /** - * Required field that contains the signature of the bytes of msg. - * For license requests, the signing algorithm is determined by the - * certificate contained in the request. - * For license responses, the signing algorithm is HMAC with signing key based - * on |session_key|. - */ - signature: Buffer; - /** - * If populated, the contents of this field will be signaled by the - * |session_key_type| type. If the |session_key_type| is WRAPPED_AES_KEY the - * key is the bytes of an encrypted AES key. If the |session_key_type| is - * EPHERMERAL_ECC_PUBLIC_KEY the field contains the bytes of an RFC5208 ASN1 - * serialized ECC public key. - */ - sessionKey: Buffer; - /** - * Remote attestation data which will be present in the initial license - * request for ChromeOS client devices operating in verified mode. Remote - * attestation challenge data is |msg| field above. Optional. - */ - remoteAttestation: Buffer; - metricData: MetricData[]; - /** - * Version information from the SDK and license service. This information is - * provided in the license response. - */ - serviceVersionInfo: VersionInfo | undefined; - /** - * Optional field that contains the algorithm type used to generate the - * session_key and signature in a LICENSE message. - */ - sessionKeyType: SignedMessage_SessionKeyType; - /** - * The core message is the simple serialization of fields used by OEMCrypto. - * This field was introduced in OEMCrypto API v16. - */ - oemcryptoCoreMessage: Buffer; -} - -export enum SignedMessage_MessageType { - LICENSE_REQUEST = 1, - LICENSE = 2, - ERROR_RESPONSE = 3, - SERVICE_CERTIFICATE_REQUEST = 4, - SERVICE_CERTIFICATE = 5, - SUB_LICENSE = 6, - CAS_LICENSE_REQUEST = 7, - CAS_LICENSE = 8, - EXTERNAL_LICENSE_REQUEST = 9, - EXTERNAL_LICENSE = 10, - UNRECOGNIZED = -1 -} - -export function signedMessage_MessageTypeFromJSON(object: any): SignedMessage_MessageType { - switch (object) { - case 1: - case 'LICENSE_REQUEST': - return SignedMessage_MessageType.LICENSE_REQUEST; - case 2: - case 'LICENSE': - return SignedMessage_MessageType.LICENSE; - case 3: - case 'ERROR_RESPONSE': - return SignedMessage_MessageType.ERROR_RESPONSE; - case 4: - case 'SERVICE_CERTIFICATE_REQUEST': - return SignedMessage_MessageType.SERVICE_CERTIFICATE_REQUEST; - case 5: - case 'SERVICE_CERTIFICATE': - return SignedMessage_MessageType.SERVICE_CERTIFICATE; - case 6: - case 'SUB_LICENSE': - return SignedMessage_MessageType.SUB_LICENSE; - case 7: - case 'CAS_LICENSE_REQUEST': - return SignedMessage_MessageType.CAS_LICENSE_REQUEST; - case 8: - case 'CAS_LICENSE': - return SignedMessage_MessageType.CAS_LICENSE; - case 9: - case 'EXTERNAL_LICENSE_REQUEST': - return SignedMessage_MessageType.EXTERNAL_LICENSE_REQUEST; - case 10: - case 'EXTERNAL_LICENSE': - return SignedMessage_MessageType.EXTERNAL_LICENSE; - case -1: - case 'UNRECOGNIZED': - default: - return SignedMessage_MessageType.UNRECOGNIZED; - } -} - -export function signedMessage_MessageTypeToJSON(object: SignedMessage_MessageType): string { - switch (object) { - case SignedMessage_MessageType.LICENSE_REQUEST: - return 'LICENSE_REQUEST'; - case SignedMessage_MessageType.LICENSE: - return 'LICENSE'; - case SignedMessage_MessageType.ERROR_RESPONSE: - return 'ERROR_RESPONSE'; - case SignedMessage_MessageType.SERVICE_CERTIFICATE_REQUEST: - return 'SERVICE_CERTIFICATE_REQUEST'; - case SignedMessage_MessageType.SERVICE_CERTIFICATE: - return 'SERVICE_CERTIFICATE'; - case SignedMessage_MessageType.SUB_LICENSE: - return 'SUB_LICENSE'; - case SignedMessage_MessageType.CAS_LICENSE_REQUEST: - return 'CAS_LICENSE_REQUEST'; - case SignedMessage_MessageType.CAS_LICENSE: - return 'CAS_LICENSE'; - case SignedMessage_MessageType.EXTERNAL_LICENSE_REQUEST: - return 'EXTERNAL_LICENSE_REQUEST'; - case SignedMessage_MessageType.EXTERNAL_LICENSE: - return 'EXTERNAL_LICENSE'; - case SignedMessage_MessageType.UNRECOGNIZED: - default: - return 'UNRECOGNIZED'; - } -} - -export enum SignedMessage_SessionKeyType { - UNDEFINED = 0, - WRAPPED_AES_KEY = 1, - EPHERMERAL_ECC_PUBLIC_KEY = 2, - UNRECOGNIZED = -1 -} - -export function signedMessage_SessionKeyTypeFromJSON(object: any): SignedMessage_SessionKeyType { - switch (object) { - case 0: - case 'UNDEFINED': - return SignedMessage_SessionKeyType.UNDEFINED; - case 1: - case 'WRAPPED_AES_KEY': - return SignedMessage_SessionKeyType.WRAPPED_AES_KEY; - case 2: - case 'EPHERMERAL_ECC_PUBLIC_KEY': - return SignedMessage_SessionKeyType.EPHERMERAL_ECC_PUBLIC_KEY; - case -1: - case 'UNRECOGNIZED': - default: - return SignedMessage_SessionKeyType.UNRECOGNIZED; - } -} - -export function signedMessage_SessionKeyTypeToJSON(object: SignedMessage_SessionKeyType): string { - switch (object) { - case SignedMessage_SessionKeyType.UNDEFINED: - return 'UNDEFINED'; - case SignedMessage_SessionKeyType.WRAPPED_AES_KEY: - return 'WRAPPED_AES_KEY'; - case SignedMessage_SessionKeyType.EPHERMERAL_ECC_PUBLIC_KEY: - return 'EPHERMERAL_ECC_PUBLIC_KEY'; - case SignedMessage_SessionKeyType.UNRECOGNIZED: - default: - return 'UNRECOGNIZED'; - } -} - -/** ClientIdentification message used to authenticate the client device. */ -export interface ClientIdentification { - /** Type of factory-provisioned device root of trust. Optional. */ - type: ClientIdentification_TokenType; - /** Factory-provisioned device root of trust. Required. */ - token: Buffer; - /** Optional client information name/value pairs. */ - clientInfo: ClientIdentification_NameValue[]; - /** Client token generated by the content provider. Optional. */ - providerClientToken: Buffer; - /** - * Number of licenses received by the client to which the token above belongs. - * Only present if client_token is specified. - */ - licenseCounter: number; - /** List of non-baseline client capabilities. */ - clientCapabilities: ClientIdentification_ClientCapabilities | undefined; - /** Serialized VmpData message. Optional. */ - vmpData: Buffer; - /** Optional field that may contain additional provisioning credentials. */ - deviceCredentials: ClientIdentification_ClientCredentials[]; -} - -export enum ClientIdentification_TokenType { - KEYBOX = 0, - DRM_DEVICE_CERTIFICATE = 1, - REMOTE_ATTESTATION_CERTIFICATE = 2, - OEM_DEVICE_CERTIFICATE = 3, - UNRECOGNIZED = -1 -} - -export function clientIdentification_TokenTypeFromJSON(object: any): ClientIdentification_TokenType { - switch (object) { - case 0: - case 'KEYBOX': - return ClientIdentification_TokenType.KEYBOX; - case 1: - case 'DRM_DEVICE_CERTIFICATE': - return ClientIdentification_TokenType.DRM_DEVICE_CERTIFICATE; - case 2: - case 'REMOTE_ATTESTATION_CERTIFICATE': - return ClientIdentification_TokenType.REMOTE_ATTESTATION_CERTIFICATE; - case 3: - case 'OEM_DEVICE_CERTIFICATE': - return ClientIdentification_TokenType.OEM_DEVICE_CERTIFICATE; - case -1: - case 'UNRECOGNIZED': - default: - return ClientIdentification_TokenType.UNRECOGNIZED; - } -} - -export function clientIdentification_TokenTypeToJSON(object: ClientIdentification_TokenType): string { - switch (object) { - case ClientIdentification_TokenType.KEYBOX: - return 'KEYBOX'; - case ClientIdentification_TokenType.DRM_DEVICE_CERTIFICATE: - return 'DRM_DEVICE_CERTIFICATE'; - case ClientIdentification_TokenType.REMOTE_ATTESTATION_CERTIFICATE: - return 'REMOTE_ATTESTATION_CERTIFICATE'; - case ClientIdentification_TokenType.OEM_DEVICE_CERTIFICATE: - return 'OEM_DEVICE_CERTIFICATE'; - case ClientIdentification_TokenType.UNRECOGNIZED: - default: - return 'UNRECOGNIZED'; - } -} - -export interface ClientIdentification_NameValue { - name: string; - value: string; -} - -/** - * Capabilities which not all clients may support. Used for the license - * exchange protocol only. - */ -export interface ClientIdentification_ClientCapabilities { - clientToken: boolean; - sessionToken: boolean; - videoResolutionConstraints: boolean; - maxHdcpVersion: ClientIdentification_ClientCapabilities_HdcpVersion; - oemCryptoApiVersion: number; - /** - * Client has hardware support for protecting the usage table, such as - * storing the generation number in secure memory. For Details, see: - * Widevine Modular DRM Security Integration Guide for CENC - */ - antiRollbackUsageTable: boolean; - /** The client shall report |srm_version| if available. */ - srmVersion: number; - /** - * A device may have SRM data, and report a version, but may not be capable - * of updating SRM data. - */ - canUpdateSrm: boolean; - supportedCertificateKeyType: ClientIdentification_ClientCapabilities_CertificateKeyType[]; - analogOutputCapabilities: ClientIdentification_ClientCapabilities_AnalogOutputCapabilities; - canDisableAnalogOutput: boolean; - /** - * Clients can indicate a performance level supported by OEMCrypto. - * This will allow applications and providers to choose an appropriate - * quality of content to serve. Currently defined tiers are - * 1 (low), 2 (medium) and 3 (high). Any other value indicates that - * the resource rating is unavailable or reporting erroneous values - * for that device. For details see, - * Widevine Modular DRM Security Integration Guide for CENC - */ - resourceRatingTier: number; -} - -export enum ClientIdentification_ClientCapabilities_HdcpVersion { - HDCP_NONE = 0, - HDCP_V1 = 1, - HDCP_V2 = 2, - HDCP_V2_1 = 3, - HDCP_V2_2 = 4, - HDCP_V2_3 = 5, - HDCP_NO_DIGITAL_OUTPUT = 255, - UNRECOGNIZED = -1 -} - -export function clientIdentification_ClientCapabilities_HdcpVersionFromJSON(object: any): ClientIdentification_ClientCapabilities_HdcpVersion { - switch (object) { - case 0: - case 'HDCP_NONE': - return ClientIdentification_ClientCapabilities_HdcpVersion.HDCP_NONE; - case 1: - case 'HDCP_V1': - return ClientIdentification_ClientCapabilities_HdcpVersion.HDCP_V1; - case 2: - case 'HDCP_V2': - return ClientIdentification_ClientCapabilities_HdcpVersion.HDCP_V2; - case 3: - case 'HDCP_V2_1': - return ClientIdentification_ClientCapabilities_HdcpVersion.HDCP_V2_1; - case 4: - case 'HDCP_V2_2': - return ClientIdentification_ClientCapabilities_HdcpVersion.HDCP_V2_2; - case 5: - case 'HDCP_V2_3': - return ClientIdentification_ClientCapabilities_HdcpVersion.HDCP_V2_3; - case 255: - case 'HDCP_NO_DIGITAL_OUTPUT': - return ClientIdentification_ClientCapabilities_HdcpVersion.HDCP_NO_DIGITAL_OUTPUT; - case -1: - case 'UNRECOGNIZED': - default: - return ClientIdentification_ClientCapabilities_HdcpVersion.UNRECOGNIZED; - } -} - -export function clientIdentification_ClientCapabilities_HdcpVersionToJSON(object: ClientIdentification_ClientCapabilities_HdcpVersion): string { - switch (object) { - case ClientIdentification_ClientCapabilities_HdcpVersion.HDCP_NONE: - return 'HDCP_NONE'; - case ClientIdentification_ClientCapabilities_HdcpVersion.HDCP_V1: - return 'HDCP_V1'; - case ClientIdentification_ClientCapabilities_HdcpVersion.HDCP_V2: - return 'HDCP_V2'; - case ClientIdentification_ClientCapabilities_HdcpVersion.HDCP_V2_1: - return 'HDCP_V2_1'; - case ClientIdentification_ClientCapabilities_HdcpVersion.HDCP_V2_2: - return 'HDCP_V2_2'; - case ClientIdentification_ClientCapabilities_HdcpVersion.HDCP_V2_3: - return 'HDCP_V2_3'; - case ClientIdentification_ClientCapabilities_HdcpVersion.HDCP_NO_DIGITAL_OUTPUT: - return 'HDCP_NO_DIGITAL_OUTPUT'; - case ClientIdentification_ClientCapabilities_HdcpVersion.UNRECOGNIZED: - default: - return 'UNRECOGNIZED'; - } -} - -export enum ClientIdentification_ClientCapabilities_CertificateKeyType { - RSA_2048 = 0, - RSA_3072 = 1, - ECC_SECP256R1 = 2, - ECC_SECP384R1 = 3, - ECC_SECP521R1 = 4, - UNRECOGNIZED = -1 -} - -export function clientIdentification_ClientCapabilities_CertificateKeyTypeFromJSON( - object: any -): ClientIdentification_ClientCapabilities_CertificateKeyType { - switch (object) { - case 0: - case 'RSA_2048': - return ClientIdentification_ClientCapabilities_CertificateKeyType.RSA_2048; - case 1: - case 'RSA_3072': - return ClientIdentification_ClientCapabilities_CertificateKeyType.RSA_3072; - case 2: - case 'ECC_SECP256R1': - return ClientIdentification_ClientCapabilities_CertificateKeyType.ECC_SECP256R1; - case 3: - case 'ECC_SECP384R1': - return ClientIdentification_ClientCapabilities_CertificateKeyType.ECC_SECP384R1; - case 4: - case 'ECC_SECP521R1': - return ClientIdentification_ClientCapabilities_CertificateKeyType.ECC_SECP521R1; - case -1: - case 'UNRECOGNIZED': - default: - return ClientIdentification_ClientCapabilities_CertificateKeyType.UNRECOGNIZED; - } -} - -export function clientIdentification_ClientCapabilities_CertificateKeyTypeToJSON( - object: ClientIdentification_ClientCapabilities_CertificateKeyType -): string { - switch (object) { - case ClientIdentification_ClientCapabilities_CertificateKeyType.RSA_2048: - return 'RSA_2048'; - case ClientIdentification_ClientCapabilities_CertificateKeyType.RSA_3072: - return 'RSA_3072'; - case ClientIdentification_ClientCapabilities_CertificateKeyType.ECC_SECP256R1: - return 'ECC_SECP256R1'; - case ClientIdentification_ClientCapabilities_CertificateKeyType.ECC_SECP384R1: - return 'ECC_SECP384R1'; - case ClientIdentification_ClientCapabilities_CertificateKeyType.ECC_SECP521R1: - return 'ECC_SECP521R1'; - case ClientIdentification_ClientCapabilities_CertificateKeyType.UNRECOGNIZED: - default: - return 'UNRECOGNIZED'; - } -} - -export enum ClientIdentification_ClientCapabilities_AnalogOutputCapabilities { - ANALOG_OUTPUT_UNKNOWN = 0, - ANALOG_OUTPUT_NONE = 1, - ANALOG_OUTPUT_SUPPORTED = 2, - ANALOG_OUTPUT_SUPPORTS_CGMS_A = 3, - UNRECOGNIZED = -1 -} - -export function clientIdentification_ClientCapabilities_AnalogOutputCapabilitiesFromJSON( - object: any -): ClientIdentification_ClientCapabilities_AnalogOutputCapabilities { - switch (object) { - case 0: - case 'ANALOG_OUTPUT_UNKNOWN': - return ClientIdentification_ClientCapabilities_AnalogOutputCapabilities.ANALOG_OUTPUT_UNKNOWN; - case 1: - case 'ANALOG_OUTPUT_NONE': - return ClientIdentification_ClientCapabilities_AnalogOutputCapabilities.ANALOG_OUTPUT_NONE; - case 2: - case 'ANALOG_OUTPUT_SUPPORTED': - return ClientIdentification_ClientCapabilities_AnalogOutputCapabilities.ANALOG_OUTPUT_SUPPORTED; - case 3: - case 'ANALOG_OUTPUT_SUPPORTS_CGMS_A': - return ClientIdentification_ClientCapabilities_AnalogOutputCapabilities.ANALOG_OUTPUT_SUPPORTS_CGMS_A; - case -1: - case 'UNRECOGNIZED': - default: - return ClientIdentification_ClientCapabilities_AnalogOutputCapabilities.UNRECOGNIZED; - } -} - -export function clientIdentification_ClientCapabilities_AnalogOutputCapabilitiesToJSON( - object: ClientIdentification_ClientCapabilities_AnalogOutputCapabilities -): string { - switch (object) { - case ClientIdentification_ClientCapabilities_AnalogOutputCapabilities.ANALOG_OUTPUT_UNKNOWN: - return 'ANALOG_OUTPUT_UNKNOWN'; - case ClientIdentification_ClientCapabilities_AnalogOutputCapabilities.ANALOG_OUTPUT_NONE: - return 'ANALOG_OUTPUT_NONE'; - case ClientIdentification_ClientCapabilities_AnalogOutputCapabilities.ANALOG_OUTPUT_SUPPORTED: - return 'ANALOG_OUTPUT_SUPPORTED'; - case ClientIdentification_ClientCapabilities_AnalogOutputCapabilities.ANALOG_OUTPUT_SUPPORTS_CGMS_A: - return 'ANALOG_OUTPUT_SUPPORTS_CGMS_A'; - case ClientIdentification_ClientCapabilities_AnalogOutputCapabilities.UNRECOGNIZED: - default: - return 'UNRECOGNIZED'; - } -} - -export interface ClientIdentification_ClientCredentials { - type: ClientIdentification_TokenType; - token: Buffer; -} - -/** - * EncryptedClientIdentification message used to hold ClientIdentification - * messages encrypted for privacy purposes. - */ -export interface EncryptedClientIdentification { - /** - * Provider ID for which the ClientIdentifcation is encrypted (owner of - * service certificate). - */ - providerId: string; - /** - * Serial number for the service certificate for which ClientIdentification is - * encrypted. - */ - serviceCertificateSerialNumber: Buffer; - /** - * Serialized ClientIdentification message, encrypted with the privacy key - * using AES-128-CBC with PKCS#5 padding. - */ - encryptedClientId: Buffer; - /** Initialization vector needed to decrypt encrypted_client_id. */ - encryptedClientIdIv: Buffer; - /** AES-128 privacy key, encrypted with the service public key using RSA-OAEP. */ - encryptedPrivacyKey: Buffer; -} - -/** - * DRM certificate definition for user devices, intermediate, service, and root - * certificates. - */ -export interface DrmCertificate { - /** Type of certificate. Required. */ - type: DrmCertificate_Type; - /** - * 128-bit globally unique serial number of certificate. - * Value is 0 for root certificate. Required. - */ - serialNumber: Buffer; - /** POSIX time, in seconds, when the certificate was created. Required. */ - creationTimeSeconds: number; - /** - * POSIX time, in seconds, when the certificate should expire. Value of zero - * denotes indefinite expiry time. For more information on limited lifespan - * DRM certificates see (go/limited-lifespan-drm-certificates). - */ - expirationTimeSeconds: number; - /** Device public key. PKCS#1 ASN.1 DER-encoded. Required. */ - publicKey: Buffer; - /** - * Widevine system ID for the device. Required for intermediate and - * user device certificates. - */ - systemId: number; - /** - * Deprecated field, which used to indicate whether the device was a test - * (non-production) device. The test_device field in ProvisionedDeviceInfo - * below should be observed instead. - * - * @deprecated - */ - testDeviceDeprecated: boolean; - /** - * Service identifier (web origin) for the provider which owns the - * certificate. Required for service and provisioner certificates. - */ - providerId: string; - /** - * This field is used only when type = SERVICE to specify which SDK uses - * service certificate. This repeated field is treated as a set. A certificate - * may be used for the specified service SDK if the appropriate ServiceType - * is specified in this field. - */ - serviceTypes: DrmCertificate_ServiceType[]; - /** - * Required. The algorithm field contains the curve used to create the - * |public_key| if algorithm is one of the ECC types. - * The |algorithm| is used for both to determine the if the certificate is ECC - * or RSA. The |algorithm| also specifies the parameters that were used to - * create |public_key| and are used to create an ephemeral session key. - */ - algorithm: DrmCertificate_Algorithm; - /** - * Optional. May be present in DEVICE certificate types. This is the root - * of trust identifier that holds an encrypted value that identifies the - * keybox or other root of trust that was used to provision a DEVICE drm - * certificate. - */ - rotId: Buffer; - /** - * Optional. May be present in devices that explicitly support dual keys. When - * present the |public_key| is used for verification of received license - * request messages. - */ - encryptionKey: DrmCertificate_EncryptionKey | undefined; -} - -export enum DrmCertificate_Type { - /** ROOT - ProtoBestPractices: ignore. */ - ROOT = 0, - DEVICE_MODEL = 1, - DEVICE = 2, - SERVICE = 3, - PROVISIONER = 4, - UNRECOGNIZED = -1 -} - -export function drmCertificate_TypeFromJSON(object: any): DrmCertificate_Type { - switch (object) { - case 0: - case 'ROOT': - return DrmCertificate_Type.ROOT; - case 1: - case 'DEVICE_MODEL': - return DrmCertificate_Type.DEVICE_MODEL; - case 2: - case 'DEVICE': - return DrmCertificate_Type.DEVICE; - case 3: - case 'SERVICE': - return DrmCertificate_Type.SERVICE; - case 4: - case 'PROVISIONER': - return DrmCertificate_Type.PROVISIONER; - case -1: - case 'UNRECOGNIZED': - default: - return DrmCertificate_Type.UNRECOGNIZED; - } -} - -export function drmCertificate_TypeToJSON(object: DrmCertificate_Type): string { - switch (object) { - case DrmCertificate_Type.ROOT: - return 'ROOT'; - case DrmCertificate_Type.DEVICE_MODEL: - return 'DEVICE_MODEL'; - case DrmCertificate_Type.DEVICE: - return 'DEVICE'; - case DrmCertificate_Type.SERVICE: - return 'SERVICE'; - case DrmCertificate_Type.PROVISIONER: - return 'PROVISIONER'; - case DrmCertificate_Type.UNRECOGNIZED: - default: - return 'UNRECOGNIZED'; - } -} - -export enum DrmCertificate_ServiceType { - UNKNOWN_SERVICE_TYPE = 0, - LICENSE_SERVER_SDK = 1, - LICENSE_SERVER_PROXY_SDK = 2, - PROVISIONING_SDK = 3, - CAS_PROXY_SDK = 4, - UNRECOGNIZED = -1 -} - -export function drmCertificate_ServiceTypeFromJSON(object: any): DrmCertificate_ServiceType { - switch (object) { - case 0: - case 'UNKNOWN_SERVICE_TYPE': - return DrmCertificate_ServiceType.UNKNOWN_SERVICE_TYPE; - case 1: - case 'LICENSE_SERVER_SDK': - return DrmCertificate_ServiceType.LICENSE_SERVER_SDK; - case 2: - case 'LICENSE_SERVER_PROXY_SDK': - return DrmCertificate_ServiceType.LICENSE_SERVER_PROXY_SDK; - case 3: - case 'PROVISIONING_SDK': - return DrmCertificate_ServiceType.PROVISIONING_SDK; - case 4: - case 'CAS_PROXY_SDK': - return DrmCertificate_ServiceType.CAS_PROXY_SDK; - case -1: - case 'UNRECOGNIZED': - default: - return DrmCertificate_ServiceType.UNRECOGNIZED; - } -} - -export function drmCertificate_ServiceTypeToJSON(object: DrmCertificate_ServiceType): string { - switch (object) { - case DrmCertificate_ServiceType.UNKNOWN_SERVICE_TYPE: - return 'UNKNOWN_SERVICE_TYPE'; - case DrmCertificate_ServiceType.LICENSE_SERVER_SDK: - return 'LICENSE_SERVER_SDK'; - case DrmCertificate_ServiceType.LICENSE_SERVER_PROXY_SDK: - return 'LICENSE_SERVER_PROXY_SDK'; - case DrmCertificate_ServiceType.PROVISIONING_SDK: - return 'PROVISIONING_SDK'; - case DrmCertificate_ServiceType.CAS_PROXY_SDK: - return 'CAS_PROXY_SDK'; - case DrmCertificate_ServiceType.UNRECOGNIZED: - default: - return 'UNRECOGNIZED'; - } -} - -export enum DrmCertificate_Algorithm { - UNKNOWN_ALGORITHM = 0, - RSA = 1, - ECC_SECP256R1 = 2, - ECC_SECP384R1 = 3, - ECC_SECP521R1 = 4, - UNRECOGNIZED = -1 -} - -export function drmCertificate_AlgorithmFromJSON(object: any): DrmCertificate_Algorithm { - switch (object) { - case 0: - case 'UNKNOWN_ALGORITHM': - return DrmCertificate_Algorithm.UNKNOWN_ALGORITHM; - case 1: - case 'RSA': - return DrmCertificate_Algorithm.RSA; - case 2: - case 'ECC_SECP256R1': - return DrmCertificate_Algorithm.ECC_SECP256R1; - case 3: - case 'ECC_SECP384R1': - return DrmCertificate_Algorithm.ECC_SECP384R1; - case 4: - case 'ECC_SECP521R1': - return DrmCertificate_Algorithm.ECC_SECP521R1; - case -1: - case 'UNRECOGNIZED': - default: - return DrmCertificate_Algorithm.UNRECOGNIZED; - } -} - -export function drmCertificate_AlgorithmToJSON(object: DrmCertificate_Algorithm): string { - switch (object) { - case DrmCertificate_Algorithm.UNKNOWN_ALGORITHM: - return 'UNKNOWN_ALGORITHM'; - case DrmCertificate_Algorithm.RSA: - return 'RSA'; - case DrmCertificate_Algorithm.ECC_SECP256R1: - return 'ECC_SECP256R1'; - case DrmCertificate_Algorithm.ECC_SECP384R1: - return 'ECC_SECP384R1'; - case DrmCertificate_Algorithm.ECC_SECP521R1: - return 'ECC_SECP521R1'; - case DrmCertificate_Algorithm.UNRECOGNIZED: - default: - return 'UNRECOGNIZED'; - } -} - -export interface DrmCertificate_EncryptionKey { - /** Device public key. PKCS#1 ASN.1 DER-encoded. Required. */ - publicKey: Buffer; - /** - * Required. The algorithm field contains the curve used to create the - * |public_key| if algorithm is one of the ECC types. - * The |algorithm| is used for both to determine the if the certificate is - * ECC or RSA. The |algorithm| also specifies the parameters that were used - * to create |public_key| and are used to create an ephemeral session key. - */ - algorithm: DrmCertificate_Algorithm; -} - -/** DrmCertificate signed by a higher (CA) DRM certificate. */ -export interface SignedDrmCertificate { - /** Serialized certificate. Required. */ - drmCertificate: Buffer; - /** - * Signature of certificate. Signed with root or intermediate - * certificate specified below. Required. - */ - signature: Buffer; - /** SignedDrmCertificate used to sign this certificate. */ - signer: SignedDrmCertificate | undefined; - /** Optional field that indicates the hash algorithm used in signature scheme. */ - hashAlgorithm: HashAlgorithmProto; -} - -export interface WidevinePsshData { - /** - * Entitlement or content key IDs. Can onnly present in SINGLE or ENTITLEMENT - * PSSHs. May be repeated to facilitate delivery of multiple keys in a - * single license. Cannot be used in conjunction with content_id or - * group_ids, which are the preferred mechanism. - */ - keyIds: Buffer[]; - /** - * Content identifier which may map to multiple entitlement or content key - * IDs to facilitate the delivery of multiple keys in a single license. - * Cannot be present in conjunction with key_ids, but if used must be in all - * PSSHs. - */ - contentId: Buffer; - /** - * Crypto period index, for media using key rotation. Always corresponds to - * The content key period. This means that if using entitlement licensing - * the ENTITLED_KEY PSSHs will have sequential crypto_period_index's, whereas - * the ENTITELEMENT PSSHs will have gaps in the sequence. Required if doing - * key rotation. - */ - cryptoPeriodIndex: number; - /** - * Protection scheme identifying the encryption algorithm. The protection - * scheme is represented as a uint32 value. The uint32 contains 4 bytes each - * representing a single ascii character in one of the 4CC protection scheme - * values. To be deprecated in favor of signaling from content. - * 'cenc' (AES-CTR) protection_scheme = 0x63656E63, - * 'cbc1' (AES-CBC) protection_scheme = 0x63626331, - * 'cens' (AES-CTR pattern encryption) protection_scheme = 0x63656E73, - * 'cbcs' (AES-CBC pattern encryption) protection_scheme = 0x63626373. - */ - protectionScheme: number; - /** - * Optional. For media using key rotation, this represents the duration - * of each crypto period in seconds. - */ - cryptoPeriodSeconds: number; - /** Type of PSSH. Required if not SINGLE. */ - type: WidevinePsshData_Type; - /** Key sequence for Widevine-managed keys. Optional. */ - keySequence: number; - /** - * Group identifiers for all groups to which the content belongs. This can - * be used to deliver licenses to unlock multiple titles / channels. - * Optional, and may only be present in ENTITLEMENT and ENTITLED_KEY PSSHs, and - * not in conjunction with key_ids. - */ - groupIds: Buffer[]; - /** - * Copy/copies of the content key used to decrypt the media stream in which - * the PSSH box is embedded, each wrapped with a different entitlement key. - * May also contain sub-licenses to support devices with OEMCrypto 13 or - * older. May be repeated if using group entitlement keys. Present only in - * PSSHs of type ENTITLED_KEY. - */ - entitledKeys: WidevinePsshData_EntitledKey[]; - /** - * Video feature identifier, which is used in conjunction with |content_id| - * to determine the set of keys to be returned in the license. Cannot be - * present in conjunction with |key_ids|. - * Current values are "HDR". - */ - videoFeature: string; - /** @deprecated */ - algorithm: WidevinePsshData_Algorithm; - /** - * Content provider name. - * - * @deprecated - */ - provider: string; - /** - * Track type. Acceptable values are SD, HD and AUDIO. Used to - * differentiate content keys used by an asset. - * - * @deprecated - */ - trackType: string; - /** - * The name of a registered policy to be used for this asset. - * - * @deprecated - */ - policy: string; - /** - * Optional protected context for group content. The grouped_license is a - * serialized SignedMessage. - * - * @deprecated - */ - groupedLicense: Buffer; -} - -export enum WidevinePsshData_Type { - /** SINGLE - Single PSSH to be used to retrieve content keys. */ - SINGLE = 0, - /** ENTITLEMENT - Primary PSSH used to retrieve entitlement keys. */ - ENTITLEMENT = 1, - /** ENTITLED_KEY - Secondary PSSH containing entitled key(s). */ - ENTITLED_KEY = 2, - UNRECOGNIZED = -1 -} - -export function widevinePsshData_TypeFromJSON(object: any): WidevinePsshData_Type { - switch (object) { - case 0: - case 'SINGLE': - return WidevinePsshData_Type.SINGLE; - case 1: - case 'ENTITLEMENT': - return WidevinePsshData_Type.ENTITLEMENT; - case 2: - case 'ENTITLED_KEY': - return WidevinePsshData_Type.ENTITLED_KEY; - case -1: - case 'UNRECOGNIZED': - default: - return WidevinePsshData_Type.UNRECOGNIZED; - } -} - -export function widevinePsshData_TypeToJSON(object: WidevinePsshData_Type): string { - switch (object) { - case WidevinePsshData_Type.SINGLE: - return 'SINGLE'; - case WidevinePsshData_Type.ENTITLEMENT: - return 'ENTITLEMENT'; - case WidevinePsshData_Type.ENTITLED_KEY: - return 'ENTITLED_KEY'; - case WidevinePsshData_Type.UNRECOGNIZED: - default: - return 'UNRECOGNIZED'; - } -} - -/** ////////////////////////// Deprecated Fields //////////////////////////// */ -export enum WidevinePsshData_Algorithm { - UNENCRYPTED = 0, - AESCTR = 1, - UNRECOGNIZED = -1 -} - -export function widevinePsshData_AlgorithmFromJSON(object: any): WidevinePsshData_Algorithm { - switch (object) { - case 0: - case 'UNENCRYPTED': - return WidevinePsshData_Algorithm.UNENCRYPTED; - case 1: - case 'AESCTR': - return WidevinePsshData_Algorithm.AESCTR; - case -1: - case 'UNRECOGNIZED': - default: - return WidevinePsshData_Algorithm.UNRECOGNIZED; - } -} - -export function widevinePsshData_AlgorithmToJSON(object: WidevinePsshData_Algorithm): string { - switch (object) { - case WidevinePsshData_Algorithm.UNENCRYPTED: - return 'UNENCRYPTED'; - case WidevinePsshData_Algorithm.AESCTR: - return 'AESCTR'; - case WidevinePsshData_Algorithm.UNRECOGNIZED: - default: - return 'UNRECOGNIZED'; - } -} - -export interface WidevinePsshData_EntitledKey { - /** ID of entitlement key used for wrapping |key|. */ - entitlementKeyId: Buffer; - /** ID of the entitled key. */ - keyId: Buffer; - /** Wrapped key. Required. */ - key: Buffer; - /** IV used for wrapping |key|. Required. */ - iv: Buffer; - /** Size of entitlement key used for wrapping |key|. */ - entitlementKeySizeBytes: number; -} - -/** File Hashes for Verified Media Path (VMP) support. */ -export interface FileHashes { - signer: Buffer; - signatures: FileHashes_Signature[]; -} - -export interface FileHashes_Signature { - filename: string; - /** 0 - release, 1 - testing */ - testSigning: boolean; - SHA512Hash: Buffer; - /** 0 for dlls, 1 for exe, this is field 3 in file */ - mainExe: boolean; - signature: Buffer; -} - -function createBaseLicenseIdentification(): LicenseIdentification { - return { - requestId: Buffer.alloc(0), - sessionId: Buffer.alloc(0), - purchaseId: Buffer.alloc(0), - type: 1, - version: 0, - providerSessionToken: Buffer.alloc(0) - }; -} - -export const LicenseIdentification = { - encode(message: LicenseIdentification, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { - if (message.requestId.length !== 0) { - writer.uint32(10).bytes(message.requestId); - } - if (message.sessionId.length !== 0) { - writer.uint32(18).bytes(message.sessionId); - } - if (message.purchaseId.length !== 0) { - writer.uint32(26).bytes(message.purchaseId); - } - if (message.type !== 1) { - writer.uint32(32).int32(message.type); - } - if (message.version !== 0) { - writer.uint32(40).int32(message.version); - } - if (message.providerSessionToken.length !== 0) { - writer.uint32(50).bytes(message.providerSessionToken); - } - return writer; - }, - - decode(input: _m0.Reader | Uint8Array, length?: number): LicenseIdentification { - const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); - const end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseLicenseIdentification(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - message.requestId = reader.bytes() as Buffer; - break; - case 2: - message.sessionId = reader.bytes() as Buffer; - break; - case 3: - message.purchaseId = reader.bytes() as Buffer; - break; - case 4: - message.type = reader.int32() as any; - break; - case 5: - message.version = reader.int32(); - break; - case 6: - message.providerSessionToken = reader.bytes() as Buffer; - break; - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }, - - fromJSON(object: any): LicenseIdentification { - return { - requestId: isSet(object.requestId) ? Buffer.from(bytesFromBase64(object.requestId)) : Buffer.alloc(0), - sessionId: isSet(object.sessionId) ? Buffer.from(bytesFromBase64(object.sessionId)) : Buffer.alloc(0), - purchaseId: isSet(object.purchaseId) ? Buffer.from(bytesFromBase64(object.purchaseId)) : Buffer.alloc(0), - type: isSet(object.type) ? licenseTypeFromJSON(object.type) : 1, - version: isSet(object.version) ? Number(object.version) : 0, - providerSessionToken: isSet(object.providerSessionToken) ? Buffer.from(bytesFromBase64(object.providerSessionToken)) : Buffer.alloc(0) - }; - }, - - toJSON(message: LicenseIdentification): unknown { - const obj: any = {}; - message.requestId !== undefined && (obj.requestId = base64FromBytes(message.requestId !== undefined ? message.requestId : Buffer.alloc(0))); - message.sessionId !== undefined && (obj.sessionId = base64FromBytes(message.sessionId !== undefined ? message.sessionId : Buffer.alloc(0))); - message.purchaseId !== undefined && (obj.purchaseId = base64FromBytes(message.purchaseId !== undefined ? message.purchaseId : Buffer.alloc(0))); - message.type !== undefined && (obj.type = licenseTypeToJSON(message.type)); - message.version !== undefined && (obj.version = Math.round(message.version)); - message.providerSessionToken !== undefined && - (obj.providerSessionToken = base64FromBytes(message.providerSessionToken !== undefined ? message.providerSessionToken : Buffer.alloc(0))); - return obj; - }, - - fromPartial, I>>(object: I): LicenseIdentification { - const message = createBaseLicenseIdentification(); - message.requestId = object.requestId ?? Buffer.alloc(0); - message.sessionId = object.sessionId ?? Buffer.alloc(0); - message.purchaseId = object.purchaseId ?? Buffer.alloc(0); - message.type = object.type ?? 1; - message.version = object.version ?? 0; - message.providerSessionToken = object.providerSessionToken ?? Buffer.alloc(0); - return message; - } -}; - -function createBaseLicense(): License { - return { - id: undefined, - policy: undefined, - key: [], - licenseStartTime: Long.ZERO, - remoteAttestationVerified: false, - providerClientToken: Buffer.alloc(0), - protectionScheme: 0, - srmRequirement: Buffer.alloc(0), - srmUpdate: Buffer.alloc(0), - platformVerificationStatus: 0, - groupIds: [] - }; -} - -export const License = { - encode(message: License, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { - if (message.id !== undefined) { - LicenseIdentification.encode(message.id, writer.uint32(10).fork()).ldelim(); - } - if (message.policy !== undefined) { - License_Policy.encode(message.policy, writer.uint32(18).fork()).ldelim(); - } - for (const v of message.key) { - License_KeyContainer.encode(v!, writer.uint32(26).fork()).ldelim(); - } - if (!message.licenseStartTime.isZero()) { - writer.uint32(32).int64(message.licenseStartTime); - } - if (message.remoteAttestationVerified === true) { - writer.uint32(40).bool(message.remoteAttestationVerified); - } - if (message.providerClientToken.length !== 0) { - writer.uint32(50).bytes(message.providerClientToken); - } - if (message.protectionScheme !== 0) { - writer.uint32(56).uint32(message.protectionScheme); - } - if (message.srmRequirement.length !== 0) { - writer.uint32(66).bytes(message.srmRequirement); - } - if (message.srmUpdate.length !== 0) { - writer.uint32(74).bytes(message.srmUpdate); - } - if (message.platformVerificationStatus !== 0) { - writer.uint32(80).int32(message.platformVerificationStatus); - } - for (const v of message.groupIds) { - writer.uint32(90).bytes(v!); - } - return writer; - }, - - decode(input: _m0.Reader | Uint8Array, length?: number): License { - const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); - const end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseLicense(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - message.id = LicenseIdentification.decode(reader, reader.uint32()); - break; - case 2: - message.policy = License_Policy.decode(reader, reader.uint32()); - break; - case 3: - message.key.push(License_KeyContainer.decode(reader, reader.uint32())); - break; - case 4: - message.licenseStartTime = reader.int64() as Long; - break; - case 5: - message.remoteAttestationVerified = reader.bool(); - break; - case 6: - message.providerClientToken = reader.bytes() as Buffer; - break; - case 7: - message.protectionScheme = reader.uint32(); - break; - case 8: - message.srmRequirement = reader.bytes() as Buffer; - break; - case 9: - message.srmUpdate = reader.bytes() as Buffer; - break; - case 10: - message.platformVerificationStatus = reader.int32() as any; - break; - case 11: - message.groupIds.push(reader.bytes() as Buffer); - break; - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }, - - fromJSON(object: any): License { - return { - id: isSet(object.id) ? LicenseIdentification.fromJSON(object.id) : undefined, - policy: isSet(object.policy) ? License_Policy.fromJSON(object.policy) : undefined, - key: Array.isArray(object?.key) ? object.key.map((e: any) => License_KeyContainer.fromJSON(e)) : [], - licenseStartTime: isSet(object.licenseStartTime) ? Long.fromValue(object.licenseStartTime) : Long.ZERO, - remoteAttestationVerified: isSet(object.remoteAttestationVerified) ? Boolean(object.remoteAttestationVerified) : false, - providerClientToken: isSet(object.providerClientToken) ? Buffer.from(bytesFromBase64(object.providerClientToken)) : Buffer.alloc(0), - protectionScheme: isSet(object.protectionScheme) ? Number(object.protectionScheme) : 0, - srmRequirement: isSet(object.srmRequirement) ? Buffer.from(bytesFromBase64(object.srmRequirement)) : Buffer.alloc(0), - srmUpdate: isSet(object.srmUpdate) ? Buffer.from(bytesFromBase64(object.srmUpdate)) : Buffer.alloc(0), - platformVerificationStatus: isSet(object.platformVerificationStatus) - ? platformVerificationStatusFromJSON(object.platformVerificationStatus) - : 0, - groupIds: Array.isArray(object?.groupIds) ? object.groupIds.map((e: any) => Buffer.from(bytesFromBase64(e))) : [] - }; - }, - - toJSON(message: License): unknown { - const obj: any = {}; - message.id !== undefined && (obj.id = message.id ? LicenseIdentification.toJSON(message.id) : undefined); - message.policy !== undefined && (obj.policy = message.policy ? License_Policy.toJSON(message.policy) : undefined); - if (message.key) { - obj.key = message.key.map((e) => (e ? License_KeyContainer.toJSON(e) : undefined)); - } else { - obj.key = []; - } - message.licenseStartTime !== undefined && (obj.licenseStartTime = (message.licenseStartTime || Long.ZERO).toString()); - message.remoteAttestationVerified !== undefined && (obj.remoteAttestationVerified = message.remoteAttestationVerified); - message.providerClientToken !== undefined && - (obj.providerClientToken = base64FromBytes(message.providerClientToken !== undefined ? message.providerClientToken : Buffer.alloc(0))); - message.protectionScheme !== undefined && (obj.protectionScheme = Math.round(message.protectionScheme)); - message.srmRequirement !== undefined && - (obj.srmRequirement = base64FromBytes(message.srmRequirement !== undefined ? message.srmRequirement : Buffer.alloc(0))); - message.srmUpdate !== undefined && (obj.srmUpdate = base64FromBytes(message.srmUpdate !== undefined ? message.srmUpdate : Buffer.alloc(0))); - message.platformVerificationStatus !== undefined && - (obj.platformVerificationStatus = platformVerificationStatusToJSON(message.platformVerificationStatus)); - if (message.groupIds) { - obj.groupIds = message.groupIds.map((e) => base64FromBytes(e !== undefined ? e : Buffer.alloc(0))); - } else { - obj.groupIds = []; - } - return obj; - }, - - fromPartial, I>>(object: I): License { - const message = createBaseLicense(); - message.id = object.id !== undefined && object.id !== null ? LicenseIdentification.fromPartial(object.id) : undefined; - message.policy = object.policy !== undefined && object.policy !== null ? License_Policy.fromPartial(object.policy) : undefined; - message.key = object.key?.map((e) => License_KeyContainer.fromPartial(e)) || []; - message.licenseStartTime = - object.licenseStartTime !== undefined && object.licenseStartTime !== null ? Long.fromValue(object.licenseStartTime) : Long.ZERO; - message.remoteAttestationVerified = object.remoteAttestationVerified ?? false; - message.providerClientToken = object.providerClientToken ?? Buffer.alloc(0); - message.protectionScheme = object.protectionScheme ?? 0; - message.srmRequirement = object.srmRequirement ?? Buffer.alloc(0); - message.srmUpdate = object.srmUpdate ?? Buffer.alloc(0); - message.platformVerificationStatus = object.platformVerificationStatus ?? 0; - message.groupIds = object.groupIds?.map((e) => e) || []; - return message; - } -}; - -function createBaseLicense_Policy(): License_Policy { - return { - canPlay: false, - canPersist: false, - canRenew: false, - rentalDurationSeconds: Long.ZERO, - playbackDurationSeconds: Long.ZERO, - licenseDurationSeconds: Long.ZERO, - renewalRecoveryDurationSeconds: Long.ZERO, - renewalServerUrl: '', - renewalDelaySeconds: Long.ZERO, - renewalRetryIntervalSeconds: Long.ZERO, - renewWithUsage: false, - alwaysIncludeClientId: false, - playStartGracePeriodSeconds: Long.ZERO, - softEnforcePlaybackDuration: false, - softEnforceRentalDuration: false - }; -} - -export const License_Policy = { - encode(message: License_Policy, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { - if (message.canPlay === true) { - writer.uint32(8).bool(message.canPlay); - } - if (message.canPersist === true) { - writer.uint32(16).bool(message.canPersist); - } - if (message.canRenew === true) { - writer.uint32(24).bool(message.canRenew); - } - if (!message.rentalDurationSeconds.isZero()) { - writer.uint32(32).int64(message.rentalDurationSeconds); - } - if (!message.playbackDurationSeconds.isZero()) { - writer.uint32(40).int64(message.playbackDurationSeconds); - } - if (!message.licenseDurationSeconds.isZero()) { - writer.uint32(48).int64(message.licenseDurationSeconds); - } - if (!message.renewalRecoveryDurationSeconds.isZero()) { - writer.uint32(56).int64(message.renewalRecoveryDurationSeconds); - } - if (message.renewalServerUrl !== '') { - writer.uint32(66).string(message.renewalServerUrl); - } - if (!message.renewalDelaySeconds.isZero()) { - writer.uint32(72).int64(message.renewalDelaySeconds); - } - if (!message.renewalRetryIntervalSeconds.isZero()) { - writer.uint32(80).int64(message.renewalRetryIntervalSeconds); - } - if (message.renewWithUsage === true) { - writer.uint32(88).bool(message.renewWithUsage); - } - if (message.alwaysIncludeClientId === true) { - writer.uint32(96).bool(message.alwaysIncludeClientId); - } - if (!message.playStartGracePeriodSeconds.isZero()) { - writer.uint32(104).int64(message.playStartGracePeriodSeconds); - } - if (message.softEnforcePlaybackDuration === true) { - writer.uint32(112).bool(message.softEnforcePlaybackDuration); - } - if (message.softEnforceRentalDuration === true) { - writer.uint32(120).bool(message.softEnforceRentalDuration); - } - return writer; - }, - - decode(input: _m0.Reader | Uint8Array, length?: number): License_Policy { - const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); - const end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseLicense_Policy(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - message.canPlay = reader.bool(); - break; - case 2: - message.canPersist = reader.bool(); - break; - case 3: - message.canRenew = reader.bool(); - break; - case 4: - message.rentalDurationSeconds = reader.int64() as Long; - break; - case 5: - message.playbackDurationSeconds = reader.int64() as Long; - break; - case 6: - message.licenseDurationSeconds = reader.int64() as Long; - break; - case 7: - message.renewalRecoveryDurationSeconds = reader.int64() as Long; - break; - case 8: - message.renewalServerUrl = reader.string(); - break; - case 9: - message.renewalDelaySeconds = reader.int64() as Long; - break; - case 10: - message.renewalRetryIntervalSeconds = reader.int64() as Long; - break; - case 11: - message.renewWithUsage = reader.bool(); - break; - case 12: - message.alwaysIncludeClientId = reader.bool(); - break; - case 13: - message.playStartGracePeriodSeconds = reader.int64() as Long; - break; - case 14: - message.softEnforcePlaybackDuration = reader.bool(); - break; - case 15: - message.softEnforceRentalDuration = reader.bool(); - break; - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }, - - fromJSON(object: any): License_Policy { - return { - canPlay: isSet(object.canPlay) ? Boolean(object.canPlay) : false, - canPersist: isSet(object.canPersist) ? Boolean(object.canPersist) : false, - canRenew: isSet(object.canRenew) ? Boolean(object.canRenew) : false, - rentalDurationSeconds: isSet(object.rentalDurationSeconds) ? Long.fromValue(object.rentalDurationSeconds) : Long.ZERO, - playbackDurationSeconds: isSet(object.playbackDurationSeconds) ? Long.fromValue(object.playbackDurationSeconds) : Long.ZERO, - licenseDurationSeconds: isSet(object.licenseDurationSeconds) ? Long.fromValue(object.licenseDurationSeconds) : Long.ZERO, - renewalRecoveryDurationSeconds: isSet(object.renewalRecoveryDurationSeconds) - ? Long.fromValue(object.renewalRecoveryDurationSeconds) - : Long.ZERO, - renewalServerUrl: isSet(object.renewalServerUrl) ? String(object.renewalServerUrl) : '', - renewalDelaySeconds: isSet(object.renewalDelaySeconds) ? Long.fromValue(object.renewalDelaySeconds) : Long.ZERO, - renewalRetryIntervalSeconds: isSet(object.renewalRetryIntervalSeconds) ? Long.fromValue(object.renewalRetryIntervalSeconds) : Long.ZERO, - renewWithUsage: isSet(object.renewWithUsage) ? Boolean(object.renewWithUsage) : false, - alwaysIncludeClientId: isSet(object.alwaysIncludeClientId) ? Boolean(object.alwaysIncludeClientId) : false, - playStartGracePeriodSeconds: isSet(object.playStartGracePeriodSeconds) ? Long.fromValue(object.playStartGracePeriodSeconds) : Long.ZERO, - softEnforcePlaybackDuration: isSet(object.softEnforcePlaybackDuration) ? Boolean(object.softEnforcePlaybackDuration) : false, - softEnforceRentalDuration: isSet(object.softEnforceRentalDuration) ? Boolean(object.softEnforceRentalDuration) : false - }; - }, - - toJSON(message: License_Policy): unknown { - const obj: any = {}; - message.canPlay !== undefined && (obj.canPlay = message.canPlay); - message.canPersist !== undefined && (obj.canPersist = message.canPersist); - message.canRenew !== undefined && (obj.canRenew = message.canRenew); - message.rentalDurationSeconds !== undefined && (obj.rentalDurationSeconds = (message.rentalDurationSeconds || Long.ZERO).toString()); - message.playbackDurationSeconds !== undefined && (obj.playbackDurationSeconds = (message.playbackDurationSeconds || Long.ZERO).toString()); - message.licenseDurationSeconds !== undefined && (obj.licenseDurationSeconds = (message.licenseDurationSeconds || Long.ZERO).toString()); - message.renewalRecoveryDurationSeconds !== undefined && - (obj.renewalRecoveryDurationSeconds = (message.renewalRecoveryDurationSeconds || Long.ZERO).toString()); - message.renewalServerUrl !== undefined && (obj.renewalServerUrl = message.renewalServerUrl); - message.renewalDelaySeconds !== undefined && (obj.renewalDelaySeconds = (message.renewalDelaySeconds || Long.ZERO).toString()); - message.renewalRetryIntervalSeconds !== undefined && - (obj.renewalRetryIntervalSeconds = (message.renewalRetryIntervalSeconds || Long.ZERO).toString()); - message.renewWithUsage !== undefined && (obj.renewWithUsage = message.renewWithUsage); - message.alwaysIncludeClientId !== undefined && (obj.alwaysIncludeClientId = message.alwaysIncludeClientId); - message.playStartGracePeriodSeconds !== undefined && - (obj.playStartGracePeriodSeconds = (message.playStartGracePeriodSeconds || Long.ZERO).toString()); - message.softEnforcePlaybackDuration !== undefined && (obj.softEnforcePlaybackDuration = message.softEnforcePlaybackDuration); - message.softEnforceRentalDuration !== undefined && (obj.softEnforceRentalDuration = message.softEnforceRentalDuration); - return obj; - }, - - fromPartial, I>>(object: I): License_Policy { - const message = createBaseLicense_Policy(); - message.canPlay = object.canPlay ?? false; - message.canPersist = object.canPersist ?? false; - message.canRenew = object.canRenew ?? false; - message.rentalDurationSeconds = - object.rentalDurationSeconds !== undefined && object.rentalDurationSeconds !== null ? Long.fromValue(object.rentalDurationSeconds) : Long.ZERO; - message.playbackDurationSeconds = - object.playbackDurationSeconds !== undefined && object.playbackDurationSeconds !== null - ? Long.fromValue(object.playbackDurationSeconds) - : Long.ZERO; - message.licenseDurationSeconds = - object.licenseDurationSeconds !== undefined && object.licenseDurationSeconds !== null - ? Long.fromValue(object.licenseDurationSeconds) - : Long.ZERO; - message.renewalRecoveryDurationSeconds = - object.renewalRecoveryDurationSeconds !== undefined && object.renewalRecoveryDurationSeconds !== null - ? Long.fromValue(object.renewalRecoveryDurationSeconds) - : Long.ZERO; - message.renewalServerUrl = object.renewalServerUrl ?? ''; - message.renewalDelaySeconds = - object.renewalDelaySeconds !== undefined && object.renewalDelaySeconds !== null ? Long.fromValue(object.renewalDelaySeconds) : Long.ZERO; - message.renewalRetryIntervalSeconds = - object.renewalRetryIntervalSeconds !== undefined && object.renewalRetryIntervalSeconds !== null - ? Long.fromValue(object.renewalRetryIntervalSeconds) - : Long.ZERO; - message.renewWithUsage = object.renewWithUsage ?? false; - message.alwaysIncludeClientId = object.alwaysIncludeClientId ?? false; - message.playStartGracePeriodSeconds = - object.playStartGracePeriodSeconds !== undefined && object.playStartGracePeriodSeconds !== null - ? Long.fromValue(object.playStartGracePeriodSeconds) - : Long.ZERO; - message.softEnforcePlaybackDuration = object.softEnforcePlaybackDuration ?? false; - message.softEnforceRentalDuration = object.softEnforceRentalDuration ?? false; - return message; - } -}; - -function createBaseLicense_KeyContainer(): License_KeyContainer { - return { - id: Buffer.alloc(0), - iv: Buffer.alloc(0), - key: Buffer.alloc(0), - type: 1, - level: 1, - requiredProtection: undefined, - requestedProtection: undefined, - keyControl: undefined, - operatorSessionKeyPermissions: undefined, - videoResolutionConstraints: [], - antiRollbackUsageTable: false, - trackLabel: '' - }; -} - -export const License_KeyContainer = { - encode(message: License_KeyContainer, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { - if (message.id.length !== 0) { - writer.uint32(10).bytes(message.id); - } - if (message.iv.length !== 0) { - writer.uint32(18).bytes(message.iv); - } - if (message.key.length !== 0) { - writer.uint32(26).bytes(message.key); - } - if (message.type !== 1) { - writer.uint32(32).int32(message.type); - } - if (message.level !== 1) { - writer.uint32(40).int32(message.level); - } - if (message.requiredProtection !== undefined) { - License_KeyContainer_OutputProtection.encode(message.requiredProtection, writer.uint32(50).fork()).ldelim(); - } - if (message.requestedProtection !== undefined) { - License_KeyContainer_OutputProtection.encode(message.requestedProtection, writer.uint32(58).fork()).ldelim(); - } - if (message.keyControl !== undefined) { - License_KeyContainer_KeyControl.encode(message.keyControl, writer.uint32(66).fork()).ldelim(); - } - if (message.operatorSessionKeyPermissions !== undefined) { - License_KeyContainer_OperatorSessionKeyPermissions.encode(message.operatorSessionKeyPermissions, writer.uint32(74).fork()).ldelim(); - } - for (const v of message.videoResolutionConstraints) { - License_KeyContainer_VideoResolutionConstraint.encode(v!, writer.uint32(82).fork()).ldelim(); - } - if (message.antiRollbackUsageTable === true) { - writer.uint32(88).bool(message.antiRollbackUsageTable); - } - if (message.trackLabel !== '') { - writer.uint32(98).string(message.trackLabel); - } - return writer; - }, - - decode(input: _m0.Reader | Uint8Array, length?: number): License_KeyContainer { - const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); - const end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseLicense_KeyContainer(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - message.id = reader.bytes() as Buffer; - break; - case 2: - message.iv = reader.bytes() as Buffer; - break; - case 3: - message.key = reader.bytes() as Buffer; - break; - case 4: - message.type = reader.int32() as any; - break; - case 5: - message.level = reader.int32() as any; - break; - case 6: - message.requiredProtection = License_KeyContainer_OutputProtection.decode(reader, reader.uint32()); - break; - case 7: - message.requestedProtection = License_KeyContainer_OutputProtection.decode(reader, reader.uint32()); - break; - case 8: - message.keyControl = License_KeyContainer_KeyControl.decode(reader, reader.uint32()); - break; - case 9: - message.operatorSessionKeyPermissions = License_KeyContainer_OperatorSessionKeyPermissions.decode(reader, reader.uint32()); - break; - case 10: - message.videoResolutionConstraints.push(License_KeyContainer_VideoResolutionConstraint.decode(reader, reader.uint32())); - break; - case 11: - message.antiRollbackUsageTable = reader.bool(); - break; - case 12: - message.trackLabel = reader.string(); - break; - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }, - - fromJSON(object: any): License_KeyContainer { - return { - id: isSet(object.id) ? Buffer.from(bytesFromBase64(object.id)) : Buffer.alloc(0), - iv: isSet(object.iv) ? Buffer.from(bytesFromBase64(object.iv)) : Buffer.alloc(0), - key: isSet(object.key) ? Buffer.from(bytesFromBase64(object.key)) : Buffer.alloc(0), - type: isSet(object.type) ? license_KeyContainer_KeyTypeFromJSON(object.type) : 1, - level: isSet(object.level) ? license_KeyContainer_SecurityLevelFromJSON(object.level) : 1, - requiredProtection: isSet(object.requiredProtection) ? License_KeyContainer_OutputProtection.fromJSON(object.requiredProtection) : undefined, - requestedProtection: isSet(object.requestedProtection) ? License_KeyContainer_OutputProtection.fromJSON(object.requestedProtection) : undefined, - keyControl: isSet(object.keyControl) ? License_KeyContainer_KeyControl.fromJSON(object.keyControl) : undefined, - operatorSessionKeyPermissions: isSet(object.operatorSessionKeyPermissions) - ? License_KeyContainer_OperatorSessionKeyPermissions.fromJSON(object.operatorSessionKeyPermissions) - : undefined, - videoResolutionConstraints: Array.isArray(object?.videoResolutionConstraints) - ? object.videoResolutionConstraints.map((e: any) => License_KeyContainer_VideoResolutionConstraint.fromJSON(e)) - : [], - antiRollbackUsageTable: isSet(object.antiRollbackUsageTable) ? Boolean(object.antiRollbackUsageTable) : false, - trackLabel: isSet(object.trackLabel) ? String(object.trackLabel) : '' - }; - }, - - toJSON(message: License_KeyContainer): unknown { - const obj: any = {}; - message.id !== undefined && (obj.id = base64FromBytes(message.id !== undefined ? message.id : Buffer.alloc(0))); - message.iv !== undefined && (obj.iv = base64FromBytes(message.iv !== undefined ? message.iv : Buffer.alloc(0))); - message.key !== undefined && (obj.key = base64FromBytes(message.key !== undefined ? message.key : Buffer.alloc(0))); - message.type !== undefined && (obj.type = license_KeyContainer_KeyTypeToJSON(message.type)); - message.level !== undefined && (obj.level = license_KeyContainer_SecurityLevelToJSON(message.level)); - message.requiredProtection !== undefined && - (obj.requiredProtection = message.requiredProtection ? License_KeyContainer_OutputProtection.toJSON(message.requiredProtection) : undefined); - message.requestedProtection !== undefined && - (obj.requestedProtection = message.requestedProtection ? License_KeyContainer_OutputProtection.toJSON(message.requestedProtection) : undefined); - message.keyControl !== undefined && - (obj.keyControl = message.keyControl ? License_KeyContainer_KeyControl.toJSON(message.keyControl) : undefined); - message.operatorSessionKeyPermissions !== undefined && - (obj.operatorSessionKeyPermissions = message.operatorSessionKeyPermissions - ? License_KeyContainer_OperatorSessionKeyPermissions.toJSON(message.operatorSessionKeyPermissions) - : undefined); - if (message.videoResolutionConstraints) { - obj.videoResolutionConstraints = message.videoResolutionConstraints.map((e) => - e ? License_KeyContainer_VideoResolutionConstraint.toJSON(e) : undefined - ); - } else { - obj.videoResolutionConstraints = []; - } - message.antiRollbackUsageTable !== undefined && (obj.antiRollbackUsageTable = message.antiRollbackUsageTable); - message.trackLabel !== undefined && (obj.trackLabel = message.trackLabel); - return obj; - }, - - fromPartial, I>>(object: I): License_KeyContainer { - const message = createBaseLicense_KeyContainer(); - message.id = object.id ?? Buffer.alloc(0); - message.iv = object.iv ?? Buffer.alloc(0); - message.key = object.key ?? Buffer.alloc(0); - message.type = object.type ?? 1; - message.level = object.level ?? 1; - message.requiredProtection = - object.requiredProtection !== undefined && object.requiredProtection !== null - ? License_KeyContainer_OutputProtection.fromPartial(object.requiredProtection) - : undefined; - message.requestedProtection = - object.requestedProtection !== undefined && object.requestedProtection !== null - ? License_KeyContainer_OutputProtection.fromPartial(object.requestedProtection) - : undefined; - message.keyControl = - object.keyControl !== undefined && object.keyControl !== null ? License_KeyContainer_KeyControl.fromPartial(object.keyControl) : undefined; - message.operatorSessionKeyPermissions = - object.operatorSessionKeyPermissions !== undefined && object.operatorSessionKeyPermissions !== null - ? License_KeyContainer_OperatorSessionKeyPermissions.fromPartial(object.operatorSessionKeyPermissions) - : undefined; - message.videoResolutionConstraints = - object.videoResolutionConstraints?.map((e) => License_KeyContainer_VideoResolutionConstraint.fromPartial(e)) || []; - message.antiRollbackUsageTable = object.antiRollbackUsageTable ?? false; - message.trackLabel = object.trackLabel ?? ''; - return message; - } -}; - -function createBaseLicense_KeyContainer_KeyControl(): License_KeyContainer_KeyControl { - return { keyControlBlock: Buffer.alloc(0), iv: Buffer.alloc(0) }; -} - -export const License_KeyContainer_KeyControl = { - encode(message: License_KeyContainer_KeyControl, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { - if (message.keyControlBlock.length !== 0) { - writer.uint32(10).bytes(message.keyControlBlock); - } - if (message.iv.length !== 0) { - writer.uint32(18).bytes(message.iv); - } - return writer; - }, - - decode(input: _m0.Reader | Uint8Array, length?: number): License_KeyContainer_KeyControl { - const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); - const end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseLicense_KeyContainer_KeyControl(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - message.keyControlBlock = reader.bytes() as Buffer; - break; - case 2: - message.iv = reader.bytes() as Buffer; - break; - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }, - - fromJSON(object: any): License_KeyContainer_KeyControl { - return { - keyControlBlock: isSet(object.keyControlBlock) ? Buffer.from(bytesFromBase64(object.keyControlBlock)) : Buffer.alloc(0), - iv: isSet(object.iv) ? Buffer.from(bytesFromBase64(object.iv)) : Buffer.alloc(0) - }; - }, - - toJSON(message: License_KeyContainer_KeyControl): unknown { - const obj: any = {}; - message.keyControlBlock !== undefined && - (obj.keyControlBlock = base64FromBytes(message.keyControlBlock !== undefined ? message.keyControlBlock : Buffer.alloc(0))); - message.iv !== undefined && (obj.iv = base64FromBytes(message.iv !== undefined ? message.iv : Buffer.alloc(0))); - return obj; - }, - - fromPartial, I>>(object: I): License_KeyContainer_KeyControl { - const message = createBaseLicense_KeyContainer_KeyControl(); - message.keyControlBlock = object.keyControlBlock ?? Buffer.alloc(0); - message.iv = object.iv ?? Buffer.alloc(0); - return message; - } -}; - -function createBaseLicense_KeyContainer_OutputProtection(): License_KeyContainer_OutputProtection { - return { hdcp: 0, cgmsFlags: 0, hdcpSrmRule: 0, disableAnalogOutput: false, disableDigitalOutput: false }; -} - -export const License_KeyContainer_OutputProtection = { - encode(message: License_KeyContainer_OutputProtection, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { - if (message.hdcp !== 0) { - writer.uint32(8).int32(message.hdcp); - } - if (message.cgmsFlags !== 0) { - writer.uint32(16).int32(message.cgmsFlags); - } - if (message.hdcpSrmRule !== 0) { - writer.uint32(24).int32(message.hdcpSrmRule); - } - if (message.disableAnalogOutput === true) { - writer.uint32(32).bool(message.disableAnalogOutput); - } - if (message.disableDigitalOutput === true) { - writer.uint32(40).bool(message.disableDigitalOutput); - } - return writer; - }, - - decode(input: _m0.Reader | Uint8Array, length?: number): License_KeyContainer_OutputProtection { - const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); - const end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseLicense_KeyContainer_OutputProtection(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - message.hdcp = reader.int32() as any; - break; - case 2: - message.cgmsFlags = reader.int32() as any; - break; - case 3: - message.hdcpSrmRule = reader.int32() as any; - break; - case 4: - message.disableAnalogOutput = reader.bool(); - break; - case 5: - message.disableDigitalOutput = reader.bool(); - break; - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }, - - fromJSON(object: any): License_KeyContainer_OutputProtection { - return { - hdcp: isSet(object.hdcp) ? license_KeyContainer_OutputProtection_HDCPFromJSON(object.hdcp) : 0, - cgmsFlags: isSet(object.cgmsFlags) ? license_KeyContainer_OutputProtection_CGMSFromJSON(object.cgmsFlags) : 0, - hdcpSrmRule: isSet(object.hdcpSrmRule) ? license_KeyContainer_OutputProtection_HdcpSrmRuleFromJSON(object.hdcpSrmRule) : 0, - disableAnalogOutput: isSet(object.disableAnalogOutput) ? Boolean(object.disableAnalogOutput) : false, - disableDigitalOutput: isSet(object.disableDigitalOutput) ? Boolean(object.disableDigitalOutput) : false - }; - }, - - toJSON(message: License_KeyContainer_OutputProtection): unknown { - const obj: any = {}; - message.hdcp !== undefined && (obj.hdcp = license_KeyContainer_OutputProtection_HDCPToJSON(message.hdcp)); - message.cgmsFlags !== undefined && (obj.cgmsFlags = license_KeyContainer_OutputProtection_CGMSToJSON(message.cgmsFlags)); - message.hdcpSrmRule !== undefined && (obj.hdcpSrmRule = license_KeyContainer_OutputProtection_HdcpSrmRuleToJSON(message.hdcpSrmRule)); - message.disableAnalogOutput !== undefined && (obj.disableAnalogOutput = message.disableAnalogOutput); - message.disableDigitalOutput !== undefined && (obj.disableDigitalOutput = message.disableDigitalOutput); - return obj; - }, - - fromPartial, I>>(object: I): License_KeyContainer_OutputProtection { - const message = createBaseLicense_KeyContainer_OutputProtection(); - message.hdcp = object.hdcp ?? 0; - message.cgmsFlags = object.cgmsFlags ?? 0; - message.hdcpSrmRule = object.hdcpSrmRule ?? 0; - message.disableAnalogOutput = object.disableAnalogOutput ?? false; - message.disableDigitalOutput = object.disableDigitalOutput ?? false; - return message; - } -}; - -function createBaseLicense_KeyContainer_VideoResolutionConstraint(): License_KeyContainer_VideoResolutionConstraint { - return { minResolutionPixels: 0, maxResolutionPixels: 0, requiredProtection: undefined }; -} - -export const License_KeyContainer_VideoResolutionConstraint = { - encode(message: License_KeyContainer_VideoResolutionConstraint, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { - if (message.minResolutionPixels !== 0) { - writer.uint32(8).uint32(message.minResolutionPixels); - } - if (message.maxResolutionPixels !== 0) { - writer.uint32(16).uint32(message.maxResolutionPixels); - } - if (message.requiredProtection !== undefined) { - License_KeyContainer_OutputProtection.encode(message.requiredProtection, writer.uint32(26).fork()).ldelim(); - } - return writer; - }, - - decode(input: _m0.Reader | Uint8Array, length?: number): License_KeyContainer_VideoResolutionConstraint { - const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); - const end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseLicense_KeyContainer_VideoResolutionConstraint(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - message.minResolutionPixels = reader.uint32(); - break; - case 2: - message.maxResolutionPixels = reader.uint32(); - break; - case 3: - message.requiredProtection = License_KeyContainer_OutputProtection.decode(reader, reader.uint32()); - break; - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }, - - fromJSON(object: any): License_KeyContainer_VideoResolutionConstraint { - return { - minResolutionPixels: isSet(object.minResolutionPixels) ? Number(object.minResolutionPixels) : 0, - maxResolutionPixels: isSet(object.maxResolutionPixels) ? Number(object.maxResolutionPixels) : 0, - requiredProtection: isSet(object.requiredProtection) ? License_KeyContainer_OutputProtection.fromJSON(object.requiredProtection) : undefined - }; - }, - - toJSON(message: License_KeyContainer_VideoResolutionConstraint): unknown { - const obj: any = {}; - message.minResolutionPixels !== undefined && (obj.minResolutionPixels = Math.round(message.minResolutionPixels)); - message.maxResolutionPixels !== undefined && (obj.maxResolutionPixels = Math.round(message.maxResolutionPixels)); - message.requiredProtection !== undefined && - (obj.requiredProtection = message.requiredProtection ? License_KeyContainer_OutputProtection.toJSON(message.requiredProtection) : undefined); - return obj; - }, - - fromPartial, I>>( - object: I - ): License_KeyContainer_VideoResolutionConstraint { - const message = createBaseLicense_KeyContainer_VideoResolutionConstraint(); - message.minResolutionPixels = object.minResolutionPixels ?? 0; - message.maxResolutionPixels = object.maxResolutionPixels ?? 0; - message.requiredProtection = - object.requiredProtection !== undefined && object.requiredProtection !== null - ? License_KeyContainer_OutputProtection.fromPartial(object.requiredProtection) - : undefined; - return message; - } -}; - -function createBaseLicense_KeyContainer_OperatorSessionKeyPermissions(): License_KeyContainer_OperatorSessionKeyPermissions { - return { allowEncrypt: false, allowDecrypt: false, allowSign: false, allowSignatureVerify: false }; -} - -export const License_KeyContainer_OperatorSessionKeyPermissions = { - encode(message: License_KeyContainer_OperatorSessionKeyPermissions, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { - if (message.allowEncrypt === true) { - writer.uint32(8).bool(message.allowEncrypt); - } - if (message.allowDecrypt === true) { - writer.uint32(16).bool(message.allowDecrypt); - } - if (message.allowSign === true) { - writer.uint32(24).bool(message.allowSign); - } - if (message.allowSignatureVerify === true) { - writer.uint32(32).bool(message.allowSignatureVerify); - } - return writer; - }, - - decode(input: _m0.Reader | Uint8Array, length?: number): License_KeyContainer_OperatorSessionKeyPermissions { - const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); - const end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseLicense_KeyContainer_OperatorSessionKeyPermissions(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - message.allowEncrypt = reader.bool(); - break; - case 2: - message.allowDecrypt = reader.bool(); - break; - case 3: - message.allowSign = reader.bool(); - break; - case 4: - message.allowSignatureVerify = reader.bool(); - break; - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }, - - fromJSON(object: any): License_KeyContainer_OperatorSessionKeyPermissions { - return { - allowEncrypt: isSet(object.allowEncrypt) ? Boolean(object.allowEncrypt) : false, - allowDecrypt: isSet(object.allowDecrypt) ? Boolean(object.allowDecrypt) : false, - allowSign: isSet(object.allowSign) ? Boolean(object.allowSign) : false, - allowSignatureVerify: isSet(object.allowSignatureVerify) ? Boolean(object.allowSignatureVerify) : false - }; - }, - - toJSON(message: License_KeyContainer_OperatorSessionKeyPermissions): unknown { - const obj: any = {}; - message.allowEncrypt !== undefined && (obj.allowEncrypt = message.allowEncrypt); - message.allowDecrypt !== undefined && (obj.allowDecrypt = message.allowDecrypt); - message.allowSign !== undefined && (obj.allowSign = message.allowSign); - message.allowSignatureVerify !== undefined && (obj.allowSignatureVerify = message.allowSignatureVerify); - return obj; - }, - - fromPartial, I>>( - object: I - ): License_KeyContainer_OperatorSessionKeyPermissions { - const message = createBaseLicense_KeyContainer_OperatorSessionKeyPermissions(); - message.allowEncrypt = object.allowEncrypt ?? false; - message.allowDecrypt = object.allowDecrypt ?? false; - message.allowSign = object.allowSign ?? false; - message.allowSignatureVerify = object.allowSignatureVerify ?? false; - return message; - } -}; - -function createBaseLicenseRequest(): LicenseRequest { - return { - clientId: undefined, - contentId: undefined, - type: 1, - requestTime: Long.ZERO, - keyControlNonceDeprecated: Buffer.alloc(0), - protocolVersion: 20, - keyControlNonce: 0, - encryptedClientId: undefined - }; -} - -export const LicenseRequest = { - encode(message: LicenseRequest, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { - if (message.clientId !== undefined) { - ClientIdentification.encode(message.clientId, writer.uint32(10).fork()).ldelim(); - } - if (message.contentId !== undefined) { - LicenseRequest_ContentIdentification.encode(message.contentId, writer.uint32(18).fork()).ldelim(); - } - if (message.type !== 1) { - writer.uint32(24).int32(message.type); - } - if (!message.requestTime.isZero()) { - writer.uint32(32).int64(message.requestTime); - } - if (message.keyControlNonceDeprecated.length !== 0) { - writer.uint32(42).bytes(message.keyControlNonceDeprecated); - } - if (message.protocolVersion !== 20) { - writer.uint32(48).int32(message.protocolVersion); - } - if (message.keyControlNonce !== 0) { - writer.uint32(56).uint32(message.keyControlNonce); - } - if (message.encryptedClientId !== undefined) { - EncryptedClientIdentification.encode(message.encryptedClientId, writer.uint32(66).fork()).ldelim(); - } - return writer; - }, - - decode(input: _m0.Reader | Uint8Array, length?: number): LicenseRequest { - const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); - const end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseLicenseRequest(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - message.clientId = ClientIdentification.decode(reader, reader.uint32()); - break; - case 2: - message.contentId = LicenseRequest_ContentIdentification.decode(reader, reader.uint32()); - break; - case 3: - message.type = reader.int32() as any; - break; - case 4: - message.requestTime = reader.int64() as Long; - break; - case 5: - message.keyControlNonceDeprecated = reader.bytes() as Buffer; - break; - case 6: - message.protocolVersion = reader.int32() as any; - break; - case 7: - message.keyControlNonce = reader.uint32(); - break; - case 8: - message.encryptedClientId = EncryptedClientIdentification.decode(reader, reader.uint32()); - break; - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }, - - fromJSON(object: any): LicenseRequest { - return { - clientId: isSet(object.clientId) ? ClientIdentification.fromJSON(object.clientId) : undefined, - contentId: isSet(object.contentId) ? LicenseRequest_ContentIdentification.fromJSON(object.contentId) : undefined, - type: isSet(object.type) ? licenseRequest_RequestTypeFromJSON(object.type) : 1, - requestTime: isSet(object.requestTime) ? Long.fromValue(object.requestTime) : Long.ZERO, - keyControlNonceDeprecated: isSet(object.keyControlNonceDeprecated) - ? Buffer.from(bytesFromBase64(object.keyControlNonceDeprecated)) - : Buffer.alloc(0), - protocolVersion: isSet(object.protocolVersion) ? protocolVersionFromJSON(object.protocolVersion) : 20, - keyControlNonce: isSet(object.keyControlNonce) ? Number(object.keyControlNonce) : 0, - encryptedClientId: isSet(object.encryptedClientId) ? EncryptedClientIdentification.fromJSON(object.encryptedClientId) : undefined - }; - }, - - toJSON(message: LicenseRequest): unknown { - const obj: any = {}; - message.clientId !== undefined && (obj.clientId = message.clientId ? ClientIdentification.toJSON(message.clientId) : undefined); - message.contentId !== undefined && - (obj.contentId = message.contentId ? LicenseRequest_ContentIdentification.toJSON(message.contentId) : undefined); - message.type !== undefined && (obj.type = licenseRequest_RequestTypeToJSON(message.type)); - message.requestTime !== undefined && (obj.requestTime = (message.requestTime || Long.ZERO).toString()); - message.keyControlNonceDeprecated !== undefined && - (obj.keyControlNonceDeprecated = base64FromBytes( - message.keyControlNonceDeprecated !== undefined ? message.keyControlNonceDeprecated : Buffer.alloc(0) - )); - message.protocolVersion !== undefined && (obj.protocolVersion = protocolVersionToJSON(message.protocolVersion)); - message.keyControlNonce !== undefined && (obj.keyControlNonce = Math.round(message.keyControlNonce)); - message.encryptedClientId !== undefined && - (obj.encryptedClientId = message.encryptedClientId ? EncryptedClientIdentification.toJSON(message.encryptedClientId) : undefined); - return obj; - }, - - fromPartial, I>>(object: I): LicenseRequest { - const message = createBaseLicenseRequest(); - message.clientId = object.clientId !== undefined && object.clientId !== null ? ClientIdentification.fromPartial(object.clientId) : undefined; - message.contentId = - object.contentId !== undefined && object.contentId !== null ? LicenseRequest_ContentIdentification.fromPartial(object.contentId) : undefined; - message.type = object.type ?? 1; - message.requestTime = object.requestTime !== undefined && object.requestTime !== null ? Long.fromValue(object.requestTime) : Long.ZERO; - message.keyControlNonceDeprecated = object.keyControlNonceDeprecated ?? Buffer.alloc(0); - message.protocolVersion = object.protocolVersion ?? 20; - message.keyControlNonce = object.keyControlNonce ?? 0; - message.encryptedClientId = - object.encryptedClientId !== undefined && object.encryptedClientId !== null - ? EncryptedClientIdentification.fromPartial(object.encryptedClientId) - : undefined; - return message; - } -}; - -function createBaseLicenseRequest_ContentIdentification(): LicenseRequest_ContentIdentification { - return { widevinePsshData: undefined, webmKeyId: undefined, existingLicense: undefined, initData: undefined }; -} - -export const LicenseRequest_ContentIdentification = { - encode(message: LicenseRequest_ContentIdentification, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { - if (message.widevinePsshData !== undefined) { - LicenseRequest_ContentIdentification_WidevinePsshData.encode(message.widevinePsshData, writer.uint32(10).fork()).ldelim(); - } - if (message.webmKeyId !== undefined) { - LicenseRequest_ContentIdentification_WebmKeyId.encode(message.webmKeyId, writer.uint32(18).fork()).ldelim(); - } - if (message.existingLicense !== undefined) { - LicenseRequest_ContentIdentification_ExistingLicense.encode(message.existingLicense, writer.uint32(26).fork()).ldelim(); - } - if (message.initData !== undefined) { - LicenseRequest_ContentIdentification_InitData.encode(message.initData, writer.uint32(34).fork()).ldelim(); - } - return writer; - }, - - decode(input: _m0.Reader | Uint8Array, length?: number): LicenseRequest_ContentIdentification { - const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); - const end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseLicenseRequest_ContentIdentification(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - message.widevinePsshData = LicenseRequest_ContentIdentification_WidevinePsshData.decode(reader, reader.uint32()); - break; - case 2: - message.webmKeyId = LicenseRequest_ContentIdentification_WebmKeyId.decode(reader, reader.uint32()); - break; - case 3: - message.existingLicense = LicenseRequest_ContentIdentification_ExistingLicense.decode(reader, reader.uint32()); - break; - case 4: - message.initData = LicenseRequest_ContentIdentification_InitData.decode(reader, reader.uint32()); - break; - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }, - - fromJSON(object: any): LicenseRequest_ContentIdentification { - return { - widevinePsshData: isSet(object.widevinePsshData) - ? LicenseRequest_ContentIdentification_WidevinePsshData.fromJSON(object.widevinePsshData) - : undefined, - webmKeyId: isSet(object.webmKeyId) ? LicenseRequest_ContentIdentification_WebmKeyId.fromJSON(object.webmKeyId) : undefined, - existingLicense: isSet(object.existingLicense) - ? LicenseRequest_ContentIdentification_ExistingLicense.fromJSON(object.existingLicense) - : undefined, - initData: isSet(object.initData) ? LicenseRequest_ContentIdentification_InitData.fromJSON(object.initData) : undefined - }; - }, - - toJSON(message: LicenseRequest_ContentIdentification): unknown { - const obj: any = {}; - message.widevinePsshData !== undefined && - (obj.widevinePsshData = message.widevinePsshData - ? LicenseRequest_ContentIdentification_WidevinePsshData.toJSON(message.widevinePsshData) - : undefined); - message.webmKeyId !== undefined && - (obj.webmKeyId = message.webmKeyId ? LicenseRequest_ContentIdentification_WebmKeyId.toJSON(message.webmKeyId) : undefined); - message.existingLicense !== undefined && - (obj.existingLicense = message.existingLicense - ? LicenseRequest_ContentIdentification_ExistingLicense.toJSON(message.existingLicense) - : undefined); - message.initData !== undefined && - (obj.initData = message.initData ? LicenseRequest_ContentIdentification_InitData.toJSON(message.initData) : undefined); - return obj; - }, - - fromPartial, I>>(object: I): LicenseRequest_ContentIdentification { - const message = createBaseLicenseRequest_ContentIdentification(); - message.widevinePsshData = - object.widevinePsshData !== undefined && object.widevinePsshData !== null - ? LicenseRequest_ContentIdentification_WidevinePsshData.fromPartial(object.widevinePsshData) - : undefined; - message.webmKeyId = - object.webmKeyId !== undefined && object.webmKeyId !== null - ? LicenseRequest_ContentIdentification_WebmKeyId.fromPartial(object.webmKeyId) - : undefined; - message.existingLicense = - object.existingLicense !== undefined && object.existingLicense !== null - ? LicenseRequest_ContentIdentification_ExistingLicense.fromPartial(object.existingLicense) - : undefined; - message.initData = - object.initData !== undefined && object.initData !== null - ? LicenseRequest_ContentIdentification_InitData.fromPartial(object.initData) - : undefined; - return message; - } -}; - -function createBaseLicenseRequest_ContentIdentification_WidevinePsshData(): LicenseRequest_ContentIdentification_WidevinePsshData { - return { psshData: [], licenseType: 1, requestId: Buffer.alloc(0) }; -} - -export const LicenseRequest_ContentIdentification_WidevinePsshData = { - encode(message: LicenseRequest_ContentIdentification_WidevinePsshData, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { - for (const v of message.psshData) { - writer.uint32(10).bytes(v!); - } - if (message.licenseType !== 1) { - writer.uint32(16).int32(message.licenseType); - } - if (message.requestId.length !== 0) { - writer.uint32(26).bytes(message.requestId); - } - return writer; - }, - - decode(input: _m0.Reader | Uint8Array, length?: number): LicenseRequest_ContentIdentification_WidevinePsshData { - const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); - const end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseLicenseRequest_ContentIdentification_WidevinePsshData(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - message.psshData.push(reader.bytes() as Buffer); - break; - case 2: - message.licenseType = reader.int32() as any; - break; - case 3: - message.requestId = reader.bytes() as Buffer; - break; - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }, - - fromJSON(object: any): LicenseRequest_ContentIdentification_WidevinePsshData { - return { - psshData: Array.isArray(object?.psshData) ? object.psshData.map((e: any) => Buffer.from(bytesFromBase64(e))) : [], - licenseType: isSet(object.licenseType) ? licenseTypeFromJSON(object.licenseType) : 1, - requestId: isSet(object.requestId) ? Buffer.from(bytesFromBase64(object.requestId)) : Buffer.alloc(0) - }; - }, - - toJSON(message: LicenseRequest_ContentIdentification_WidevinePsshData): unknown { - const obj: any = {}; - if (message.psshData) { - obj.psshData = message.psshData.map((e) => base64FromBytes(e !== undefined ? e : Buffer.alloc(0))); - } else { - obj.psshData = []; - } - message.licenseType !== undefined && (obj.licenseType = licenseTypeToJSON(message.licenseType)); - message.requestId !== undefined && (obj.requestId = base64FromBytes(message.requestId !== undefined ? message.requestId : Buffer.alloc(0))); - return obj; - }, - - fromPartial, I>>( - object: I - ): LicenseRequest_ContentIdentification_WidevinePsshData { - const message = createBaseLicenseRequest_ContentIdentification_WidevinePsshData(); - message.psshData = object.psshData?.map((e) => e) || []; - message.licenseType = object.licenseType ?? 1; - message.requestId = object.requestId ?? Buffer.alloc(0); - return message; - } -}; - -function createBaseLicenseRequest_ContentIdentification_WebmKeyId(): LicenseRequest_ContentIdentification_WebmKeyId { - return { header: Buffer.alloc(0), licenseType: 1, requestId: Buffer.alloc(0) }; -} - -export const LicenseRequest_ContentIdentification_WebmKeyId = { - encode(message: LicenseRequest_ContentIdentification_WebmKeyId, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { - if (message.header.length !== 0) { - writer.uint32(10).bytes(message.header); - } - if (message.licenseType !== 1) { - writer.uint32(16).int32(message.licenseType); - } - if (message.requestId.length !== 0) { - writer.uint32(26).bytes(message.requestId); - } - return writer; - }, - - decode(input: _m0.Reader | Uint8Array, length?: number): LicenseRequest_ContentIdentification_WebmKeyId { - const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); - const end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseLicenseRequest_ContentIdentification_WebmKeyId(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - message.header = reader.bytes() as Buffer; - break; - case 2: - message.licenseType = reader.int32() as any; - break; - case 3: - message.requestId = reader.bytes() as Buffer; - break; - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }, - - fromJSON(object: any): LicenseRequest_ContentIdentification_WebmKeyId { - return { - header: isSet(object.header) ? Buffer.from(bytesFromBase64(object.header)) : Buffer.alloc(0), - licenseType: isSet(object.licenseType) ? licenseTypeFromJSON(object.licenseType) : 1, - requestId: isSet(object.requestId) ? Buffer.from(bytesFromBase64(object.requestId)) : Buffer.alloc(0) - }; - }, - - toJSON(message: LicenseRequest_ContentIdentification_WebmKeyId): unknown { - const obj: any = {}; - message.header !== undefined && (obj.header = base64FromBytes(message.header !== undefined ? message.header : Buffer.alloc(0))); - message.licenseType !== undefined && (obj.licenseType = licenseTypeToJSON(message.licenseType)); - message.requestId !== undefined && (obj.requestId = base64FromBytes(message.requestId !== undefined ? message.requestId : Buffer.alloc(0))); - return obj; - }, - - fromPartial, I>>( - object: I - ): LicenseRequest_ContentIdentification_WebmKeyId { - const message = createBaseLicenseRequest_ContentIdentification_WebmKeyId(); - message.header = object.header ?? Buffer.alloc(0); - message.licenseType = object.licenseType ?? 1; - message.requestId = object.requestId ?? Buffer.alloc(0); - return message; - } -}; - -function createBaseLicenseRequest_ContentIdentification_ExistingLicense(): LicenseRequest_ContentIdentification_ExistingLicense { - return { - licenseId: undefined, - secondsSinceStarted: Long.ZERO, - secondsSinceLastPlayed: Long.ZERO, - sessionUsageTableEntry: Buffer.alloc(0) - }; -} - -export const LicenseRequest_ContentIdentification_ExistingLicense = { - encode(message: LicenseRequest_ContentIdentification_ExistingLicense, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { - if (message.licenseId !== undefined) { - LicenseIdentification.encode(message.licenseId, writer.uint32(10).fork()).ldelim(); - } - if (!message.secondsSinceStarted.isZero()) { - writer.uint32(16).int64(message.secondsSinceStarted); - } - if (!message.secondsSinceLastPlayed.isZero()) { - writer.uint32(24).int64(message.secondsSinceLastPlayed); - } - if (message.sessionUsageTableEntry.length !== 0) { - writer.uint32(34).bytes(message.sessionUsageTableEntry); - } - return writer; - }, - - decode(input: _m0.Reader | Uint8Array, length?: number): LicenseRequest_ContentIdentification_ExistingLicense { - const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); - const end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseLicenseRequest_ContentIdentification_ExistingLicense(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - message.licenseId = LicenseIdentification.decode(reader, reader.uint32()); - break; - case 2: - message.secondsSinceStarted = reader.int64() as Long; - break; - case 3: - message.secondsSinceLastPlayed = reader.int64() as Long; - break; - case 4: - message.sessionUsageTableEntry = reader.bytes() as Buffer; - break; - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }, - - fromJSON(object: any): LicenseRequest_ContentIdentification_ExistingLicense { - return { - licenseId: isSet(object.licenseId) ? LicenseIdentification.fromJSON(object.licenseId) : undefined, - secondsSinceStarted: isSet(object.secondsSinceStarted) ? Long.fromValue(object.secondsSinceStarted) : Long.ZERO, - secondsSinceLastPlayed: isSet(object.secondsSinceLastPlayed) ? Long.fromValue(object.secondsSinceLastPlayed) : Long.ZERO, - sessionUsageTableEntry: isSet(object.sessionUsageTableEntry) ? Buffer.from(bytesFromBase64(object.sessionUsageTableEntry)) : Buffer.alloc(0) - }; - }, - - toJSON(message: LicenseRequest_ContentIdentification_ExistingLicense): unknown { - const obj: any = {}; - message.licenseId !== undefined && (obj.licenseId = message.licenseId ? LicenseIdentification.toJSON(message.licenseId) : undefined); - message.secondsSinceStarted !== undefined && (obj.secondsSinceStarted = (message.secondsSinceStarted || Long.ZERO).toString()); - message.secondsSinceLastPlayed !== undefined && (obj.secondsSinceLastPlayed = (message.secondsSinceLastPlayed || Long.ZERO).toString()); - message.sessionUsageTableEntry !== undefined && - (obj.sessionUsageTableEntry = base64FromBytes(message.sessionUsageTableEntry !== undefined ? message.sessionUsageTableEntry : Buffer.alloc(0))); - return obj; - }, - - fromPartial, I>>( - object: I - ): LicenseRequest_ContentIdentification_ExistingLicense { - const message = createBaseLicenseRequest_ContentIdentification_ExistingLicense(); - message.licenseId = object.licenseId !== undefined && object.licenseId !== null ? LicenseIdentification.fromPartial(object.licenseId) : undefined; - message.secondsSinceStarted = - object.secondsSinceStarted !== undefined && object.secondsSinceStarted !== null ? Long.fromValue(object.secondsSinceStarted) : Long.ZERO; - message.secondsSinceLastPlayed = - object.secondsSinceLastPlayed !== undefined && object.secondsSinceLastPlayed !== null - ? Long.fromValue(object.secondsSinceLastPlayed) - : Long.ZERO; - message.sessionUsageTableEntry = object.sessionUsageTableEntry ?? Buffer.alloc(0); - return message; - } -}; - -function createBaseLicenseRequest_ContentIdentification_InitData(): LicenseRequest_ContentIdentification_InitData { - return { initDataType: 1, initData: Buffer.alloc(0), licenseType: 1, requestId: Buffer.alloc(0) }; -} - -export const LicenseRequest_ContentIdentification_InitData = { - encode(message: LicenseRequest_ContentIdentification_InitData, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { - if (message.initDataType !== 1) { - writer.uint32(8).int32(message.initDataType); - } - if (message.initData.length !== 0) { - writer.uint32(18).bytes(message.initData); - } - if (message.licenseType !== 1) { - writer.uint32(24).int32(message.licenseType); - } - if (message.requestId.length !== 0) { - writer.uint32(34).bytes(message.requestId); - } - return writer; - }, - - decode(input: _m0.Reader | Uint8Array, length?: number): LicenseRequest_ContentIdentification_InitData { - const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); - const end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseLicenseRequest_ContentIdentification_InitData(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - message.initDataType = reader.int32() as any; - break; - case 2: - message.initData = reader.bytes() as Buffer; - break; - case 3: - message.licenseType = reader.int32() as any; - break; - case 4: - message.requestId = reader.bytes() as Buffer; - break; - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }, - - fromJSON(object: any): LicenseRequest_ContentIdentification_InitData { - return { - initDataType: isSet(object.initDataType) ? licenseRequest_ContentIdentification_InitData_InitDataTypeFromJSON(object.initDataType) : 1, - initData: isSet(object.initData) ? Buffer.from(bytesFromBase64(object.initData)) : Buffer.alloc(0), - licenseType: isSet(object.licenseType) ? licenseTypeFromJSON(object.licenseType) : 1, - requestId: isSet(object.requestId) ? Buffer.from(bytesFromBase64(object.requestId)) : Buffer.alloc(0) - }; - }, - - toJSON(message: LicenseRequest_ContentIdentification_InitData): unknown { - const obj: any = {}; - message.initDataType !== undefined && (obj.initDataType = licenseRequest_ContentIdentification_InitData_InitDataTypeToJSON(message.initDataType)); - message.initData !== undefined && (obj.initData = base64FromBytes(message.initData !== undefined ? message.initData : Buffer.alloc(0))); - message.licenseType !== undefined && (obj.licenseType = licenseTypeToJSON(message.licenseType)); - message.requestId !== undefined && (obj.requestId = base64FromBytes(message.requestId !== undefined ? message.requestId : Buffer.alloc(0))); - return obj; - }, - - fromPartial, I>>( - object: I - ): LicenseRequest_ContentIdentification_InitData { - const message = createBaseLicenseRequest_ContentIdentification_InitData(); - message.initDataType = object.initDataType ?? 1; - message.initData = object.initData ?? Buffer.alloc(0); - message.licenseType = object.licenseType ?? 1; - message.requestId = object.requestId ?? Buffer.alloc(0); - return message; - } -}; - -function createBaseMetricData(): MetricData { - return { stageName: '', metricData: [] }; -} - -export const MetricData = { - encode(message: MetricData, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { - if (message.stageName !== '') { - writer.uint32(10).string(message.stageName); - } - for (const v of message.metricData) { - MetricData_TypeValue.encode(v!, writer.uint32(18).fork()).ldelim(); - } - return writer; - }, - - decode(input: _m0.Reader | Uint8Array, length?: number): MetricData { - const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); - const end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseMetricData(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - message.stageName = reader.string(); - break; - case 2: - message.metricData.push(MetricData_TypeValue.decode(reader, reader.uint32())); - break; - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }, - - fromJSON(object: any): MetricData { - return { - stageName: isSet(object.stageName) ? String(object.stageName) : '', - metricData: Array.isArray(object?.metricData) ? object.metricData.map((e: any) => MetricData_TypeValue.fromJSON(e)) : [] - }; - }, - - toJSON(message: MetricData): unknown { - const obj: any = {}; - message.stageName !== undefined && (obj.stageName = message.stageName); - if (message.metricData) { - obj.metricData = message.metricData.map((e) => (e ? MetricData_TypeValue.toJSON(e) : undefined)); - } else { - obj.metricData = []; - } - return obj; - }, - - fromPartial, I>>(object: I): MetricData { - const message = createBaseMetricData(); - message.stageName = object.stageName ?? ''; - message.metricData = object.metricData?.map((e) => MetricData_TypeValue.fromPartial(e)) || []; - return message; - } -}; - -function createBaseMetricData_TypeValue(): MetricData_TypeValue { - return { type: 1, value: Long.ZERO }; -} - -export const MetricData_TypeValue = { - encode(message: MetricData_TypeValue, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { - if (message.type !== 1) { - writer.uint32(8).int32(message.type); - } - if (!message.value.isZero()) { - writer.uint32(16).int64(message.value); - } - return writer; - }, - - decode(input: _m0.Reader | Uint8Array, length?: number): MetricData_TypeValue { - const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); - const end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseMetricData_TypeValue(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - message.type = reader.int32() as any; - break; - case 2: - message.value = reader.int64() as Long; - break; - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }, - - fromJSON(object: any): MetricData_TypeValue { - return { - type: isSet(object.type) ? metricData_MetricTypeFromJSON(object.type) : 1, - value: isSet(object.value) ? Long.fromValue(object.value) : Long.ZERO - }; - }, - - toJSON(message: MetricData_TypeValue): unknown { - const obj: any = {}; - message.type !== undefined && (obj.type = metricData_MetricTypeToJSON(message.type)); - message.value !== undefined && (obj.value = (message.value || Long.ZERO).toString()); - return obj; - }, - - fromPartial, I>>(object: I): MetricData_TypeValue { - const message = createBaseMetricData_TypeValue(); - message.type = object.type ?? 1; - message.value = object.value !== undefined && object.value !== null ? Long.fromValue(object.value) : Long.ZERO; - return message; - } -}; - -function createBaseVersionInfo(): VersionInfo { - return { licenseSdkVersion: '', licenseServiceVersion: '' }; -} - -export const VersionInfo = { - encode(message: VersionInfo, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { - if (message.licenseSdkVersion !== '') { - writer.uint32(10).string(message.licenseSdkVersion); - } - if (message.licenseServiceVersion !== '') { - writer.uint32(18).string(message.licenseServiceVersion); - } - return writer; - }, - - decode(input: _m0.Reader | Uint8Array, length?: number): VersionInfo { - const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); - const end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseVersionInfo(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - message.licenseSdkVersion = reader.string(); - break; - case 2: - message.licenseServiceVersion = reader.string(); - break; - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }, - - fromJSON(object: any): VersionInfo { - return { - licenseSdkVersion: isSet(object.licenseSdkVersion) ? String(object.licenseSdkVersion) : '', - licenseServiceVersion: isSet(object.licenseServiceVersion) ? String(object.licenseServiceVersion) : '' - }; - }, - - toJSON(message: VersionInfo): unknown { - const obj: any = {}; - message.licenseSdkVersion !== undefined && (obj.licenseSdkVersion = message.licenseSdkVersion); - message.licenseServiceVersion !== undefined && (obj.licenseServiceVersion = message.licenseServiceVersion); - return obj; - }, - - fromPartial, I>>(object: I): VersionInfo { - const message = createBaseVersionInfo(); - message.licenseSdkVersion = object.licenseSdkVersion ?? ''; - message.licenseServiceVersion = object.licenseServiceVersion ?? ''; - return message; - } -}; - -function createBaseSignedMessage(): SignedMessage { - return { - type: 1, - msg: Buffer.alloc(0), - signature: Buffer.alloc(0), - sessionKey: Buffer.alloc(0), - remoteAttestation: Buffer.alloc(0), - metricData: [], - serviceVersionInfo: undefined, - sessionKeyType: 0, - oemcryptoCoreMessage: Buffer.alloc(0) - }; -} - -export const SignedMessage = { - encode(message: SignedMessage, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { - if (message.type !== 1) { - writer.uint32(8).int32(message.type); - } - if (message.msg.length !== 0) { - writer.uint32(18).bytes(message.msg); - } - if (message.signature.length !== 0) { - writer.uint32(26).bytes(message.signature); - } - if (message.sessionKey.length !== 0) { - writer.uint32(34).bytes(message.sessionKey); - } - if (message.remoteAttestation.length !== 0) { - writer.uint32(42).bytes(message.remoteAttestation); - } - for (const v of message.metricData) { - MetricData.encode(v!, writer.uint32(50).fork()).ldelim(); - } - if (message.serviceVersionInfo !== undefined) { - VersionInfo.encode(message.serviceVersionInfo, writer.uint32(58).fork()).ldelim(); - } - if (message.sessionKeyType !== 0) { - writer.uint32(64).int32(message.sessionKeyType); - } - if (message.oemcryptoCoreMessage.length !== 0) { - writer.uint32(74).bytes(message.oemcryptoCoreMessage); - } - return writer; - }, - - decode(input: _m0.Reader | Uint8Array, length?: number): SignedMessage { - const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); - const end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseSignedMessage(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - message.type = reader.int32() as any; - break; - case 2: - message.msg = reader.bytes() as Buffer; - break; - case 3: - message.signature = reader.bytes() as Buffer; - break; - case 4: - message.sessionKey = reader.bytes() as Buffer; - break; - case 5: - message.remoteAttestation = reader.bytes() as Buffer; - break; - case 6: - message.metricData.push(MetricData.decode(reader, reader.uint32())); - break; - case 7: - message.serviceVersionInfo = VersionInfo.decode(reader, reader.uint32()); - break; - case 8: - message.sessionKeyType = reader.int32() as any; - break; - case 9: - message.oemcryptoCoreMessage = reader.bytes() as Buffer; - break; - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }, - - fromJSON(object: any): SignedMessage { - return { - type: isSet(object.type) ? signedMessage_MessageTypeFromJSON(object.type) : 1, - msg: isSet(object.msg) ? Buffer.from(bytesFromBase64(object.msg)) : Buffer.alloc(0), - signature: isSet(object.signature) ? Buffer.from(bytesFromBase64(object.signature)) : Buffer.alloc(0), - sessionKey: isSet(object.sessionKey) ? Buffer.from(bytesFromBase64(object.sessionKey)) : Buffer.alloc(0), - remoteAttestation: isSet(object.remoteAttestation) ? Buffer.from(bytesFromBase64(object.remoteAttestation)) : Buffer.alloc(0), - metricData: Array.isArray(object?.metricData) ? object.metricData.map((e: any) => MetricData.fromJSON(e)) : [], - serviceVersionInfo: isSet(object.serviceVersionInfo) ? VersionInfo.fromJSON(object.serviceVersionInfo) : undefined, - sessionKeyType: isSet(object.sessionKeyType) ? signedMessage_SessionKeyTypeFromJSON(object.sessionKeyType) : 0, - oemcryptoCoreMessage: isSet(object.oemcryptoCoreMessage) ? Buffer.from(bytesFromBase64(object.oemcryptoCoreMessage)) : Buffer.alloc(0) - }; - }, - - toJSON(message: SignedMessage): unknown { - const obj: any = {}; - message.type !== undefined && (obj.type = signedMessage_MessageTypeToJSON(message.type)); - message.msg !== undefined && (obj.msg = base64FromBytes(message.msg !== undefined ? message.msg : Buffer.alloc(0))); - message.signature !== undefined && (obj.signature = base64FromBytes(message.signature !== undefined ? message.signature : Buffer.alloc(0))); - message.sessionKey !== undefined && (obj.sessionKey = base64FromBytes(message.sessionKey !== undefined ? message.sessionKey : Buffer.alloc(0))); - message.remoteAttestation !== undefined && - (obj.remoteAttestation = base64FromBytes(message.remoteAttestation !== undefined ? message.remoteAttestation : Buffer.alloc(0))); - if (message.metricData) { - obj.metricData = message.metricData.map((e) => (e ? MetricData.toJSON(e) : undefined)); - } else { - obj.metricData = []; - } - message.serviceVersionInfo !== undefined && - (obj.serviceVersionInfo = message.serviceVersionInfo ? VersionInfo.toJSON(message.serviceVersionInfo) : undefined); - message.sessionKeyType !== undefined && (obj.sessionKeyType = signedMessage_SessionKeyTypeToJSON(message.sessionKeyType)); - message.oemcryptoCoreMessage !== undefined && - (obj.oemcryptoCoreMessage = base64FromBytes(message.oemcryptoCoreMessage !== undefined ? message.oemcryptoCoreMessage : Buffer.alloc(0))); - return obj; - }, - - fromPartial, I>>(object: I): SignedMessage { - const message = createBaseSignedMessage(); - message.type = object.type ?? 1; - message.msg = object.msg ?? Buffer.alloc(0); - message.signature = object.signature ?? Buffer.alloc(0); - message.sessionKey = object.sessionKey ?? Buffer.alloc(0); - message.remoteAttestation = object.remoteAttestation ?? Buffer.alloc(0); - message.metricData = object.metricData?.map((e) => MetricData.fromPartial(e)) || []; - message.serviceVersionInfo = - object.serviceVersionInfo !== undefined && object.serviceVersionInfo !== null ? VersionInfo.fromPartial(object.serviceVersionInfo) : undefined; - message.sessionKeyType = object.sessionKeyType ?? 0; - message.oemcryptoCoreMessage = object.oemcryptoCoreMessage ?? Buffer.alloc(0); - return message; - } -}; - -function createBaseClientIdentification(): ClientIdentification { - return { - type: 0, - token: Buffer.alloc(0), - clientInfo: [], - providerClientToken: Buffer.alloc(0), - licenseCounter: 0, - clientCapabilities: undefined, - vmpData: Buffer.alloc(0), - deviceCredentials: [] - }; -} - -export const ClientIdentification = { - encode(message: ClientIdentification, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { - if (message.type !== 0) { - writer.uint32(8).int32(message.type); - } - if (message.token.length !== 0) { - writer.uint32(18).bytes(message.token); - } - for (const v of message.clientInfo) { - ClientIdentification_NameValue.encode(v!, writer.uint32(26).fork()).ldelim(); - } - if (message.providerClientToken.length !== 0) { - writer.uint32(34).bytes(message.providerClientToken); - } - if (message.licenseCounter !== 0) { - writer.uint32(40).uint32(message.licenseCounter); - } - if (message.clientCapabilities !== undefined) { - ClientIdentification_ClientCapabilities.encode(message.clientCapabilities, writer.uint32(50).fork()).ldelim(); - } - if (message.vmpData.length !== 0) { - writer.uint32(58).bytes(message.vmpData); - } - for (const v of message.deviceCredentials) { - ClientIdentification_ClientCredentials.encode(v!, writer.uint32(66).fork()).ldelim(); - } - return writer; - }, - - decode(input: _m0.Reader | Uint8Array, length?: number): ClientIdentification { - const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); - const end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseClientIdentification(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - message.type = reader.int32() as any; - break; - case 2: - message.token = reader.bytes() as Buffer; - break; - case 3: - message.clientInfo.push(ClientIdentification_NameValue.decode(reader, reader.uint32())); - break; - case 4: - message.providerClientToken = reader.bytes() as Buffer; - break; - case 5: - message.licenseCounter = reader.uint32(); - break; - case 6: - message.clientCapabilities = ClientIdentification_ClientCapabilities.decode(reader, reader.uint32()); - break; - case 7: - message.vmpData = reader.bytes() as Buffer; - break; - case 8: - message.deviceCredentials.push(ClientIdentification_ClientCredentials.decode(reader, reader.uint32())); - break; - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }, - - fromJSON(object: any): ClientIdentification { - return { - type: isSet(object.type) ? clientIdentification_TokenTypeFromJSON(object.type) : 0, - token: isSet(object.token) ? Buffer.from(bytesFromBase64(object.token)) : Buffer.alloc(0), - clientInfo: Array.isArray(object?.clientInfo) ? object.clientInfo.map((e: any) => ClientIdentification_NameValue.fromJSON(e)) : [], - providerClientToken: isSet(object.providerClientToken) ? Buffer.from(bytesFromBase64(object.providerClientToken)) : Buffer.alloc(0), - licenseCounter: isSet(object.licenseCounter) ? Number(object.licenseCounter) : 0, - clientCapabilities: isSet(object.clientCapabilities) ? ClientIdentification_ClientCapabilities.fromJSON(object.clientCapabilities) : undefined, - vmpData: isSet(object.vmpData) ? Buffer.from(bytesFromBase64(object.vmpData)) : Buffer.alloc(0), - deviceCredentials: Array.isArray(object?.deviceCredentials) - ? object.deviceCredentials.map((e: any) => ClientIdentification_ClientCredentials.fromJSON(e)) - : [] - }; - }, - - toJSON(message: ClientIdentification): unknown { - const obj: any = {}; - message.type !== undefined && (obj.type = clientIdentification_TokenTypeToJSON(message.type)); - message.token !== undefined && (obj.token = base64FromBytes(message.token !== undefined ? message.token : Buffer.alloc(0))); - if (message.clientInfo) { - obj.clientInfo = message.clientInfo.map((e) => (e ? ClientIdentification_NameValue.toJSON(e) : undefined)); - } else { - obj.clientInfo = []; - } - message.providerClientToken !== undefined && - (obj.providerClientToken = base64FromBytes(message.providerClientToken !== undefined ? message.providerClientToken : Buffer.alloc(0))); - message.licenseCounter !== undefined && (obj.licenseCounter = Math.round(message.licenseCounter)); - message.clientCapabilities !== undefined && - (obj.clientCapabilities = message.clientCapabilities ? ClientIdentification_ClientCapabilities.toJSON(message.clientCapabilities) : undefined); - message.vmpData !== undefined && (obj.vmpData = base64FromBytes(message.vmpData !== undefined ? message.vmpData : Buffer.alloc(0))); - if (message.deviceCredentials) { - obj.deviceCredentials = message.deviceCredentials.map((e) => (e ? ClientIdentification_ClientCredentials.toJSON(e) : undefined)); - } else { - obj.deviceCredentials = []; - } - return obj; - }, - - fromPartial, I>>(object: I): ClientIdentification { - const message = createBaseClientIdentification(); - message.type = object.type ?? 0; - message.token = object.token ?? Buffer.alloc(0); - message.clientInfo = object.clientInfo?.map((e) => ClientIdentification_NameValue.fromPartial(e)) || []; - message.providerClientToken = object.providerClientToken ?? Buffer.alloc(0); - message.licenseCounter = object.licenseCounter ?? 0; - message.clientCapabilities = - object.clientCapabilities !== undefined && object.clientCapabilities !== null - ? ClientIdentification_ClientCapabilities.fromPartial(object.clientCapabilities) - : undefined; - message.vmpData = object.vmpData ?? Buffer.alloc(0); - message.deviceCredentials = object.deviceCredentials?.map((e) => ClientIdentification_ClientCredentials.fromPartial(e)) || []; - return message; - } -}; - -function createBaseClientIdentification_NameValue(): ClientIdentification_NameValue { - return { name: '', value: '' }; -} - -export const ClientIdentification_NameValue = { - encode(message: ClientIdentification_NameValue, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { - if (message.name !== '') { - writer.uint32(10).string(message.name); - } - if (message.value !== '') { - writer.uint32(18).string(message.value); - } - return writer; - }, - - decode(input: _m0.Reader | Uint8Array, length?: number): ClientIdentification_NameValue { - const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); - const end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseClientIdentification_NameValue(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - message.name = reader.string(); - break; - case 2: - message.value = reader.string(); - break; - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }, - - fromJSON(object: any): ClientIdentification_NameValue { - return { - name: isSet(object.name) ? String(object.name) : '', - value: isSet(object.value) ? String(object.value) : '' - }; - }, - - toJSON(message: ClientIdentification_NameValue): unknown { - const obj: any = {}; - message.name !== undefined && (obj.name = message.name); - message.value !== undefined && (obj.value = message.value); - return obj; - }, - - fromPartial, I>>(object: I): ClientIdentification_NameValue { - const message = createBaseClientIdentification_NameValue(); - message.name = object.name ?? ''; - message.value = object.value ?? ''; - return message; - } -}; - -function createBaseClientIdentification_ClientCapabilities(): ClientIdentification_ClientCapabilities { - return { - clientToken: false, - sessionToken: false, - videoResolutionConstraints: false, - maxHdcpVersion: 0, - oemCryptoApiVersion: 0, - antiRollbackUsageTable: false, - srmVersion: 0, - canUpdateSrm: false, - supportedCertificateKeyType: [], - analogOutputCapabilities: 0, - canDisableAnalogOutput: false, - resourceRatingTier: 0 - }; -} - -export const ClientIdentification_ClientCapabilities = { - encode(message: ClientIdentification_ClientCapabilities, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { - if (message.clientToken === true) { - writer.uint32(8).bool(message.clientToken); - } - if (message.sessionToken === true) { - writer.uint32(16).bool(message.sessionToken); - } - if (message.videoResolutionConstraints === true) { - writer.uint32(24).bool(message.videoResolutionConstraints); - } - if (message.maxHdcpVersion !== 0) { - writer.uint32(32).int32(message.maxHdcpVersion); - } - if (message.oemCryptoApiVersion !== 0) { - writer.uint32(40).uint32(message.oemCryptoApiVersion); - } - if (message.antiRollbackUsageTable === true) { - writer.uint32(48).bool(message.antiRollbackUsageTable); - } - if (message.srmVersion !== 0) { - writer.uint32(56).uint32(message.srmVersion); - } - if (message.canUpdateSrm === true) { - writer.uint32(64).bool(message.canUpdateSrm); - } - writer.uint32(74).fork(); - for (const v of message.supportedCertificateKeyType) { - writer.int32(v); - } - writer.ldelim(); - if (message.analogOutputCapabilities !== 0) { - writer.uint32(80).int32(message.analogOutputCapabilities); - } - if (message.canDisableAnalogOutput === true) { - writer.uint32(88).bool(message.canDisableAnalogOutput); - } - if (message.resourceRatingTier !== 0) { - writer.uint32(96).uint32(message.resourceRatingTier); - } - return writer; - }, - - decode(input: _m0.Reader | Uint8Array, length?: number): ClientIdentification_ClientCapabilities { - const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); - const end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseClientIdentification_ClientCapabilities(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - message.clientToken = reader.bool(); - break; - case 2: - message.sessionToken = reader.bool(); - break; - case 3: - message.videoResolutionConstraints = reader.bool(); - break; - case 4: - message.maxHdcpVersion = reader.int32() as any; - break; - case 5: - message.oemCryptoApiVersion = reader.uint32(); - break; - case 6: - message.antiRollbackUsageTable = reader.bool(); - break; - case 7: - message.srmVersion = reader.uint32(); - break; - case 8: - message.canUpdateSrm = reader.bool(); - break; - case 9: - if ((tag & 7) === 2) { - const end2 = reader.uint32() + reader.pos; - while (reader.pos < end2) { - message.supportedCertificateKeyType.push(reader.int32() as any); - } - } else { - message.supportedCertificateKeyType.push(reader.int32() as any); - } - break; - case 10: - message.analogOutputCapabilities = reader.int32() as any; - break; - case 11: - message.canDisableAnalogOutput = reader.bool(); - break; - case 12: - message.resourceRatingTier = reader.uint32(); - break; - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }, - - fromJSON(object: any): ClientIdentification_ClientCapabilities { - return { - clientToken: isSet(object.clientToken) ? Boolean(object.clientToken) : false, - sessionToken: isSet(object.sessionToken) ? Boolean(object.sessionToken) : false, - videoResolutionConstraints: isSet(object.videoResolutionConstraints) ? Boolean(object.videoResolutionConstraints) : false, - maxHdcpVersion: isSet(object.maxHdcpVersion) ? clientIdentification_ClientCapabilities_HdcpVersionFromJSON(object.maxHdcpVersion) : 0, - oemCryptoApiVersion: isSet(object.oemCryptoApiVersion) ? Number(object.oemCryptoApiVersion) : 0, - antiRollbackUsageTable: isSet(object.antiRollbackUsageTable) ? Boolean(object.antiRollbackUsageTable) : false, - srmVersion: isSet(object.srmVersion) ? Number(object.srmVersion) : 0, - canUpdateSrm: isSet(object.canUpdateSrm) ? Boolean(object.canUpdateSrm) : false, - supportedCertificateKeyType: Array.isArray(object?.supportedCertificateKeyType) - ? object.supportedCertificateKeyType.map((e: any) => clientIdentification_ClientCapabilities_CertificateKeyTypeFromJSON(e)) - : [], - analogOutputCapabilities: isSet(object.analogOutputCapabilities) - ? clientIdentification_ClientCapabilities_AnalogOutputCapabilitiesFromJSON(object.analogOutputCapabilities) - : 0, - canDisableAnalogOutput: isSet(object.canDisableAnalogOutput) ? Boolean(object.canDisableAnalogOutput) : false, - resourceRatingTier: isSet(object.resourceRatingTier) ? Number(object.resourceRatingTier) : 0 - }; - }, - - toJSON(message: ClientIdentification_ClientCapabilities): unknown { - const obj: any = {}; - message.clientToken !== undefined && (obj.clientToken = message.clientToken); - message.sessionToken !== undefined && (obj.sessionToken = message.sessionToken); - message.videoResolutionConstraints !== undefined && (obj.videoResolutionConstraints = message.videoResolutionConstraints); - message.maxHdcpVersion !== undefined && (obj.maxHdcpVersion = clientIdentification_ClientCapabilities_HdcpVersionToJSON(message.maxHdcpVersion)); - message.oemCryptoApiVersion !== undefined && (obj.oemCryptoApiVersion = Math.round(message.oemCryptoApiVersion)); - message.antiRollbackUsageTable !== undefined && (obj.antiRollbackUsageTable = message.antiRollbackUsageTable); - message.srmVersion !== undefined && (obj.srmVersion = Math.round(message.srmVersion)); - message.canUpdateSrm !== undefined && (obj.canUpdateSrm = message.canUpdateSrm); - if (message.supportedCertificateKeyType) { - obj.supportedCertificateKeyType = message.supportedCertificateKeyType.map((e) => - clientIdentification_ClientCapabilities_CertificateKeyTypeToJSON(e) - ); - } else { - obj.supportedCertificateKeyType = []; - } - message.analogOutputCapabilities !== undefined && - (obj.analogOutputCapabilities = clientIdentification_ClientCapabilities_AnalogOutputCapabilitiesToJSON(message.analogOutputCapabilities)); - message.canDisableAnalogOutput !== undefined && (obj.canDisableAnalogOutput = message.canDisableAnalogOutput); - message.resourceRatingTier !== undefined && (obj.resourceRatingTier = Math.round(message.resourceRatingTier)); - return obj; - }, - - fromPartial, I>>(object: I): ClientIdentification_ClientCapabilities { - const message = createBaseClientIdentification_ClientCapabilities(); - message.clientToken = object.clientToken ?? false; - message.sessionToken = object.sessionToken ?? false; - message.videoResolutionConstraints = object.videoResolutionConstraints ?? false; - message.maxHdcpVersion = object.maxHdcpVersion ?? 0; - message.oemCryptoApiVersion = object.oemCryptoApiVersion ?? 0; - message.antiRollbackUsageTable = object.antiRollbackUsageTable ?? false; - message.srmVersion = object.srmVersion ?? 0; - message.canUpdateSrm = object.canUpdateSrm ?? false; - message.supportedCertificateKeyType = object.supportedCertificateKeyType?.map((e) => e) || []; - message.analogOutputCapabilities = object.analogOutputCapabilities ?? 0; - message.canDisableAnalogOutput = object.canDisableAnalogOutput ?? false; - message.resourceRatingTier = object.resourceRatingTier ?? 0; - return message; - } -}; - -function createBaseClientIdentification_ClientCredentials(): ClientIdentification_ClientCredentials { - return { type: 0, token: Buffer.alloc(0) }; -} - -export const ClientIdentification_ClientCredentials = { - encode(message: ClientIdentification_ClientCredentials, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { - if (message.type !== 0) { - writer.uint32(8).int32(message.type); - } - if (message.token.length !== 0) { - writer.uint32(18).bytes(message.token); - } - return writer; - }, - - decode(input: _m0.Reader | Uint8Array, length?: number): ClientIdentification_ClientCredentials { - const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); - const end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseClientIdentification_ClientCredentials(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - message.type = reader.int32() as any; - break; - case 2: - message.token = reader.bytes() as Buffer; - break; - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }, - - fromJSON(object: any): ClientIdentification_ClientCredentials { - return { - type: isSet(object.type) ? clientIdentification_TokenTypeFromJSON(object.type) : 0, - token: isSet(object.token) ? Buffer.from(bytesFromBase64(object.token)) : Buffer.alloc(0) - }; - }, - - toJSON(message: ClientIdentification_ClientCredentials): unknown { - const obj: any = {}; - message.type !== undefined && (obj.type = clientIdentification_TokenTypeToJSON(message.type)); - message.token !== undefined && (obj.token = base64FromBytes(message.token !== undefined ? message.token : Buffer.alloc(0))); - return obj; - }, - - fromPartial, I>>(object: I): ClientIdentification_ClientCredentials { - const message = createBaseClientIdentification_ClientCredentials(); - message.type = object.type ?? 0; - message.token = object.token ?? Buffer.alloc(0); - return message; - } -}; - -function createBaseEncryptedClientIdentification(): EncryptedClientIdentification { - return { - providerId: '', - serviceCertificateSerialNumber: Buffer.alloc(0), - encryptedClientId: Buffer.alloc(0), - encryptedClientIdIv: Buffer.alloc(0), - encryptedPrivacyKey: Buffer.alloc(0) - }; -} - -export const EncryptedClientIdentification = { - encode(message: EncryptedClientIdentification, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { - if (message.providerId !== '') { - writer.uint32(10).string(message.providerId); - } - if (message.serviceCertificateSerialNumber.length !== 0) { - writer.uint32(18).bytes(message.serviceCertificateSerialNumber); - } - if (message.encryptedClientId.length !== 0) { - writer.uint32(26).bytes(message.encryptedClientId); - } - if (message.encryptedClientIdIv.length !== 0) { - writer.uint32(34).bytes(message.encryptedClientIdIv); - } - if (message.encryptedPrivacyKey.length !== 0) { - writer.uint32(42).bytes(message.encryptedPrivacyKey); - } - return writer; - }, - - decode(input: _m0.Reader | Uint8Array, length?: number): EncryptedClientIdentification { - const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); - const end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseEncryptedClientIdentification(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - message.providerId = reader.string(); - break; - case 2: - message.serviceCertificateSerialNumber = reader.bytes() as Buffer; - break; - case 3: - message.encryptedClientId = reader.bytes() as Buffer; - break; - case 4: - message.encryptedClientIdIv = reader.bytes() as Buffer; - break; - case 5: - message.encryptedPrivacyKey = reader.bytes() as Buffer; - break; - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }, - - fromJSON(object: any): EncryptedClientIdentification { - return { - providerId: isSet(object.providerId) ? String(object.providerId) : '', - serviceCertificateSerialNumber: isSet(object.serviceCertificateSerialNumber) - ? Buffer.from(bytesFromBase64(object.serviceCertificateSerialNumber)) - : Buffer.alloc(0), - encryptedClientId: isSet(object.encryptedClientId) ? Buffer.from(bytesFromBase64(object.encryptedClientId)) : Buffer.alloc(0), - encryptedClientIdIv: isSet(object.encryptedClientIdIv) ? Buffer.from(bytesFromBase64(object.encryptedClientIdIv)) : Buffer.alloc(0), - encryptedPrivacyKey: isSet(object.encryptedPrivacyKey) ? Buffer.from(bytesFromBase64(object.encryptedPrivacyKey)) : Buffer.alloc(0) - }; - }, - - toJSON(message: EncryptedClientIdentification): unknown { - const obj: any = {}; - message.providerId !== undefined && (obj.providerId = message.providerId); - message.serviceCertificateSerialNumber !== undefined && - (obj.serviceCertificateSerialNumber = base64FromBytes( - message.serviceCertificateSerialNumber !== undefined ? message.serviceCertificateSerialNumber : Buffer.alloc(0) - )); - message.encryptedClientId !== undefined && - (obj.encryptedClientId = base64FromBytes(message.encryptedClientId !== undefined ? message.encryptedClientId : Buffer.alloc(0))); - message.encryptedClientIdIv !== undefined && - (obj.encryptedClientIdIv = base64FromBytes(message.encryptedClientIdIv !== undefined ? message.encryptedClientIdIv : Buffer.alloc(0))); - message.encryptedPrivacyKey !== undefined && - (obj.encryptedPrivacyKey = base64FromBytes(message.encryptedPrivacyKey !== undefined ? message.encryptedPrivacyKey : Buffer.alloc(0))); - return obj; - }, - - fromPartial, I>>(object: I): EncryptedClientIdentification { - const message = createBaseEncryptedClientIdentification(); - message.providerId = object.providerId ?? ''; - message.serviceCertificateSerialNumber = object.serviceCertificateSerialNumber ?? Buffer.alloc(0); - message.encryptedClientId = object.encryptedClientId ?? Buffer.alloc(0); - message.encryptedClientIdIv = object.encryptedClientIdIv ?? Buffer.alloc(0); - message.encryptedPrivacyKey = object.encryptedPrivacyKey ?? Buffer.alloc(0); - return message; - } -}; - -function createBaseDrmCertificate(): DrmCertificate { - return { - type: 0, - serialNumber: Buffer.alloc(0), - creationTimeSeconds: 0, - expirationTimeSeconds: 0, - publicKey: Buffer.alloc(0), - systemId: 0, - testDeviceDeprecated: false, - providerId: '', - serviceTypes: [], - algorithm: 0, - rotId: Buffer.alloc(0), - encryptionKey: undefined - }; -} - -export const DrmCertificate = { - encode(message: DrmCertificate, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { - if (message.type !== 0) { - writer.uint32(8).int32(message.type); - } - if (message.serialNumber.length !== 0) { - writer.uint32(18).bytes(message.serialNumber); - } - if (message.creationTimeSeconds !== 0) { - writer.uint32(24).uint32(message.creationTimeSeconds); - } - if (message.expirationTimeSeconds !== 0) { - writer.uint32(96).uint32(message.expirationTimeSeconds); - } - if (message.publicKey.length !== 0) { - writer.uint32(34).bytes(message.publicKey); - } - if (message.systemId !== 0) { - writer.uint32(40).uint32(message.systemId); - } - if (message.testDeviceDeprecated === true) { - writer.uint32(48).bool(message.testDeviceDeprecated); - } - if (message.providerId !== '') { - writer.uint32(58).string(message.providerId); - } - writer.uint32(66).fork(); - for (const v of message.serviceTypes) { - writer.int32(v); - } - writer.ldelim(); - if (message.algorithm !== 0) { - writer.uint32(72).int32(message.algorithm); - } - if (message.rotId.length !== 0) { - writer.uint32(82).bytes(message.rotId); - } - if (message.encryptionKey !== undefined) { - DrmCertificate_EncryptionKey.encode(message.encryptionKey, writer.uint32(90).fork()).ldelim(); - } - return writer; - }, - - decode(input: _m0.Reader | Uint8Array, length?: number): DrmCertificate { - const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); - const end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseDrmCertificate(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - message.type = reader.int32() as any; - break; - case 2: - message.serialNumber = reader.bytes() as Buffer; - break; - case 3: - message.creationTimeSeconds = reader.uint32(); - break; - case 12: - message.expirationTimeSeconds = reader.uint32(); - break; - case 4: - message.publicKey = reader.bytes() as Buffer; - break; - case 5: - message.systemId = reader.uint32(); - break; - case 6: - message.testDeviceDeprecated = reader.bool(); - break; - case 7: - message.providerId = reader.string(); - break; - case 8: - if ((tag & 7) === 2) { - const end2 = reader.uint32() + reader.pos; - while (reader.pos < end2) { - message.serviceTypes.push(reader.int32() as any); - } - } else { - message.serviceTypes.push(reader.int32() as any); - } - break; - case 9: - message.algorithm = reader.int32() as any; - break; - case 10: - message.rotId = reader.bytes() as Buffer; - break; - case 11: - message.encryptionKey = DrmCertificate_EncryptionKey.decode(reader, reader.uint32()); - break; - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }, - - fromJSON(object: any): DrmCertificate { - return { - type: isSet(object.type) ? drmCertificate_TypeFromJSON(object.type) : 0, - serialNumber: isSet(object.serialNumber) ? Buffer.from(bytesFromBase64(object.serialNumber)) : Buffer.alloc(0), - creationTimeSeconds: isSet(object.creationTimeSeconds) ? Number(object.creationTimeSeconds) : 0, - expirationTimeSeconds: isSet(object.expirationTimeSeconds) ? Number(object.expirationTimeSeconds) : 0, - publicKey: isSet(object.publicKey) ? Buffer.from(bytesFromBase64(object.publicKey)) : Buffer.alloc(0), - systemId: isSet(object.systemId) ? Number(object.systemId) : 0, - testDeviceDeprecated: isSet(object.testDeviceDeprecated) ? Boolean(object.testDeviceDeprecated) : false, - providerId: isSet(object.providerId) ? String(object.providerId) : '', - serviceTypes: Array.isArray(object?.serviceTypes) ? object.serviceTypes.map((e: any) => drmCertificate_ServiceTypeFromJSON(e)) : [], - algorithm: isSet(object.algorithm) ? drmCertificate_AlgorithmFromJSON(object.algorithm) : 0, - rotId: isSet(object.rotId) ? Buffer.from(bytesFromBase64(object.rotId)) : Buffer.alloc(0), - encryptionKey: isSet(object.encryptionKey) ? DrmCertificate_EncryptionKey.fromJSON(object.encryptionKey) : undefined - }; - }, - - toJSON(message: DrmCertificate): unknown { - const obj: any = {}; - message.type !== undefined && (obj.type = drmCertificate_TypeToJSON(message.type)); - message.serialNumber !== undefined && - (obj.serialNumber = base64FromBytes(message.serialNumber !== undefined ? message.serialNumber : Buffer.alloc(0))); - message.creationTimeSeconds !== undefined && (obj.creationTimeSeconds = Math.round(message.creationTimeSeconds)); - message.expirationTimeSeconds !== undefined && (obj.expirationTimeSeconds = Math.round(message.expirationTimeSeconds)); - message.publicKey !== undefined && (obj.publicKey = base64FromBytes(message.publicKey !== undefined ? message.publicKey : Buffer.alloc(0))); - message.systemId !== undefined && (obj.systemId = Math.round(message.systemId)); - message.testDeviceDeprecated !== undefined && (obj.testDeviceDeprecated = message.testDeviceDeprecated); - message.providerId !== undefined && (obj.providerId = message.providerId); - if (message.serviceTypes) { - obj.serviceTypes = message.serviceTypes.map((e) => drmCertificate_ServiceTypeToJSON(e)); - } else { - obj.serviceTypes = []; - } - message.algorithm !== undefined && (obj.algorithm = drmCertificate_AlgorithmToJSON(message.algorithm)); - message.rotId !== undefined && (obj.rotId = base64FromBytes(message.rotId !== undefined ? message.rotId : Buffer.alloc(0))); - message.encryptionKey !== undefined && - (obj.encryptionKey = message.encryptionKey ? DrmCertificate_EncryptionKey.toJSON(message.encryptionKey) : undefined); - return obj; - }, - - fromPartial, I>>(object: I): DrmCertificate { - const message = createBaseDrmCertificate(); - message.type = object.type ?? 0; - message.serialNumber = object.serialNumber ?? Buffer.alloc(0); - message.creationTimeSeconds = object.creationTimeSeconds ?? 0; - message.expirationTimeSeconds = object.expirationTimeSeconds ?? 0; - message.publicKey = object.publicKey ?? Buffer.alloc(0); - message.systemId = object.systemId ?? 0; - message.testDeviceDeprecated = object.testDeviceDeprecated ?? false; - message.providerId = object.providerId ?? ''; - message.serviceTypes = object.serviceTypes?.map((e) => e) || []; - message.algorithm = object.algorithm ?? 0; - message.rotId = object.rotId ?? Buffer.alloc(0); - message.encryptionKey = - object.encryptionKey !== undefined && object.encryptionKey !== null - ? DrmCertificate_EncryptionKey.fromPartial(object.encryptionKey) - : undefined; - return message; - } -}; - -function createBaseDrmCertificate_EncryptionKey(): DrmCertificate_EncryptionKey { - return { publicKey: Buffer.alloc(0), algorithm: 0 }; -} - -export const DrmCertificate_EncryptionKey = { - encode(message: DrmCertificate_EncryptionKey, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { - if (message.publicKey.length !== 0) { - writer.uint32(10).bytes(message.publicKey); - } - if (message.algorithm !== 0) { - writer.uint32(16).int32(message.algorithm); - } - return writer; - }, - - decode(input: _m0.Reader | Uint8Array, length?: number): DrmCertificate_EncryptionKey { - const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); - const end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseDrmCertificate_EncryptionKey(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - message.publicKey = reader.bytes() as Buffer; - break; - case 2: - message.algorithm = reader.int32() as any; - break; - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }, - - fromJSON(object: any): DrmCertificate_EncryptionKey { - return { - publicKey: isSet(object.publicKey) ? Buffer.from(bytesFromBase64(object.publicKey)) : Buffer.alloc(0), - algorithm: isSet(object.algorithm) ? drmCertificate_AlgorithmFromJSON(object.algorithm) : 0 - }; - }, - - toJSON(message: DrmCertificate_EncryptionKey): unknown { - const obj: any = {}; - message.publicKey !== undefined && (obj.publicKey = base64FromBytes(message.publicKey !== undefined ? message.publicKey : Buffer.alloc(0))); - message.algorithm !== undefined && (obj.algorithm = drmCertificate_AlgorithmToJSON(message.algorithm)); - return obj; - }, - - fromPartial, I>>(object: I): DrmCertificate_EncryptionKey { - const message = createBaseDrmCertificate_EncryptionKey(); - message.publicKey = object.publicKey ?? Buffer.alloc(0); - message.algorithm = object.algorithm ?? 0; - return message; - } -}; - -function createBaseSignedDrmCertificate(): SignedDrmCertificate { - return { drmCertificate: Buffer.alloc(0), signature: Buffer.alloc(0), signer: undefined, hashAlgorithm: 0 }; -} - -export const SignedDrmCertificate = { - encode(message: SignedDrmCertificate, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { - if (message.drmCertificate.length !== 0) { - writer.uint32(10).bytes(message.drmCertificate); - } - if (message.signature.length !== 0) { - writer.uint32(18).bytes(message.signature); - } - if (message.signer !== undefined) { - SignedDrmCertificate.encode(message.signer, writer.uint32(26).fork()).ldelim(); - } - if (message.hashAlgorithm !== 0) { - writer.uint32(32).int32(message.hashAlgorithm); - } - return writer; - }, - - decode(input: _m0.Reader | Uint8Array, length?: number): SignedDrmCertificate { - const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); - const end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseSignedDrmCertificate(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - message.drmCertificate = reader.bytes() as Buffer; - break; - case 2: - message.signature = reader.bytes() as Buffer; - break; - case 3: - message.signer = SignedDrmCertificate.decode(reader, reader.uint32()); - break; - case 4: - message.hashAlgorithm = reader.int32() as any; - break; - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }, - - fromJSON(object: any): SignedDrmCertificate { - return { - drmCertificate: isSet(object.drmCertificate) ? Buffer.from(bytesFromBase64(object.drmCertificate)) : Buffer.alloc(0), - signature: isSet(object.signature) ? Buffer.from(bytesFromBase64(object.signature)) : Buffer.alloc(0), - signer: isSet(object.signer) ? SignedDrmCertificate.fromJSON(object.signer) : undefined, - hashAlgorithm: isSet(object.hashAlgorithm) ? hashAlgorithmProtoFromJSON(object.hashAlgorithm) : 0 - }; - }, - - toJSON(message: SignedDrmCertificate): unknown { - const obj: any = {}; - message.drmCertificate !== undefined && - (obj.drmCertificate = base64FromBytes(message.drmCertificate !== undefined ? message.drmCertificate : Buffer.alloc(0))); - message.signature !== undefined && (obj.signature = base64FromBytes(message.signature !== undefined ? message.signature : Buffer.alloc(0))); - message.signer !== undefined && (obj.signer = message.signer ? SignedDrmCertificate.toJSON(message.signer) : undefined); - message.hashAlgorithm !== undefined && (obj.hashAlgorithm = hashAlgorithmProtoToJSON(message.hashAlgorithm)); - return obj; - }, - - fromPartial, I>>(object: I): SignedDrmCertificate { - const message = createBaseSignedDrmCertificate(); - message.drmCertificate = object.drmCertificate ?? Buffer.alloc(0); - message.signature = object.signature ?? Buffer.alloc(0); - message.signer = object.signer !== undefined && object.signer !== null ? SignedDrmCertificate.fromPartial(object.signer) : undefined; - message.hashAlgorithm = object.hashAlgorithm ?? 0; - return message; - } -}; - -function createBaseWidevinePsshData(): WidevinePsshData { - return { - keyIds: [], - contentId: Buffer.alloc(0), - cryptoPeriodIndex: 0, - protectionScheme: 0, - cryptoPeriodSeconds: 0, - type: 0, - keySequence: 0, - groupIds: [], - entitledKeys: [], - videoFeature: '', - algorithm: 0, - provider: '', - trackType: '', - policy: '', - groupedLicense: Buffer.alloc(0) - }; -} - -export const WidevinePsshData = { - encode(message: WidevinePsshData, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { - for (const v of message.keyIds) { - writer.uint32(18).bytes(v!); - } - if (message.contentId.length !== 0) { - writer.uint32(34).bytes(message.contentId); - } - if (message.cryptoPeriodIndex !== 0) { - writer.uint32(56).uint32(message.cryptoPeriodIndex); - } - if (message.protectionScheme !== 0) { - writer.uint32(72).uint32(message.protectionScheme); - } - if (message.cryptoPeriodSeconds !== 0) { - writer.uint32(80).uint32(message.cryptoPeriodSeconds); - } - if (message.type !== 0) { - writer.uint32(88).int32(message.type); - } - if (message.keySequence !== 0) { - writer.uint32(96).uint32(message.keySequence); - } - for (const v of message.groupIds) { - writer.uint32(106).bytes(v!); - } - for (const v of message.entitledKeys) { - WidevinePsshData_EntitledKey.encode(v!, writer.uint32(114).fork()).ldelim(); - } - if (message.videoFeature !== '') { - writer.uint32(122).string(message.videoFeature); - } - if (message.algorithm !== 0) { - writer.uint32(8).int32(message.algorithm); - } - if (message.provider !== '') { - writer.uint32(26).string(message.provider); - } - if (message.trackType !== '') { - writer.uint32(42).string(message.trackType); - } - if (message.policy !== '') { - writer.uint32(50).string(message.policy); - } - if (message.groupedLicense.length !== 0) { - writer.uint32(66).bytes(message.groupedLicense); - } - return writer; - }, - - decode(input: _m0.Reader | Uint8Array, length?: number): WidevinePsshData { - const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); - const end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseWidevinePsshData(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 2: - message.keyIds.push(reader.bytes() as Buffer); - break; - case 4: - message.contentId = reader.bytes() as Buffer; - break; - case 7: - message.cryptoPeriodIndex = reader.uint32(); - break; - case 9: - message.protectionScheme = reader.uint32(); - break; - case 10: - message.cryptoPeriodSeconds = reader.uint32(); - break; - case 11: - message.type = reader.int32() as any; - break; - case 12: - message.keySequence = reader.uint32(); - break; - case 13: - message.groupIds.push(reader.bytes() as Buffer); - break; - case 14: - message.entitledKeys.push(WidevinePsshData_EntitledKey.decode(reader, reader.uint32())); - break; - case 15: - message.videoFeature = reader.string(); - break; - case 1: - message.algorithm = reader.int32() as any; - break; - case 3: - message.provider = reader.string(); - break; - case 5: - message.trackType = reader.string(); - break; - case 6: - message.policy = reader.string(); - break; - case 8: - message.groupedLicense = reader.bytes() as Buffer; - break; - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }, - - fromJSON(object: any): WidevinePsshData { - return { - keyIds: Array.isArray(object?.keyIds) ? object.keyIds.map((e: any) => Buffer.from(bytesFromBase64(e))) : [], - contentId: isSet(object.contentId) ? Buffer.from(bytesFromBase64(object.contentId)) : Buffer.alloc(0), - cryptoPeriodIndex: isSet(object.cryptoPeriodIndex) ? Number(object.cryptoPeriodIndex) : 0, - protectionScheme: isSet(object.protectionScheme) ? Number(object.protectionScheme) : 0, - cryptoPeriodSeconds: isSet(object.cryptoPeriodSeconds) ? Number(object.cryptoPeriodSeconds) : 0, - type: isSet(object.type) ? widevinePsshData_TypeFromJSON(object.type) : 0, - keySequence: isSet(object.keySequence) ? Number(object.keySequence) : 0, - groupIds: Array.isArray(object?.groupIds) ? object.groupIds.map((e: any) => Buffer.from(bytesFromBase64(e))) : [], - entitledKeys: Array.isArray(object?.entitledKeys) ? object.entitledKeys.map((e: any) => WidevinePsshData_EntitledKey.fromJSON(e)) : [], - videoFeature: isSet(object.videoFeature) ? String(object.videoFeature) : '', - algorithm: isSet(object.algorithm) ? widevinePsshData_AlgorithmFromJSON(object.algorithm) : 0, - provider: isSet(object.provider) ? String(object.provider) : '', - trackType: isSet(object.trackType) ? String(object.trackType) : '', - policy: isSet(object.policy) ? String(object.policy) : '', - groupedLicense: isSet(object.groupedLicense) ? Buffer.from(bytesFromBase64(object.groupedLicense)) : Buffer.alloc(0) - }; - }, - - toJSON(message: WidevinePsshData): unknown { - const obj: any = {}; - if (message.keyIds) { - obj.keyIds = message.keyIds.map((e) => base64FromBytes(e !== undefined ? e : Buffer.alloc(0))); - } else { - obj.keyIds = []; - } - message.contentId !== undefined && (obj.contentId = base64FromBytes(message.contentId !== undefined ? message.contentId : Buffer.alloc(0))); - message.cryptoPeriodIndex !== undefined && (obj.cryptoPeriodIndex = Math.round(message.cryptoPeriodIndex)); - message.protectionScheme !== undefined && (obj.protectionScheme = Math.round(message.protectionScheme)); - message.cryptoPeriodSeconds !== undefined && (obj.cryptoPeriodSeconds = Math.round(message.cryptoPeriodSeconds)); - message.type !== undefined && (obj.type = widevinePsshData_TypeToJSON(message.type)); - message.keySequence !== undefined && (obj.keySequence = Math.round(message.keySequence)); - if (message.groupIds) { - obj.groupIds = message.groupIds.map((e) => base64FromBytes(e !== undefined ? e : Buffer.alloc(0))); - } else { - obj.groupIds = []; - } - if (message.entitledKeys) { - obj.entitledKeys = message.entitledKeys.map((e) => (e ? WidevinePsshData_EntitledKey.toJSON(e) : undefined)); - } else { - obj.entitledKeys = []; - } - message.videoFeature !== undefined && (obj.videoFeature = message.videoFeature); - message.algorithm !== undefined && (obj.algorithm = widevinePsshData_AlgorithmToJSON(message.algorithm)); - message.provider !== undefined && (obj.provider = message.provider); - message.trackType !== undefined && (obj.trackType = message.trackType); - message.policy !== undefined && (obj.policy = message.policy); - message.groupedLicense !== undefined && - (obj.groupedLicense = base64FromBytes(message.groupedLicense !== undefined ? message.groupedLicense : Buffer.alloc(0))); - return obj; - }, - - fromPartial, I>>(object: I): WidevinePsshData { - const message = createBaseWidevinePsshData(); - message.keyIds = object.keyIds?.map((e) => e) || []; - message.contentId = object.contentId ?? Buffer.alloc(0); - message.cryptoPeriodIndex = object.cryptoPeriodIndex ?? 0; - message.protectionScheme = object.protectionScheme ?? 0; - message.cryptoPeriodSeconds = object.cryptoPeriodSeconds ?? 0; - message.type = object.type ?? 0; - message.keySequence = object.keySequence ?? 0; - message.groupIds = object.groupIds?.map((e) => e) || []; - message.entitledKeys = object.entitledKeys?.map((e) => WidevinePsshData_EntitledKey.fromPartial(e)) || []; - message.videoFeature = object.videoFeature ?? ''; - message.algorithm = object.algorithm ?? 0; - message.provider = object.provider ?? ''; - message.trackType = object.trackType ?? ''; - message.policy = object.policy ?? ''; - message.groupedLicense = object.groupedLicense ?? Buffer.alloc(0); - return message; - } -}; - -function createBaseWidevinePsshData_EntitledKey(): WidevinePsshData_EntitledKey { - return { - entitlementKeyId: Buffer.alloc(0), - keyId: Buffer.alloc(0), - key: Buffer.alloc(0), - iv: Buffer.alloc(0), - entitlementKeySizeBytes: 0 - }; -} - -export const WidevinePsshData_EntitledKey = { - encode(message: WidevinePsshData_EntitledKey, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { - if (message.entitlementKeyId.length !== 0) { - writer.uint32(10).bytes(message.entitlementKeyId); - } - if (message.keyId.length !== 0) { - writer.uint32(18).bytes(message.keyId); - } - if (message.key.length !== 0) { - writer.uint32(26).bytes(message.key); - } - if (message.iv.length !== 0) { - writer.uint32(34).bytes(message.iv); - } - if (message.entitlementKeySizeBytes !== 0) { - writer.uint32(40).uint32(message.entitlementKeySizeBytes); - } - return writer; - }, - - decode(input: _m0.Reader | Uint8Array, length?: number): WidevinePsshData_EntitledKey { - const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); - const end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseWidevinePsshData_EntitledKey(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - message.entitlementKeyId = reader.bytes() as Buffer; - break; - case 2: - message.keyId = reader.bytes() as Buffer; - break; - case 3: - message.key = reader.bytes() as Buffer; - break; - case 4: - message.iv = reader.bytes() as Buffer; - break; - case 5: - message.entitlementKeySizeBytes = reader.uint32(); - break; - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }, - - fromJSON(object: any): WidevinePsshData_EntitledKey { - return { - entitlementKeyId: isSet(object.entitlementKeyId) ? Buffer.from(bytesFromBase64(object.entitlementKeyId)) : Buffer.alloc(0), - keyId: isSet(object.keyId) ? Buffer.from(bytesFromBase64(object.keyId)) : Buffer.alloc(0), - key: isSet(object.key) ? Buffer.from(bytesFromBase64(object.key)) : Buffer.alloc(0), - iv: isSet(object.iv) ? Buffer.from(bytesFromBase64(object.iv)) : Buffer.alloc(0), - entitlementKeySizeBytes: isSet(object.entitlementKeySizeBytes) ? Number(object.entitlementKeySizeBytes) : 0 - }; - }, - - toJSON(message: WidevinePsshData_EntitledKey): unknown { - const obj: any = {}; - message.entitlementKeyId !== undefined && - (obj.entitlementKeyId = base64FromBytes(message.entitlementKeyId !== undefined ? message.entitlementKeyId : Buffer.alloc(0))); - message.keyId !== undefined && (obj.keyId = base64FromBytes(message.keyId !== undefined ? message.keyId : Buffer.alloc(0))); - message.key !== undefined && (obj.key = base64FromBytes(message.key !== undefined ? message.key : Buffer.alloc(0))); - message.iv !== undefined && (obj.iv = base64FromBytes(message.iv !== undefined ? message.iv : Buffer.alloc(0))); - message.entitlementKeySizeBytes !== undefined && (obj.entitlementKeySizeBytes = Math.round(message.entitlementKeySizeBytes)); - return obj; - }, - - fromPartial, I>>(object: I): WidevinePsshData_EntitledKey { - const message = createBaseWidevinePsshData_EntitledKey(); - message.entitlementKeyId = object.entitlementKeyId ?? Buffer.alloc(0); - message.keyId = object.keyId ?? Buffer.alloc(0); - message.key = object.key ?? Buffer.alloc(0); - message.iv = object.iv ?? Buffer.alloc(0); - message.entitlementKeySizeBytes = object.entitlementKeySizeBytes ?? 0; - return message; - } -}; - -function createBaseFileHashes(): FileHashes { - return { signer: Buffer.alloc(0), signatures: [] }; -} - -export const FileHashes = { - encode(message: FileHashes, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { - if (message.signer.length !== 0) { - writer.uint32(10).bytes(message.signer); - } - for (const v of message.signatures) { - FileHashes_Signature.encode(v!, writer.uint32(18).fork()).ldelim(); - } - return writer; - }, - - decode(input: _m0.Reader | Uint8Array, length?: number): FileHashes { - const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); - const end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseFileHashes(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - message.signer = reader.bytes() as Buffer; - break; - case 2: - message.signatures.push(FileHashes_Signature.decode(reader, reader.uint32())); - break; - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }, - - fromJSON(object: any): FileHashes { - return { - signer: isSet(object.signer) ? Buffer.from(bytesFromBase64(object.signer)) : Buffer.alloc(0), - signatures: Array.isArray(object?.signatures) ? object.signatures.map((e: any) => FileHashes_Signature.fromJSON(e)) : [] - }; - }, - - toJSON(message: FileHashes): unknown { - const obj: any = {}; - message.signer !== undefined && (obj.signer = base64FromBytes(message.signer !== undefined ? message.signer : Buffer.alloc(0))); - if (message.signatures) { - obj.signatures = message.signatures.map((e) => (e ? FileHashes_Signature.toJSON(e) : undefined)); - } else { - obj.signatures = []; - } - return obj; - }, - - fromPartial, I>>(object: I): FileHashes { - const message = createBaseFileHashes(); - message.signer = object.signer ?? Buffer.alloc(0); - message.signatures = object.signatures?.map((e) => FileHashes_Signature.fromPartial(e)) || []; - return message; - } -}; - -function createBaseFileHashes_Signature(): FileHashes_Signature { - return { filename: '', testSigning: false, SHA512Hash: Buffer.alloc(0), mainExe: false, signature: Buffer.alloc(0) }; -} - -export const FileHashes_Signature = { - encode(message: FileHashes_Signature, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { - if (message.filename !== '') { - writer.uint32(10).string(message.filename); - } - if (message.testSigning === true) { - writer.uint32(16).bool(message.testSigning); - } - if (message.SHA512Hash.length !== 0) { - writer.uint32(26).bytes(message.SHA512Hash); - } - if (message.mainExe === true) { - writer.uint32(32).bool(message.mainExe); - } - if (message.signature.length !== 0) { - writer.uint32(42).bytes(message.signature); - } - return writer; - }, - - decode(input: _m0.Reader | Uint8Array, length?: number): FileHashes_Signature { - const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); - const end = length === undefined ? reader.len : reader.pos + length; - const message = createBaseFileHashes_Signature(); - while (reader.pos < end) { - const tag = reader.uint32(); - switch (tag >>> 3) { - case 1: - message.filename = reader.string(); - break; - case 2: - message.testSigning = reader.bool(); - break; - case 3: - message.SHA512Hash = reader.bytes() as Buffer; - break; - case 4: - message.mainExe = reader.bool(); - break; - case 5: - message.signature = reader.bytes() as Buffer; - break; - default: - reader.skipType(tag & 7); - break; - } - } - return message; - }, - - fromJSON(object: any): FileHashes_Signature { - return { - filename: isSet(object.filename) ? String(object.filename) : '', - testSigning: isSet(object.testSigning) ? Boolean(object.testSigning) : false, - SHA512Hash: isSet(object.SHA512Hash) ? Buffer.from(bytesFromBase64(object.SHA512Hash)) : Buffer.alloc(0), - mainExe: isSet(object.mainExe) ? Boolean(object.mainExe) : false, - signature: isSet(object.signature) ? Buffer.from(bytesFromBase64(object.signature)) : Buffer.alloc(0) - }; - }, - - toJSON(message: FileHashes_Signature): unknown { - const obj: any = {}; - message.filename !== undefined && (obj.filename = message.filename); - message.testSigning !== undefined && (obj.testSigning = message.testSigning); - message.SHA512Hash !== undefined && (obj.SHA512Hash = base64FromBytes(message.SHA512Hash !== undefined ? message.SHA512Hash : Buffer.alloc(0))); - message.mainExe !== undefined && (obj.mainExe = message.mainExe); - message.signature !== undefined && (obj.signature = base64FromBytes(message.signature !== undefined ? message.signature : Buffer.alloc(0))); - return obj; - }, - - fromPartial, I>>(object: I): FileHashes_Signature { - const message = createBaseFileHashes_Signature(); - message.filename = object.filename ?? ''; - message.testSigning = object.testSigning ?? false; - message.SHA512Hash = object.SHA512Hash ?? Buffer.alloc(0); - message.mainExe = object.mainExe ?? false; - message.signature = object.signature ?? Buffer.alloc(0); - return message; - } -}; - -declare let self: any | undefined; -declare let window: any | undefined; -declare let global: any | undefined; -const tsProtoGlobalThis: any = (() => { - if (typeof globalThis !== 'undefined') { - return globalThis; - } - if (typeof self !== 'undefined') { - return self; - } - if (typeof window !== 'undefined') { - return window; - } - if (typeof global !== 'undefined') { - return global; - } - throw 'Unable to locate global object'; -})(); - -function bytesFromBase64(b64: string): Uint8Array { - if (tsProtoGlobalThis.Buffer) { - return Uint8Array.from(tsProtoGlobalThis.Buffer.from(b64, 'base64')); - } else { - const bin = tsProtoGlobalThis.atob(b64); - const arr = new Uint8Array(bin.length); - for (let i = 0; i < bin.length; ++i) { - arr[i] = bin.charCodeAt(i); - } - return arr; - } -} - -function base64FromBytes(arr: Uint8Array): string { - if (tsProtoGlobalThis.Buffer) { - return tsProtoGlobalThis.Buffer.from(arr).toString('base64'); - } else { - const bin: string[] = []; - arr.forEach((byte) => { - bin.push(String.fromCharCode(byte)); - }); - return tsProtoGlobalThis.btoa(bin.join('')); - } -} - -type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined; //eslint-disable-line - -export type DeepPartial = T extends Builtin - ? T - : T extends Long - ? string | number | Long - : T extends Array - ? Array> - : T extends ReadonlyArray - ? ReadonlyArray> - : T extends {} //eslint-disable-line - ? { [K in keyof T]?: DeepPartial } - : Partial; - -type KeysOfUnion = T extends T ? keyof T : never; -export type Exact = P extends Builtin - ? P - : P & { [K in keyof P]: Exact } & { [K in Exclude>]: never }; - -if (_m0.util.Long !== Long) { - _m0.util.Long = Long as any; - _m0.configure(); -} - -function isSet(value: any): boolean { - return value !== null && value !== undefined; -} \ No newline at end of file diff --git a/modules/log.ts b/modules/log.ts deleted file mode 100644 index e77ba43..0000000 --- a/modules/log.ts +++ /dev/null @@ -1,69 +0,0 @@ -import fs from 'fs'; -import path from 'path'; -import { workingDir } from './module.cfg-loader'; -import log4js from 'log4js'; - -const logFolder = path.join(workingDir, 'logs'); -const latest = path.join(logFolder, 'latest.log'); - -const makeLogFolder = () => { - if (!fs.existsSync(logFolder)) - fs.mkdirSync(logFolder); - if (fs.existsSync(latest)) { - const stats = fs.statSync(latest); - fs.renameSync(latest, path.join(logFolder, `${stats.mtimeMs}.log`)); - } -}; - -const makeLogger = () => { - global.console.log = - global.console.info = - global.console.warn = - global.console.error = - global.console.debug = (...data: any[]) => { - console.info((data.length >= 1 ? data.shift() : ''), ...data); - }; - makeLogFolder(); - log4js.configure({ - appenders: { - console: { - type: 'console', layout: { - type: 'pattern', - pattern: process.env.isGUI === 'true' ? '%[%x{info}%m%]' : '%x{info}%m', - tokens: { - info: (ev) => { - return ev.level.levelStr === 'INFO' ? '' : `[${ev.level.levelStr}] `; - } - } - } - }, - file: { - type: 'file', - filename: latest, - layout: { - type: 'pattern', - pattern: '%x{info}%m', - tokens: { - info: (ev) => { - return ev.level.levelStr === 'INFO' ? '' : `[${ev.level.levelStr}] `; - } - } - } - } - }, - categories: { - default: { - appenders: ['console', 'file'], - level: 'all', - } - } - }); -}; - -const getLogger = () => { - if (!log4js.isConfigured()) - makeLogger(); - return log4js.getLogger(); -}; - -export const console = getLogger(); \ No newline at end of file diff --git a/modules/module.api-urls.ts b/modules/module.api-urls.ts deleted file mode 100644 index 6cd46b2..0000000 --- a/modules/module.api-urls.ts +++ /dev/null @@ -1,119 +0,0 @@ -// api domains -const domain = { - www: 'https://www.crunchyroll.com', - api: 'https://api.crunchyroll.com', - www_beta: 'https://beta.crunchyroll.com', - api_beta: 'https://beta-api.crunchyroll.com', - hd_www: 'https://www.hidive.com', - hd_api: 'https://api.hidive.com', - hd_new: 'https://dce-frontoffice.imggaming.com' -}; - -export type APIType = { - newani: string, - search1: string, - search2: string, - rss_cid: string, - rss_gid: string - media_page: string - series_page: string - auth: string - // mobile api - search3: string - session: string - collections: string - // beta api - beta_auth: string - authBasic: string - authBasicMob: string - authBasicSwitch: string, - beta_profile: string - beta_cmsToken: string - search: string - cms: string - beta_browse: string - beta_cms: string, - drm: string; - /** - * Web Header - */ - crunchyAuthHeader: Record, - /** - * Mobile Header - */ - crunchyAuthHeaderMob: Record, - /** - * Switch Header - */ - crunchyAuthHeaderSwitch: Record, - hd_apikey: string, - hd_devName: string, - hd_appId: string, - hd_clientWeb: string, - hd_clientExo: string, - hd_api: string, - hd_new_api: string, - hd_new_apiKey: string, - hd_new_version: string, -} - -// api urls -const api: APIType = { - // web - newani: `${domain.www}/rss/anime`, - search1: `${domain.www}/ajax/?req=RpcApiSearch_GetSearchCandidates`, - search2: `${domain.www}/search_page`, - rss_cid: `${domain.www}/syndication/feed?type=episodes&id=`, // &lang=enUS - rss_gid: `${domain.www}/syndication/feed?type=episodes&group_id=`, // &lang=enUS - media_page: `${domain.www}/media-`, - series_page: `${domain.www}/series-`, - auth: `${domain.www}/login`, - // mobile api - search3: `${domain.api}/autocomplete.0.json`, - session: `${domain.api}/start_session.0.json`, - collections: `${domain.api}/list_collections.0.json`, - // beta api - beta_auth: `${domain.api_beta}/auth/v1/token`, - authBasic: 'Basic bm9haWhkZXZtXzZpeWcwYThsMHE6', - authBasicMob: 'Basic dXU4aG0wb2g4dHFpOWV0eXl2aGo6SDA2VnVjRnZUaDJ1dEYxM0FBS3lLNE85UTRhX3BlX1o=', - authBasicSwitch: 'Basic dC1rZGdwMmg4YzNqdWI4Zm4wZnE6eWZMRGZNZnJZdktYaDRKWFMxTEVJMmNDcXUxdjVXYW4=', - beta_profile: `${domain.api_beta}/accounts/v1/me/profile`, - beta_cmsToken: `${domain.api_beta}/index/v2`, - search: `${domain.api_beta}/content/v2/discover/search`, - cms: `${domain.api_beta}/content/v2/cms`, - beta_browse: `${domain.api_beta}/content/v1/browse`, - beta_cms: `${domain.api_beta}/cms/v2`, - drm: `${domain.api_beta}/drm/v1/auth`, - crunchyAuthHeader: {}, - crunchyAuthHeaderMob: {}, - crunchyAuthHeaderSwitch: {}, - //hidive API - hd_apikey: '508efd7b42d546e19cc24f4d0b414e57e351ca73', - hd_devName: 'Android', - hd_appId: '24i-Android', - hd_clientWeb: 'okhttp/3.4.1', - hd_clientExo: 'smartexoplayer/1.6.0.R (Linux;Android 6.0) ExoPlayerLib/2.6.0', - hd_api: `${domain.hd_api}/api/v1`, - //Hidive New API - hd_new_api: `${domain.hd_new}/api`, - hd_new_apiKey: '857a1e5d-e35e-4fdf-805b-a87b6f8364bf', - hd_new_version: '6.0.1.bbf09a2' -}; - -// set header -api.crunchyAuthHeader = { - Authorization: api.authBasic, -}; - -api.crunchyAuthHeaderMob = { - Authorization: api.authBasicMob, - 'user-agent': 'Crunchyroll/3.60.0 Android/9 okhttp/4.12.0' -}; - -api.crunchyAuthHeaderSwitch = { - Authorization: api.authBasicSwitch, -}; - -export { - domain, api -}; diff --git a/modules/module.app-args.js b/modules/module.app-args.js new file mode 100644 index 0000000..5c4d11b --- /dev/null +++ b/modules/module.app-args.js @@ -0,0 +1,217 @@ +const yargs = require('yargs'); + +const appArgv = (cfg) => { + // init + return yargs.parserConfiguration({ + 'duplicate-arguments-array': false, + }) + // main + .wrap(Math.min(120)) // yargs.terminalWidth() + .help(false).version(false) + .usage('Usage: $0 [options]') + // auth + .option('auth', { + group: 'Authentication:', + describe: 'Enter authentication mode', + type: 'boolean', + }) + // search + .option('search', { + alias: 'f', + group: 'Search:', + describe: 'Search show ids', + type: 'string', + }) + // select show and eps + .option('s', { + group: 'Downloading:', + describe: 'Sets the show id', + type: 'number', + }) + .option('e', { + group: 'Downloading:', + describe: 'Select episode ids (comma-separated, hyphen-sequence)', + type: 'string', + }) + .option('all', { + group: 'Downloading:', + describe: 'Used to download all episodes from the show', + type: 'boolean', + default: cfg.all || false + }) + .option('partsize', { + group: 'Downloading:', + describe: 'The amount of parts that should be downloaded in paralell', + type: 'number', + default: cfg.partsize || 10 + }) + // quality + .option('q', { + group: 'Downloading:', + describe: 'Select video layer (0 is max)', + choices: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], + default: cfg.videoLayer || 7, + type: 'number', + }) + // alt listing + .option('alt', { + group: 'Downloading:', + describe: 'Alternative episode listing (if available)', + default: cfg.altList || false, + type: 'boolean', + }) + // switch to subs + .option('dub', { + group: 'Downloading:', + describe: 'Download non-Japanese Dub (English Dub mode by default)', + choices: [ 'enUS', 'esLA', 'ptBR', 'zhMN' ], + default: cfg.dub || 'enUS', + type: 'string', + }) + .option('sub', { + group: 'Downloading:', + describe: 'Japanese Dub with subtitles mode (English Dub mode by default)', + default: cfg.subsMode || false, + type: 'boolean', + }) + .option('subLang', { + group: 'Downloading:', + describe: 'Set the subtitle language (English is default and fallback)', + default: cfg.subLang || 'en', + choices: [ 'enUS', 'esLA', 'ptBR' ], + type: 'string' + }) + // simulcast + .option('simul', { + group: 'Downloading:', + describe: 'Force downloading simulcast ver. instead of uncut ver. (if uncut ver. available)', + default: cfg.forceSimul || false, + type: 'boolean', + }) + // server number + .option('x', { + alias: 'server', + group: 'Downloading:', + describe: 'Select server', + choices: [1, 2, 3, 4], + default: cfg.nServer || 1, + type: 'number', + }) + // skip + .option('noaudio', { + group: 'Downloading:', + describe: 'Skip downloading audio', + type: 'boolean' + }) + .option('novids', { + group: 'Downloading:', + alias: 'skipdl', + describe: 'Skip downloading video', + type: 'boolean', + }) + .option('nosubs', { + group: 'Downloading:', + describe: 'Skip downloading subtitles for English Dub (if available)', + type: 'boolean', + }) + // proxy + .option('proxy', { + group: 'Proxy:', + describe: 'Set http(s)/socks proxy WHATWG url', + default: cfg.proxy || false, + hidden: true, + }) + .option('proxy-auth', { + group: 'Proxy:', + describe: 'Colon-separated username and password for proxy', + default: cfg.proxy_auth || false, + hidden: true, + }) + .option('ssp', { + group: 'Proxy:', + describe: 'Don\'t use proxy for stream and subtitles downloading', + default: cfg.proxy_ssp || false, + hidden: true, + type: 'boolean', + }) + // muxing + .option('skipmux', { + group: 'Muxing:', + describe: 'Skip muxing video and subtitles', + type: 'boolean', + }) + .option('mp4', { + group: 'Muxing:', + describe: 'Mux into mp4', + default: cfg.mp4mux || false, + type: 'boolean' + }) + .option('mks', { + group: 'Muxing:', + describe: 'Add subtitles to mkv/mp4 (if available)', + default: cfg.muxSubs || false, + type: 'boolean' + }) + // filenaming + .option('a', { + alias: 'grouptag', + group: 'Filename Template:', + describe: 'Release group', + default: cfg.releaseGroup || 'Funimation', + type: 'string' + }) + .option('t', { + alias: 'title', + group: 'Filename Template:', + describe: 'Series title override', + type: 'string' + }) + .option('ep', { + group: 'Filename Template:', + describe: 'Episode number override (ignored in batch mode)', + type: 'string' + }) + .option('suffix', { + group: 'Filename Template:', + describe: 'Filename suffix override (first "SIZEp" will be replaced with actual video size)', + default: cfg.fileSuffix || 'SIZEp', + type: 'string' + }) + // util + .option('nocleanup', { + group: 'Utilities:', + describe: 'Move temporary files to trash folder instead of deleting', + default: cfg.noCleanUp || false, + type: 'boolean' + }) + .option('notrashfolder', { + implies: ['nocleanup'], + group: 'Utilities:', + describe: 'Don\'t move temporary files to trash folder (Used with --nocleanup)', + default: cfg.noTrashFolder || false, + type: 'boolean' + }) + // help + .option('help', { + alias: 'h', + group: 'Help:', + describe: 'Show this help', + type: 'boolean' + }) + // usage + .example([ + ['$0 --search "My Hero"', 'search "My Hero" in title'], + ['$0 -s 124389 -e 1,2,3', 'download episodes 1-3 from show with id 124389'], + ['$0 -s 124389 -e 1-3,2-7,s1-2', 'download episodes 1-7 and "S"-episodes 1-2 from show with id 124389'], + ]) + + // -- + .argv; +}; + +const showHelp = yargs.showHelp; + +module.exports = { + appArgv, + showHelp +}; diff --git a/modules/module.app-args.ts b/modules/module.app-args.ts deleted file mode 100644 index 953418e..0000000 --- a/modules/module.app-args.ts +++ /dev/null @@ -1,177 +0,0 @@ -import yargs, { Choices } from 'yargs'; -import { args, AvailableMuxer, groups } from './module.args'; -import { LanguageItem } from './module.langsData'; -import { DownloadInfo } from '../@types/messageHandler'; -import { HLSCallback } from './hls-download'; -import leven from 'leven'; -import { console } from './log'; -import { CrunchyPlayStreams } from '../@types/enums'; - -let argvC: { - [x: string]: unknown; - ccTag: string, - defaultAudio: LanguageItem, - defaultSub: LanguageItem, - ffmpegOptions: string[], - mkvmergeOptions: string[], - force: 'Y'|'y'|'N'|'n'|'C'|'c', - skipUpdate: boolean, - videoTitle: string, - override: string[], - fsRetryTime: number, - forceMuxer: AvailableMuxer|undefined; - username: string|undefined, - password: string|undefined, - token: string|undefined, - silentAuth: boolean, - skipSubMux: boolean, - downloadArchive: boolean, - addArchive: boolean, - but: boolean, - auth: boolean | undefined; - dlFonts: boolean | undefined; - search: string | undefined; - 'search-type': string; - page: number | undefined; - locale: string; - new: boolean | undefined; - 'movie-listing': string | undefined; - series: string | undefined; - s: string | undefined; - srz: string | undefined; - e: string | undefined; - extid: string | undefined; - q: number; - x: number; - kstream: number; - cstream: keyof typeof CrunchyPlayStreams | 'none'; - partsize: number; - hslang: string; - dlsubs: string[]; - novids: boolean | undefined; - noaudio: boolean | undefined; - nosubs: boolean | undefined; - dubLang: string[]; - all: boolean; - fontSize: number; - combineLines: boolean; - allDubs: boolean; - timeout: number; - waittime: number; - simul: boolean; - mp4: boolean; - skipmux: boolean | undefined; - fileName: string; - numbers: number; - nosess: string; - debug: boolean | undefined; - nocleanup: boolean; - help: boolean | undefined; - service: 'crunchy' | 'hidive' | 'ao' | 'adn'; - update: boolean; - fontName: string | undefined; - _: (string | number)[]; - $0: string; - dlVideoOnce: boolean; - chapters: boolean; - crapi: 'android' | 'web'; - removeBumpers: boolean; - originalFontSize: boolean; - keepAllVideos: boolean; - syncTiming: boolean; - callbackMaker?: (data: DownloadInfo) => HLSCallback; -}; - -export type ArgvType = typeof argvC; - -const appArgv = (cfg: { - [key: string]: unknown -}, isGUI = false) => { - if (argvC) - return argvC; - yargs(process.argv.slice(2)); - const argv = getArgv(cfg, isGUI) - .parseSync(); - argvC = argv; - return argv; -}; - - -const overrideArguments = (cfg: { [key:string]: unknown }, override: Partial, isGUI = false) => { - const argv = getArgv(cfg, isGUI).middleware((ar) => { - for (const key of Object.keys(override)) { - ar[key] = override[key]; - } - }).parseSync(); - argvC = argv; -}; - -export { - appArgv, - overrideArguments -}; - -const getArgv = (cfg: { [key:string]: unknown }, isGUI: boolean) => { - const parseDefault = (key: string, _default: T) : T=> { - if (Object.prototype.hasOwnProperty.call(cfg, key)) { - return cfg[key] as T; - } else - return _default; - }; - const argv = yargs.parserConfiguration({ - 'duplicate-arguments-array': false, - 'camel-case-expansion': false, - }) - .wrap(yargs.terminalWidth()) - .usage('Usage: $0 [options]') - .help(true); - //.strictOptions() - const data = args.map(a => { - return { - ...a, - demandOption: !isGUI && a.demandOption, - group: groups[a.group], - default: typeof a.default === 'object' && !Array.isArray(a.default) ? - parseDefault((a.default as any).name || a.name, (a.default as any).default) : a.default - }; - }); - for (const item of data) - argv.option(item.name, { - ...item, - coerce: (value) => { - if (item.transformer) { - return item.transformer(value); - } else { - return value; - } - }, - choices: item.name === 'service' && isGUI ? undefined : item.choices as unknown as Choices - }); - - // Custom logic for suggesting corrections for misspelled options - argv.middleware((argv: Record) => { - // List of valid options - const validOptions = [ - ...args.map(a => a.name), - ...args.map(a => a.alias).filter(alias => alias !== undefined) as string[] - ]; - const unknownOptions = Object.keys(argv).filter(key => !validOptions.includes(key) && key !== '_' && key !== '$0'); // Filter out known options - - const suggestedOptions: Record = {}; - unknownOptions.forEach(actualOption => { - const closestOption = validOptions.find(option => { - const levenVal = leven(option, actualOption); - return levenVal <= 2 && levenVal > 0; - }); - - if (closestOption && !suggestedOptions[closestOption]) { - suggestedOptions[closestOption] = true; - console.info(`Unknown option ${actualOption}, did you mean ${closestOption}?`); - } else if (!suggestedOptions[actualOption]) { - suggestedOptions[actualOption] = true; - console.info(`Unknown option ${actualOption}`); - } - }); - }); - return argv as unknown as yargs.Argv; -}; \ No newline at end of file diff --git a/modules/module.args.ts b/modules/module.args.ts deleted file mode 100644 index 5592f22..0000000 --- a/modules/module.args.ts +++ /dev/null @@ -1,888 +0,0 @@ -import { aoSearchLocales, dubLanguageCodes, languages, searchLocales, subtitleLanguagesFilter } from './module.langsData'; -import { CrunchyPlayStreams } from '../@types/enums'; - -const groups = { - 'auth': 'Authentication:', - 'fonts': 'Fonts:', - 'search': 'Search:', - 'dl': 'Downloading:', - 'mux': 'Muxing:', - 'fileName': 'Filename Template:', - 'debug': 'Debug:', - 'util': 'Utilities:', - 'help': 'Help:', - 'gui': 'GUI:' -}; - -export type AvailableFilenameVars = 'title' | 'episode' | 'showTitle' | 'seriesTitle' | 'season' | 'width' | 'height' | 'service' - -const availableFilenameVars: AvailableFilenameVars[] = [ - 'title', - 'episode', - 'showTitle', - 'seriesTitle', - 'season', - 'width', - 'height', - 'service' -]; - -export type AvailableMuxer = 'ffmpeg' | 'mkvmerge' -export const muxer: AvailableMuxer[] = [ 'ffmpeg', 'mkvmerge' ]; - -export type TAppArg = { - name: string, - group: keyof typeof groups, - type: 'boolean'|'string'|'number'|'array', - choices?: T[], - alias?: string, - describe: string, - docDescribe: true|string, // true means use describe for the docs - default?: T|{ - default: T|undefined, - name?: string - }, - service: Array<'crunchy'|'hidive'|'ao'|'adn'|'all'>, - usage: string // -(-)${name} will be added for each command, - demandOption?: true, - transformer?: (value: T) => K -} - -const args: TAppArg[] = [ - { - name: 'auth', - describe: 'Enter authentication mode', - type: 'boolean', - group: 'auth', - service: ['all'], - docDescribe: 'Most of the shows on both services are only accessible if you payed for the service.' - + '\nIn order for them to know who you are you are required to log in.' - + '\nIf you trigger this command, you will be prompted for the username and password for the selected service', - usage: '' - }, - { - name: 'dlFonts', - group: 'fonts', - describe: 'Download all required fonts for mkv muxing', - docDescribe: 'Crunchyroll uses a variaty of fonts for the subtitles.' - + '\nUse this command to download all the fonts and add them to the muxed **mkv** file.', - service: ['crunchy'], - type: 'boolean', - usage: '' - }, - { - name: 'search', - group: 'search', - alias: 'f', - describe: 'Search of an anime by the given string', - type: 'string', - docDescribe: true, - service: ['all'], - usage: '${search}' - }, - { - name: 'search-type', - describe: 'Search by type', - docDescribe: 'Search only for type of anime listings (e.g. episodes, series)', - group: 'search', - service: ['crunchy'], - type: 'string', - usage: '${type}', - choices: [ '', 'top_results', 'series', 'movie_listing', 'episode' ], - default: { - default: '' - } - }, - { - name: 'page', - alias: 'p', - describe: 'Set the page number for search results', - docDescribe: 'The output is organized in pages. Use this command to output the items for the given page', - group: 'search', - service: ['crunchy', 'hidive'], - type: 'number', - usage: '${page}' - }, - { - name: 'locale', - describe: 'Set the service locale', - docDescribe: 'Set the local that will be used for the API.', - group: 'search', - choices: ([...searchLocales.filter(a => a !== undefined), ...aoSearchLocales.filter(a => a !== undefined)] as string[]), - default: { - default: 'en-US' - }, - type: 'string', - service: ['crunchy', 'ao', 'adn'], - usage: '${locale}' - }, - { - group: 'search', - name: 'new', - describe: 'Get last updated series list', - docDescribe: true, - service: ['crunchy', 'hidive'], - type: 'boolean', - usage: '', - }, - { - group: 'dl', - alias: 'flm', - name: 'movie-listing', - describe: 'Get video list by Movie Listing ID', - docDescribe: true, - service: ['crunchy'], - type: 'string', - usage: '${ID}', - }, - { - name: 'series', - group: 'dl', - alias: 'srz', - describe: 'Get season list by series ID', - docDescribe: 'Requested is the ID of a show not a season.', - service: ['crunchy'], - type: 'string', - usage: '${ID}' - }, - { - name: 's', - group: 'dl', - type: 'string', - describe: 'Set the season ID', - docDescribe: 'Used to set the season ID to download from', - service: ['all'], - usage: '${ID}' - }, - { - name: 'e', - group: 'dl', - describe: 'Set the episode(s) to download from any given show', - docDescribe: 'Set the episode(s) to download from any given show.' - + '\nFor multiple selection: 1-4 OR 1,2,3,4 ' - + '\nFor special episodes: S1-4 OR S1,S2,S3,S4 where S is the special letter', - service: ['all'], - type: 'string', - usage: '${selection}', - alias: 'episode' - }, - { - name: 'extid', - group: 'dl', - describe: 'Set the external id to lookup/download', - docDescribe: 'Set the external id to lookup/download.' - + '\nAllows you to download or view legacy Crunchyroll Ids ', - service: ['crunchy'], - type: 'string', - usage: '${selection}', - alias: 'externalid' - }, - { - name: 'q', - group: 'dl', - describe: 'Set the quality level. Use 0 to use the maximum quality.', - default: { - default: 0 - }, - docDescribe: true, - service: ['all'], - type: 'number', - usage: '${qualityLevel}' - }, - { - name: 'dlVideoOnce', - describe: 'Download only once the video with the best selected quality', - type: 'boolean', - group: 'dl', - service: ['crunchy', 'ao'], - docDescribe: 'If selected, the best selected quality will be downloaded only for the first language,' - + '\nthen the worst video quality with the same audio quality will be downloaded for every other language.' - + '\nBy the later merge of the videos, no quality difference will be present.' - + '\nThis will speed up the download speed, if multiple languages are selected.', - usage: '', - default: { - default: false - } - }, - { - name: 'chapters', - describe: 'Will fetch the chapters and add them into the final video', - type: 'boolean', - group: 'dl', - service: ['crunchy', 'adn'], - docDescribe: 'Will fetch the chapters and add them into the final video.' - + '\nCurrently only works with mkvmerge.', - usage: '', - default: { - default: true - } - }, - { - name: 'crapi', - describe: 'Selects the API type for Crunchyroll', - type: 'string', - group: 'dl', - service: ['crunchy'], - docDescribe: 'If set to Android, it has lower quality, but Non-DRM streams,' - + '\nIf set to Web, it has a higher quality adaptive stream, but everything is DRM.', - usage: '', - choices: ['android', 'web'], - default: { - default: 'web' - } - }, - { - name: 'removeBumpers', - describe: 'Remove bumpers from final video', - type: 'boolean', - group: 'dl', - service: ['hidive'], - docDescribe: 'If selected, it will remove the bumpers such as the hidive intro from the final file.' - + '\nCurrently disabling this sometimes results in bugs such as video/audio desync', - usage: '', - default: { - default: true - } - }, - { - name: 'originalFontSize', - describe: 'Keep original font size', - type: 'boolean', - group: 'dl', - service: ['hidive'], - docDescribe: 'If selected, it will prefer to keep the original Font Size defined by the service.', - usage: '', - default: { - default: true - } - }, - { - name: 'x', - group: 'dl', - describe: 'Select the server to use', - choices: [1, 2, 3, 4], - default: { - default: 1 - }, - type: 'number', - alias: 'server', - docDescribe: true, - service: ['crunchy'], - usage: '${server}' - }, - { - name: 'kstream', - group: 'dl', - alias: 'k', - describe: 'Select specific stream', - choices: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], - default: { - default: 1 - }, - docDescribe: true, - service: ['crunchy'], - type: 'number', - usage: '${stream}' - }, - { - name: 'cstream', - group: 'dl', - alias: 'cs', - service: ['crunchy'], - type: 'string', - describe: 'Select specific crunchy play stream by device, or disable stream with "none"', - choices: [...Object.keys(CrunchyPlayStreams), 'none'], - default: { - default: 'chrome' - }, - docDescribe: true, - usage: '${device}' - }, - { - name: 'hslang', - group: 'dl', - describe: 'Download video with specific hardsubs', - choices: subtitleLanguagesFilter.slice(1), - default: { - default: 'none' - }, - type: 'string', - usage: '${hslang}', - docDescribe: true, - service: ['crunchy'] - }, - { - name: 'dlsubs', - group: 'dl', - describe: 'Download subtitles by language tag (space-separated)' - + `\nCrunchy Only: ${languages.filter(a => a.cr_locale).map(a => a.locale).join(', ')}`, - docDescribe: true, - service: ['all'], - type: 'array', - choices: subtitleLanguagesFilter, - default: { - default: [ 'all' ] - }, - usage: '${sub1} ${sub2}' - }, - { - name: 'novids', - group: 'dl', - describe: 'Skip downloading videos', - docDescribe: true, - service: ['all'], - type: 'boolean', - usage: '' - }, - { - name: 'noaudio', - group: 'dl', - describe: 'Skip downloading audio', - docDescribe: true, - service: ['crunchy', 'hidive'], - type: 'boolean', - usage: '' - }, - { - name: 'nosubs', - group: 'dl', - describe: 'Skip downloading subtitles', - docDescribe: true, - service: ['all'], - type: 'boolean', - usage: '' - }, - { - name: 'dubLang', - describe: 'Set the language to download: ' - + `\nCrunchy Only: ${languages.filter(a => a.cr_locale).map(a => a.code).join(', ')}`, - docDescribe: true, - group: 'dl', - choices: dubLanguageCodes, - default: { - default: [dubLanguageCodes.slice(-1)[0]] - }, - service: ['all'], - type: 'array', - usage: '${dub1} ${dub2}', - }, - { - name: 'all', - describe: 'Used to download all episodes from the show', - docDescribe: true, - group: 'dl', - service: ['all'], - default: { - default: false - }, - type: 'boolean', - usage: '' - }, - { - name: 'fontSize', - describe: 'Used to set the fontsize of the subtitles', - default: { - default: 55 - }, - docDescribe: 'When converting the subtitles to ass, this will change the font size' - + '\nIn most cases, requires "--originaFontSize false" to take effect', - group: 'dl', - service: ['all'], - type: 'number', - usage: '${fontSize}' - }, - { - name: 'combineLines', - describe: 'Merge adjacent lines with same style and text', - docDescribe: 'If selected, will prevent a line from shifting downwards', - group: 'dl', - service: ['hidive'], - type: 'boolean', - usage: '' - }, - { - name: 'allDubs', - describe: 'If selected, all available dubs will get downloaded', - docDescribe: true, - group: 'dl', - service: ['all'], - type: 'boolean', - usage: '' - }, - { - name: 'timeout', - group: 'dl', - type: 'number', - describe: 'Set the timeout of all download reqests. Set in millisecods', - docDescribe: true, - service: ['all'], - usage: '${timeout}', - default: { - default: 15 * 1000 - } - }, - { - name: 'waittime', - group: 'dl', - type: 'number', - describe: 'Set the time the program waits between downloads. Set in millisecods', - docDescribe: true, - service: ['crunchy','hidive'], - usage: '${waittime}', - default: { - default: 0 * 1000 - } - }, - { - name: 'simul', - group: 'dl', - describe: 'Force downloading simulcast version instead of uncut version (if available).', - docDescribe: true, - service: ['hidive'], - type: 'boolean', - usage: '', - default: { - default: false - } - }, - { - name: 'mp4', - group: 'mux', - describe: 'Mux video into mp4', - docDescribe: 'If selected, the output file will be an mp4 file (not recommended tho)', - service: ['all'], - type: 'boolean', - usage: '', - default: { - default: false - } - }, - { - name: 'keepAllVideos', - group: 'mux', - describe: 'Keeps all videos when merging instead of discarding extras', - docDescribe: 'If set to true, it will keep all videos in the merge process, rather than discarding the extra videos.', - service: ['crunchy','hidive'], - type: 'boolean', - usage: '', - default: { - default: false - } - }, - { - name: 'syncTiming', - group: 'mux', - describe: 'Attempts to sync timing for multi-dub downloads EXPERIMENTAL', - docDescribe: 'If enabled attempts to sync timing for multi-dub downloads.' - + '\nNOTE: This is currently experimental and syncs audio and subtitles, though subtitles has a lot of guesswork' - + '\nIf you find bugs with this, please report it in the discord or github', - service: ['crunchy','hidive'], - type: 'boolean', - usage: '', - default: { - default: false - } - }, - { - name: 'skipmux', - describe: 'Skip muxing video, audio and subtitles', - docDescribe: true, - group: 'mux', - service: ['all'], - type: 'boolean', - usage: '' - }, - { - name: 'fileName', - group: 'fileName', - describe: `Set the filename template. Use \${variable_name} to insert variables.\nYou can also create folders by inserting a path seperator in the filename\nYou may use ${availableFilenameVars - .map(a => `'${a}'`).join(', ')} as variables.`, - docDescribe: true, - service: ['all'], - type: 'string', - usage: '${fileName}', - default: { - default: '[${service}] ${showTitle} - S${season}E${episode} [${height}p]' - } - }, - { - name: 'numbers', - group: 'fileName', - describe: `Set how long a number in the title should be at least.\n${[[3, 5, '005'], [2, 1, '01'], [1, 20, '20']] - .map(val => `Set in config: ${val[0]}; Episode number: ${val[1]}; Output: ${val[2]}`).join('\n')}`, - type: 'number', - default: { - default: 2 - }, - docDescribe: true, - service: ['all'], - usage: '${number}' - }, - { - name: 'nosess', - group: 'debug', - describe: 'Reset session cookie for testing purposes', - docDescribe: true, - service: ['all'], - type: 'boolean', - usage: '', - default: { - default: false - } - }, - { - name: 'debug', - group: 'debug', - describe: 'Debug mode (tokens may be revealed in the console output)', - docDescribe: true, - service: ['all'], - type: 'boolean', - usage: '', - default: { - default: false - } - }, - { - name: 'nocleanup', - describe: 'Don\'t delete subtitle, audio and video files after muxing', - docDescribe: true, - group: 'mux', - service: ['all'], - type: 'boolean', - default: { - default: false - }, - usage: '' - }, - { - name: 'help', - alias: 'h', - describe: 'Show the help output', - docDescribe: true, - group: 'help', - service: ['all'], - type: 'boolean', - usage: '' - }, - { - name: 'service', - describe: 'Set the service you want to use', - docDescribe: true, - group: 'util', - service: ['all'], - type: 'string', - choices: ['crunchy', 'hidive', 'ao', 'adn'], - usage: '${service}', - default: { - default: '' - }, - demandOption: true - }, - { - name: 'update', - group: 'util', - describe: 'Force the tool to check for updates (code version only)', - docDescribe: true, - service: ['all'], - type: 'boolean', - usage: '' - }, - { - name: 'fontName', - group: 'fonts', - describe: 'Set the font to use in subtiles', - docDescribe: true, - service: ['hidive', 'adn'], - type: 'string', - usage: '${fontName}', - }, - { - name: 'but', - describe: 'Download everything but the -e selection', - docDescribe: true, - group: 'dl', - service: ['all'], - type: 'boolean', - usage: '' - }, - { - name: 'downloadArchive', - describe: 'Used to download all archived shows', - group: 'dl', - docDescribe: true, - service: ['all'], - type: 'boolean', - usage: '' - }, - { - name: 'addArchive', - describe: 'Used to add the `-s` and `--srz` to downloadArchive', - group: 'dl', - docDescribe: true, - service: ['all'], - type: 'boolean', - usage: '' - }, - { - name: 'skipSubMux', - describe: 'Skip muxing the subtitles', - docDescribe: true, - group: 'mux', - service: ['all'], - type: 'boolean', - usage: '', - default: { - default: false - } - }, - { - name: 'partsize', - describe: 'Set the amount of parts to download at once', - docDescribe: 'Set the amount of parts to download at once\nIf you have a good connection try incresing this number to get a higher overall speed', - group: 'dl', - service: ['all'], - type: 'number', - usage: '${amount}', - default: { - default: 10 - } - }, - { - name: 'username', - describe: 'Set the username to use for the authentication. If not provided, you will be prompted for the input', - docDescribe: true, - group: 'auth', - service: ['all'], - type: 'string', - usage: '${username}', - default: { - default: undefined - } - }, - { - name: 'password', - describe: 'Set the password to use for the authentication. If not provided, you will be prompted for the input', - docDescribe: true, - group: 'auth', - service: ['all'], - type: 'string', - usage: '${password}', - default: { - default: undefined - } - }, - { - name: 'silentAuth', - describe: 'Authenticate every time the script runs. Use at your own risk.', - docDescribe: true, - group: 'auth', - service: ['crunchy'], - type: 'boolean', - usage: '', - default: { - default: false - } - }, - { - name: 'token', - describe: 'Allows you to login with your token (Example on crunchy is Refresh Token/etp-rt cookie)', - docDescribe: true, - group: 'auth', - service: ['crunchy', 'ao'], - type: 'string', - usage: '${token}', - default: { - default: undefined - } - }, - { - name: 'forceMuxer', - describe: 'Force the program to use said muxer or don\'t mux if the given muxer is not present', - docDescribe: true, - group: 'mux', - service: ['all'], - type: 'string', - usage: '${muxer}', - choices: muxer, - default: { - default: undefined - } - }, - { - name: 'fsRetryTime', - describe: 'Set the time the downloader waits before retrying if an error while writing the file occurs', - docDescribe: true, - group: 'dl', - service: ['all'], - type: 'number', - usage: '${time in seconds}', - default: { - default: 5 - }, - }, - { - name: 'override', - describe: 'Override a template variable', - docDescribe: true, - group: 'fileName', - service: ['all'], - type: 'array', - usage: '"${toOverride}=\'${value}\'"', - default: { - default: [ ] - } - }, - { - name: 'videoTitle', - describe: 'Set the video track name of the merged file', - docDescribe: true, - group: 'mux', - service: ['all'], - type: 'string', - usage: '${title}' - }, - { - name: 'skipUpdate', - describe: 'If true, the tool won\'t check for updates', - docDescribe: true, - group: 'util', - service: ['all'], - type: 'boolean', - usage: '', - default: { - default: false - } - }, - { - name: 'force', - describe: 'Set the default option for the \'alredy exists\' prompt', - docDescribe: 'If a file already exists, the tool will ask you how to proceed. With this, you can answer in advance.', - group: 'dl', - service: ['all'], - type: 'string', - usage: '${option}', - choices: [ 'y', 'Y', 'n', 'N', 'c', 'C' ] - }, - { - name: 'mkvmergeOptions', - describe: 'Set the options given to mkvmerge', - docDescribe: true, - group: 'mux', - service: ['all'], - type: 'array', - usage: '${args}', - default: { - default: [ - '--no-date', - '--disable-track-statistics-tags', - '--engage no_variable_data' - ] - } - }, - { - name: 'ffmpegOptions', - describe: 'Set the options given to ffmpeg', - docDescribe: true, - group: 'mux', - service: ['all'], - type: 'array', - usage: '${args}', - default: { - default: [] - } - }, - { - name: 'defaultAudio', - describe: `Set the default audio track by language code\nPossible Values: ${languages.map(a => a.code).join(', ')}`, - docDescribe: true, - group: 'mux', - service: ['all'], - type: 'string', - usage: '${args}', - default: { - default: 'eng' - }, - transformer: (val) => { - const item = languages.find(a => a.code === val); - if (!item) { - throw new Error(`Unable to find language code ${val}!`); - } - return item; - } - }, - { - name: 'defaultSub', - describe: `Set the default subtitle track by language code\nPossible Values: ${languages.map(a => a.code).join(', ')}`, - docDescribe: true, - group: 'mux', - service: ['all'], - type: 'string', - usage: '${args}', - default: { - default: 'eng' - }, - transformer: (val) => { - const item = languages.find(a => a.code === val); - if (!item) { - throw new Error(`Unable to find language code ${val}!`); - } - return item; - } - }, - { - name: 'ccTag', - describe: 'Used to set the name for subtitles that contain tranlations for none verbal communication (e.g. signs)', - docDescribe: true, - group: 'fileName', - service: ['all'], - type: 'string', - usage: '${tag}', - default: { - default: 'cc' - } - } -]; - -const getDefault = (name: string, cfg: Record): T => { - const option = args.find(item => item.name === name); - if (!option) - throw new Error(`Unable to find option ${name}`); - if (option.default === undefined) - throw new Error(`Option ${name} has no default`); - if (typeof option.default === 'object') { - if (Array.isArray(option.default)) - return option.default as T; - if (Object.prototype.hasOwnProperty.call(cfg, (option.default as any).name ?? option.name)) { - return cfg[(option.default as any).name ?? option.name]; - } else { - return (option.default as any).default as T; - } - } else { - return option.default as T; - } -}; - -const buildDefault = () => { - const data: Record = {}; - const defaultArgs = args.filter(a => a.default); - defaultArgs.forEach(item => { - if (typeof item.default === 'object') { - if (Array.isArray(item.default)) { - data[item.name] = item.default; - } else { - data[(item.default as any).name ?? item.name] = (item.default as any).default; - } - } else { - data[item.name] = item.default; - } - }); - return data; -}; - -export { - getDefault, - buildDefault, - args, - groups, - availableFilenameVars -}; diff --git a/modules/module.cfg-loader.js b/modules/module.cfg-loader.js new file mode 100644 index 0000000..3b5d207 --- /dev/null +++ b/modules/module.cfg-loader.js @@ -0,0 +1,26 @@ +const yaml = require('yaml'); +const fs = require('fs'); +const existsFile = fs.existsSync; + +const loadYamlFile = (file) => { + return yaml.parse(fs.readFileSync(file, 'utf8')); +}; + +const loadYamlCfg = (file) => { + if(existsFile(`${file}.user.yml`)){ + file += '.user'; + } + file += '.yml'; + if(fs.existsSync(file)){ + + try{ + return loadYamlFile(file, 'utf8'); + } + catch(e){ + return {}; + } + } + return {}; +}; + +module.exports = loadYamlCfg; diff --git a/modules/module.cfg-loader.ts b/modules/module.cfg-loader.ts deleted file mode 100644 index f09da06..0000000 --- a/modules/module.cfg-loader.ts +++ /dev/null @@ -1,410 +0,0 @@ -import path from 'path'; -import yaml from 'yaml'; -import fs from 'fs-extra'; -import { lookpath } from 'lookpath'; -import { console } from './log'; -import { GuiState } from '../@types/messageHandler'; - -// new-cfg -const workingDir = (process as NodeJS.Process & { - pkg?: unknown -}).pkg ? path.dirname(process.execPath) : process.env.contentDirectory ? process.env.contentDirectory : path.join(__dirname, '/..'); - -export { workingDir }; - -const binCfgFile = path.join(workingDir, 'config', 'bin-path'); -const dirCfgFile = path.join(workingDir, 'config', 'dir-path'); -const guiCfgFile = path.join(workingDir, 'config', 'gui'); -const cliCfgFile = path.join(workingDir, 'config', 'cli-defaults'); -const hdPflCfgFile = path.join(workingDir, 'config', 'hd_profile'); -const sessCfgFile = { - cr: path.join(workingDir, 'config', 'cr_sess'), - hd: path.join(workingDir, 'config', 'hd_sess'), - ao: path.join(workingDir, 'config', 'ao_sess'), - adn: path.join(workingDir, 'config', 'adn_sess') -}; -const stateFile = path.join(workingDir, 'config', 'guistate'); -const tokenFile = { - cr: path.join(workingDir, 'config', 'cr_token'), - hd: path.join(workingDir, 'config', 'hd_token'), - hdNew:path.join(workingDir, 'config', 'hd_new_token'), - ao: path.join(workingDir, 'config', 'ao_token'), - adn: path.join(workingDir, 'config', 'adn_token') -}; - -export const ensureConfig = () => { - if (!fs.existsSync(path.join(workingDir, 'config'))) - fs.mkdirSync(path.join(workingDir, 'config')); - if (process.env.contentDirectory) - [binCfgFile, dirCfgFile, cliCfgFile, guiCfgFile].forEach(a => { - if (!fs.existsSync(`${a}.yml`)) - fs.copyFileSync(path.join(__dirname, '..', 'config', `${path.basename(a)}.yml`), `${a}.yml`); - }); -}; - -const loadYamlCfgFile = >(file: string, isSess?: boolean): T => { - if(fs.existsSync(`${file}.user.yml`) && !isSess){ - file += '.user'; - } - file += '.yml'; - if(fs.existsSync(file)){ - try{ - return yaml.parse(fs.readFileSync(file, 'utf8')); - } - catch(e){ - console.error('[ERROR]', e); - return {} as T; - } - } - return {} as T; -}; - -export type WriteObjects = { - gui: GUIConfig -} - -const writeYamlCfgFile = (file: T, data: WriteObjects[T]) => { - const fn = path.join(workingDir, 'config', `${file}.yml`); - if (fs.existsSync(fn)) - fs.removeSync(fn); - fs.writeFileSync(fn, yaml.stringify(data)); -}; - -export type GUIConfig = { - port: number, - password?: string -}; - -export type ConfigObject = { - dir: { - content: string, - trash: string, - fonts: string; - config: string; - }, - bin: { - ffmpeg?: string, - mkvmerge?: string, - ffprobe?: string, - mp4decrypt?: string - }, - cli: { - [key: string]: any - }, - gui: GUIConfig -} - -const loadCfg = () : ConfigObject => { - // load cfgs - const defaultCfg: ConfigObject = { - bin: {}, - dir: loadYamlCfgFile<{ - content: string, - trash: string, - fonts: string - config: string - }>(dirCfgFile), - cli: loadYamlCfgFile<{ - [key: string]: any - }>(cliCfgFile), - gui: loadYamlCfgFile(guiCfgFile) - }; - const defaultDirs = { - fonts: '${wdir}/fonts/', - content: '${wdir}/videos/', - trash: '${wdir}/videos/_trash/', - config: '${wdir}/config' - }; - if (typeof defaultCfg.dir !== 'object' || defaultCfg.dir === null || Array.isArray(defaultCfg.dir)) { - defaultCfg.dir = defaultDirs; - } - - const keys = Object.keys(defaultDirs) as (keyof typeof defaultDirs)[]; - for (const key of keys) { - if (!Object.prototype.hasOwnProperty.call(defaultCfg.dir, key) || typeof defaultCfg.dir[key] !== 'string') { - defaultCfg.dir[key] = defaultDirs[key]; - } - if (!path.isAbsolute(defaultCfg.dir[key])) { - defaultCfg.dir[key] = path.join(workingDir, defaultCfg.dir[key].replace(/^\${wdir}/, '')); - } - } - if(!fs.existsSync(defaultCfg.dir.content)){ - try{ - fs.ensureDirSync(defaultCfg.dir.content); - } - catch(e){ - console.error('Content directory not accessible!'); - return defaultCfg; - } - } - if(!fs.existsSync(defaultCfg.dir.trash)){ - defaultCfg.dir.trash = defaultCfg.dir.content; - } - // output - return defaultCfg; -}; - -const loadBinCfg = async () => { - const binCfg = loadYamlCfgFile(binCfgFile); - // binaries - const defaultBin = { - ffmpeg: 'ffmpeg', - mkvmerge: 'mkvmerge', - ffprobe: 'ffprobe', - mp4decrypt: 'mp4decrypt' - }; - const keys = Object.keys(defaultBin) as (keyof typeof defaultBin)[]; - for(const dir of keys){ - if(!Object.prototype.hasOwnProperty.call(binCfg, dir) || typeof binCfg[dir] != 'string'){ - binCfg[dir] = defaultBin[dir]; - } - if ((binCfg[dir] as string).match(/^\${wdir}/)) { - binCfg[dir] = (binCfg[dir] as string).replace(/^\${wdir}/, ''); - binCfg[dir] = path.join(workingDir, binCfg[dir] as string); - } - if (!path.isAbsolute(binCfg[dir] as string)){ - binCfg[dir] = path.join(workingDir, binCfg[dir] as string); - } - binCfg[dir] = await lookpath(binCfg[dir] as string); - binCfg[dir] = binCfg[dir] ? binCfg[dir] : undefined; - if(!binCfg[dir]){ - const binFile = await lookpath(path.basename(defaultBin[dir])); - binCfg[dir] = binFile ? binFile : binCfg[dir]; - } - } - return binCfg; -}; - -const loadCRSession = () => { - let session = loadYamlCfgFile(sessCfgFile.cr, true); - if(typeof session !== 'object' || session === null || Array.isArray(session)){ - session = {}; - } - for(const cv of Object.keys(session)){ - if(typeof session[cv] !== 'object' || session[cv] === null || Array.isArray(session[cv])){ - session[cv] = {}; - } - } - return session; -}; - -const saveCRSession = (data: Record) => { - const cfgFolder = path.dirname(sessCfgFile.cr); - try{ - fs.ensureDirSync(cfgFolder); - fs.writeFileSync(`${sessCfgFile.cr}.yml`, yaml.stringify(data)); - } - catch(e){ - console.error('Can\'t save session file to disk!'); - } -}; - -const loadCRToken = () => { - let token = loadYamlCfgFile(tokenFile.cr, true); - if(typeof token !== 'object' || token === null || Array.isArray(token)){ - token = {}; - } - return token; -}; - -const saveCRToken = (data: Record) => { - const cfgFolder = path.dirname(tokenFile.cr); - try{ - fs.ensureDirSync(cfgFolder); - fs.writeFileSync(`${tokenFile.cr}.yml`, yaml.stringify(data)); - } - catch(e){ - console.error('Can\'t save token file to disk!'); - } -}; - -const loadADNToken = () => { - let token = loadYamlCfgFile(tokenFile.adn, true); - if(typeof token !== 'object' || token === null || Array.isArray(token)){ - token = {}; - } - return token; -}; - -const saveADNToken = (data: Record) => { - const cfgFolder = path.dirname(tokenFile.adn); - try{ - fs.ensureDirSync(cfgFolder); - fs.writeFileSync(`${tokenFile.adn}.yml`, yaml.stringify(data)); - } - catch(e){ - console.error('Can\'t save token file to disk!'); - } -}; - -const loadAOToken = () => { - let token = loadYamlCfgFile(tokenFile.ao, true); - if(typeof token !== 'object' || token === null || Array.isArray(token)){ - token = {}; - } - return token; -}; - -const saveAOToken = (data: Record) => { - const cfgFolder = path.dirname(tokenFile.ao); - try{ - fs.ensureDirSync(cfgFolder); - fs.writeFileSync(`${tokenFile.ao}.yml`, yaml.stringify(data)); - } - catch(e){ - console.error('Can\'t save token file to disk!'); - } -}; - -const loadHDSession = () => { - let session = loadYamlCfgFile(sessCfgFile.hd, true); - if(typeof session !== 'object' || session === null || Array.isArray(session)){ - session = {}; - } - for(const cv of Object.keys(session)){ - if(typeof session[cv] !== 'object' || session[cv] === null || Array.isArray(session[cv])){ - session[cv] = {}; - } - } - return session; -}; - -const saveHDSession = (data: Record) => { - const cfgFolder = path.dirname(sessCfgFile.hd); - try{ - fs.ensureDirSync(cfgFolder); - fs.writeFileSync(`${sessCfgFile.hd}.yml`, yaml.stringify(data)); - } - catch(e){ - console.error('Can\'t save session file to disk!'); - } -}; - - -const loadHDToken = () => { - let token = loadYamlCfgFile(tokenFile.hd, true); - if(typeof token !== 'object' || token === null || Array.isArray(token)){ - token = {}; - } - return token; -}; - -const saveHDToken = (data: Record) => { - const cfgFolder = path.dirname(tokenFile.hd); - try{ - fs.ensureDirSync(cfgFolder); - fs.writeFileSync(`${tokenFile.hd}.yml`, yaml.stringify(data)); - } - catch(e){ - console.error('Can\'t save token file to disk!'); - } -}; - -const saveHDProfile = (data: Record) => { - const cfgFolder = path.dirname(hdPflCfgFile); - try{ - fs.ensureDirSync(cfgFolder); - fs.writeFileSync(`${hdPflCfgFile}.yml`, yaml.stringify(data)); - } - catch(e){ - console.error('Can\'t save profile file to disk!'); - } -}; - -const loadHDProfile = () => { - let profile = loadYamlCfgFile(hdPflCfgFile, true); - if(typeof profile !== 'object' || profile === null || Array.isArray(profile) || Object.keys(profile).length === 0){ - profile = { - // base - ipAddress : '', - xNonce : '', - xSignature: '', - // personal - visitId : '', - // profile data - profile: { - userId : 0, - profileId: 0, - deviceId : '', - }, - }; - } - return profile; -}; - -const loadNewHDToken = () => { - let token = loadYamlCfgFile(tokenFile.hdNew, true); - if(typeof token !== 'object' || token === null || Array.isArray(token)){ - token = {}; - } - return token; -}; - -const saveNewHDToken = (data: Record) => { - const cfgFolder = path.dirname(tokenFile.hdNew); - try{ - fs.ensureDirSync(cfgFolder); - fs.writeFileSync(`${tokenFile.hdNew}.yml`, yaml.stringify(data)); - } - catch(e){ - console.error('Can\'t save token file to disk!'); - } -}; - -const cfgDir = path.join(workingDir, 'config'); - -const getState = (): GuiState => { - const fn = `${stateFile}.json`; - if (!fs.existsSync(fn)) { - return { - 'setup': false, - 'services': {} - }; - } - try { - return JSON.parse(fs.readFileSync(fn).toString()); - } catch(e) { - console.error('Invalid state file, regenerating'); - return { - 'setup': false, - 'services': {} - }; - } -}; - -const setState = (state: GuiState) => { - const fn = `${stateFile}.json`; - try { - fs.writeFileSync(fn, JSON.stringify(state, null, 2)); - } catch(e) { - console.error('Failed to write state file.'); - } -}; - - -export { - loadBinCfg, - loadCfg, - saveCRSession, - loadCRSession, - saveCRToken, - loadCRToken, - saveADNToken, - loadADNToken, - saveHDSession, - loadHDSession, - saveHDToken, - loadHDToken, - saveNewHDToken, - loadNewHDToken, - saveHDProfile, - loadHDProfile, - saveAOToken, - loadAOToken, - getState, - setState, - writeYamlCfgFile, - sessCfgFile, - hdPflCfgFile, - cfgDir -}; \ No newline at end of file diff --git a/modules/module.cookieFile.ts b/modules/module.cookieFile.ts deleted file mode 100644 index b9bd2c7..0000000 --- a/modules/module.cookieFile.ts +++ /dev/null @@ -1,26 +0,0 @@ -const parse = (data: string) => { - const res: Record = {}; - const split = data.replace(/\r/g,'').split('\n'); - for (const line of split) { - const c = line.split('\t'); - if(c.length < 7){ - continue; - } - res[c[5]] = { - value: c[6], - expires: new Date(parseInt(c[4])*1000), - path: c[2], - domain: c[0].replace(/^\./,''), - secure: c[3] == 'TRUE' ? true : false - }; - } - return res; -}; - -export default parse; diff --git a/modules/module.curl-req.ts b/modules/module.curl-req.ts deleted file mode 100644 index 7ea8e27..0000000 --- a/modules/module.curl-req.ts +++ /dev/null @@ -1,163 +0,0 @@ -// build-in -import child_process from 'child_process'; -import fs from 'fs-extra'; -import { Headers } from 'got'; -import path from 'path'; -import { console } from './log'; - -export type CurlOptions = { - headers?: Headers, - curlProxy?: boolean, - curlProxyAuth?: string, - minVersion?: string, - http2?: boolean, - body?: unknown, - curlDebug?: boolean -} | undefined; - -export type Res = { - httpVersion: string, - statusCode: string, - statusMessage: string, - rawHeaders: string, - headers: Record, - rawBody: Buffer, - body: string, -} - -// req -const curlReq = async (curlBin: string, url: string, options: CurlOptions, cache: string) => { - - const curlOpt = [ - `"${curlBin}"`, - `"${url}"`, - ]; - - options = options || {}; - - if(options.headers && Object.keys(options.headers).length > 0){ - for(const h of Object.keys(options.headers)){ - const hC = options.headers[h]; - curlOpt.push('-H', `"${h}: ${hC}"`); - } - } - - if(options.curlProxy){ - curlOpt.push('--proxy-insecure', '-x', `"${options.curlProxy}"`); - if(options.curlProxyAuth && typeof options.curlProxyAuth == 'string' && options.curlProxyAuth.match(':')){ - curlOpt.push('-U', `"${options.curlProxyAuth}"`); - } - } - - const reqId = uuidv4(); - const headFile = path.join(cache, `/res-headers-${reqId}`); - const bodyFile = path.join(cache, `/res-body-${reqId}`); - const errFile = path.join(cache, `/res-err-${reqId}`); - - curlOpt.push('-D', `"${headFile}"`); - curlOpt.push('-o', `"${bodyFile}"`); - curlOpt.push('--stderr', `"${errFile}"`); - curlOpt.push('-L', '-s', '-S'); - - if(options.minVersion == 'TLSv1.3'){ - curlOpt.push('--tlsv1.3'); - } - if(options.http2){ - curlOpt.push('--http2'); - } - - if(options.body){ - curlOpt.push('--data-urlencode', `"${options.body}"`); - } - - const curlComm = curlOpt.join(' '); - - try{ - if(options.curlDebug){ - console.info(curlComm, '\n'); - } - child_process.execSync(curlComm, { stdio: 'inherit', windowsHide: true }); - } - catch(next){ - const errData = { name: 'RequestError', message: 'EACCES' }; - try{ - fs.unlinkSync(headFile); - } - catch(e){ - // ignore it... - } - try{ - errData.message = - fs.readFileSync(errFile, 'utf8') - .replace(/^curl: /, ''); - fs.unlinkSync(errFile); - } - catch(e){ - // ignore it... - } - throw errData; - } - - const rawHeaders = fs.readFileSync(headFile, 'utf8'); - const rawBody = fs.readFileSync(bodyFile); - fs.unlinkSync(headFile); - fs.unlinkSync(bodyFile); - fs.unlinkSync(errFile); - - const res: Res = { - httpVersion: '', - statusCode: '', - statusMessage: '', - rawHeaders: rawHeaders, - headers: {}, - rawBody: rawBody, - body: rawBody.toString(), - }; - - const headersCont = rawHeaders.replace(/\r/g, '').split('\n'); - - for(const h of headersCont){ - if( h == '' ){ continue; } - if(!h.match(':')){ - const statusRes = h.split(' '); - res.httpVersion = statusRes[0].split('/')[1]; - res.statusCode = statusRes[1]; - res.statusMessage = statusRes.slice(2).join(' '); - } - else{ - const resHeader = h.split(': '); - const resHeadName = resHeader[0].toLowerCase(); - const resHeadCont = resHeader.slice(1).join(': '); - if(resHeadName == 'set-cookie'){ - if(!Object.prototype.hasOwnProperty.call(res.headers, resHeadName)){ - res.headers[resHeadName] = []; - } - (res.headers[resHeadName] as string[]).push(resHeadCont); - } - else{ - res.headers[resHeadName] = resHeadCont; - } - } - } - - if(!res.statusCode.match(/^(2|3)\d\d$/)){ - const httpStatusMessage = res.statusMessage ? ` (${res.statusMessage})` : ''; - throw { - name: 'HTTPError', - message: `Response code ${res.statusCode}${httpStatusMessage}`, - response: res - }; - } - - return res; - -}; - -function uuidv4() { - return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { - const r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); - return v.toString(16); - }); -} - -export default curlReq; diff --git a/modules/module.downloadArchive.ts b/modules/module.downloadArchive.ts deleted file mode 100644 index 46833ac..0000000 --- a/modules/module.downloadArchive.ts +++ /dev/null @@ -1,155 +0,0 @@ -import * as path from 'path'; -import * as fs from 'fs'; -import { ArgvType } from './module.app-args'; -import { workingDir } from './module.cfg-loader'; - -export const archiveFile = path.join(workingDir, 'config', 'archive.json'); - -export type ItemType = { - id: string, - already: string[] -}[] - -export type DataType = { - hidive: { - s: ItemType - }, - ao: { - s: ItemType - }, - adn: { - s: ItemType - }, - crunchy: { - srz: ItemType, - s: ItemType - } -} - -const addToArchive = (kind: { - service: 'crunchy', - type: 's'|'srz' -} | { - service: 'hidive', - type: 's' -} | { - service: 'ao', - type: 's' -} | { - service: 'adn', - type: 's' -}, ID: string) => { - const data = loadData(); - - if (Object.prototype.hasOwnProperty.call(data, kind.service)) { - const items = kind.service === 'crunchy' ? data[kind.service][kind.type] : data[kind.service][kind.type]; - if (items.findIndex(a => a.id === ID) >= 0) // Prevent duplicate - return; - items.push({ - id: ID, - already: [] - }); - (data as any)[kind.service][kind.type] = items; - } else { - if (kind.service === 'ao') { - data['ao'] = { - s: [ - { - id: ID, - already: [] - } - ] - }; - } else if (kind.service === 'crunchy') { - data['crunchy'] = { - s: ([] as ItemType).concat(kind.type === 's' ? { - id: ID, - already: [] as string[] - } : []), - srz: ([] as ItemType).concat(kind.type === 'srz' ? { - id: ID, - already: [] as string[] - } : []), - }; - } else if (kind.service === 'adn') { - data['adn'] = { - s: [ - { - id: ID, - already: [] - } - ] - }; - } else { - data['hidive'] = { - s: [ - { - id: ID, - already: [] - } - ] - }; - } - } - fs.writeFileSync(archiveFile, JSON.stringify(data, null, 4)); -}; - -const downloaded = (kind: { - service: 'crunchy', - type: 's'|'srz' -} | { - service: 'hidive', - type: 's' -} | { - service: 'ao', - type: 's' -} | { - service: 'adn', - type: 's' -}, ID: string, episode: string[]) => { - let data = loadData(); - if (!Object.prototype.hasOwnProperty.call(data, kind.service) || !Object.prototype.hasOwnProperty.call(data[kind.service], kind.type) - || !Object.prototype.hasOwnProperty.call((data as any)[kind.service][kind.type], ID)) { - addToArchive(kind, ID); - data = loadData(); // Load updated version - } - - const archivedata = (kind.service == 'crunchy' ? data[kind.service][kind.type] : data[kind.service][kind.type]); - const alreadyData = archivedata.find(a => a.id === ID)?.already; - for (const ep of episode) { - if (alreadyData?.includes(ep)) continue; - alreadyData?.push(ep); - } - fs.writeFileSync(archiveFile, JSON.stringify(data, null, 4)); -}; - -const makeCommand = (service: 'crunchy'|'hidive'|'ao'|'adn') : Partial[] => { - const data = loadData(); - const ret: Partial[] = []; - const kind = data[service]; - for (const type of Object.keys(kind)) { - const item = kind[type as 's']; // 'srz' is also possible but will be ignored for the compiler - item.forEach(i => ret.push({ - but: true, - all: false, - service, - e: i.already.join(','), - ...(type === 's' ? { - s: i.id, - series: undefined - } : { - series: i.id, - s: undefined - }) - })); - } - return ret; -}; - -const loadData = () : DataType => { - if (fs.existsSync(archiveFile)) - return JSON.parse(fs.readFileSync(archiveFile).toString()) as DataType; - return {} as DataType; -}; - -export { addToArchive, downloaded, makeCommand }; \ No newline at end of file diff --git a/modules/module.fetch.ts b/modules/module.fetch.ts deleted file mode 100644 index 9798f20..0000000 --- a/modules/module.fetch.ts +++ /dev/null @@ -1,146 +0,0 @@ -import * as yamlCfg from './module.cfg-loader'; -import { console } from './log'; -import { Method } from 'got'; - -export type Params = { - method?: Method, - headers?: Record, - body?: string | Buffer, - binary?: boolean, - followRedirect?: 'follow' | 'error' | 'manual' -} - -// req -export class Req { - private sessCfg: string; - private service: 'cr'|'hd'|'ao'|'adn'; - private session: Record = {}; - private cfgDir = yamlCfg.cfgDir; - private curl: boolean|string = false; - - constructor(private domain: Record, private debug: boolean, private nosess = false, private type: 'cr'|'hd'|'ao'|'adn') { - this.sessCfg = yamlCfg.sessCfgFile[type]; - this.service = type; - } - - async getData(durl: string, params?: RequestInit) { - params = params || {}; - // options - const options: RequestInit = { - method: params.method ? params.method : 'GET', - headers: { - 'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7', - 'accept-language': 'en-US,en;q=0.9', - 'cache-control': 'no-cache', - 'pragma': 'no-cache', - 'sec-ch-ua': '"Google Chrome";v="123", "Not:A-Brand";v="8", "Chromium";v="123"', - 'sec-ch-ua-mobile': '?0', - 'sec-ch-ua-platform': '"Windows"', - 'sec-fetch-dest': 'document', - 'sec-fetch-mode': 'navigate', - 'sec-fetch-site': 'none', - 'sec-fetch-user': '?1', - 'upgrade-insecure-requests': '1', - }, - }; - // additional params - if(params.headers){ - options.headers = {...options.headers, ...params.headers}; - } - if(options.method == 'POST'){ - if (!(options.headers as Record)['Content-Type']) { - (options.headers as Record)['Content-Type'] = 'application/x-www-form-urlencoded'; - } - } - if(params.body){ - options.body = params.body; - } - if(typeof params.redirect == 'string'){ - options.redirect = params.redirect; - } - // debug - if(this.debug){ - console.debug('[DEBUG] FETCH OPTIONS:'); - console.debug(options); - } - // try do request - try { - const res = await fetch(durl, options); - if (!res.ok) { - console.error(`${res.status}: ${res.statusText}`); - const body = await res.text(); - const docTitle = body.match(/(.*)<\/title>/); - if(body && docTitle){ - console.error(docTitle[1]); - } else { - console.error(body); - } - } - return { - ok: res.ok, - res - }; - } - catch(_error){ - const error = _error as { - name: string - } & TypeError & { - res: Response - }; - if (error.res && error.res.status && error.res.statusText) { - console.error(`${error.name} ${error.res.status}: ${error.res.statusText}`); - } else { - console.error(`${error.name}: ${error.res?.statusText || error.message}`); - } - if(error.res) { - const body = await error.res.text(); - const docTitle = body.match(/<title>(.*)<\/title>/); - if(body && docTitle){ - console.error(docTitle[1]); - } - } - return { - ok: false, - error, - }; - } - } -} - -export function buildProxy(proxyBaseUrl: string, proxyAuth: string){ - if(!proxyBaseUrl.match(/^(https?|socks4|socks5):/)){ - proxyBaseUrl = 'http://' + proxyBaseUrl; - } - - const proxyCfg = new URL(proxyBaseUrl); - let proxyStr = `${proxyCfg.protocol}//`; - - if(typeof proxyCfg.hostname != 'string' || proxyCfg.hostname == ''){ - throw new Error('[ERROR] Hostname and port required for proxy!'); - } - - if(proxyAuth && typeof proxyAuth == 'string' && proxyAuth.match(':')){ - proxyCfg.username = proxyAuth.split(':')[0]; - proxyCfg.password = proxyAuth.split(':')[1]; - proxyStr += `${proxyCfg.username}:${proxyCfg.password}@`; - } - - proxyStr += proxyCfg.hostname; - - if(!proxyCfg.port && proxyCfg.protocol == 'http:'){ - proxyStr += ':80'; - } - else if(!proxyCfg.port && proxyCfg.protocol == 'https:'){ - proxyStr += ':443'; - } - - return proxyStr; -} - \ No newline at end of file diff --git a/modules/module.filename.ts b/modules/module.filename.ts deleted file mode 100644 index 46f8dbf..0000000 --- a/modules/module.filename.ts +++ /dev/null @@ -1,88 +0,0 @@ -import * as shlp from 'sei-helper'; -import path from 'path'; -import { AvailableFilenameVars } from './module.args'; -import { console } from './log'; - -export type Variable<T extends string = AvailableFilenameVars> = ({ - type: 'number', - replaceWith: number -} | { - type: 'string', - replaceWith: string -}) & { - name: T, - sanitize?: boolean -} - -const parseFileName = (input: string, variables: Variable[], numbers: number, override: string[]): string[] => { - const varRegex = /\${[A-Za-z1-9]+}/g; - const vars = input.match(varRegex); - const overridenVars = parseOverride(variables, override); - if (!vars) - return [input]; - for (let i = 0; i < vars.length; i++) { - const type = vars[i]; - const varName = type.slice(2, -1); - const use = overridenVars.find(a => a.name === varName); - if (use === undefined) { - console.info(`[ERROR] Found variable '${type}' in fileName but no values was internally found!`); - continue; - } - - if (use.type === 'number') { - const len = use.replaceWith.toFixed(0).length; - const replaceStr = len < numbers ? '0'.repeat(numbers - len) + use.replaceWith : use.replaceWith+''; - input = input.replace(type, replaceStr); - } else { - if (use.sanitize) - use.replaceWith = shlp.cleanupFilename(use.replaceWith); - input = input.replace(type, use.replaceWith); - } - } - return input.split(path.sep).map(a => shlp.cleanupFilename(a)); -}; - -const parseOverride = (variables: Variable[], override: string[]): Variable<string>[] => { - const vars: Variable<string>[] = variables; - override.forEach(item => { - const index = item.indexOf('='); - if (index === -1) - return logError(item, 'invalid'); - const parts = [ item.slice(0, index), item.slice(index + 1) ]; - if (!(parts[1].startsWith('\'') && parts[1].endsWith('\'') && parts[1].length >= 2)) - return logError(item, 'invalid'); - parts[1] = parts[1].slice(1, -1); - const already = vars.findIndex(a => a.name === parts[0]); - if (already > -1) { - if (vars[already].type === 'number') { - if (isNaN(parseFloat(parts[1]))) - return logError(item, 'wrongType'); - vars[already].replaceWith = parseFloat(parts[1]); - } else { - vars[already].replaceWith = parts[1]; - } - } else { - const isNumber = !isNaN(parseFloat(parts[1])); - vars.push({ - name: parts[0], - replaceWith: isNumber ? parseFloat(parts[1]) : parts[1], - type: isNumber ? 'number' : 'string' - } as Variable<string>); - } - }); - - return variables; -}; - -const logError = (override: string, reason: 'invalid'|'wrongType') => { - switch (reason) { - case 'wrongType': - console.error(`[ERROR] Invalid type on \`${override}\`. Expected number but found string. It has been ignored`); - break; - case 'invalid': - default: - console.error(`[ERROR] Invalid override \`${override}\`. It has been ignored`); - } -}; - -export default parseFileName; \ No newline at end of file diff --git a/modules/module.fontsData.ts b/modules/module.fontsData.ts deleted file mode 100644 index 5567e3a..0000000 --- a/modules/module.fontsData.ts +++ /dev/null @@ -1,59 +0,0 @@ -// fonts src -const root = 'https://static.crunchyroll.com/vilos-v2/web/vilos/assets/libass-fonts/'; - -// file list -const fontFamilies = { - 'Adobe Arabic': [ 'AdobeArabic-Bold.otf', ], - 'Andale Mono': [ 'andalemo.ttf', ], - 'Arial': [ 'arial.ttf', 'arialbd.ttf', 'arialbi.ttf', 'ariali.ttf', ], - 'Arial Unicode MS': [ 'arialuni.ttf', ], - 'Arial Black': [ 'ariblk.ttf', ], - 'Comic Sans MS': [ 'comic.ttf', 'comicbd.ttf', ], - 'Courier New': [ 'cour.ttf', 'courbd.ttf', 'courbi.ttf', 'couri.ttf', ], - 'DejaVu LGC Sans Mono': [ 'DejaVuLGCSansMono-Bold.ttf', 'DejaVuLGCSansMono-BoldOblique.ttf', 'DejaVuLGCSansMono-Oblique.ttf', 'DejaVuLGCSansMono.ttf', ], - 'DejaVu Sans': [ 'DejaVuSans-Bold.ttf', 'DejaVuSans-BoldOblique.ttf', 'DejaVuSans-ExtraLight.ttf', 'DejaVuSans-Oblique.ttf', 'DejaVuSans.ttf', ], - 'DejaVu Sans Condensed': [ 'DejaVuSansCondensed-Bold.ttf', 'DejaVuSansCondensed-BoldOblique.ttf', 'DejaVuSansCondensed-Oblique.ttf', 'DejaVuSansCondensed.ttf', ], - 'DejaVu Sans Mono': [ 'DejaVuSansMono-Bold.ttf', 'DejaVuSansMono-BoldOblique.ttf', 'DejaVuSansMono-Oblique.ttf', 'DejaVuSansMono.ttf', ], - 'Georgia': [ 'georgia.ttf', 'georgiab.ttf', 'georgiai.ttf', 'georgiaz.ttf', ], - 'Impact': [ 'impact.ttf', ], - 'Rubik Black': [ 'Rubik-Black.ttf', 'Rubik-BlackItalic.ttf', ], - 'Rubik': [ 'Rubik-Bold.ttf', 'Rubik-BoldItalic.ttf', 'Rubik-Italic.ttf', 'Rubik-Light.ttf', 'Rubik-LightItalic.ttf', 'Rubik-Medium.ttf', 'Rubik-MediumItalic.ttf', 'Rubik-Regular.ttf', ], - 'Tahoma': [ 'tahoma.ttf', ], - 'Times New Roman': [ 'times.ttf', 'timesbd.ttf', 'timesbi.ttf', 'timesi.ttf', ], - 'Trebuchet MS': [ 'trebuc.ttf', 'trebucbd.ttf', 'trebucbi.ttf', 'trebucit.ttf', ], - 'Verdana': [ 'verdana.ttf', 'verdanab.ttf', 'verdanai.ttf', 'verdanaz.ttf', ], - 'Webdings': [ 'webdings.ttf', ], -}; - -// collect styles from ass string -function assFonts(ass: string){ - const strings = ass.replace(/\r/g,'').split('\n'); - const styles: string[] = []; - for(const s of strings){ - if(s.match(/^Style: /)){ - const addStyle = s.split(','); - styles.push(addStyle[1]); - } - } - const fontMatches = ass.matchAll(/\\fn([^\\}]+)/g); - for (const match of fontMatches) { - styles.push(match[1]); - } - return [...new Set(styles)]; -} - -// font mime type -function fontMime(fontFile: string){ - if(fontFile.match(/\.otf$/)){ - return 'application/vnd.ms-opentype'; - } - if(fontFile.match(/\.ttf$/)){ - return 'application/x-truetype-font'; - } - return 'application/octet-stream'; -} - -export type AvailableFonts = keyof typeof fontFamilies; - -// output -export { root, fontFamilies, assFonts, fontMime }; diff --git a/modules/module.getdata.js b/modules/module.getdata.js new file mode 100644 index 0000000..fa65fef --- /dev/null +++ b/modules/module.getdata.js @@ -0,0 +1,76 @@ +const FormData = require('form-data'); +const got = require('got'); + +// do req +const getData = async (options) => { + let gOptions = { + url: options.url, + headers: { + 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:70.0) Gecko/20100101 Firefox/70.0', + } + }; + if(options.responseType) { + gOptions.responseType = options.responseType; + } + if(options.baseUrl){ + gOptions.prefixUrl = options.baseUrl; + gOptions.url = gOptions.url.replace(/^\//,''); + } + if(options.querystring){ + gOptions.url += `?${new URLSearchParams(options.querystring).toString()}`; + } + if(options.auth){ + gOptions.method = 'POST'; + gOptions.body = new FormData(); + gOptions.body.append('username', options.auth.user); + gOptions.body.append('password', options.auth.pass); + } + if(options.useToken && options.token){ + gOptions.headers.Authorization = `Token ${options.token}`; + } + if(options.dinstid){ + gOptions.headers.devicetype = 'Android Phone'; + } + // debug + gOptions.hooks = { + beforeRequest: [ + (gotOpts) => { + if(options.debug){ + console.log('[DEBUG] GOT OPTIONS:'); + console.log(gotOpts); + } + } + ] + }; + try { + let res = await got(gOptions); + if(res.body && (options.responseType !== 'buffer' && res.body.match(/^</))){ + throw { name: 'HTMLError', res }; + } + return { + ok: true, + res, + }; + } + catch(error){ + if(options.debug){ + console.log(error); + } + if(error.response && error.response.statusCode && error.response.statusMessage){ + console.log(`[ERROR] ${error.name} ${error.response.statusCode}: ${error.response.statusMessage}`); + } + else if(error.name && error.name == 'HTMLError' && error.res && error.res.body){ + console.log(`[ERROR] ${error.name}:`); + console.log(error.res.body); + } + else{ + console.log(`[ERROR] ${error.name}: ${error.code||error.message}`); + } + return { + ok: false, + error, + }; + } +}; + +module.exports = getData; diff --git a/modules/module.getdata.ts b/modules/module.getdata.ts deleted file mode 100644 index def6854..0000000 --- a/modules/module.getdata.ts +++ /dev/null @@ -1,132 +0,0 @@ -import got, { OptionsOfUnknownResponseBody, ReadError, Response, ResponseType } from 'got'; -import { console } from './log'; - -// Used for future updates -// const argv = require('../funi').argv; -// -// const lang = { -// 'ptBR': { -// langCode: 'pt-BR', -// regionCode: 'BR' -// }, -// 'esLA': { -// langCode: 'es-LA', -// regionCode: 'MX' -// } -// }; - - -export type Options = { - url: string, - responseType?: ResponseType, - baseUrl?: string, - querystring?: Record<string, any>, - auth?: { - user: string, - pass: string - }, - useToken?: boolean, - token?: string|boolean, - dinstid?: boolean|string, - debug?: boolean -} -// TODO convert to class -const getData = async <T = string>(options: Options) => { - const regionHeaders = {}; - - - const gOptions = { - url: options.url, - http2: true, - headers: { - 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:70.0) Gecko/20100101 Firefox/70.0', - 'Accept-Encoding': 'gzip', - ...regionHeaders - } - } as OptionsOfUnknownResponseBody; - if(options.responseType) { - gOptions.responseType = options.responseType; - } - if(options.baseUrl){ - gOptions.prefixUrl = options.baseUrl; - gOptions.url = gOptions.url?.toString().replace(/^\//,''); - } - if(options.querystring){ - gOptions.url += `?${new URLSearchParams(options.querystring).toString()}`; - } - if(options.auth){ - gOptions.method = 'POST'; - const newHeaders = { - ...gOptions.headers, - 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', - 'Origin': 'https://ww.funimation.com', - 'Accept': 'application/json, text/javascript, */*; q=0.01', - 'Accept-Encoding': 'gzip, deflate, br', - 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0' - }; - gOptions.headers = newHeaders; - gOptions.body = `username=${encodeURIComponent(options.auth.user)}&password=${encodeURIComponent(options.auth.pass)}`; - } - if(options.useToken && options.token){ - gOptions.headers = { - ...gOptions.headers, - Authorization: `Token ${options.token}` - }; - } - if(options.dinstid){ - gOptions.headers = { - ...gOptions.headers, - devicetype: 'Android Phone' - }; - } - // debug - gOptions.hooks = { - beforeRequest: [ - (gotOpts) => { - if(options.debug){ - console.debug('GOT OPTIONS:'); - console.debug(gotOpts); - } - } - ] - }; - try { - const res = await got(gOptions); - if(res.body && (options.responseType !== 'buffer' && (res.body as string).match(/^</))){ - throw { name: 'HTMLError', res }; - } - return { - ok: true, - res: { - ...res, - body: res.body as T - }, - }; - } - catch(_error){ - const error = _error as { - name: string, - } & ReadError & { - res: Response<unknown> - }; - if(options.debug){ - console.debug(error); - } - if(error.response && error.response.statusCode && error.response.statusMessage){ - console.error(`${error.name} ${error.response.statusCode}: ${error.response.statusMessage}`); - } - else if(error.name && error.name == 'HTMLError' && error.res && error.res.body){ - console.error(`${error.name}:`); - console.error(error.res.body); - } - else{ - console.error(`${error.name}: ${error.code||error.message}`); - } - return { - ok: false, - error, - }; - } -}; - -export default getData; diff --git a/modules/module.langsData.ts b/modules/module.langsData.ts deleted file mode 100644 index 33bf048..0000000 --- a/modules/module.langsData.ts +++ /dev/null @@ -1,203 +0,0 @@ -// available langs - -export type LanguageItem = { - cr_locale?: string, - hd_locale?: string, - adn_locale?: string, - new_hd_locale?: string, - ao_locale?: string, - locale: string, - code: string, - name: string, - language?: string -} - -const languages: LanguageItem[] = [ - { cr_locale: 'en-US', new_hd_locale: 'en-US', hd_locale: 'English', locale: 'en', code: 'eng', name: 'English' }, - { cr_locale: 'en-IN', locale: 'en-IN', code: 'eng', name: 'English (India)', }, - { cr_locale: 'es-LA', new_hd_locale: 'es-MX', hd_locale: 'Spanish LatAm', locale: 'es-419', code: 'spa', name: 'Spanish', language: 'Latin American Spanish' }, - { cr_locale: 'es-419',ao_locale: 'es',hd_locale: 'Spanish', locale: 'es-419', code: 'spa-419', name: 'Spanish', language: 'Latin American Spanish' }, - { cr_locale: 'es-ES', new_hd_locale: 'es-ES', hd_locale: 'Spanish Europe', locale: 'es-ES', code: 'spa-ES', name: 'Castilian', language: 'European Spanish' }, - { cr_locale: 'pt-BR', ao_locale: 'pt',new_hd_locale: 'pt-BR', hd_locale: 'Portuguese', locale: 'pt-BR', code: 'por', name: 'Portuguese', language: 'Brazilian Portuguese' }, - { cr_locale: 'pt-PT', locale: 'pt-PT', code: 'por', name: 'Portuguese (Portugal)', language: 'Portugues (Portugal)' }, - { cr_locale: 'fr-FR', adn_locale: 'fr', hd_locale: 'French', locale: 'fr', code: 'fra', name: 'French' }, - { cr_locale: 'de-DE', adn_locale: 'de', hd_locale: 'German', locale: 'de', code: 'deu', name: 'German' }, - { cr_locale: 'ar-ME', locale: 'ar', code: 'ara-ME', name: 'Arabic' }, - { cr_locale: 'ar-SA', hd_locale: 'Arabic', locale: 'ar', code: 'ara', name: 'Arabic (Saudi Arabia)' }, - { cr_locale: 'it-IT', hd_locale: 'Italian', locale: 'it', code: 'ita', name: 'Italian' }, - { cr_locale: 'ru-RU', hd_locale: 'Russian', locale: 'ru', code: 'rus', name: 'Russian' }, - { cr_locale: 'tr-TR', hd_locale: 'Turkish', locale: 'tr', code: 'tur', name: 'Turkish' }, - { cr_locale: 'hi-IN', locale: 'hi', code: 'hin', name: 'Hindi' }, - { locale: 'zh', code: 'cmn', name: 'Chinese (Mandarin, PRC)' }, - { cr_locale: 'zh-CN', locale: 'zh-CN', code: 'zho', name: 'Chinese (Mainland China)' }, - { cr_locale: 'zh-TW', locale: 'zh-TW', code: 'chi', name: 'Chinese (Taiwan)' }, - { cr_locale: 'zh-HK', locale: 'zh-HK', code: 'zh-HK', name: 'Chinese (Hong-Kong)', language: '中文 (粵語)' }, - { cr_locale: 'ko-KR', hd_locale: 'Korean', locale: 'ko', code: 'kor', name: 'Korean' }, - { cr_locale: 'ca-ES', locale: 'ca-ES', code: 'cat', name: 'Catalan' }, - { cr_locale: 'pl-PL', locale: 'pl-PL', code: 'pol', name: 'Polish' }, - { cr_locale: 'th-TH', locale: 'th-TH', code: 'tha', name: 'Thai', language: 'ไทย' }, - { cr_locale: 'ta-IN', locale: 'ta-IN', code: 'tam', name: 'Tamil (India)', language: 'தமிழ்' }, - { cr_locale: 'ms-MY', locale: 'ms-MY', code: 'may', name: 'Malay (Malaysia)', language: 'Bahasa Melayu' }, - { cr_locale: 'vi-VN', locale: 'vi-VN', code: 'vie', name: 'Vietnamese', language: 'Tiếng Việt' }, - { cr_locale: 'id-ID', locale: 'id-ID', code: 'ind', name: 'Indonesian', language: 'Bahasa Indonesia' }, - { cr_locale: 'te-IN', locale: 'te-IN', code: 'tel', name: 'Telugu (India)', language: 'తెలుగు' }, - { cr_locale: 'ja-JP', adn_locale: 'ja', ao_locale: 'ja', hd_locale: 'Japanese', locale: 'ja', code: 'jpn', name: 'Japanese' }, -]; - -// add en language names -(() =>{ - for(const languageIndex in languages){ - if(!languages[languageIndex].language){ - languages[languageIndex].language = languages[languageIndex].name; - } - } -})(); - -// construct dub language codes -const dubLanguageCodes = (() => { - const dubLanguageCodesArray: string[] = []; - for(const language of languages){ - dubLanguageCodesArray.push(language.code); - } - return [...new Set(dubLanguageCodesArray)]; -})(); - -// construct subtitle languages filter -const subtitleLanguagesFilter = (() => { - const subtitleLanguagesExtraParameters = ['all', 'none']; - return [...subtitleLanguagesExtraParameters, ...new Set(languages.map(l => { return l.locale; }))]; -})(); - -const searchLocales = (() => { - return ['', ...new Set(languages.map(l => { return l.cr_locale; }).slice(0, -1)), ...new Set(languages.map(l => { return l.adn_locale; }).slice(0, -1))]; -})(); - -export const aoSearchLocales = (() => { - return ['', ...new Set(languages.map(l => { return l.ao_locale; }).slice(0, -1))]; -})(); - -// convert -const fixLanguageTag = (tag: string) => { - tag = typeof tag == 'string' ? tag : 'und'; - const tagLangLC = tag.match(/^(\w{2})-?(\w{2})$/); - if(tagLangLC){ - const tagLang = `${tagLangLC[1]}-${tagLangLC[2].toUpperCase()}`; - if(findLang(tagLang).cr_locale != 'und'){ - return findLang(tagLang).cr_locale; - } - else{ - return tagLang; - } - } - else{ - return tag; - } -}; - -// find lang by cr_locale -const findLang = (cr_locale: string) => { - const lang = languages.find(l => { return l.cr_locale == cr_locale; }); - return lang ? lang : { cr_locale: 'und', locale: 'un', code: 'und', name: '', language: '' }; -}; - -const fixAndFindCrLC = (cr_locale: string) => { - const str = fixLanguageTag(cr_locale); - return findLang(str || ''); -}; - -// rss subs lang parser -const parseRssSubtitlesString = (subs: string) => { - const splitMap = subs.replace(/\s/g, '').split(',').map((s) => { - return fixAndFindCrLC(s).locale; - }); - const sort = sortTags(splitMap); - return sort.join(', '); -}; - - -// parse subtitles Array -const parseSubtitlesArray = (tags: string[]) => { - const sort = sortSubtitles(tags.map((t) => { - return { locale: fixAndFindCrLC(t).locale }; - })); - return sort.map((t) => { return t.locale; }).join(', '); -}; - -// sort subtitles -const sortSubtitles = <T extends { - [key: string]: unknown -} = Record<string, string>> (data: T[], sortkey?: keyof T) : T[] => { - const idx: Record<string, number> = {}; - const key = sortkey || 'locale' as keyof T; - const tags = [...new Set(Object.values(languages).map(e => e.locale))]; - for(const l of tags){ - idx[l] = Object.keys(idx).length + 1; - } - data.sort((a, b) => { - const ia = idx[a[key] as string] ? idx[a[key] as string] : 50; - const ib = idx[b[key] as string] ? idx[b[key] as string] : 50; - return ia - ib; - }); - return data; -}; - -const sortTags = (data: string[]) => { - const retData = data.map(e => { return { locale: e }; }); - const sort = sortSubtitles(retData); - return sort.map(e => e.locale as string); -}; - -const subsFile = (fnOutput:string, subsIndex: string, langItem: LanguageItem, isCC: boolean, ccTag: string, isSigns?: boolean, format?: string) => { - subsIndex = (parseInt(subsIndex) + 1).toString().padStart(2, '0'); - return `${fnOutput}.${subsIndex}.${langItem.code}.${langItem.language}${isCC ? `.${ccTag}` : ''}${isSigns ? '.signs' : ''}.${format ? format : 'ass'}`; -}; - -// construct dub langs const -const dubLanguages = (() => { - const dubDb: Record<string, string> = {}; - for(const lang of languages){ - if(!Object.keys(dubDb).includes(lang.name)){ - dubDb[lang.name] = lang.code; - } - } - return dubDb; -})(); - -// dub regex -const dubRegExpStr = - `\\((${Object.keys(dubLanguages).join('|')})(?: (Dub|VO))?\\)$`; -const dubRegExp = new RegExp(dubRegExpStr); - -// code to lang name -const langCode2name = (code: string) => { - const codeIdx = dubLanguageCodes.indexOf(code); - return Object.keys(dubLanguages)[codeIdx]; -}; - -// locale to lang name -const locale2language = (locale: string) => { - const filteredLocale = languages.filter(l => { - return l.locale == locale; - }); - return filteredLocale[0]; -}; - -// output -export { - languages, - dubLanguageCodes, - dubLanguages, - langCode2name, - locale2language, - dubRegExp, - subtitleLanguagesFilter, - searchLocales, - fixLanguageTag, - findLang, - fixAndFindCrLC, - parseRssSubtitlesString, - parseSubtitlesArray, - sortSubtitles, - sortTags, - subsFile, -}; diff --git a/modules/module.merger.ts b/modules/module.merger.ts deleted file mode 100644 index 4b64346..0000000 --- a/modules/module.merger.ts +++ /dev/null @@ -1,424 +0,0 @@ -import * as iso639 from 'iso-639'; -import * as yamlCfg from './module.cfg-loader'; -import { fontFamilies, fontMime } from './module.fontsData'; -import path from 'path'; -import fs from 'fs'; -import { LanguageItem } from './module.langsData'; -import { AvailableMuxer } from './module.args'; -import { exec } from './sei-helper-fixes'; -import { console } from './log'; -import ffprobe from 'ffprobe'; - -export type MergerInput = { - path: string, - lang: LanguageItem, - duration?: number, - delay?: number, - isPrimary?: boolean, -} - -export type SubtitleInput = { - language: LanguageItem, - file: string, - closedCaption?: boolean, - signs?: boolean, - delay?: number -} - -export type Font = keyof typeof fontFamilies; - -export type ParsedFont = { - name: string, - path: string, - mime: string, -} - -export type MergerOptions = { - videoAndAudio: MergerInput[], - onlyVid: MergerInput[], - onlyAudio: MergerInput[], - subtitles: SubtitleInput[], - chapters?: MergerInput[], - ccTag: string, - output: string, - videoTitle?: string, - simul?: boolean, - inverseTrackOrder?: boolean, - keepAllVideos?: boolean, - fonts?: ParsedFont[], - skipSubMux?: boolean, - options: { - ffmpeg: string[], - mkvmerge: string[] - }, - defaults: { - audio: LanguageItem, - sub: LanguageItem - } -} - -class Merger { - - constructor(private options: MergerOptions) { - if (this.options.skipSubMux) - this.options.subtitles = []; - if (this.options.videoTitle) - this.options.videoTitle = this.options.videoTitle.replace(/"/g, '\''); - } - - public async createDelays() { - //Don't bother scanning it if there is only 1 vna stream - if (this.options.videoAndAudio.length > 1) { - const bin = await yamlCfg.loadBinCfg(); - const vnas = this.options.videoAndAudio; - //get and set durations on each videoAndAudio Stream - for (const [vnaIndex, vna] of vnas.entries()) { - const streamInfo = await ffprobe(vna.path, { path: bin.ffprobe as string }); - const videoInfo = streamInfo.streams.filter(stream => stream.codec_type == 'video'); - vnas[vnaIndex].duration = parseInt(videoInfo[0].duration as string); - } - //Sort videoAndAudio streams by duration (shortest first) - vnas.sort((a,b) => { - if (!a.duration || !b.duration) return -1; - return a.duration - b.duration; - }); - //Set Delays - const shortestDuration = vnas[0].duration; - for (const [vnaIndex, vna] of vnas.entries()) { - //Don't calculate the shortestDuration track - if (vnaIndex == 0) { - if (!vna.isPrimary && vna.isPrimary !== undefined) - console.warn('Shortest video isn\'t primary, this might lead to problems with subtitles. Please report on github or discord if you experience issues.'); - continue; - } - if (vna.duration && shortestDuration) { - //Calculate the tracks delay - vna.delay = Math.ceil((vna.duration-shortestDuration) * 1000) / 1000; - //TODO: set primary language for audio so it can be used to determine which track needs the delay - //The above is a problem in the event that it isn't the dub that needs the delay, but rather the sub. - //Alternatively: Might not work: it could be checked if there are multiple of the same video language, and if there is - //more than 1 of the same video language, then do the subtitle delay on CC, else normal language. - const subtitles = this.options.subtitles.filter(sub => sub.language.code == vna.lang.code); - for (const [subIndex, sub] of subtitles.entries()) { - if (vna.isPrimary) subtitles[subIndex].delay = vna.delay; - else if (sub.closedCaption) subtitles[subIndex].delay = vna.delay; - } - } - } - } - } - - public FFmpeg() : string { - const args: string[] = []; - const metaData: string[] = []; - - let index = 0; - let audioIndex = 0; - let hasVideo = false; - - for (const vid of this.options.videoAndAudio) { - if (vid.delay && hasVideo) { - args.push( - `-itsoffset -${Math.ceil(vid.delay*1000)}ms` - ); - } - args.push(`-i "${vid.path}"`); - if (!hasVideo || this.options.keepAllVideos) { - metaData.push(`-map ${index}:a -map ${index}:v`); - metaData.push(`-metadata:s:a:${audioIndex} language=${vid.lang.code}`); - metaData.push(`-metadata:s:v:${index} title="${this.options.videoTitle}"`); - hasVideo = true; - } else { - metaData.push(`-map ${index}:a`); - metaData.push(`-metadata:s:a:${audioIndex} language=${vid.lang.code}`); - } - audioIndex++; - index++; - } - - for (const vid of this.options.onlyVid) { - if (!hasVideo || this.options.keepAllVideos) { - args.push(`-i "${vid.path}"`); - metaData.push(`-map ${index} -map -${index}:a`); - metaData.push(`-metadata:s:v:${index} title="${this.options.videoTitle}"`); - hasVideo = true; - index++; - } - } - - for (const aud of this.options.onlyAudio) { - args.push(`-i "${aud.path}"`); - metaData.push(`-map ${index}`); - metaData.push(`-metadata:s:a:${audioIndex} language=${aud.lang.code}`); - index++; - audioIndex++; - } - - for (const index in this.options.subtitles) { - const sub = this.options.subtitles[index]; - if (sub.delay) { - args.push( - `-itsoffset -${Math.ceil(sub.delay*1000)}ms` - ); - } - args.push(`-i "${sub.file}"`); - } - - if (this.options.output.split('.').pop() === 'mkv') { - if (this.options.fonts) { - let fontIndex = 0; - for (const font of this.options.fonts) { - args.push(`-attach ${font.path} -metadata:s:t:${fontIndex} mimetype=${font.mime}`); - fontIndex++; - } - } - } - - //TODO: Make it possible for chapters to work with ffmpeg merging - - args.push(...metaData); - args.push(...this.options.subtitles.map((_, subIndex) => `-map ${subIndex + index}`)); - args.push( - '-c:v copy', - '-c:a copy', - this.options.output.split('.').pop()?.toLowerCase() === 'mp4' ? '-c:s mov_text' : '-c:s ass', - ...this.options.subtitles.map((sub, subindex) => `-metadata:s:s:${subindex} title="${ - (sub.language.language || sub.language.name) + `${sub.closedCaption === true ? ` ${this.options.ccTag}` : ''}` + `${sub.signs === true ? ' Signs' : ''}` - }" -metadata:s:s:${subindex} language=${sub.language.code}`) - ); - args.push(...this.options.options.ffmpeg); - args.push(`"${this.options.output}"`); - return args.join(' '); - } - - public static getLanguageCode = (from: string, _default = 'eng'): string => { - if (from === 'cmn') return 'chi'; - for (const lang in iso639.iso_639_2) { - const langObj = iso639.iso_639_2[lang]; - if (Object.prototype.hasOwnProperty.call(langObj, '639-1') && langObj['639-1'] === from) { - return langObj['639-2'] as string; - } - } - return _default; - }; - - public MkvMerge = () => { - const args: string[] = []; - - let hasVideo = false; - - args.push(`-o "${this.options.output}"`); - args.push(...this.options.options.mkvmerge); - - for (const vid of this.options.onlyVid) { - if (!hasVideo || this.options.keepAllVideos) { - args.push( - '--video-tracks 0', - '--no-audio' - ); - const trackName = ((this.options.videoTitle ?? vid.lang.name) + (this.options.simul ? ' [Simulcast]' : ' [Uncut]')); - args.push('--track-name', `0:"${trackName}"`); - args.push(`--language 0:${vid.lang.code}`); - hasVideo = true; - args.push(`"${vid.path}"`); - } - } - - for (const vid of this.options.videoAndAudio) { - const audioTrackNum = this.options.inverseTrackOrder ? '0' : '1'; - const videoTrackNum = this.options.inverseTrackOrder ? '1' : '0'; - if (vid.delay) { - args.push( - `--sync ${audioTrackNum}:-${Math.ceil(vid.delay*1000)}` - ); - } - if (!hasVideo || this.options.keepAllVideos) { - args.push( - `--video-tracks ${videoTrackNum}`, - `--audio-tracks ${audioTrackNum}` - ); - const trackName = ((this.options.videoTitle ?? vid.lang.name) + (this.options.simul ? ' [Simulcast]' : ' [Uncut]')); - args.push('--track-name', `0:"${trackName}"`); - //args.push('--track-name', `1:"${trackName}"`); - args.push(`--language ${audioTrackNum}:${vid.lang.code}`); - if (this.options.defaults.audio.code === vid.lang.code) { - args.push(`--default-track ${audioTrackNum}`); - } else { - args.push(`--default-track ${audioTrackNum}:0`); - } - hasVideo = true; - } else { - args.push( - '--no-video', - `--audio-tracks ${audioTrackNum}` - ); - if (this.options.defaults.audio.code === vid.lang.code) { - args.push(`--default-track ${audioTrackNum}`); - } else { - args.push(`--default-track ${audioTrackNum}:0`); - } - args.push('--track-name', `${audioTrackNum}:"${vid.lang.name}"`); - args.push(`--language ${audioTrackNum}:${vid.lang.code}`); - } - args.push(`"${vid.path}"`); - } - - for (const aud of this.options.onlyAudio) { - const trackName = aud.lang.name; - args.push('--track-name', `0:"${trackName}"`); - args.push(`--language 0:${aud.lang.code}`); - args.push( - '--no-video', - '--audio-tracks 0' - ); - if (this.options.defaults.audio.code === aud.lang.code) { - args.push('--default-track 0'); - } else { - args.push('--default-track 0:0'); - } - args.push(`"${aud.path}"`); - } - - if (this.options.subtitles.length > 0) { - for (const subObj of this.options.subtitles) { - if (subObj.delay) { - args.push( - `--sync 0:-${Math.ceil(subObj.delay*1000)}` - ); - } - args.push('--track-name', `0:"${(subObj.language.language || subObj.language.name) + `${subObj.closedCaption === true ? ` ${this.options.ccTag}` : ''}` + `${subObj.signs === true ? ' Signs' : ''}`}"`); - args.push('--language', `0:"${subObj.language.code}"`); - //TODO: look into making Closed Caption default if it's the only sub of the default language downloaded - if (this.options.defaults.sub.code === subObj.language.code && !subObj.closedCaption) { - args.push('--default-track 0'); - } else { - args.push('--default-track 0:0'); - } - args.push(`"${subObj.file}"`); - } - } else { - args.push( - '--no-subtitles', - ); - } - - if (this.options.fonts && this.options.fonts.length > 0) { - for (const f of this.options.fonts) { - args.push('--attachment-name', f.name); - args.push('--attachment-mime-type', f.mime); - args.push('--attach-file', `"${f.path}"`); - } - } else { - args.push( - '--no-attachments' - ); - } - - if (this.options.chapters && this.options.chapters.length > 0) { - args.push(`--chapters "${this.options.chapters[0].path}"`); - } - - return args.join(' '); - }; - - public static checkMerger(bin: { - mkvmerge?: string, - ffmpeg?: string, - }, useMP4format: boolean, force: AvailableMuxer|undefined) : { - MKVmerge?: string, - FFmpeg?: string - } { - if (force && bin[force]) { - return { - FFmpeg: force === 'ffmpeg' ? bin.ffmpeg : undefined, - MKVmerge: force === 'mkvmerge' ? bin.mkvmerge : undefined - }; - } - if (useMP4format && bin.ffmpeg) { - return { - FFmpeg: bin.ffmpeg - }; - } else if (!useMP4format && (bin.mkvmerge || bin.ffmpeg)) { - return { - MKVmerge: bin.mkvmerge, - FFmpeg: bin.ffmpeg - }; - } else if (useMP4format) { - console.warn('FFmpeg not found, skip muxing...'); - } else if (!bin.mkvmerge) { - console.warn('MKVMerge not found, skip muxing...'); - } - return {}; - } - - public static makeFontsList (fontsDir: string, subs: { - language: LanguageItem, - fonts: Font[] - }[]) : ParsedFont[] { - let fontsNameList: Font[] = []; const fontsList: { name: string, path: string, mime: string }[] = [], subsList: string[] = []; let isNstr = true; - for(const s of subs){ - fontsNameList.push(...s.fonts); - subsList.push(s.language.locale); - } - fontsNameList = [...new Set(fontsNameList)]; - if(subsList.length > 0){ - console.info('\nSubtitles: %s (Total: %s)', subsList.join(', '), subsList.length); - isNstr = false; - } - if(fontsNameList.length > 0){ - console.info((isNstr ? '\n' : '') + 'Required fonts: %s (Total: %s)', fontsNameList.join(', '), fontsNameList.length); - } - for(const f of fontsNameList){ - const fontFiles = fontFamilies[f]; - if(fontFiles){ - for (const fontFile of fontFiles) { - const fontPath = path.join(fontsDir, fontFile); - const mime = fontMime(fontFile); - if(fs.existsSync(fontPath) && fs.statSync(fontPath).size != 0){ - fontsList.push({ - name: fontFile, - path: fontPath, - mime: mime, - }); - } - } - } - } - return fontsList; - } - - public async merge(type: 'ffmpeg'|'mkvmerge', bin: string) { - let command: string|undefined = undefined; - switch (type) { - case 'ffmpeg': - command = this.FFmpeg(); - break; - case 'mkvmerge': - command = this.MkvMerge(); - break; - } - if (command === undefined) { - console.warn('Unable to merge files.'); - return; - } - console.info(`[${type}] Started merging`); - const res = exec(type, `"${bin}"`, command); - if (!res.isOk && type === 'mkvmerge' && res.err.code === 1) { - console.info(`[${type}] Mkvmerge finished with at least one warning`); - } else if (!res.isOk) { - console.error(res.err); - console.error(`[${type}] Merging failed with exit code ${res.err.code}`); - } else { - console.info(`[${type} Done]`); - } - } - - public cleanUp() { - this.options.onlyAudio.concat(this.options.onlyVid).concat(this.options.videoAndAudio).forEach(a => fs.unlinkSync(a.path)); - this.options.chapters?.forEach(a => fs.unlinkSync(a.path)); - this.options.subtitles.forEach(a => fs.unlinkSync(a.file)); - } - -} - -export default Merger; \ No newline at end of file diff --git a/modules/module.parseSelect.ts b/modules/module.parseSelect.ts deleted file mode 100644 index 6376097..0000000 --- a/modules/module.parseSelect.ts +++ /dev/null @@ -1,110 +0,0 @@ -import { console } from './log'; - -const parseSelect = (selectString: string, but = false) : { - isSelected: (val: string|string[]) => boolean, - values: string[] -} => { - if (!selectString) - return { - values: [], - isSelected: () => but - }; - const parts = selectString.split(','); - const select: string[] = []; - - parts.forEach(part => { - if (part.includes('-')) { - const splits = part.split('-'); - if (splits.length !== 2) { - console.warn(`[WARN] Unable to parse input "${part}"`); - return; - } - - const firstPart = splits[0]; - const match = firstPart.match(/[A-Za-z]+/); - if (match && match.length > 0) { - if (match.index && match.index !== 0) { - console.warn(`[WARN] Unable to parse input "${part}"`); - return; - } - const letters = firstPart.substring(0, match[0].length); - const number = parseFloat(firstPart.substring(match[0].length)); - const b = parseFloat(splits[1]); - if (isNaN(number) || isNaN(b)) { - console.warn(`[WARN] Unable to parse input "${part}"`); - return; - } - for (let i = number; i <= b; i++) { - select.push(`${letters}${i}`); - } - - } else { - const a = parseFloat(firstPart); - const b = parseFloat(splits[1]); - if (isNaN(a) || isNaN(b)) { - console.warn(`[WARN] Unable to parse input "${part}"`); - return; - } - for (let i = a; i <= b; i++) { - select.push(`${i}`); - } - } - - } else { - if (part.match(/[0-9A-Z]{9}/)) { - select.push(part); - return; - } else if (part.match(/[A-Z]{3}\.[0-9]*/)) { - select.push(part); - return; - } - const match = part.match(/[A-Za-z]+/); - if (match && match.length > 0) { - if (match.index && match.index !== 0) { - console.warn(`[WARN] Unable to parse input "${part}"`); - return; - } - const letters = part.substring(0, match[0].length); - const number = parseFloat(part.substring(match[0].length)); - if (isNaN(number)) { - console.warn(`[WARN] Unable to parse input "${part}"`); - return; - } - select.push(`${letters}${number}`); - } else { - select.push(`${parseFloat(part)}`); - } - } - }); - - return { - values: select, - isSelected: (st) => { - if (typeof st === 'string') - st = [st]; - return st.some(st => { - const match = st.match(/[A-Za-z]+/); - if (st.match(/[0-9A-Z]{9}/)) { - const included = select.includes(st); - return but ? !included : included; - } else if (match && match.length > 0) { - if (match.index && match.index !== 0) { - return false; - } - const letter = st.substring(0, match[0].length); - const number = parseFloat(st.substring(match[0].length)); - if (isNaN(number)) { - return false; - } - const included = select.includes(`${letter}${number}`); - return but ? !included : included; - } else { - const included = select.includes(`${parseFloat(st)}`); - return but ? !included : included; - } - }); - } - }; -}; - -export default parseSelect; \ No newline at end of file diff --git a/modules/module.req.ts b/modules/module.req.ts deleted file mode 100644 index cdc66ee..0000000 --- a/modules/module.req.ts +++ /dev/null @@ -1,245 +0,0 @@ -import shlp from 'sei-helper'; -import got, { Headers, Method, Options, ReadError, Response } from 'got'; -import cookieFile from './module.cookieFile'; -import * as yamlCfg from './module.cfg-loader'; -import { console } from './log'; -//import curlReq from './module.curl-req'; - -export type Params = { - method?: Method, - headers?: Headers, - body?: string | Buffer, - binary?: boolean, - followRedirect?: boolean -} - -// set usable cookies -const usefulCookies = { - auth: [ - 'etp_rt', - 'c_visitor', - ], - sess: [ - 'session_id', - ], -}; - -// req -class Req { - private sessCfg: string; - private service: 'cr'|'hd'|'ao'; - private session: Record<string, { - value: string; - expires: Date; - path: string; - domain: string; - secure: boolean; - 'Max-Age'?: string - }> = {}; - private cfgDir = yamlCfg.cfgDir; - private curl: boolean|string = false; - - constructor(private domain: Record<string, unknown>, private debug: boolean, private nosess = false, private type: 'cr'|'hd'|'ao') { - this.sessCfg = yamlCfg.sessCfgFile[type]; - this.service = type; - } - async getData<T = string> (durl: string, params?: Params) { - params = params || {}; - // options - const options: Options & { - minVersion?: string, - maxVersion?: string - curlDebug?: boolean - } = { - method: params.method ? params.method : 'GET', - headers: { - 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:90.0) Gecko/20100101 Firefox/90.0', - }, - }; - // additional params - if(params.headers){ - options.headers = {...options.headers, ...params.headers}; - } - if(options.method == 'POST'){ - if (!(options.headers as Headers)['Content-Type']) { - (options.headers as Headers)['Content-Type'] = 'application/x-www-form-urlencoded'; - } - } - if(params.body){ - options.body = params.body; - } - if(params.binary == true){ - options.responseType = 'buffer'; - } - if(typeof params.followRedirect == 'boolean'){ - options.followRedirect = params.followRedirect; - } - // if auth - //const loc = new URL(durl); - // avoid cloudflare protection - // debug - options.hooks = { - beforeRequest: [ - (options) => { - if(this.debug){ - console.debug('[DEBUG] GOT OPTIONS:'); - console.debug(options); - } - } - ] - }; - if(this.debug){ - options.curlDebug = true; - } - // try do request - try { - const res = await got(durl.toString(), options) as unknown as Response<T>; - return { - ok: true, - res - }; - } - catch(_error){ - const error = _error as { - name: string - } & ReadError & { - res: Response<unknown> - }; - if(error.response && error.response.statusCode && error.response.statusMessage){ - console.error(`${error.name} ${error.response.statusCode}: ${error.response.statusMessage}`); - } - else{ - console.error(`${error.name}: ${error.code || error.message}`); - } - if(error.response && !error.res){ - error.res = error.response; - const docTitle = (error.res.body as string).match(/<title>(.*)<\/title>/); - if(error.res.body && docTitle){ - console.error(docTitle[1]); - } - } - if(error.res && error.res.body && error.response.statusCode - && error.response.statusCode != 404 && error.response.statusCode != 403){ - console.error('Body:', error.res.body); - } - return { - ok: false, - error, - }; - } - } - setNewCookie(setCookie: Record<string, string>, isAuth: boolean, fileData?: string){ - const cookieUpdated: string[] = []; let lastExp = 0; - console.trace('Type of setCookie:', typeof setCookie, setCookie); - const parsedCookie = fileData ? cookieFile(fileData) : shlp.cookie.parse(setCookie); - for(const cookieName of Object.keys(parsedCookie)){ - if(parsedCookie[cookieName] && parsedCookie[cookieName].value && parsedCookie[cookieName].value == 'deleted'){ - delete parsedCookie[cookieName]; - } - } - for(const uCookie of usefulCookies.auth){ - const cookieForceExp = 60*60*24*7; - const cookieExpCur = this.session[uCookie] ? this.session[uCookie] : { expires: 0 }; - const cookieExp = new Date(cookieExpCur.expires).getTime() - cookieForceExp; - if(cookieExp > lastExp){ - lastExp = cookieExp; - } - } - for(const uCookie of usefulCookies.auth){ - if(!parsedCookie[uCookie]){ - continue; - } - if(isAuth || parsedCookie[uCookie] && Date.now() > lastExp){ - this.session[uCookie] = parsedCookie[uCookie]; - cookieUpdated.push(uCookie); - } - } - for(const uCookie of usefulCookies.sess){ - if(!parsedCookie[uCookie]){ - continue; - } - if( - isAuth - || this.nosess && parsedCookie[uCookie] - || parsedCookie[uCookie] && !this.checkSessId(this.session[uCookie]) - ){ - const sessionExp = 60*60; - this.session[uCookie] = parsedCookie[uCookie]; - this.session[uCookie].expires = new Date(Date.now() + sessionExp*1000); - this.session[uCookie]['Max-Age'] = sessionExp.toString(); - cookieUpdated.push(uCookie); - } - } - if(cookieUpdated.length > 0){ - if(this.debug){ - console.info('[SAVING FILE]',`${this.sessCfg}.yml`); - } - if (this.type === 'cr') { - yamlCfg.saveCRSession(this.session); - } else if (this.type === 'hd') { - yamlCfg.saveHDSession(this.session); - } - console.info(`Cookies were updated! (${cookieUpdated.join(', ')})\n`); - } - } - checkCookieVal(chcookie: Record<string, string>){ - return chcookie - && chcookie.toString() == '[object Object]' - && typeof chcookie.value == 'string' - ? true : false; - } - checkSessId(session_id: Record<string, unknown>){ - if(session_id && typeof session_id.expires == 'string'){ - session_id.expires = new Date(session_id.expires); - } - return session_id - && session_id.toString() == '[object Object]' - && typeof session_id.expires == 'object' - && Date.now() < new Date(session_id.expires as any).getTime() - && typeof session_id.value == 'string' - ? true : false; - } - uuidv4(){ - return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { - const r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); - return v.toString(16); - }); - } -} - -function buildProxy(proxyBaseUrl: string, proxyAuth: string){ - if(!proxyBaseUrl.match(/^(https?|socks4|socks5):/)){ - proxyBaseUrl = 'http://' + proxyBaseUrl; - } - - const proxyCfg = new URL(proxyBaseUrl); - let proxyStr = `${proxyCfg.protocol}//`; - - if(typeof proxyCfg.hostname != 'string' || proxyCfg.hostname == ''){ - throw new Error('[ERROR] Hostname and port required for proxy!'); - } - - if(proxyAuth && typeof proxyAuth == 'string' && proxyAuth.match(':')){ - proxyCfg.username = proxyAuth.split(':')[0]; - proxyCfg.password = proxyAuth.split(':')[1]; - proxyStr += `${proxyCfg.username}:${proxyCfg.password}@`; - } - - proxyStr += proxyCfg.hostname; - - if(!proxyCfg.port && proxyCfg.protocol == 'http:'){ - proxyStr += ':80'; - } - else if(!proxyCfg.port && proxyCfg.protocol == 'https:'){ - proxyStr += ':443'; - } - - return proxyStr; -} - -export { - buildProxy, - usefulCookies, - Req, -}; - \ No newline at end of file diff --git a/modules/module.transform-mpd.ts b/modules/module.transform-mpd.ts deleted file mode 100644 index b3727ce..0000000 --- a/modules/module.transform-mpd.ts +++ /dev/null @@ -1,204 +0,0 @@ -import { parse as mpdParse } from 'mpd-parser'; -import { LanguageItem, findLang, languages } from './module.langsData'; -import { console } from './log'; - -type Segment = { - uri: string; - timeline: number; - duration: number; - map: { - uri: string; - byterange?: { - length: number, - offset: number - }; - }; - byterange?: { - length: number, - offset: number - }; - number?: number; - presentationTime?: number; -} - -export type PlaylistItem = { - pssh?: string, - bandwidth: number, - segments: Segment[] -} - - -type AudioPlayList = { - language: LanguageItem, - default: boolean -} & PlaylistItem - -type VideoPlayList = { - quality: { - width: number, - height: number - } -} & PlaylistItem - -export type MPDParsed = { - [server: string]: { - audio: AudioPlayList[], - video: VideoPlayList[] - } -} - -export async function parse(manifest: string, language?: LanguageItem, url?: string) { - if (!manifest.includes('BaseURL') && url) { - manifest = manifest.replace(/(<MPD*\b[^>]*>)/gm, `$1<BaseURL>${url}</BaseURL>`); - } - const parsed = mpdParse(manifest); - const ret: MPDParsed = {}; - - // Audio Loop - for (const item of Object.values(parsed.mediaGroups.AUDIO.audio)){ - for (const playlist of item.playlists) { - const host = new URL(playlist.resolvedUri).hostname; - if (!Object.prototype.hasOwnProperty.call(ret, host)) - ret[host] = { audio: [], video: [] }; - - - if (playlist.sidx && playlist.segments.length == 0) { - const options: RequestInit = { - method: 'head' - }; - if (playlist.sidx.uri.includes('animecdn')) options.headers = { - 'origin': 'https://www.animeonegai.com', - 'referer': 'https://www.animeonegai.com/', - }; - const item = await fetch(playlist.sidx.uri, options); - if (!item.ok) console.warn(`${item.status}: ${item.statusText}, Unable to fetch byteLength for audio stream ${Math.round(playlist.attributes.BANDWIDTH/1024)}KiB/s`); - const byteLength = parseInt(item.headers.get('content-length') as string); - let currentByte = playlist.sidx.map.byterange.length; - while (currentByte <= byteLength) { - playlist.segments.push({ - 'duration': 0, - 'map': { - 'uri': playlist.resolvedUri, - 'resolvedUri': playlist.resolvedUri, - 'byterange': playlist.sidx.map.byterange - }, - 'uri': playlist.resolvedUri, - 'resolvedUri': playlist.resolvedUri, - 'byterange': { - 'length': 500000, - 'offset': currentByte - }, - timeline: 0, - number: 0, - presentationTime: 0 - }); - currentByte = currentByte + 500000; - } - } - - //Find and add audio language if it is found in the MPD - let audiolang: LanguageItem; - const foundlanguage = findLang(languages.find(a => a.code === item.language)?.cr_locale ?? 'unknown'); - if (item.language) { - audiolang = foundlanguage; - } else { - audiolang = language ? language : foundlanguage; - } - const pItem: AudioPlayList = { - bandwidth: playlist.attributes.BANDWIDTH, - language: audiolang, - default: item.default, - segments: playlist.segments.map((segment): Segment => { - const uri = segment.resolvedUri; - const map_uri = segment.map.resolvedUri; - return { - duration: segment.duration, - map: { uri: map_uri, byterange: segment.map.byterange }, - number: segment.number, - presentationTime: segment.presentationTime, - timeline: segment.timeline, - byterange: segment.byterange, - uri - }; - }) - }; - - if (playlist.contentProtection && - playlist.contentProtection?.['com.widevine.alpha'].pssh) - pItem.pssh = arrayBufferToBase64(playlist.contentProtection['com.widevine.alpha'].pssh); - - ret[host].audio.push(pItem); - } - } - - // Video Loop - for (const playlist of parsed.playlists) { - const host = new URL(playlist.resolvedUri).hostname; - if (!Object.prototype.hasOwnProperty.call(ret, host)) - ret[host] = { audio: [], video: [] }; - - if (playlist.sidx && playlist.segments.length == 0) { - const options: RequestInit = { - method: 'head' - }; - if (playlist.sidx.uri.includes('animecdn')) options.headers = { - 'origin': 'https://www.animeonegai.com', - 'referer': 'https://www.animeonegai.com/', - }; - const item = await fetch(playlist.sidx.uri, options); - if (!item.ok) console.warn(`${item.status}: ${item.statusText}, Unable to fetch byteLength for video stream ${playlist.attributes.RESOLUTION?.height}x${playlist.attributes.RESOLUTION?.width}@${Math.round(playlist.attributes.BANDWIDTH/1024)}KiB/s`); - const byteLength = parseInt(item.headers.get('content-length') as string); - let currentByte = playlist.sidx.map.byterange.length; - while (currentByte <= byteLength) { - playlist.segments.push({ - 'duration': 0, - 'map': { - 'uri': playlist.resolvedUri, - 'resolvedUri': playlist.resolvedUri, - 'byterange': playlist.sidx.map.byterange - }, - 'uri': playlist.resolvedUri, - 'resolvedUri': playlist.resolvedUri, - 'byterange': { - 'length': 2000000, - 'offset': currentByte - }, - timeline: 0, - number: 0, - presentationTime: 0 - }); - currentByte = currentByte + 2000000; - } - } - - const pItem: VideoPlayList = { - bandwidth: playlist.attributes.BANDWIDTH, - quality: playlist.attributes.RESOLUTION!, - segments: playlist.segments.map((segment): Segment => { - const uri = segment.resolvedUri; - const map_uri = segment.map.resolvedUri; - return { - duration: segment.duration, - map: { uri: map_uri, byterange: segment.map.byterange }, - number: segment.number, - presentationTime: segment.presentationTime, - timeline: segment.timeline, - byterange: segment.byterange, - uri - }; - }) - }; - - if (playlist.contentProtection && - playlist.contentProtection?.['com.widevine.alpha'].pssh) - pItem.pssh = arrayBufferToBase64(playlist.contentProtection['com.widevine.alpha'].pssh); - - ret[host].video.push(pItem); - } - - return ret; -} - -function arrayBufferToBase64(buffer: Uint8Array): string { - return Buffer.from(buffer).toString('base64'); -} diff --git a/modules/module.updater.ts b/modules/module.updater.ts deleted file mode 100644 index ce80fb7..0000000 --- a/modules/module.updater.ts +++ /dev/null @@ -1,179 +0,0 @@ -import got from 'got'; -import fs from 'fs'; -import { GithubTag, TagCompare } from '../@types/github'; -import path from 'path'; -import { UpdateFile } from '../@types/updateFile'; -import packageJson from '../package.json'; -import { CompilerOptions, transpileModule } from 'typescript'; -import tsConfig from '../tsconfig.json'; -import fsextra from 'fs-extra'; -import seiHelper from 'sei-helper'; -import { workingDir } from './module.cfg-loader'; -import { console } from './log'; -const updateFilePlace = path.join(workingDir, 'config', 'updates.json'); - -const updateIgnore = [ - '*.d.ts', - '.git', - 'lib', - 'node_modules', - '@types', - path.join('bin', 'mkvtoolnix'), - path.join('config', 'token.yml'), - '.eslint', - 'tsconfig.json', - 'updates.json', - 'tsc.ts' -]; - -const askBeforeUpdate = [ - '*.yml' -]; - -enum ApplyType { - DELETE, ADD, UPDATE -} - -export type ApplyItem = { - type: ApplyType, - path: string, - content: string -} - -export default (async (force = false) => { - const isPackaged = (process as NodeJS.Process & { - pkg?: unknown - }).pkg ? true : !!process.env.contentDirectory; - if (isPackaged) { - return; - } - let updateFile: UpdateFile|undefined; - if (fs.existsSync(updateFilePlace)) { - updateFile = JSON.parse(fs.readFileSync(updateFilePlace).toString()) as UpdateFile; - if (new Date() < new Date(updateFile.nextCheck) && !force) { - return; - } - } - console.info('Checking for updates...'); - const tagRequest = await got('https://api.github.com/repos/anidl/multi-downloader-nx/tags'); - const tags = JSON.parse(tagRequest.body) as GithubTag[]; - - if (tags.length > 0) { - const newer = tags.filter(a => { - return isNewer(packageJson.version, a.name); - }); - console.info(`Found ${tags.length} release tags and ${newer.length} that are new.`); - - if (newer.length < 1) { - console.info('No new tags found'); - return done(); - } - const newest = newer.sort((a, b) => a.name < b.name ? 1 : a.name > b.name ? -1 : 0)[0]; - const compareRequest = await got(`https://api.github.com/repos/anidl/multi-downloader-nx/compare/${packageJson.version}...${newest.name}`); - - const compareJSON = JSON.parse(compareRequest.body) as TagCompare; - - console.info(`You are behind by ${compareJSON.ahead_by} releases!`); - const changedFiles = compareJSON.files.map(a => ({ - ...a, - filename: path.join(...a.filename.split('/')) - })).filter(a => { - return !updateIgnore.some(_filter => matchString(_filter, a.filename)); - }); - if (changedFiles.length < 1) { - console.info('No file changes found... updating package.json. If you think this is an error please get the newst version yourself.'); - return done(newest.name); - } - console.info(`Found file changes: \n${changedFiles.map(a => ` [${ - a.status === 'modified' ? '*' : a.status === 'added' ? '+' : '-' - }] ${a.filename}`).join('\n')}`); - - const remove: string[] = []; - - for (const a of changedFiles.filter(a => a.status !== 'added')) { - if (!askBeforeUpdate.some(pattern => matchString(pattern, a.filename))) - continue; - const answer = await seiHelper.question(`The developer decided that the file '${a.filename}' may contain information you changed yourself. Should they be overriden to be updated? [y/N]`); - if (answer.toLowerCase() === 'y') - remove.push(a.sha); - } - - const changesToApply = await Promise.all(changedFiles.filter(a => !remove.includes(a.sha)).map(async (a): Promise<ApplyItem> => { - if (a.filename.endsWith('.ts') || a.filename.endsWith('tsx')) { - const isTSX = a.filename.endsWith('tsx'); - const ret = { - path: a.filename.slice(0, isTSX ? -3 : -2) + `js${isTSX ? 'x' : ''}`, - content: transpileModule((await got(a.raw_url)).body, { - compilerOptions: tsConfig.compilerOptions as unknown as CompilerOptions - }).outputText, - type: a.status === 'modified' ? ApplyType.UPDATE : a.status === 'added' ? ApplyType.ADD : ApplyType.DELETE - }; - console.info('✓ Transpiled %s', ret.path); - return ret; - } else { - const ret = { - path: a.filename, - content: (await got(a.raw_url)).body, - type: a.status === 'modified' ? ApplyType.UPDATE : a.status === 'added' ? ApplyType.ADD : ApplyType.DELETE - }; - console.info('✓ Got %s', ret.path); - return ret; - } - })); - - changesToApply.forEach(a => { - try { - fsextra.ensureDirSync(path.dirname(a.path)); - fs.writeFileSync(path.join(__dirname, '..', a.path), a.content); - console.info('✓ Written %s', a.path); - } catch (er) { - console.info('✗ Error while writing %s', a.path); - } - }); - - console.info('Done'); - return done(); - } -}); - -function done(newVersion?: string) { - const next = new Date(Date.now() + 1000 * 60 * 60 * 24); - fs.writeFileSync(updateFilePlace, JSON.stringify({ - lastCheck: Date.now(), - nextCheck: next.getTime() - } as UpdateFile, null, 2)); - if (newVersion) { - fs.writeFileSync('../package.json', JSON.stringify({ - ...packageJson, - version: newVersion - }, null, 4)); - } - console.info('[INFO] Searching for update finished. Next time running on the ' + next.toLocaleDateString() + ' at ' + next.toLocaleTimeString() + '.'); -} - -function isNewer(curr: string, compare: string) : boolean { - const currParts = curr.split('.').map(a => parseInt(a)); - const compareParts = compare.split('.').map(a => parseInt(a)); - - for (let i = 0; i < Math.max(currParts.length, compareParts.length); i++) { - if (currParts.length <= i) - return true; - if (compareParts.length <= i) - return false; - if (currParts[i] !== compareParts[i]) - return compareParts[i] > currParts[i]; - } - - return false; -} - -function matchString(pattern: string, toMatch: string) : boolean { - const filter = path.join('..', pattern); - if (pattern.startsWith('*')) { - return toMatch.endsWith(pattern.slice(1)); - } else if (filter.split(path.sep).pop()?.indexOf('.') === -1) { - return toMatch.startsWith(filter); - } else { - return toMatch.split(path.sep).pop() === pattern; - } -} \ No newline at end of file diff --git a/modules/module.vtt2ass.ts b/modules/module.vtt2ass.ts deleted file mode 100644 index e716826..0000000 --- a/modules/module.vtt2ass.ts +++ /dev/null @@ -1,528 +0,0 @@ -// const -const cssPrefixRx = /\.rmp-container>\.rmp-content>\.rmp-cc-area>\.rmp-cc-container>\.rmp-cc-display>\.rmp-cc-cue /g; - -import { console } from './log'; - -// colors -import colors from './module.colors.json'; -const defaultStyleName = 'Default'; -const defaultStyleFont = 'Arial'; - -// predefined -let relGroup = ''; -let fontSize = 0; -let tmMrg = 0; -let rFont = ''; -let doCombineLines = false; - -type Css = Record<string, { - params: string; - list: string[]; -}> - -type Vtt = { - caption: string; - time: { - start: string; - end: string; - ext: unknown; - }; - text?: string | undefined; -}; - -function loadCSS(cssStr: string): Css { - const css = cssStr.replace(cssPrefixRx, '').replace(/[\r\n]+/g, '\n').split('\n'); - const defaultSFont = rFont == '' ? defaultStyleFont : rFont; - let defaultStyle = `${defaultSFont},40,&H00FFFFFF,&H00FFFFFF,&H00000000,&H00000000,0,0,0,0,100,100,0,0,1,1,0,2,20,20,20,1`; //base for nonDialog - const styles: Record<string, { - params: string, - list: string[] - }> = { [defaultStyleName]: { params: defaultStyle, list: [] } }; - const classList: Record<string, number> = { [defaultStyleName]: 1 }; - for (const i in css) { - let clx, clz, clzx, rgx; - const l = css[i]; - if (l === '') continue; - const m = l.match(/^(.*)\{(.*)\}$/); - if (!m) { - console.error(`VTT2ASS: Invalid css in line ${i}: ${l}`); - continue; - } - - if (m[1] === '') { - const style = parseStyle(defaultStyleName, m[2], defaultStyle); - styles[defaultStyleName].params = style; - defaultStyle = style; - } else { - clx = m[1].replace(/\./g, '').split(','); - clz = clx[0].replace(/-C(\d+)_(\d+)$/i, '').replace(/-(\d+)$/i, ''); - classList[clz] = (classList[clz] || 0) + 1; - rgx = classList[clz]; - const classSubNum = rgx > 1 ? `-${rgx}` : ''; - clzx = clz + classSubNum; - const style = parseStyle(clzx, m[2], defaultStyle); - styles[clzx] = { params: style, list: clx }; - } - } - return styles; -} - -function parseStyle(stylegroup: string, line: string, style: any) { - const defaultSFont = rFont == '' ? defaultStyleFont : rFont; //redeclare cause of let - - if (stylegroup.startsWith('Subtitle') || stylegroup.startsWith('Song') || stylegroup.startsWith('Q') || stylegroup.startsWith('Default')) { //base for dialog, everything else use defaultStyle - style = `${defaultSFont},${fontSize},&H00FFFFFF,&H000000FF,&H00000000,&H00000000,0,0,0,0,100,100,0,0,1,2.6,0,2,20,20,46,1`; - } - - // Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, - // BackColour, Bold, Italic, Underline, StrikeOut, - // ScaleX, ScaleY, Spacing, Angle, BorderStyle, - // Outline, Shadow, Alignment, MarginL, MarginR, - // MarginV, Encoding - style = style.split(','); - for (const s of line.split(';')) { - if (s == '') continue; - const st = s.trim().split(':'); - if (st[0]) st[0] = st[0].trim(); - if (st[1]) st[1] = st[1].trim(); - let cl, arr, transformed_str; - switch (st[0]) { - case 'font-family': - if (rFont != '') { //do rewrite if rFont is specified - if (stylegroup.startsWith('Subtitle') || stylegroup.startsWith('Song')) { - style[0] = rFont; //dialog to rFont - } else { - style[0] = defaultStyleFont; //non-dialog to Arial - } - } else { //otherwise keep default style - style[0] = st[1].match(/[\s"]*([^",]*)/)![1]; - } - break; - case 'font-size': - style[1] = getPxSize(st[1], style[1]); //scale it based on input style size... so for dialog, this is the dialog font size set in config, for non dialog, it's 40 from default font size - break; - case 'color': - cl = getColor(st[1]); - if (cl !== null) { - if (cl == '&H0000FFFF') { - style[2] = style[3] = '&H00FFFFFF'; - } - else { - style[2] = style[3] = cl; - } - } - break; - case 'font-weight': - if (stylegroup.startsWith('Subtitle') || stylegroup.startsWith('Song')) { //don't touch font-weight if dialog - break; - } - // console.info("Changing bold weight"); - // console.info(stylegroup); - if (st[1] === 'bold') { - style[6] = -1; - break; - } - if (st[1] === 'normal') { - break; - } - break; - case 'text-decoration': - if (st[1] === 'underline') { - style[8] = -1; - } else { - console.warn(`vtt2ass: Unknown text-decoration value: ${st[1]}`); - } - break; - case 'right': - style[17] = 3; - break; - case 'left': - style[17] = 1; - break; - case 'font-style': - if (st[1] === 'italic') { - style[7] = -1; - break; - } - break; - case 'background-color': - case 'background': - if (st[1] === 'none') { - break; - } - break; - case 'text-shadow': - if (stylegroup.startsWith('Subtitle') || stylegroup.startsWith('Song')) { //don't touch shadow if dialog - break; - } - arr = transformed_str = st[1].split(',').map(r => r.trim()); - arr = arr.map(r => { return (r.split(' ').length > 3 ? r.replace(/(\d+)px black$/, '') : r.replace(/black$/, '')).trim(); }); - transformed_str[1] = arr.map(r => r.replace(/-/g, '').replace(/px/g, '').replace(/(^| )0( |$)/g, ' ').trim()).join(' '); - arr = transformed_str[1].split(' '); - if (arr.length != 10) { - console.warn(`VTT2ASS: Can't properly parse text-shadow: ${s.trim()}`); - break; - } - arr = [...new Set(arr)]; - if (arr.length > 1) { - console.warn(`VTT2ASS: Can't properly parse text-shadow: ${s.trim()}`); - break; - } - style[16] = arr[0]; - break; - default: - console.error(`VTT2ASS: Unknown style: ${s.trim()}`); - } - } - return style.join(','); -} - -function getPxSize(size_line: string, font_size: number) { - const m = size_line.trim().match(/([\d.]+)(.*)/); - if (!m) { - console.error(`VTT2ASS: Unknown size: ${size_line}`); - return; - } - let size = parseFloat(m[1]); - if (m[2] === 'em') size *= font_size; - return Math.round(size); -} - -function getColor(c: string) { - if (c[0] !== '#') { - c = colors[c as keyof typeof colors]; - } else if (c.length < 7 || c.length > 7) { - c = `#${c[1]}${c[1]}${c[2]}${c[2]}${c[3]}${c[3]}`; - } - const m = c.match(/#(..)(..)(..)/); - if (!m) return null; - return `&H00${m[3]}${m[2]}${m[1]}`.toUpperCase(); -} - -function loadVTT(vttStr: string): Vtt[] { - const rx = /^([\d:.]*) --> ([\d:.]*)\s?(.*?)\s*$/; - const lines = vttStr.replace(/\r?\n/g, '\n').split('\n'); - const data = []; - let record: null|Vtt = null; - let lineBuf = []; - for (const l of lines) { - const m = l.match(rx); - if (m) { - let caption = ''; - if (lineBuf.length > 0) { - caption = lineBuf.pop()!; - } - if (caption !== '' && lineBuf.length > 0) { - lineBuf.pop(); - } - if (record !== null) { - record.text = lineBuf.join('\n'); - data.push(record); - } - record = { - caption, - time: { - start: m[1], - end: m[2], - ext: m[3].split(' ').map(x => x.split(':')).reduce((p, c) => ((p as any)[c[0]] = c[1] ?? 'invalid-input') && p, {}), - } - }; - lineBuf = []; - continue; - } - lineBuf.push(l); - } - if (record !== null) { - if (lineBuf[lineBuf.length - 1] === '') { - lineBuf.pop(); - } - record.text = lineBuf.join('\n'); - data.push(record); - } - return data; -} - -function timestampToCentiseconds(timestamp: string) { - const timestamp_split = timestamp.split(':'); - const timestamp_sec_split = timestamp_split[2].split('.'); - const hour = parseInt(timestamp_split[0]); - const minute = parseInt(timestamp_split[1]); - const second = parseInt(timestamp_sec_split[0]); - const centisecond = parseInt(timestamp_sec_split[1]); - - return 360000 * hour + 6000 * minute + 100 * second + centisecond; -} - -function combineLines(events: string[]): string[] { - if (!doCombineLines) { - return events; - } - // This function is for combining adjacent lines with same information - const newLines: string[] = []; - for (const currentLine of events) { - let hasCombined: boolean = false; - // Check previous 7 elements, arbritary lookback amount - for (let j = 1; j < 8 && j < newLines.length; j++) { - const checkLine = newLines[newLines.length - j]; - const checkLineSplit = checkLine.split(','); - const currentLineSplit = currentLine.split(','); - // 1 = start, 2 = end, 3 = style, 9+ = text - if (checkLineSplit.slice(9).join(',') == currentLineSplit.slice(9).join(',') && - checkLineSplit[3] == currentLineSplit[3] && - checkLineSplit[2] == currentLineSplit[1] - ) { - checkLineSplit[2] = currentLineSplit[2]; - newLines[newLines.length - j] = checkLineSplit.join(','); - hasCombined = true; - break; - } - } - if (!hasCombined) { - newLines.push(currentLine); - } - } - return newLines; -} - -function pushBuffer(buffer: ReturnType<typeof convertLine>[], events: string[]) { - buffer.reverse(); - const bufferStrings: string[] = buffer.map(line => - `Dialogue: 1,${line.start},${line.end},${line.style},,0,0,0,,${line.text}`); - events.push(...bufferStrings); - buffer.splice(0,buffer.length); -} - -function convert(css: Css, vtt: Vtt[]) { - const stylesMap: Record<string, string> = {}; - let ass = [ - '\ufeff[Script Info]', - 'Title: ' + relGroup, - 'ScriptType: v4.00+', - 'WrapStyle: 0', - 'PlayResX: 1280', - 'PlayResY: 720', - 'ScaledBorderAndShadow: yes', - '', - '[V4+ Styles]', - 'Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding', - ]; - for (const s in css) { - ass.push(`Style: ${s},${css[s].params}`); - css[s].list.forEach(x => stylesMap[x] = s); - } - ass = ass.concat([ - '', - '[Events]', - 'Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text' - ]); - const events: { - subtitle: string[], - caption: string[], - capt_pos: string[], - song_cap: string[], - } = { - subtitle: [], - caption: [], - capt_pos: [], - song_cap: [], - }; - const linesMap: Record<string, number> = {}; - const buffer: ReturnType<typeof convertLine>[] = []; - const captionsBuffer: string[] = []; - for (const l in vtt) { - const x = convertLine(stylesMap, vtt[l]); - if (x.ind !== '' && linesMap[x.ind] !== undefined) { - if (x.subInd > 1) { - const fx = convertLine(stylesMap, vtt[parseInt(l) - x.subInd + 1]); - if (x.style != fx.style) { - x.text = `{\\r${x.style}}${x.text}{\\r}`; - } - } - events[x.type as keyof typeof events][linesMap[x.ind]] += '\\N' + x.text; - } - else { - events[x.type as keyof typeof events].push(x.res); - if (x.ind !== '') { - linesMap[x.ind] = events[x.type as keyof typeof events].length - 1; - } - } - /** - * What cursed code have I brought upon this land? - * This handles making lines multi-line when neccesary and reverses - * order of subtitles so that they display correctly - */ - if (x.type != 'subtitle') { - // Do nothing - } else if (x.text.includes('\\pos')) { - events['subtitle'].pop(); - captionsBuffer.push(x.res); - } else if (buffer.length > 0) { - const previousBufferLine = buffer[buffer.length - 1]; - const previousStart = timestampToCentiseconds(previousBufferLine.start); - const currentStart = timestampToCentiseconds(x.start); - events['subtitle'].pop(); - if ((currentStart - previousStart) <= 2) { - x.start = previousBufferLine.start; - if (previousBufferLine.style == x.style) { - buffer.pop(); - x.text = previousBufferLine.text + '\\N' + x.text; - } - } else { - pushBuffer(buffer, events['subtitle']); - } - buffer.push(x); - } - else { - events['subtitle'].pop(); - buffer.push(x); - } - } - - pushBuffer(buffer, events['subtitle']); - events['subtitle'].push(...captionsBuffer); - events['subtitle'] = combineLines(events['subtitle']); - - if (events.subtitle.length > 0) { - ass = ass.concat( - //`Comment: 0,0:00:00.00,0:00:00.00,${defaultStyleName},,0,0,0,,** Subtitles **`, - events.subtitle - ); - } - if (events.caption.length > 0) { - ass = ass.concat( - //`Comment: 0,0:00:00.00,0:00:00.00,${defaultStyleName},,0,0,0,,** Captions **`, - events.caption - ); - } - if (events.capt_pos.length > 0) { - ass = ass.concat( - //`Comment: 0,0:00:00.00,0:00:00.00,${defaultStyleName},,0,0,0,,** Captions with position **`, - events.capt_pos - ); - } - if (events.song_cap.length > 0) { - ass = ass.concat( - //`Comment: 0,0:00:00.00,0:00:00.00,${defaultStyleName},,0,0,0,,** Song captions **`, - events.song_cap - ); - } - return ass.join('\r\n') + '\r\n'; -} - -function convertLine(css: Record<string, string>, l: Record<any, any>) { - const start = convertTime(l.time.start); - const end = convertTime(l.time.end); - const txt = convertText(l.text); - let type = txt.style.match(/Caption/i) ? 'caption' : (txt.style.match(/SongCap/i) ? 'song_cap' : 'subtitle'); - type = type == 'caption' && l.time.ext?.position !== undefined ? 'capt_pos' : type; - if (l.time.ext?.align === 'left') { - txt.text = `{\\an7}${txt.text}`; - } - let ind = '', subInd = 1; - const sMinus = 0; // (19.2 * 2); - if (l.time.ext?.position !== undefined) { - const pos = parseInt(l.time.ext.position); - const PosX = pos < 0 ? (1280 / 100 * (100 - pos)) : ((1280 - sMinus) / 100 * pos); - const line = parseInt(l.time.ext.line) || 0; - const PosY = line < 0 ? (720 / 100 * (100 - line)) : ((720 - sMinus) / 100 * line); - txt.text = `{\\pos(${parseFloat(PosX.toFixed(3))},${parseFloat(PosY.toFixed(3))})}${txt.text}`; - } - else if (l.time.ext?.line !== undefined && type == 'caption') { - const line = parseInt(l.time.ext.line); - const PosY = line < 0 ? (720 / 100 * (100 - line)) : ((720 - sMinus) / 100 * line); - txt.text = `{\\pos(640,${parseFloat(PosY.toFixed(3))})}${txt.text}`; - } - else { - const indregx = txt.style.match(/(.*)_(\d+)$/); - if (indregx !== null) { - ind = indregx[1]; - subInd = parseInt(indregx[2]); - } - } - const style = css[txt.style as any] || defaultStyleName; - const res = `Dialogue: 0,${start},${end},${style},,0,0,0,,${txt.text}`; - return { type, ind, subInd, start, end, style, text: txt.text, res }; -} - -function convertText(text: string) { - //const m = text.match(/<c\.([^>]*)>([\S\s]*)<\/c>/); - const m = text.match(/<(?:c\.|)([^>]*)>([\S\s]*)<\/(?:c|Default)>/); - let style = ''; - if (m) { - style = m[1]; - text = m[2]; - } - const xtext = text - // .replace(/<c[^>]*>[^<]*<\/c>/g, '') - // .replace(/<ruby[^>]*>[^<]*<\/ruby>/g, '') - .replace(/ \\N$/g, '\\N') - //.replace(/<[^>]>/g, '') - .replace(/\\N$/, '') - .replace(/\r/g, '') - .replace(/\n/g, '\\N') - .replace(/\\N +/g, '\\N') - .replace(/ +\\N/g, '\\N') - .replace(/(\\N)+/g, '\\N') - .replace(/<b[^>]*>([^<]*)<\/b>/g, '{\\b1}$1{\\b0}') - .replace(/<i[^>]*>([^<]*)<\/i>/g, '{\\i1}$1{\\i0}') - .replace(/<u[^>]*>([^<]*)<\/u>/g, '{\\u1}$1{\\u0}') - .replace(/</g, '<') - .replace(/>/g, '>') - .replace(/&/g, '&') - .replace(/<[^>]>/g, '') - .replace(/\\N$/, '') - .replace(/ +$/, ''); - text = xtext; - return { style, text }; -} - -function convertTime(tm: string) { - const m = tm.match(/([\d:]*)\.?(\d*)/); - if (!m) return '0:00:00.00'; - return toSubTime(m[0]); -} - -function toSubTime(str: string) { - const n = []; - let sx; - const x: any[] = str.split(/[:.]/).map(x => Number(x)); - x[3] = '0.' + ('00' + x[3]).slice(-3); - sx = (x[0] * 60 * 60 + x[1] * 60 + x[2] + Number(x[3]) - tmMrg).toFixed(2); - sx = sx.toString().split('.'); - n.unshift(sx[1]); - sx = Number(sx[0]); - n.unshift(('0' + ((sx % 60).toString())).slice(-2)); - n.unshift(('0' + ((Math.floor(sx / 60) % 60).toString())).slice(-2)); - n.unshift((Math.floor(sx / 3600) % 60).toString()); - return n.slice(0, 3).join(':') + '.' + n[3]; -} - -export default function vtt2ass(group: string | undefined, xFontSize: number | undefined, vttStr: string, cssStr: string, timeMargin?: number, replaceFont?: string, combineLines?: boolean) { - relGroup = group ?? ''; - fontSize = xFontSize && xFontSize > 0 ? xFontSize : 34; // 1em to pix - tmMrg = timeMargin ? timeMargin : 0; // - rFont = replaceFont ? replaceFont : rFont; - doCombineLines = combineLines ? combineLines : doCombineLines; - if (vttStr.match(/::cue(?:.(.+)\) *)?{([^}]+)}/g)) { - const cssLines = []; - let defaultCss = ''; - const cssGroups = vttStr.matchAll(/::cue(?:.(.+)\) *)?{([^}]+)}/g); - for (const cssGroup of cssGroups) { - //Below code will bulldoze defined sizes for custom ones - /*if (!options.originalFontSize) { - cssGroup[2] = cssGroup[2].replace(/( font-size:.+?;)/g, '').replace(/(font-size:.+?;)/g, ''); - }*/ - if (cssGroup[1]) { - cssLines.push(`${cssGroup[1]}{${defaultCss}${cssGroup[2].replace(/(\r\n|\n|\r)/gm, '')}}`); - } else { - defaultCss = cssGroup[2].replace(/(\r\n|\n|\r)/gm, ''); - //cssLines.push(`{${defaultCss}}`); - } - } - cssStr += cssLines.join('\r\n'); - } - return convert( - loadCSS(cssStr), - loadVTT(vttStr) - ); -} diff --git a/modules/module.vttconvert.js b/modules/module.vttconvert.js new file mode 100644 index 0000000..9af46f7 --- /dev/null +++ b/modules/module.vttconvert.js @@ -0,0 +1,166 @@ +// vtt loader +function loadVtt(vttStr) { + const rx = /^([\d:.]*) --> ([\d:.]*)\s?(.*?)\s*$/; + const lines = vttStr.replace(/\r?\n/g, '\n').split('\n'); + let data = [], lineBuf = [], record = null; + // check lines + for (let l of lines) { + let m = l.match(rx); + if (m) { + if (lineBuf.length > 0) { + lineBuf.pop(); + } + if (record !== null) { + record.text = lineBuf.join('\n'); + data.push(record); + } + record = { + time_start: m[1], + time_end: m[2], + ext_param: m[3].split(' ').map(x => x.split(':')).reduce((p, c) => (p[c[0]] = c[1]) && p, {}), + }; + lineBuf = []; + continue; + } + lineBuf.push(l); + } + if (record !== null) { + if (lineBuf[lineBuf.length - 1] === '') { + lineBuf.pop(); + } + record.text = lineBuf.join('\n'); + data.push(record); + } + return data; +} + +// ass specific +function convertToAss(vttStr, lang){ + let ass = [ + '\ufeff[Script Info]', + `Title: ${lang}`, + 'ScriptType: v4.00+', + 'PlayResX: 1280', + 'PlayResY: 720', + 'WrapStyle: 0', + 'ScaledBorderAndShadow: yes', + '', + '[V4+ Styles]', + 'Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, ' + + 'Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, ' + + 'BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding', + 'Style: Main,Noto Sans,55,&H00FFFFFF,&H000000FF,&H00020713,&H00000000,0,0,0,0,100,100,0,0,1,3,0,2,10,10,10,1', + 'Style: MainTop,Noto Sans,55,&H00FFFFFF,&H000000FF,&H00020713,&H00000000,0,0,0,0,100,100,0,0,1,3,0,8,10,10,10,1', + '', + '[Events]', + 'Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text', + ]; + + let vttData = loadVtt(vttStr); + for (let l of vttData) { + l = convertToAssLine(l, 'Main'); + ass = ass.concat(l); + } + + return ass.join('\r\n') + '\r\n'; +} + +function convertToAssLine(l, style) { + let start = convertTime(l.time_start); + let end = convertTime(l.time_end); + let text = convertToAssText(l.text); + + // debugger + if (l.ext_param.line === '7%') { + style = 'MainTop'; + } + + if (l.ext_param.line === '10%') { + style = 'MainTop'; + } + + return `Dialogue: 0,${start},${end},${style},,0,0,0,,${text}`; +} + +function convertToAssText(text) { + text = text + .replace(/\r/g, '') + .replace(/\n/g, '\\N') + .replace(/\\N +/g, '\\N') + .replace(/ +\\N/g, '\\N') + .replace(/(\\N)+/g, '\\N') + .replace(/<b[^>]*>([^<]*)<\/b>/g, '{\\b1}$1{\\b0}') + .replace(/<i[^>]*>([^<]*)<\/i>/g, '{\\i1}$1{\\i0}') + .replace(/<u[^>]*>([^<]*)<\/u>/g, '{\\u1}$1{\\u0}') + .replace(/</g, '<') + .replace(/>/g, '>') + .replace(/&/g, '&') + .replace(/<[^>]>/g, '') + .replace(/\\N$/, '') + .replace(/ +$/, ''); + return text; +} + +// srt specific +function convertToSrt(vttStr){ + let srt = [], srtLineIdx = 0; + + let vttData = loadVtt(vttStr); + for (let l of vttData) { + srtLineIdx++; + l = convertToSrtLine(l, srtLineIdx); + srt = srt.concat(l); + } + + return srt.join('\r\n') + '\r\n'; +} + +function convertToSrtLine(l, idx) { + let bom = idx == 1 ? '\ufeff' : ''; + let start = convertTime(l.time_start, true); + let end = convertTime(l.time_end, true); + let text = l.text; + return `${bom}${idx}\r\n${start} --> ${end}\r\n${text}\r\n`; +} + +// time parser +function convertTime(time, srtFormat) { + let mTime = time.match(/([\d:]*)\.?(\d*)/); + if (!mTime){ + return srtFormat ? '00:00:00,000' : '0:00:00.00'; + } + return toSubsTime(mTime[0], srtFormat); +} + +function toSubsTime(str, srtFormat) { + + let n = [], x, sx; + x = str.split(/[:.]/).map(x => Number(x)); + + let msLen = srtFormat ? 3 : 2; + let hLen = srtFormat ? 2 : 1; + + x[3] = '0.' + ('' + x[3]).padStart(3, '0'); + sx = x[0]*60*60 + x[1]*60 + x[2] + Number(x[3]); + sx = sx.toFixed(msLen).split('.'); + + + n.unshift(padTimeNum((srtFormat ? ',' : '.'), sx[1], msLen)); + sx = Number(sx[0]); + + n.unshift(padTimeNum(':', sx%60, 2)); + n.unshift(padTimeNum(':', Math.floor(sx/60)%60, 2)); + n.unshift(padTimeNum('', Math.floor(sx/3600)%60, hLen)); + + return n.join(''); +} + +function padTimeNum(sep, input, pad){ + return sep + ('' + input).padStart(pad, '0'); +} + +// export module +module.exports = (vttStr, toSrt, lang = 'English') => { + const convert = toSrt ? convertToSrt : convertToAss; + return convert(vttStr, lang); +}; diff --git a/modules/module.vttconvert.ts b/modules/module.vttconvert.ts deleted file mode 100644 index 4226049..0000000 --- a/modules/module.vttconvert.ts +++ /dev/null @@ -1,174 +0,0 @@ -// vtt loader -export type Record = { - text?: string, - time_start?: string, - time_end?: string, - ext_param?: unknown -}; -export type NullRecord = Record | null; - -function loadVtt(vttStr: string) { - const rx = /^([\d:.]*) --> ([\d:.]*)\s?(.*?)\s*$/; - const lines = vttStr.replace(/\r?\n/g, '\n').split('\n'); - const data: Record[] = []; let lineBuf: string[] = [], record: NullRecord = null; - // check lines - for (const l of lines) { - const m = l.match(rx); - if (m) { - if (lineBuf.length > 0) { - lineBuf.pop(); - } - if (record !== null) { - record.text = lineBuf.join('\n'); - data.push(record); - } - record = { - time_start: m[1], - time_end: m[2], - ext_param: m[3].split(' ').map(x => x.split(':')).reduce((p: any, c: any) => (p[c[0]] = c[1]) && p, {}), - }; - lineBuf = []; - continue; - } - lineBuf.push(l); - } - if (record !== null) { - if (lineBuf[lineBuf.length - 1] === '') { - lineBuf.pop(); - } - record.text = lineBuf.join('\n'); - data.push(record); - } - return data; -} - -// ass specific -function convertToAss(vttStr: string, lang: string, fontSize: number, fontName?: string){ - let ass = [ - '\ufeff[Script Info]', - `Title: ${lang}`, - 'ScriptType: v4.00+', - 'PlayResX: 1280', - 'PlayResY: 720', - 'WrapStyle: 0', - 'ScaledBorderAndShadow: yes', - '', - '[V4+ Styles]', - 'Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, ' - + 'Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, ' - + 'BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding', - `Style: Main,${fontName || 'Noto Sans'},${fontSize},&H00FFFFFF,&H000000FF,&H00020713,&H00000000,0,0,0,0,100,100,0,0,1,3,0,2,10,10,10,1`, - `Style: MainTop,${fontName || 'Noto Sans'},${fontSize},&H00FFFFFF,&H000000FF,&H00020713,&H00000000,0,0,0,0,100,100,0,0,1,3,0,8,10,10,10,1`, - '', - '[Events]', - 'Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text', - ]; - - const vttData = loadVtt(vttStr); - for (const l of vttData) { - const line = convertToAssLine(l, 'Main'); - ass = ass.concat(line); - } - - return ass.join('\r\n') + '\r\n'; -} - -function convertToAssLine(l: Record, style: string) { - const start = convertTime(l.time_start as string); - const end = convertTime(l.time_end as string); - const text = convertToAssText(l.text as string); - - // debugger - if ((l.ext_param as any).line === '7%') { - style = 'MainTop'; - } - - if ((l.ext_param as any).line === '10%') { - style = 'MainTop'; - } - - return `Dialogue: 0,${start},${end},${style},,0,0,0,,${text}`; -} - -function convertToAssText(text: string) { - text = text - .replace(/\r/g, '') - .replace(/\n/g, '\\N') - .replace(/\\N +/g, '\\N') - .replace(/ +\\N/g, '\\N') - .replace(/(\\N)+/g, '\\N') - .replace(/<b[^>]*>([^<]*)<\/b>/g, '{\\b1}$1{\\b0}') - .replace(/<i[^>]*>([^<]*)<\/i>/g, '{\\i1}$1{\\i0}') - .replace(/<u[^>]*>([^<]*)<\/u>/g, '{\\u1}$1{\\u0}') - .replace(/</g, '<') - .replace(/>/g, '>') - .replace(/&/g, '&') - .replace(/<[^>]>/g, '') - .replace(/\\N$/, '') - .replace(/ +$/, ''); - return text; -} - -// srt specific -function convertToSrt(vttStr: string){ - let srt: string[] = [], srtLineIdx = 0; - - const vttData = loadVtt(vttStr); - for (const l of vttData) { - srtLineIdx++; - const line = convertToSrtLine(l, srtLineIdx); - srt = srt.concat(line); - } - - return srt.join('\r\n') + '\r\n'; -} - -function convertToSrtLine(l: Record, idx: number) : string { - const bom = idx == 1 ? '\ufeff' : ''; - const start = convertTime(l.time_start as string, true); - const end = convertTime(l.time_end as string, true); - const text = l.text; - return `${bom}${idx}\r\n${start} --> ${end}\r\n${text}\r\n`; -} - -// time parser -function convertTime(time: string, srtFormat = false) { - const mTime = time.match(/([\d:]*)\.?(\d*)/); - if (!mTime){ - return srtFormat ? '00:00:00,000' : '0:00:00.00'; - } - return toSubsTime(mTime[0], srtFormat); -} - -function toSubsTime(str: string, srtFormat: boolean) : string { - - const n: string[] = [], x: (string|number)[] = str.split(/[:.]/).map(x => Number(x)); let sx; - - const msLen = srtFormat ? 3 : 2; - const hLen = srtFormat ? 2 : 1; - - x[3] = '0.' + ('' + x[3]).padStart(3, '0'); - sx = (x[0] as number)*60*60 + (x[1] as number)*60 + (x[2] as number) + Number(x[3]); - sx = sx.toFixed(msLen).split('.'); - - - n.unshift(padTimeNum((srtFormat ? ',' : '.'), sx[1], msLen)); - sx = Number(sx[0]); - - n.unshift(padTimeNum(':', sx%60, 2)); - n.unshift(padTimeNum(':', Math.floor(sx/60)%60, 2)); - n.unshift(padTimeNum('', Math.floor(sx/3600)%60, hLen)); - - return n.join(''); -} - -function padTimeNum(sep: string, input: string|number , pad:number){ - return sep + ('' + input).padStart(pad, '0'); -} - -// export module -const _default = (vttStr: string, toSrt: boolean, lang = 'English', fontSize: number, fontName?: string) => { - const convert = toSrt ? convertToSrt : convertToAss; - return convert(vttStr, lang, fontSize, fontName); -}; -export default _default; diff --git a/modules/sei-helper-fixes.ts b/modules/sei-helper-fixes.ts deleted file mode 100644 index 8545b84..0000000 --- a/modules/sei-helper-fixes.ts +++ /dev/null @@ -1,33 +0,0 @@ -import childProcess from 'child_process'; -import { console } from './log'; - -const exec = (pname: string, fpath: string, pargs: string, spc = false): { - isOk: true -} | { - isOk: false, - err: Error & { code: number } -} => { - pargs = pargs ? ' ' + pargs : ''; - console.info(`\n> "${pname}"${pargs}${spc ? '\n' : ''}`); - try { - if (process.platform === 'win32') { - childProcess.execSync(('& ' + fpath + pargs), { stdio: 'inherit', 'shell': 'powershell.exe', 'windowsHide': true }); - } else { - childProcess.execSync((fpath + pargs), { stdio: 'inherit' }); - } - return { - isOk: true - }; - } catch (er) { - const err = er as Error & { status: number }; - return { - isOk: false, - err: { - ...err, - code: err.status - } - }; - } -}; - -export { exec }; \ No newline at end of file diff --git a/modules/widevine.ts b/modules/widevine.ts deleted file mode 100644 index ce4f011..0000000 --- a/modules/widevine.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { KeyContainer, Session } from './license'; -import fs from 'fs'; -import { console } from './log'; -import got from 'got'; -import { workingDir } from './module.cfg-loader'; -import path from 'path'; -import { ReadError, Response } from 'got'; - -//read cdm files located in the same directory -let privateKey: Buffer = Buffer.from([]), identifierBlob: Buffer = Buffer.from([]); -export let canDecrypt: boolean; -try { - const files = fs.readdirSync(path.join(workingDir, 'widevine')); - files.forEach(function(file) { - file = path.join(workingDir, 'widevine', file); - const stats = fs.statSync(file); - if (stats.size < 1024*8 && stats.isFile()) { - const fileContents = fs.readFileSync(file, {'encoding': 'utf8'}); - if (fileContents.includes('-BEGIN PRIVATE KEY-') || fileContents.includes('-BEGIN RSA PRIVATE KEY-')) { - privateKey = fs.readFileSync(file); - } - if (fileContents.includes('widevine_cdm_version')) { - identifierBlob = fs.readFileSync(file); - } - } - }); - - if (privateKey.length !== 0 && identifierBlob.length !== 0) { - canDecrypt = true; - } else if (privateKey.length == 0) { - console.warn('Private key missing'); - canDecrypt = false; - } else if (identifierBlob.length == 0) { - console.warn('Identifier blob missing'); - canDecrypt = false; - } -} catch (e) { - console.error(e); - canDecrypt = false; -} - -export default async function getKeys(pssh: string | undefined, licenseServer: string, authData: Record<string, string>): Promise<KeyContainer[]> { - if (!pssh || !canDecrypt) return []; - //pssh found in the mpd manifest - const psshBuffer = Buffer.from( - pssh, - 'base64' - ); - - //Create a new widevine session - const session = new Session({ privateKey, identifierBlob }, psshBuffer); - - //Generate license - let response; - try { - response = await got(licenseServer, { - method: 'POST', - body: session.createLicenseRequest(), - headers: authData, - responseType: 'text' - }); - } catch(_error){ - const error = _error as { - name: string - } & ReadError & { - res: Response<unknown> - }; - if(error.response && error.response.statusCode && error.response.statusMessage){ - console.error(`${error.name} ${error.response.statusCode}: ${error.response.statusMessage}`); - } else{ - console.error(`${error.name}: ${error.code || error.message}`); - } - if(error.response && !error.res){ - error.res = error.response; - const docTitle = (error.res.body as string).match(/<title>(.*)<\/title>/); - if(error.res.body && docTitle){ - console.error(docTitle[1]); - } - } - if(error.res && error.res.body && error.response.statusCode - && error.response.statusCode != 404 && error.response.statusCode != 403){ - console.error('Body:', error.res.body); - } - return []; - } - - if (response.statusCode === 200) { - //Parse License and return keys - try { - const json = JSON.parse(response.body); - return session.parseLicense(Buffer.from(json['license'], 'base64')); - } catch { - return session.parseLicense(response.rawBody); - } - } else { - console.info('License request failed:', response.statusMessage, response.body); - return []; - } -} diff --git a/package.json b/package.json index be6fa01..08822eb 100644 --- a/package.json +++ b/package.json @@ -1,111 +1,49 @@ { - "name": "multi-downloader-nx", - "short_name": "aniDL", - "version": "5.1.5", - "description": "Downloader for Crunchyroll, Hidive, AnimeOnegai, and AnimationDigitalNetwork with CLI and GUI", - "keywords": [ - "download", - "downloader", - "hidive", - "crunchy", - "crunchyroll", - "util", - "utility", - "cli", - "gui" - ], - "engines": { - "node": ">=14", - "pnpm": ">=7" - }, - "author": "AnimeDL <AnimeDL@users.noreply.github.com>", - "contributors": [ - { - "name": "AnimeDL <AnimeDL@users.noreply.github.com>" + "name": "funimation-downloader-nx", + "short_name": "funi", + "version": "4.8.0", + "description": "Download videos from Funimation via cli.", + "keywords": [ + "download", + "downloader", + "funimation", + "funimationnow", + "util", + "utility", + "cli" + ], + "author": "AniDL", + "homepage": "https://github.com/anidl/funimation-downloader-nx", + "repository": { + "type": "git", + "url": "https://github.com/anidl/funimation-downloader-nx.git" }, - { - "name": "AniDL <AniDL@users.noreply.github.com>" + "bugs": { + "url": "https://github.com/anidl/funimation-downloader-nx/issues" }, - { - "name": "AnidlSupport <AnidlSupport@users.noreply.github.com>" + "license": "MIT", + "main": "funi.js", + "dependencies": { + "form-data": "^3.0.0", + "got": "^11.7.0", + "iso-639": "^0.2.2", + "lookpath": "^1.1.0", + "m3u8-parsed": "^1.3.0", + "sei-helper": "^3.3.0", + "yaml": "^1.10.0", + "yargs": "^16.1.0" + }, + "devDependencies": { + "fs-extra": "^9.0.1", + "pkg": "^4.4.9", + "removeNPMAbsolutePaths": "^2.0.0" + }, + "scripts": { + "build-win64": "node modules/build win64", + "build-linux64": "node modules/build linux64", + "build-macos64": "node modules/build macos64", + "eslint": "eslint *.js modules", + "eslint-fix": "eslint *.js modules --fix", + "test": "echo \"Error: no test specified\" && exit 1" } - ], - "homepage": "https://github.com/anidl/multi-downloader-nx", - "repository": { - "type": "git", - "url": "https://github.com/anidl/multi-downloader-nx.git" - }, - "bugs": { - "url": "https://github.com/anidl/multi-downloader-nx/issues" - }, - "license": "MIT", - "dependencies": { - "@types/xmldom": "^0.1.34", - "@yao-pkg/pkg": "^5.12.0", - "cors": "^2.8.5", - "esbuild": "^0.21.5", - "express": "^4.19.2", - "ffprobe": "^1.1.2", - "fs-extra": "^11.2.0", - "got": "^11.8.6", - "iso-639": "^0.2.2", - "leven": "^3.1.0", - "log4js": "^6.9.1", - "long": "^5.2.3", - "lookpath": "^1.2.2", - "m3u8-parsed": "^1.3.0", - "mpd-parser": "^1.3.0", - "open": "^8.4.2", - "protobufjs": "^7.3.2", - "sei-helper": "^3.3.0", - "ws": "^8.17.1", - "yaml": "^2.4.5", - "yargs": "^17.7.2" - }, - "devDependencies": { - "@types/cors": "^2.8.17", - "@types/express": "^4.17.21", - "@types/ffprobe": "^1.1.8", - "@types/fs-extra": "^11.0.4", - "@types/node": "^20.14.6", - "@types/ws": "^8.5.10", - "@types/yargs": "^17.0.32", - "@typescript-eslint/eslint-plugin": "^7.13.1", - "@typescript-eslint/parser": "^7.13.1", - "eslint": "^8.57.0", - "eslint-config-react-app": "^7.0.1", - "eslint-plugin-react": "7.34.3", - "protoc": "^1.1.3", - "removeNPMAbsolutePaths": "^3.0.1", - "ts-node": "^10.9.2", - "ts-proto": "^1.180.0", - "typescript": "5.5.2", - "typescript-eslint": "7.13.1" - }, - "scripts": { - "prestart": "pnpm run tsc test", - "start": "pnpm prestart && cd lib && node gui.js", - "gui": "cd ./gui/react/ && pnpm start", - "docs": "ts-node modules/build-docs.ts", - "tsc": "ts-node tsc.ts", - "proto:compile": "protoc --plugin=protoc-gen-ts_proto=.\\node_modules\\.bin\\protoc-gen-ts_proto.cmd --ts_proto_opt=\"esModuleInterop=true\" --ts_proto_opt=\"forceLong=long\" --ts_proto_opt=\"env=node\" --ts_proto_out=. modules/*.proto", - "prebuild-cli": "pnpm run tsc false false", - "build-windows-cli": "pnpm run prebuild-cli && cd lib && node modules/build windows-x64", - "build-linux-cli": "pnpm run prebuild-cli && cd lib && node modules/build linuxstatic-x64", - "build-arm-cli": "pnpm run prebuild-cli && cd lib && node modules/build linux-arm64", - "build-macos-cli": "pnpm run prebuild-cli && cd lib && node modules/build macos-x64", - "build-alpine-cli": "pnpm run prebuild-cli && cd lib && node modules/build alpine-x64", - "build-android-cli": "pnpm run prebuild-cli && cd lib && node modules/build linuxstatic-armv7", - "prebuild-gui": "pnpm run tsc", - "build-windows-gui": "pnpm run prebuild-gui && cd lib && node modules/build windows-x64 true", - "build-linux-gui": "pnpm run prebuild-gui && cd lib && node modules/build linuxstatic-x64 true", - "build-arm-gui": "pnpm run prebuild-gui && cd lib && node modules/build linux-arm64 true", - "build-macos-gui": "pnpm run prebuild-gui && cd lib && node modules/build macos-x64 true", - "build-alpine-gui": "pnpm run prebuild-gui && cd lib && node modules/build alpine-x64 true", - "build-android-gui": "pnpm run prebuild-gui && cd lib && node modules/build linuxstatic-armv7 true", - "eslint": "npx eslint .", - "eslint-fix": "npx eslint . --fix", - "pretest": "pnpm run tsc", - "test": "pnpm run pretest && cd lib && node modules/build windows-x64 && node modules/build linuxstatic-x64 && node modules/build macos-x64" - } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml deleted file mode 100644 index 5bbf67c..0000000 --- a/pnpm-lock.yaml +++ /dev/null @@ -1,6321 +0,0 @@ -lockfileVersion: '6.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -dependencies: - '@types/xmldom': - specifier: ^0.1.34 - version: 0.1.34 - '@yao-pkg/pkg': - specifier: ^5.12.0 - version: 5.12.0 - cors: - specifier: ^2.8.5 - version: 2.8.5 - esbuild: - specifier: ^0.21.5 - version: 0.21.5 - express: - specifier: ^4.19.2 - version: 4.19.2 - ffprobe: - specifier: ^1.1.2 - version: 1.1.2 - fs-extra: - specifier: ^11.2.0 - version: 11.2.0 - got: - specifier: ^11.8.6 - version: 11.8.6 - iso-639: - specifier: ^0.2.2 - version: 0.2.2 - leven: - specifier: ^3.1.0 - version: 3.1.0 - log4js: - specifier: ^6.9.1 - version: 6.9.1 - long: - specifier: ^5.2.3 - version: 5.2.3 - lookpath: - specifier: ^1.2.2 - version: 1.2.2 - m3u8-parsed: - specifier: ^1.3.0 - version: 1.3.0 - mpd-parser: - specifier: ^1.3.0 - version: 1.3.0 - open: - specifier: ^8.4.2 - version: 8.4.2 - protobufjs: - specifier: ^7.3.2 - version: 7.3.2 - sei-helper: - specifier: ^3.3.0 - version: 3.3.0 - ws: - specifier: ^8.17.1 - version: 8.17.1 - yaml: - specifier: ^2.4.5 - version: 2.4.5 - yargs: - specifier: ^17.7.2 - version: 17.7.2 - -devDependencies: - '@types/cors': - specifier: ^2.8.17 - version: 2.8.17 - '@types/express': - specifier: ^4.17.21 - version: 4.17.21 - '@types/ffprobe': - specifier: ^1.1.8 - version: 1.1.8 - '@types/fs-extra': - specifier: ^11.0.4 - version: 11.0.4 - '@types/node': - specifier: ^20.14.6 - version: 20.14.6 - '@types/ws': - specifier: ^8.5.10 - version: 8.5.10 - '@types/yargs': - specifier: ^17.0.32 - version: 17.0.32 - '@typescript-eslint/eslint-plugin': - specifier: ^7.13.1 - version: 7.13.1(@typescript-eslint/parser@7.13.1)(eslint@8.57.0)(typescript@5.5.2) - '@typescript-eslint/parser': - specifier: ^7.13.1 - version: 7.13.1(eslint@8.57.0)(typescript@5.5.2) - eslint: - specifier: ^8.57.0 - version: 8.57.0 - eslint-config-react-app: - specifier: ^7.0.1 - version: 7.0.1(@babel/plugin-syntax-flow@7.22.5)(@babel/plugin-transform-react-jsx@7.22.5)(eslint@8.57.0)(typescript@5.5.2) - eslint-plugin-react: - specifier: 7.34.3 - version: 7.34.3(eslint@8.57.0) - protoc: - specifier: ^1.1.3 - version: 1.1.3 - removeNPMAbsolutePaths: - specifier: ^3.0.1 - version: 3.0.1 - ts-node: - specifier: ^10.9.2 - version: 10.9.2(@types/node@20.14.6)(typescript@5.5.2) - ts-proto: - specifier: ^1.180.0 - version: 1.180.0 - typescript: - specifier: 5.5.2 - version: 5.5.2 - typescript-eslint: - specifier: 7.13.1 - version: 7.13.1(eslint@8.57.0)(typescript@5.5.2) - -packages: - - /@aashutoshrathi/word-wrap@1.2.6: - resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==} - engines: {node: '>=0.10.0'} - dev: true - - /@ampproject/remapping@2.2.1: - resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==} - engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/gen-mapping': 0.3.3 - '@jridgewell/trace-mapping': 0.3.18 - dev: true - - /@babel/code-frame@7.21.4: - resolution: {integrity: sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/highlight': 7.18.6 - dev: true - - /@babel/code-frame@7.22.5: - resolution: {integrity: sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/highlight': 7.22.5 - dev: true - - /@babel/compat-data@7.21.4: - resolution: {integrity: sha512-/DYyDpeCfaVinT40FPGdkkb+lYSKvsVuMjDAG7jPOWWiM1ibOaB9CXJAlc4d1QpP/U2q2P9jbrSlClKSErd55g==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/compat-data@7.22.9: - resolution: {integrity: sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/core@7.22.9: - resolution: {integrity: sha512-G2EgeufBcYw27U4hhoIwFcgc1XU7TlXJ3mv04oOv1WCuo900U/anZSPzEqNjwdjgffkk2Gs0AN0dW1CKVLcG7w==} - engines: {node: '>=6.9.0'} - dependencies: - '@ampproject/remapping': 2.2.1 - '@babel/code-frame': 7.22.5 - '@babel/generator': 7.23.0 - '@babel/helper-compilation-targets': 7.22.9(@babel/core@7.22.9) - '@babel/helper-module-transforms': 7.22.9(@babel/core@7.22.9) - '@babel/helpers': 7.22.6 - '@babel/parser': 7.23.0 - '@babel/template': 7.22.5 - '@babel/traverse': 7.22.8 - '@babel/types': 7.23.0 - convert-source-map: 1.9.0 - debug: 4.3.4 - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/eslint-parser@7.21.3(@babel/core@7.22.9)(eslint@8.57.0): - resolution: {integrity: sha512-kfhmPimwo6k4P8zxNs8+T7yR44q1LdpsZdE1NkCsVlfiuTPRfnGgjaF8Qgug9q9Pou17u6wneYF0lDCZJATMFg==} - engines: {node: ^10.13.0 || ^12.13.0 || >=14.0.0} - peerDependencies: - '@babel/core': '>=7.11.0' - eslint: ^7.5.0 || ^8.0.0 - dependencies: - '@babel/core': 7.22.9 - '@nicolo-ribaudo/eslint-scope-5-internals': 5.1.1-v1 - eslint: 8.57.0 - eslint-visitor-keys: 2.1.0 - semver: 6.3.1 - dev: true - - /@babel/generator@7.23.0: - resolution: {integrity: sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.23.0 - '@jridgewell/gen-mapping': 0.3.3 - '@jridgewell/trace-mapping': 0.3.18 - jsesc: 2.5.2 - - /@babel/helper-annotate-as-pure@7.18.6: - resolution: {integrity: sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.23.0 - dev: true - - /@babel/helper-annotate-as-pure@7.22.5: - resolution: {integrity: sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.23.0 - dev: true - - /@babel/helper-builder-binary-assignment-operator-visitor@7.18.9: - resolution: {integrity: sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-explode-assignable-expression': 7.18.6 - '@babel/types': 7.23.0 - dev: true - - /@babel/helper-compilation-targets@7.21.4(@babel/core@7.22.9): - resolution: {integrity: sha512-Fa0tTuOXZ1iL8IeDFUWCzjZcn+sJGd9RZdH9esYVjEejGmzf+FFYQpMi/kZUk2kPy/q1H3/GPw7np8qar/stfg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/compat-data': 7.21.4 - '@babel/core': 7.22.9 - '@babel/helper-validator-option': 7.21.0 - browserslist: 4.21.5 - lru-cache: 5.1.1 - semver: 6.3.1 - dev: true - - /@babel/helper-compilation-targets@7.22.9(@babel/core@7.22.9): - resolution: {integrity: sha512-7qYrNM6HjpnPHJbopxmb8hSPoZ0gsX8IvUS32JGVoy+pU9e5N0nLr1VjJoR6kA4d9dmGLxNYOjeB8sUDal2WMw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/compat-data': 7.22.9 - '@babel/core': 7.22.9 - '@babel/helper-validator-option': 7.22.5 - browserslist: 4.21.9 - lru-cache: 5.1.1 - semver: 6.3.1 - dev: true - - /@babel/helper-create-class-features-plugin@7.21.4(@babel/core@7.22.9): - resolution: {integrity: sha512-46QrX2CQlaFRF4TkwfTt6nJD7IHq8539cCL7SDpqWSDeJKY1xylKKY5F/33mJhLZ3mFvKv2gGrVS6NkyF6qs+Q==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-annotate-as-pure': 7.18.6 - '@babel/helper-environment-visitor': 7.18.9 - '@babel/helper-function-name': 7.21.0 - '@babel/helper-member-expression-to-functions': 7.21.0 - '@babel/helper-optimise-call-expression': 7.18.6 - '@babel/helper-replace-supers': 7.20.7 - '@babel/helper-skip-transparent-expression-wrappers': 7.20.0 - '@babel/helper-split-export-declaration': 7.18.6 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/helper-create-regexp-features-plugin@7.21.4(@babel/core@7.22.9): - resolution: {integrity: sha512-M00OuhU+0GyZ5iBBN9czjugzWrEq2vDpf/zCYHxxf93ul/Q5rv+a5h+/+0WnI1AebHNVtl5bFV0qsJoH23DbfA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-annotate-as-pure': 7.18.6 - regexpu-core: 5.3.2 - dev: true - - /@babel/helper-define-polyfill-provider@0.3.3(@babel/core@7.22.9): - resolution: {integrity: sha512-z5aQKU4IzbqCC1XH0nAqfsFLMVSo22SBKUc0BxGrLkolTdPTructy0ToNnlO2zA4j9Q/7pjMZf0DSY+DSTYzww==} - peerDependencies: - '@babel/core': ^7.4.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-compilation-targets': 7.21.4(@babel/core@7.22.9) - '@babel/helper-plugin-utils': 7.20.2 - debug: 4.3.4 - lodash.debounce: 4.0.8 - resolve: 1.22.2 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/helper-environment-visitor@7.18.9: - resolution: {integrity: sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-environment-visitor@7.22.5: - resolution: {integrity: sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-explode-assignable-expression@7.18.6: - resolution: {integrity: sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.23.0 - dev: true - - /@babel/helper-function-name@7.21.0: - resolution: {integrity: sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.20.7 - '@babel/types': 7.23.0 - dev: true - - /@babel/helper-function-name@7.22.5: - resolution: {integrity: sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.22.5 - '@babel/types': 7.23.0 - dev: true - - /@babel/helper-hoist-variables@7.18.6: - resolution: {integrity: sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.23.0 - dev: true - - /@babel/helper-hoist-variables@7.22.5: - resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.23.0 - dev: true - - /@babel/helper-member-expression-to-functions@7.21.0: - resolution: {integrity: sha512-Muu8cdZwNN6mRRNG6lAYErJ5X3bRevgYR2O8wN0yn7jJSnGDu6eG59RfT29JHxGUovyfrh6Pj0XzmR7drNVL3Q==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.23.0 - dev: true - - /@babel/helper-module-imports@7.21.4: - resolution: {integrity: sha512-orajc5T2PsRYUN3ZryCEFeMDYwyw09c/pZeaQEZPH0MpKzSvn3e0uXsDBu3k03VI+9DBiRo+l22BfKTpKwa/Wg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.23.0 - dev: true - - /@babel/helper-module-imports@7.22.5: - resolution: {integrity: sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.23.0 - dev: true - - /@babel/helper-module-transforms@7.21.2: - resolution: {integrity: sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-environment-visitor': 7.18.9 - '@babel/helper-module-imports': 7.21.4 - '@babel/helper-simple-access': 7.20.2 - '@babel/helper-split-export-declaration': 7.18.6 - '@babel/helper-validator-identifier': 7.22.20 - '@babel/template': 7.20.7 - '@babel/traverse': 7.21.4 - '@babel/types': 7.23.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/helper-module-transforms@7.22.9(@babel/core@7.22.9): - resolution: {integrity: sha512-t+WA2Xn5K+rTeGtC8jCsdAH52bjggG5TKRuRrAGNM/mjIbO4GxvlLMFOEz9wXY5I2XQ60PMFsAG2WIcG82dQMQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-environment-visitor': 7.22.5 - '@babel/helper-module-imports': 7.22.5 - '@babel/helper-simple-access': 7.22.5 - '@babel/helper-split-export-declaration': 7.22.6 - '@babel/helper-validator-identifier': 7.22.20 - dev: true - - /@babel/helper-optimise-call-expression@7.18.6: - resolution: {integrity: sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.23.0 - dev: true - - /@babel/helper-plugin-utils@7.20.2: - resolution: {integrity: sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-plugin-utils@7.22.5: - resolution: {integrity: sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-remap-async-to-generator@7.18.9(@babel/core@7.22.9): - resolution: {integrity: sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-annotate-as-pure': 7.18.6 - '@babel/helper-environment-visitor': 7.18.9 - '@babel/helper-wrap-function': 7.20.5 - '@babel/types': 7.23.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/helper-replace-supers@7.20.7: - resolution: {integrity: sha512-vujDMtB6LVfNW13jhlCrp48QNslK6JXi7lQG736HVbHz/mbf4Dc7tIRh1Xf5C0rF7BP8iiSxGMCmY6Ci1ven3A==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-environment-visitor': 7.18.9 - '@babel/helper-member-expression-to-functions': 7.21.0 - '@babel/helper-optimise-call-expression': 7.18.6 - '@babel/template': 7.20.7 - '@babel/traverse': 7.21.4 - '@babel/types': 7.23.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/helper-simple-access@7.20.2: - resolution: {integrity: sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.23.0 - dev: true - - /@babel/helper-simple-access@7.22.5: - resolution: {integrity: sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.23.0 - dev: true - - /@babel/helper-skip-transparent-expression-wrappers@7.20.0: - resolution: {integrity: sha512-5y1JYeNKfvnT8sZcK9DVRtpTbGiomYIHviSP3OQWmDPU3DeH4a1ZlT/N2lyQ5P8egjcRaT/Y9aNqUxK0WsnIIg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.23.0 - dev: true - - /@babel/helper-split-export-declaration@7.18.6: - resolution: {integrity: sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.23.0 - dev: true - - /@babel/helper-split-export-declaration@7.22.6: - resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.23.0 - dev: true - - /@babel/helper-string-parser@7.22.5: - resolution: {integrity: sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==} - engines: {node: '>=6.9.0'} - - /@babel/helper-validator-identifier@7.22.20: - resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} - engines: {node: '>=6.9.0'} - - /@babel/helper-validator-option@7.21.0: - resolution: {integrity: sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-validator-option@7.22.5: - resolution: {integrity: sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-wrap-function@7.20.5: - resolution: {integrity: sha512-bYMxIWK5mh+TgXGVqAtnu5Yn1un+v8DDZtqyzKRLUzrh70Eal2O3aZ7aPYiMADO4uKlkzOiRiZ6GX5q3qxvW9Q==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-function-name': 7.21.0 - '@babel/template': 7.20.7 - '@babel/traverse': 7.21.4 - '@babel/types': 7.23.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/helpers@7.22.6: - resolution: {integrity: sha512-YjDs6y/fVOYFV8hAf1rxd1QvR9wJe1pDBZ2AREKq/SDayfPzgk0PBnVuTCE5X1acEpMMNOVUqoe+OwiZGJ+OaA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.22.5 - '@babel/traverse': 7.22.8 - '@babel/types': 7.23.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/highlight@7.18.6: - resolution: {integrity: sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-validator-identifier': 7.22.20 - chalk: 2.4.2 - js-tokens: 4.0.0 - dev: true - - /@babel/highlight@7.22.5: - resolution: {integrity: sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-validator-identifier': 7.22.20 - chalk: 2.4.2 - js-tokens: 4.0.0 - dev: true - - /@babel/parser@7.23.0: - resolution: {integrity: sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==} - engines: {node: '>=6.0.0'} - hasBin: true - dependencies: - '@babel/types': 7.23.0 - - /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.18.6(@babel/core@7.22.9): - resolution: {integrity: sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.20.7(@babel/core@7.22.9): - resolution: {integrity: sha512-sbr9+wNE5aXMBBFBICk01tt7sBf2Oc9ikRFEcem/ZORup9IMUdNhW7/wVLEbbtlWOsEubJet46mHAL2C8+2jKQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.13.0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - '@babel/helper-skip-transparent-expression-wrappers': 7.20.0 - '@babel/plugin-proposal-optional-chaining': 7.21.0(@babel/core@7.22.9) - dev: true - - /@babel/plugin-proposal-async-generator-functions@7.20.7(@babel/core@7.22.9): - resolution: {integrity: sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-environment-visitor': 7.18.9 - '@babel/helper-plugin-utils': 7.20.2 - '@babel/helper-remap-async-to-generator': 7.18.9(@babel/core@7.22.9) - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.22.9) - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/plugin-proposal-class-properties@7.18.6(@babel/core@7.22.9): - resolution: {integrity: sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-create-class-features-plugin': 7.21.4(@babel/core@7.22.9) - '@babel/helper-plugin-utils': 7.20.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/plugin-proposal-class-static-block@7.21.0(@babel/core@7.22.9): - resolution: {integrity: sha512-XP5G9MWNUskFuP30IfFSEFB0Z6HzLIUcjYM4bYOPHXl7eiJ9HFv8tWj6TXTN5QODiEhDZAeI4hLok2iHFFV4hw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.12.0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-create-class-features-plugin': 7.21.4(@babel/core@7.22.9) - '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.22.9) - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/plugin-proposal-decorators@7.21.0(@babel/core@7.22.9): - resolution: {integrity: sha512-MfgX49uRrFUTL/HvWtmx3zmpyzMMr4MTj3d527MLlr/4RTT9G/ytFFP7qet2uM2Ve03b+BkpWUpK+lRXnQ+v9w==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-create-class-features-plugin': 7.21.4(@babel/core@7.22.9) - '@babel/helper-plugin-utils': 7.20.2 - '@babel/helper-replace-supers': 7.20.7 - '@babel/helper-split-export-declaration': 7.18.6 - '@babel/plugin-syntax-decorators': 7.21.0(@babel/core@7.22.9) - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/plugin-proposal-dynamic-import@7.18.6(@babel/core@7.22.9): - resolution: {integrity: sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.22.9) - dev: true - - /@babel/plugin-proposal-export-namespace-from@7.18.9(@babel/core@7.22.9): - resolution: {integrity: sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.22.9) - dev: true - - /@babel/plugin-proposal-json-strings@7.18.6(@babel/core@7.22.9): - resolution: {integrity: sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.22.9) - dev: true - - /@babel/plugin-proposal-logical-assignment-operators@7.20.7(@babel/core@7.22.9): - resolution: {integrity: sha512-y7C7cZgpMIjWlKE5T7eJwp+tnRYM89HmRvWM5EQuB5BoHEONjmQ8lSNmBUwOyy/GFRsohJED51YBF79hE1djug==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.22.9) - dev: true - - /@babel/plugin-proposal-nullish-coalescing-operator@7.18.6(@babel/core@7.22.9): - resolution: {integrity: sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.22.9) - dev: true - - /@babel/plugin-proposal-numeric-separator@7.18.6(@babel/core@7.22.9): - resolution: {integrity: sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.22.9) - dev: true - - /@babel/plugin-proposal-object-rest-spread@7.20.7(@babel/core@7.22.9): - resolution: {integrity: sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/compat-data': 7.21.4 - '@babel/core': 7.22.9 - '@babel/helper-compilation-targets': 7.21.4(@babel/core@7.22.9) - '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.22.9) - '@babel/plugin-transform-parameters': 7.21.3(@babel/core@7.22.9) - dev: true - - /@babel/plugin-proposal-optional-catch-binding@7.18.6(@babel/core@7.22.9): - resolution: {integrity: sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.22.9) - dev: true - - /@babel/plugin-proposal-optional-chaining@7.21.0(@babel/core@7.22.9): - resolution: {integrity: sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - '@babel/helper-skip-transparent-expression-wrappers': 7.20.0 - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.22.9) - dev: true - - /@babel/plugin-proposal-private-methods@7.18.6(@babel/core@7.22.9): - resolution: {integrity: sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-create-class-features-plugin': 7.21.4(@babel/core@7.22.9) - '@babel/helper-plugin-utils': 7.20.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/plugin-proposal-private-property-in-object@7.21.0(@babel/core@7.22.9): - resolution: {integrity: sha512-ha4zfehbJjc5MmXBlHec1igel5TJXXLDDRbuJ4+XT2TJcyD9/V1919BA8gMvsdHcNMBy4WBUBiRb3nw/EQUtBw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-annotate-as-pure': 7.18.6 - '@babel/helper-create-class-features-plugin': 7.21.4(@babel/core@7.22.9) - '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.22.9) - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/plugin-proposal-unicode-property-regex@7.18.6(@babel/core@7.22.9): - resolution: {integrity: sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==} - engines: {node: '>=4'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-create-regexp-features-plugin': 7.21.4(@babel/core@7.22.9) - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.22.9): - resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.22.9): - resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.22.9): - resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-syntax-decorators@7.21.0(@babel/core@7.22.9): - resolution: {integrity: sha512-tIoPpGBR8UuM4++ccWN3gifhVvQu7ZizuR1fklhRJrd5ewgbkUS+0KVFeWWxELtn18NTLoW32XV7zyOgIAiz+w==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.22.9): - resolution: {integrity: sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-syntax-export-namespace-from@7.8.3(@babel/core@7.22.9): - resolution: {integrity: sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-syntax-flow@7.22.5(@babel/core@7.22.9): - resolution: {integrity: sha512-9RdCl0i+q0QExayk2nOS7853w08yLucnnPML6EN9S8fgMPVtdLDCdx/cOQ/i44Lb9UeQX9A35yaqBBOMMZxPxQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.22.5 - dev: true - - /@babel/plugin-syntax-import-assertions@7.20.0(@babel/core@7.22.9): - resolution: {integrity: sha512-IUh1vakzNoWalR8ch/areW7qFopR2AEw03JlG7BbrDqmQ4X3q9uuipQwSGrUn7oGiemKjtSLDhNtQHzMHr1JdQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.22.9): - resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-syntax-jsx@7.21.4(@babel/core@7.22.9): - resolution: {integrity: sha512-5hewiLct5OKyh6PLKEYaFclcqtIgCb6bmELouxjF6up5q3Sov7rOayW4RwhbaBL0dit8rA80GNfY+UuDp2mBbQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-syntax-jsx@7.22.5(@babel/core@7.22.9): - resolution: {integrity: sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.22.5 - dev: true - - /@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.22.9): - resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.22.9): - resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.22.9): - resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.22.9): - resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.22.9): - resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.22.9): - resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.22.9): - resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.22.9): - resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-syntax-typescript@7.21.4(@babel/core@7.22.9): - resolution: {integrity: sha512-xz0D39NvhQn4t4RNsHmDnnsaQizIlUkdtYvLs8La1BlfjQ6JEwxkJGeqJMW2tAXx+q6H+WFuUTXNdYVpEya0YA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-transform-arrow-functions@7.20.7(@babel/core@7.22.9): - resolution: {integrity: sha512-3poA5E7dzDomxj9WXWwuD6A5F3kc7VXwIJO+E+J8qtDtS+pXPAhrgEyh+9GBwBgPq1Z+bB+/JD60lp5jsN7JPQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-transform-async-to-generator@7.20.7(@babel/core@7.22.9): - resolution: {integrity: sha512-Uo5gwHPT9vgnSXQxqGtpdufUiWp96gk7yiP4Mp5bm1QMkEmLXBO7PAGYbKoJ6DhAwiNkcHFBol/x5zZZkL/t0Q==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-module-imports': 7.21.4 - '@babel/helper-plugin-utils': 7.20.2 - '@babel/helper-remap-async-to-generator': 7.18.9(@babel/core@7.22.9) - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/plugin-transform-block-scoped-functions@7.18.6(@babel/core@7.22.9): - resolution: {integrity: sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-transform-block-scoping@7.21.0(@babel/core@7.22.9): - resolution: {integrity: sha512-Mdrbunoh9SxwFZapeHVrwFmri16+oYotcZysSzhNIVDwIAb1UV+kvnxULSYq9J3/q5MDG+4X6w8QVgD1zhBXNQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-transform-classes@7.21.0(@babel/core@7.22.9): - resolution: {integrity: sha512-RZhbYTCEUAe6ntPehC4hlslPWosNHDox+vAs4On/mCLRLfoDVHf6hVEd7kuxr1RnHwJmxFfUM3cZiZRmPxJPXQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-annotate-as-pure': 7.18.6 - '@babel/helper-compilation-targets': 7.21.4(@babel/core@7.22.9) - '@babel/helper-environment-visitor': 7.18.9 - '@babel/helper-function-name': 7.21.0 - '@babel/helper-optimise-call-expression': 7.18.6 - '@babel/helper-plugin-utils': 7.20.2 - '@babel/helper-replace-supers': 7.20.7 - '@babel/helper-split-export-declaration': 7.18.6 - globals: 11.12.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/plugin-transform-computed-properties@7.20.7(@babel/core@7.22.9): - resolution: {integrity: sha512-Lz7MvBK6DTjElHAmfu6bfANzKcxpyNPeYBGEafyA6E5HtRpjpZwU+u7Qrgz/2OR0z+5TvKYbPdphfSaAcZBrYQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - '@babel/template': 7.20.7 - dev: true - - /@babel/plugin-transform-destructuring@7.21.3(@babel/core@7.22.9): - resolution: {integrity: sha512-bp6hwMFzuiE4HqYEyoGJ/V2LeIWn+hLVKc4pnj++E5XQptwhtcGmSayM029d/j2X1bPKGTlsyPwAubuU22KhMA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-transform-dotall-regex@7.18.6(@babel/core@7.22.9): - resolution: {integrity: sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-create-regexp-features-plugin': 7.21.4(@babel/core@7.22.9) - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-transform-duplicate-keys@7.18.9(@babel/core@7.22.9): - resolution: {integrity: sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-transform-exponentiation-operator@7.18.6(@babel/core@7.22.9): - resolution: {integrity: sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-builder-binary-assignment-operator-visitor': 7.18.9 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-transform-flow-strip-types@7.21.0(@babel/core@7.22.9): - resolution: {integrity: sha512-FlFA2Mj87a6sDkW4gfGrQQqwY/dLlBAyJa2dJEZ+FHXUVHBflO2wyKvg+OOEzXfrKYIa4HWl0mgmbCzt0cMb7w==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-flow': 7.22.5(@babel/core@7.22.9) - dev: true - - /@babel/plugin-transform-for-of@7.21.0(@babel/core@7.22.9): - resolution: {integrity: sha512-LlUYlydgDkKpIY7mcBWvyPPmMcOphEyYA27Ef4xpbh1IiDNLr0kZsos2nf92vz3IccvJI25QUwp86Eo5s6HmBQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-transform-function-name@7.18.9(@babel/core@7.22.9): - resolution: {integrity: sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-compilation-targets': 7.21.4(@babel/core@7.22.9) - '@babel/helper-function-name': 7.21.0 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-transform-literals@7.18.9(@babel/core@7.22.9): - resolution: {integrity: sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-transform-member-expression-literals@7.18.6(@babel/core@7.22.9): - resolution: {integrity: sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-transform-modules-amd@7.20.11(@babel/core@7.22.9): - resolution: {integrity: sha512-NuzCt5IIYOW0O30UvqktzHYR2ud5bOWbY0yaxWZ6G+aFzOMJvrs5YHNikrbdaT15+KNO31nPOy5Fim3ku6Zb5g==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-module-transforms': 7.21.2 - '@babel/helper-plugin-utils': 7.20.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/plugin-transform-modules-commonjs@7.21.2(@babel/core@7.22.9): - resolution: {integrity: sha512-Cln+Yy04Gxua7iPdj6nOV96smLGjpElir5YwzF0LBPKoPlLDNJePNlrGGaybAJkd0zKRnOVXOgizSqPYMNYkzA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-module-transforms': 7.21.2 - '@babel/helper-plugin-utils': 7.20.2 - '@babel/helper-simple-access': 7.20.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/plugin-transform-modules-systemjs@7.20.11(@babel/core@7.22.9): - resolution: {integrity: sha512-vVu5g9BPQKSFEmvt2TA4Da5N+QVS66EX21d8uoOihC+OCpUoGvzVsXeqFdtAEfVa5BILAeFt+U7yVmLbQnAJmw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-hoist-variables': 7.18.6 - '@babel/helper-module-transforms': 7.21.2 - '@babel/helper-plugin-utils': 7.20.2 - '@babel/helper-validator-identifier': 7.22.20 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/plugin-transform-modules-umd@7.18.6(@babel/core@7.22.9): - resolution: {integrity: sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-module-transforms': 7.21.2 - '@babel/helper-plugin-utils': 7.20.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/plugin-transform-named-capturing-groups-regex@7.20.5(@babel/core@7.22.9): - resolution: {integrity: sha512-mOW4tTzi5iTLnw+78iEq3gr8Aoq4WNRGpmSlrogqaiCBoR1HFhpU4JkpQFOHfeYx3ReVIFWOQJS4aZBRvuZ6mA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-create-regexp-features-plugin': 7.21.4(@babel/core@7.22.9) - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-transform-new-target@7.18.6(@babel/core@7.22.9): - resolution: {integrity: sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-transform-object-super@7.18.6(@babel/core@7.22.9): - resolution: {integrity: sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - '@babel/helper-replace-supers': 7.20.7 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/plugin-transform-parameters@7.21.3(@babel/core@7.22.9): - resolution: {integrity: sha512-Wxc+TvppQG9xWFYatvCGPvZ6+SIUxQ2ZdiBP+PHYMIjnPXD+uThCshaz4NZOnODAtBjjcVQQ/3OKs9LW28purQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-transform-property-literals@7.18.6(@babel/core@7.22.9): - resolution: {integrity: sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-transform-react-display-name@7.18.6(@babel/core@7.22.9): - resolution: {integrity: sha512-TV4sQ+T013n61uMoygyMRm+xf04Bd5oqFpv2jAEQwSZ8NwQA7zeRPg1LMVg2PWi3zWBz+CLKD+v5bcpZ/BS0aA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-transform-react-jsx-development@7.18.6(@babel/core@7.22.9): - resolution: {integrity: sha512-SA6HEjwYFKF7WDjWcMcMGUimmw/nhNRDWxr+KaLSCrkD/LMDBvWRmHAYgE1HDeF8KUuI8OAu+RT6EOtKxSW2qA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/plugin-transform-react-jsx': 7.22.5(@babel/core@7.22.9) - dev: true - - /@babel/plugin-transform-react-jsx@7.22.5(@babel/core@7.22.9): - resolution: {integrity: sha512-rog5gZaVbUip5iWDMTYbVM15XQq+RkUKhET/IHR6oizR+JEoN6CAfTTuHcK4vwUyzca30qqHqEpzBOnaRMWYMA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-module-imports': 7.22.5 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-jsx': 7.22.5(@babel/core@7.22.9) - '@babel/types': 7.23.0 - dev: true - - /@babel/plugin-transform-react-pure-annotations@7.18.6(@babel/core@7.22.9): - resolution: {integrity: sha512-I8VfEPg9r2TRDdvnHgPepTKvuRomzA8+u+nhY7qSI1fR2hRNebasZEETLyM5mAUr0Ku56OkXJ0I7NHJnO6cJiQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-annotate-as-pure': 7.18.6 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-transform-regenerator@7.20.5(@babel/core@7.22.9): - resolution: {integrity: sha512-kW/oO7HPBtntbsahzQ0qSE3tFvkFwnbozz3NWFhLGqH75vLEg+sCGngLlhVkePlCs3Jv0dBBHDzCHxNiFAQKCQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - regenerator-transform: 0.15.1 - dev: true - - /@babel/plugin-transform-reserved-words@7.18.6(@babel/core@7.22.9): - resolution: {integrity: sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-transform-runtime@7.21.4(@babel/core@7.22.9): - resolution: {integrity: sha512-1J4dhrw1h1PqnNNpzwxQ2UBymJUF8KuPjAAnlLwZcGhHAIqUigFW7cdK6GHoB64ubY4qXQNYknoUeks4Wz7CUA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-module-imports': 7.21.4 - '@babel/helper-plugin-utils': 7.20.2 - babel-plugin-polyfill-corejs2: 0.3.3(@babel/core@7.22.9) - babel-plugin-polyfill-corejs3: 0.6.0(@babel/core@7.22.9) - babel-plugin-polyfill-regenerator: 0.4.1(@babel/core@7.22.9) - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/plugin-transform-shorthand-properties@7.18.6(@babel/core@7.22.9): - resolution: {integrity: sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-transform-spread@7.20.7(@babel/core@7.22.9): - resolution: {integrity: sha512-ewBbHQ+1U/VnH1fxltbJqDeWBU1oNLG8Dj11uIv3xVf7nrQu0bPGe5Rf716r7K5Qz+SqtAOVswoVunoiBtGhxw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - '@babel/helper-skip-transparent-expression-wrappers': 7.20.0 - dev: true - - /@babel/plugin-transform-sticky-regex@7.18.6(@babel/core@7.22.9): - resolution: {integrity: sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-transform-template-literals@7.18.9(@babel/core@7.22.9): - resolution: {integrity: sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-transform-typeof-symbol@7.18.9(@babel/core@7.22.9): - resolution: {integrity: sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-transform-typescript@7.21.3(@babel/core@7.22.9): - resolution: {integrity: sha512-RQxPz6Iqt8T0uw/WsJNReuBpWpBqs/n7mNo18sKLoTbMp+UrEekhH+pKSVC7gWz+DNjo9gryfV8YzCiT45RgMw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-annotate-as-pure': 7.18.6 - '@babel/helper-create-class-features-plugin': 7.21.4(@babel/core@7.22.9) - '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-syntax-typescript': 7.21.4(@babel/core@7.22.9) - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/plugin-transform-unicode-escapes@7.18.10(@babel/core@7.22.9): - resolution: {integrity: sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/plugin-transform-unicode-regex@7.18.6(@babel/core@7.22.9): - resolution: {integrity: sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-create-regexp-features-plugin': 7.21.4(@babel/core@7.22.9) - '@babel/helper-plugin-utils': 7.20.2 - dev: true - - /@babel/preset-env@7.21.4(@babel/core@7.22.9): - resolution: {integrity: sha512-2W57zHs2yDLm6GD5ZpvNn71lZ0B/iypSdIeq25OurDKji6AdzV07qp4s3n1/x5BqtiGaTrPN3nerlSCaC5qNTw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/compat-data': 7.21.4 - '@babel/core': 7.22.9 - '@babel/helper-compilation-targets': 7.21.4(@babel/core@7.22.9) - '@babel/helper-plugin-utils': 7.20.2 - '@babel/helper-validator-option': 7.21.0 - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.18.6(@babel/core@7.22.9) - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.20.7(@babel/core@7.22.9) - '@babel/plugin-proposal-async-generator-functions': 7.20.7(@babel/core@7.22.9) - '@babel/plugin-proposal-class-properties': 7.18.6(@babel/core@7.22.9) - '@babel/plugin-proposal-class-static-block': 7.21.0(@babel/core@7.22.9) - '@babel/plugin-proposal-dynamic-import': 7.18.6(@babel/core@7.22.9) - '@babel/plugin-proposal-export-namespace-from': 7.18.9(@babel/core@7.22.9) - '@babel/plugin-proposal-json-strings': 7.18.6(@babel/core@7.22.9) - '@babel/plugin-proposal-logical-assignment-operators': 7.20.7(@babel/core@7.22.9) - '@babel/plugin-proposal-nullish-coalescing-operator': 7.18.6(@babel/core@7.22.9) - '@babel/plugin-proposal-numeric-separator': 7.18.6(@babel/core@7.22.9) - '@babel/plugin-proposal-object-rest-spread': 7.20.7(@babel/core@7.22.9) - '@babel/plugin-proposal-optional-catch-binding': 7.18.6(@babel/core@7.22.9) - '@babel/plugin-proposal-optional-chaining': 7.21.0(@babel/core@7.22.9) - '@babel/plugin-proposal-private-methods': 7.18.6(@babel/core@7.22.9) - '@babel/plugin-proposal-private-property-in-object': 7.21.0(@babel/core@7.22.9) - '@babel/plugin-proposal-unicode-property-regex': 7.18.6(@babel/core@7.22.9) - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.22.9) - '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.22.9) - '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.22.9) - '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.22.9) - '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.22.9) - '@babel/plugin-syntax-import-assertions': 7.20.0(@babel/core@7.22.9) - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.22.9) - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.22.9) - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.22.9) - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.22.9) - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.22.9) - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.22.9) - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.22.9) - '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.22.9) - '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.22.9) - '@babel/plugin-transform-arrow-functions': 7.20.7(@babel/core@7.22.9) - '@babel/plugin-transform-async-to-generator': 7.20.7(@babel/core@7.22.9) - '@babel/plugin-transform-block-scoped-functions': 7.18.6(@babel/core@7.22.9) - '@babel/plugin-transform-block-scoping': 7.21.0(@babel/core@7.22.9) - '@babel/plugin-transform-classes': 7.21.0(@babel/core@7.22.9) - '@babel/plugin-transform-computed-properties': 7.20.7(@babel/core@7.22.9) - '@babel/plugin-transform-destructuring': 7.21.3(@babel/core@7.22.9) - '@babel/plugin-transform-dotall-regex': 7.18.6(@babel/core@7.22.9) - '@babel/plugin-transform-duplicate-keys': 7.18.9(@babel/core@7.22.9) - '@babel/plugin-transform-exponentiation-operator': 7.18.6(@babel/core@7.22.9) - '@babel/plugin-transform-for-of': 7.21.0(@babel/core@7.22.9) - '@babel/plugin-transform-function-name': 7.18.9(@babel/core@7.22.9) - '@babel/plugin-transform-literals': 7.18.9(@babel/core@7.22.9) - '@babel/plugin-transform-member-expression-literals': 7.18.6(@babel/core@7.22.9) - '@babel/plugin-transform-modules-amd': 7.20.11(@babel/core@7.22.9) - '@babel/plugin-transform-modules-commonjs': 7.21.2(@babel/core@7.22.9) - '@babel/plugin-transform-modules-systemjs': 7.20.11(@babel/core@7.22.9) - '@babel/plugin-transform-modules-umd': 7.18.6(@babel/core@7.22.9) - '@babel/plugin-transform-named-capturing-groups-regex': 7.20.5(@babel/core@7.22.9) - '@babel/plugin-transform-new-target': 7.18.6(@babel/core@7.22.9) - '@babel/plugin-transform-object-super': 7.18.6(@babel/core@7.22.9) - '@babel/plugin-transform-parameters': 7.21.3(@babel/core@7.22.9) - '@babel/plugin-transform-property-literals': 7.18.6(@babel/core@7.22.9) - '@babel/plugin-transform-regenerator': 7.20.5(@babel/core@7.22.9) - '@babel/plugin-transform-reserved-words': 7.18.6(@babel/core@7.22.9) - '@babel/plugin-transform-shorthand-properties': 7.18.6(@babel/core@7.22.9) - '@babel/plugin-transform-spread': 7.20.7(@babel/core@7.22.9) - '@babel/plugin-transform-sticky-regex': 7.18.6(@babel/core@7.22.9) - '@babel/plugin-transform-template-literals': 7.18.9(@babel/core@7.22.9) - '@babel/plugin-transform-typeof-symbol': 7.18.9(@babel/core@7.22.9) - '@babel/plugin-transform-unicode-escapes': 7.18.10(@babel/core@7.22.9) - '@babel/plugin-transform-unicode-regex': 7.18.6(@babel/core@7.22.9) - '@babel/preset-modules': 0.1.5(@babel/core@7.22.9) - '@babel/types': 7.23.0 - babel-plugin-polyfill-corejs2: 0.3.3(@babel/core@7.22.9) - babel-plugin-polyfill-corejs3: 0.6.0(@babel/core@7.22.9) - babel-plugin-polyfill-regenerator: 0.4.1(@babel/core@7.22.9) - core-js-compat: 3.30.0 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/preset-modules@0.1.5(@babel/core@7.22.9): - resolution: {integrity: sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - '@babel/plugin-proposal-unicode-property-regex': 7.18.6(@babel/core@7.22.9) - '@babel/plugin-transform-dotall-regex': 7.18.6(@babel/core@7.22.9) - '@babel/types': 7.23.0 - esutils: 2.0.3 - dev: true - - /@babel/preset-react@7.18.6(@babel/core@7.22.9): - resolution: {integrity: sha512-zXr6atUmyYdiWRVLOZahakYmOBHtWc2WGCkP8PYTgZi0iJXDY2CN180TdrIW4OGOAdLc7TifzDIvtx6izaRIzg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - '@babel/helper-validator-option': 7.21.0 - '@babel/plugin-transform-react-display-name': 7.18.6(@babel/core@7.22.9) - '@babel/plugin-transform-react-jsx': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-react-jsx-development': 7.18.6(@babel/core@7.22.9) - '@babel/plugin-transform-react-pure-annotations': 7.18.6(@babel/core@7.22.9) - dev: true - - /@babel/preset-typescript@7.21.4(@babel/core@7.22.9): - resolution: {integrity: sha512-sMLNWY37TCdRH/bJ6ZeeOH1nPuanED7Ai9Y/vH31IPqalioJ6ZNFUWONsakhv4r4n+I6gm5lmoE0olkgib/j/A==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-plugin-utils': 7.20.2 - '@babel/helper-validator-option': 7.21.0 - '@babel/plugin-syntax-jsx': 7.21.4(@babel/core@7.22.9) - '@babel/plugin-transform-modules-commonjs': 7.21.2(@babel/core@7.22.9) - '@babel/plugin-transform-typescript': 7.21.3(@babel/core@7.22.9) - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/regjsgen@0.8.0: - resolution: {integrity: sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==} - dev: true - - /@babel/runtime@7.21.0: - resolution: {integrity: sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==} - engines: {node: '>=6.9.0'} - dependencies: - regenerator-runtime: 0.13.11 - - /@babel/template@7.20.7: - resolution: {integrity: sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.21.4 - '@babel/parser': 7.23.0 - '@babel/types': 7.23.0 - dev: true - - /@babel/template@7.22.5: - resolution: {integrity: sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.22.5 - '@babel/parser': 7.23.0 - '@babel/types': 7.23.0 - dev: true - - /@babel/traverse@7.21.4: - resolution: {integrity: sha512-eyKrRHKdyZxqDm+fV1iqL9UAHMoIg0nDaGqfIOd8rKH17m5snv7Gn4qgjBoFfLz9APvjFU/ICT00NVCv1Epp8Q==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.21.4 - '@babel/generator': 7.23.0 - '@babel/helper-environment-visitor': 7.18.9 - '@babel/helper-function-name': 7.21.0 - '@babel/helper-hoist-variables': 7.18.6 - '@babel/helper-split-export-declaration': 7.18.6 - '@babel/parser': 7.23.0 - '@babel/types': 7.23.0 - debug: 4.3.4 - globals: 11.12.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/traverse@7.22.8: - resolution: {integrity: sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.22.5 - '@babel/generator': 7.23.0 - '@babel/helper-environment-visitor': 7.22.5 - '@babel/helper-function-name': 7.22.5 - '@babel/helper-hoist-variables': 7.22.5 - '@babel/helper-split-export-declaration': 7.22.6 - '@babel/parser': 7.23.0 - '@babel/types': 7.23.0 - debug: 4.3.4 - globals: 11.12.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/types@7.23.0: - resolution: {integrity: sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-string-parser': 7.22.5 - '@babel/helper-validator-identifier': 7.22.20 - to-fast-properties: 2.0.0 - - /@cspotcode/source-map-support@0.8.1: - resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} - engines: {node: '>=12'} - dependencies: - '@jridgewell/trace-mapping': 0.3.9 - dev: true - - /@esbuild/aix-ppc64@0.21.5: - resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [aix] - requiresBuild: true - dev: false - optional: true - - /@esbuild/android-arm64@0.21.5: - resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - requiresBuild: true - dev: false - optional: true - - /@esbuild/android-arm@0.21.5: - resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} - engines: {node: '>=12'} - cpu: [arm] - os: [android] - requiresBuild: true - dev: false - optional: true - - /@esbuild/android-x64@0.21.5: - resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} - engines: {node: '>=12'} - cpu: [x64] - os: [android] - requiresBuild: true - dev: false - optional: true - - /@esbuild/darwin-arm64@0.21.5: - resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} - engines: {node: '>=12'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: false - optional: true - - /@esbuild/darwin-x64@0.21.5: - resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} - engines: {node: '>=12'} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: false - optional: true - - /@esbuild/freebsd-arm64@0.21.5: - resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} - engines: {node: '>=12'} - cpu: [arm64] - os: [freebsd] - requiresBuild: true - dev: false - optional: true - - /@esbuild/freebsd-x64@0.21.5: - resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [freebsd] - requiresBuild: true - dev: false - optional: true - - /@esbuild/linux-arm64@0.21.5: - resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} - engines: {node: '>=12'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@esbuild/linux-arm@0.21.5: - resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} - engines: {node: '>=12'} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@esbuild/linux-ia32@0.21.5: - resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} - engines: {node: '>=12'} - cpu: [ia32] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@esbuild/linux-loong64@0.21.5: - resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} - engines: {node: '>=12'} - cpu: [loong64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@esbuild/linux-mips64el@0.21.5: - resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} - engines: {node: '>=12'} - cpu: [mips64el] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@esbuild/linux-ppc64@0.21.5: - resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@esbuild/linux-riscv64@0.21.5: - resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} - engines: {node: '>=12'} - cpu: [riscv64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@esbuild/linux-s390x@0.21.5: - resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} - engines: {node: '>=12'} - cpu: [s390x] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@esbuild/linux-x64@0.21.5: - resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: false - optional: true - - /@esbuild/netbsd-x64@0.21.5: - resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} - engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] - requiresBuild: true - dev: false - optional: true - - /@esbuild/openbsd-x64@0.21.5: - resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} - engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] - requiresBuild: true - dev: false - optional: true - - /@esbuild/sunos-x64@0.21.5: - resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - requiresBuild: true - dev: false - optional: true - - /@esbuild/win32-arm64@0.21.5: - resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: false - optional: true - - /@esbuild/win32-ia32@0.21.5: - resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: false - optional: true - - /@esbuild/win32-x64@0.21.5: - resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: false - optional: true - - /@eslint-community/eslint-utils@4.4.0(eslint@8.57.0): - resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - dependencies: - eslint: 8.57.0 - eslint-visitor-keys: 3.4.3 - dev: true - - /@eslint-community/regexpp@4.10.0: - resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==} - engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - dev: true - - /@eslint/eslintrc@2.1.4: - resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - ajv: 6.12.6 - debug: 4.3.4 - espree: 9.6.1 - globals: 13.20.0 - ignore: 5.2.4 - import-fresh: 3.3.0 - js-yaml: 4.1.0 - minimatch: 3.1.2 - strip-json-comments: 3.1.1 - transitivePeerDependencies: - - supports-color - dev: true - - /@eslint/js@8.57.0: - resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: true - - /@humanwhocodes/config-array@0.11.14: - resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} - engines: {node: '>=10.10.0'} - dependencies: - '@humanwhocodes/object-schema': 2.0.3 - debug: 4.3.4 - minimatch: 3.1.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@humanwhocodes/module-importer@1.0.1: - resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} - engines: {node: '>=12.22'} - dev: true - - /@humanwhocodes/object-schema@2.0.3: - resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} - dev: true - - /@jridgewell/gen-mapping@0.3.3: - resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==} - engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/set-array': 1.1.2 - '@jridgewell/sourcemap-codec': 1.4.15 - '@jridgewell/trace-mapping': 0.3.18 - - /@jridgewell/resolve-uri@3.1.0: - resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==} - engines: {node: '>=6.0.0'} - - /@jridgewell/resolve-uri@3.1.1: - resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==} - engines: {node: '>=6.0.0'} - dev: true - - /@jridgewell/set-array@1.1.2: - resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==} - engines: {node: '>=6.0.0'} - - /@jridgewell/sourcemap-codec@1.4.14: - resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==} - - /@jridgewell/sourcemap-codec@1.4.15: - resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} - - /@jridgewell/trace-mapping@0.3.18: - resolution: {integrity: sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==} - dependencies: - '@jridgewell/resolve-uri': 3.1.0 - '@jridgewell/sourcemap-codec': 1.4.14 - - /@jridgewell/trace-mapping@0.3.9: - resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} - dependencies: - '@jridgewell/resolve-uri': 3.1.1 - '@jridgewell/sourcemap-codec': 1.4.15 - dev: true - - /@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1: - resolution: {integrity: sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==} - dependencies: - eslint-scope: 5.1.1 - dev: true - - /@nodelib/fs.scandir@2.1.5: - resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} - engines: {node: '>= 8'} - dependencies: - '@nodelib/fs.stat': 2.0.5 - run-parallel: 1.2.0 - - /@nodelib/fs.stat@2.0.5: - resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} - engines: {node: '>= 8'} - - /@nodelib/fs.walk@1.2.8: - resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} - engines: {node: '>= 8'} - dependencies: - '@nodelib/fs.scandir': 2.1.5 - fastq: 1.15.0 - - /@protobufjs/aspromise@1.1.2: - resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} - - /@protobufjs/base64@1.1.2: - resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==} - - /@protobufjs/codegen@2.0.4: - resolution: {integrity: sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==} - - /@protobufjs/eventemitter@1.1.0: - resolution: {integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==} - - /@protobufjs/fetch@1.1.0: - resolution: {integrity: sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==} - dependencies: - '@protobufjs/aspromise': 1.1.2 - '@protobufjs/inquire': 1.1.0 - - /@protobufjs/float@1.0.2: - resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==} - - /@protobufjs/inquire@1.1.0: - resolution: {integrity: sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==} - - /@protobufjs/path@1.1.2: - resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==} - - /@protobufjs/pool@1.1.0: - resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==} - - /@protobufjs/utf8@1.1.0: - resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==} - - /@rushstack/eslint-patch@1.2.0: - resolution: {integrity: sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg==} - dev: true - - /@sindresorhus/is@4.6.0: - resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==} - engines: {node: '>=10'} - dev: false - - /@szmarczak/http-timer@4.0.6: - resolution: {integrity: sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==} - engines: {node: '>=10'} - dependencies: - defer-to-connect: 2.0.1 - dev: false - - /@tsconfig/node10@1.0.9: - resolution: {integrity: sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==} - dev: true - - /@tsconfig/node12@1.0.11: - resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} - dev: true - - /@tsconfig/node14@1.0.3: - resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} - dev: true - - /@tsconfig/node16@1.0.3: - resolution: {integrity: sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==} - dev: true - - /@types/body-parser@1.19.5: - resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==} - dependencies: - '@types/connect': 3.4.38 - '@types/node': 20.14.6 - dev: true - - /@types/cacheable-request@6.0.3: - resolution: {integrity: sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==} - dependencies: - '@types/http-cache-semantics': 4.0.1 - '@types/keyv': 3.1.4 - '@types/node': 20.14.6 - '@types/responselike': 1.0.0 - dev: false - - /@types/connect@3.4.38: - resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} - dependencies: - '@types/node': 20.14.6 - dev: true - - /@types/cors@2.8.17: - resolution: {integrity: sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==} - dependencies: - '@types/node': 20.14.6 - dev: true - - /@types/express-serve-static-core@4.19.0: - resolution: {integrity: sha512-bGyep3JqPCRry1wq+O5n7oiBgGWmeIJXPjXXCo8EK0u8duZGSYar7cGqd3ML2JUsLGeB7fmc06KYo9fLGWqPvQ==} - dependencies: - '@types/node': 20.14.6 - '@types/qs': 6.9.14 - '@types/range-parser': 1.2.7 - '@types/send': 0.17.4 - dev: true - - /@types/express@4.17.21: - resolution: {integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==} - dependencies: - '@types/body-parser': 1.19.5 - '@types/express-serve-static-core': 4.19.0 - '@types/qs': 6.9.14 - '@types/serve-static': 1.15.7 - dev: true - - /@types/ffprobe@1.1.8: - resolution: {integrity: sha512-qPxx8Dy0HyH12hQCESN39NQOmU2Yl2b7tCyUhWy0l11HQv/8Yv7U+vcaveFXmXK8hcAP0oj29DPFuSM7vcC3Tg==} - dev: true - - /@types/fs-extra@11.0.4: - resolution: {integrity: sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==} - dependencies: - '@types/jsonfile': 6.1.4 - '@types/node': 20.14.6 - dev: true - - /@types/http-cache-semantics@4.0.1: - resolution: {integrity: sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==} - dev: false - - /@types/http-errors@2.0.4: - resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==} - dev: true - - /@types/json-schema@7.0.15: - resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - dev: true - - /@types/json5@0.0.29: - resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} - dev: true - - /@types/jsonfile@6.1.4: - resolution: {integrity: sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==} - dependencies: - '@types/node': 20.14.6 - dev: true - - /@types/keyv@3.1.4: - resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} - dependencies: - '@types/node': 20.14.6 - dev: false - - /@types/mime@1.3.5: - resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} - dev: true - - /@types/node@20.14.6: - resolution: {integrity: sha512-JbA0XIJPL1IiNnU7PFxDXyfAwcwVVrOoqyzzyQTyMeVhBzkJVMSkC1LlVsRQ2lpqiY4n6Bb9oCS6lzDKVQxbZw==} - dependencies: - undici-types: 5.26.5 - - /@types/parse-json@4.0.0: - resolution: {integrity: sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==} - dev: true - - /@types/qs@6.9.14: - resolution: {integrity: sha512-5khscbd3SwWMhFqylJBLQ0zIu7c1K6Vz0uBIt915BI3zV0q1nfjRQD3RqSBcPaO6PHEF4ov/t9y89fSiyThlPA==} - dev: true - - /@types/range-parser@1.2.7: - resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} - dev: true - - /@types/responselike@1.0.0: - resolution: {integrity: sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==} - dependencies: - '@types/node': 20.14.6 - dev: false - - /@types/semver@7.5.8: - resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} - dev: true - - /@types/send@0.17.4: - resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==} - dependencies: - '@types/mime': 1.3.5 - '@types/node': 20.14.6 - dev: true - - /@types/serve-static@1.15.7: - resolution: {integrity: sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==} - dependencies: - '@types/http-errors': 2.0.4 - '@types/node': 20.14.6 - '@types/send': 0.17.4 - dev: true - - /@types/ws@8.5.10: - resolution: {integrity: sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==} - dependencies: - '@types/node': 20.14.6 - dev: true - - /@types/xmldom@0.1.34: - resolution: {integrity: sha512-7eZFfxI9XHYjJJuugddV6N5YNeXgQE1lArWOcd1eCOKWb/FGs5SIjacSYuEJuwhsGS3gy4RuZ5EUIcqYscuPDA==} - dev: false - - /@types/yargs-parser@21.0.3: - resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} - dev: true - - /@types/yargs@17.0.32: - resolution: {integrity: sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==} - dependencies: - '@types/yargs-parser': 21.0.3 - dev: true - - /@typescript-eslint/eslint-plugin@5.57.1(@typescript-eslint/parser@5.57.1)(eslint@8.57.0)(typescript@5.5.2): - resolution: {integrity: sha512-1MeobQkQ9tztuleT3v72XmY0XuKXVXusAhryoLuU5YZ+mXoYKZP9SQ7Flulh1NX4DTjpGTc2b/eMu4u7M7dhnQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - '@typescript-eslint/parser': ^5.0.0 - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@eslint-community/regexpp': 4.10.0 - '@typescript-eslint/parser': 5.57.1(eslint@8.57.0)(typescript@5.5.2) - '@typescript-eslint/scope-manager': 5.57.1 - '@typescript-eslint/type-utils': 5.57.1(eslint@8.57.0)(typescript@5.5.2) - '@typescript-eslint/utils': 5.57.1(eslint@8.57.0)(typescript@5.5.2) - debug: 4.3.4 - eslint: 8.57.0 - grapheme-splitter: 1.0.4 - ignore: 5.2.4 - natural-compare-lite: 1.4.0 - semver: 7.5.4 - tsutils: 3.21.0(typescript@5.5.2) - typescript: 5.5.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/eslint-plugin@7.13.1(@typescript-eslint/parser@7.13.1)(eslint@8.57.0)(typescript@5.5.2): - resolution: {integrity: sha512-kZqi+WZQaZfPKnsflLJQCz6Ze9FFSMfXrrIOcyargekQxG37ES7DJNpJUE9Q/X5n3yTIP/WPutVNzgknQ7biLg==} - engines: {node: ^18.18.0 || >=20.0.0} - peerDependencies: - '@typescript-eslint/parser': ^7.0.0 - eslint: ^8.56.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@eslint-community/regexpp': 4.10.0 - '@typescript-eslint/parser': 7.13.1(eslint@8.57.0)(typescript@5.5.2) - '@typescript-eslint/scope-manager': 7.13.1 - '@typescript-eslint/type-utils': 7.13.1(eslint@8.57.0)(typescript@5.5.2) - '@typescript-eslint/utils': 7.13.1(eslint@8.57.0)(typescript@5.5.2) - '@typescript-eslint/visitor-keys': 7.13.1 - eslint: 8.57.0 - graphemer: 1.4.0 - ignore: 5.3.1 - natural-compare: 1.4.0 - ts-api-utils: 1.3.0(typescript@5.5.2) - typescript: 5.5.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/experimental-utils@5.57.1(eslint@8.57.0)(typescript@5.5.2): - resolution: {integrity: sha512-5F5s8mpM1Y0RQ5iWzKQPQm5cmhARgcMfUwyHX1ZZFL8Tm0PyzyQ+9jgYSMaW74XXvpDg9/KdmMICLlwNwKtO7w==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - dependencies: - '@typescript-eslint/utils': 5.57.1(eslint@8.57.0)(typescript@5.5.2) - eslint: 8.57.0 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /@typescript-eslint/parser@5.57.1(eslint@8.57.0)(typescript@5.5.2): - resolution: {integrity: sha512-hlA0BLeVSA/wBPKdPGxoVr9Pp6GutGoY380FEhbVi0Ph4WNe8kLvqIRx76RSQt1lynZKfrXKs0/XeEk4zZycuA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/scope-manager': 5.57.1 - '@typescript-eslint/types': 5.57.1 - '@typescript-eslint/typescript-estree': 5.57.1(typescript@5.5.2) - debug: 4.3.4 - eslint: 8.57.0 - typescript: 5.5.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/parser@7.13.1(eslint@8.57.0)(typescript@5.5.2): - resolution: {integrity: sha512-1ELDPlnLvDQ5ybTSrMhRTFDfOQEOXNM+eP+3HT/Yq7ruWpciQw+Avi73pdEbA4SooCawEWo3dtYbF68gN7Ed1A==} - engines: {node: ^18.18.0 || >=20.0.0} - peerDependencies: - eslint: ^8.56.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/scope-manager': 7.13.1 - '@typescript-eslint/types': 7.13.1 - '@typescript-eslint/typescript-estree': 7.13.1(typescript@5.5.2) - '@typescript-eslint/visitor-keys': 7.13.1 - debug: 4.3.4 - eslint: 8.57.0 - typescript: 5.5.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/scope-manager@5.57.1: - resolution: {integrity: sha512-N/RrBwEUKMIYxSKl0oDK5sFVHd6VI7p9K5MyUlVYAY6dyNb/wHUqndkTd3XhpGlXgnQsBkRZuu4f9kAHghvgPw==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - '@typescript-eslint/types': 5.57.1 - '@typescript-eslint/visitor-keys': 5.57.1 - dev: true - - /@typescript-eslint/scope-manager@7.13.1: - resolution: {integrity: sha512-adbXNVEs6GmbzaCpymHQ0MB6E4TqoiVbC0iqG3uijR8ZYfpAXMGttouQzF4Oat3P2GxDVIrg7bMI/P65LiQZdg==} - engines: {node: ^18.18.0 || >=20.0.0} - dependencies: - '@typescript-eslint/types': 7.13.1 - '@typescript-eslint/visitor-keys': 7.13.1 - dev: true - - /@typescript-eslint/type-utils@5.57.1(eslint@8.57.0)(typescript@5.5.2): - resolution: {integrity: sha512-/RIPQyx60Pt6ga86hKXesXkJ2WOS4UemFrmmq/7eOyiYjYv/MUSHPlkhU6k9T9W1ytnTJueqASW+wOmW4KrViw==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: '*' - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/typescript-estree': 5.57.1(typescript@5.5.2) - '@typescript-eslint/utils': 5.57.1(eslint@8.57.0)(typescript@5.5.2) - debug: 4.3.4 - eslint: 8.57.0 - tsutils: 3.21.0(typescript@5.5.2) - typescript: 5.5.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/type-utils@7.13.1(eslint@8.57.0)(typescript@5.5.2): - resolution: {integrity: sha512-aWDbLu1s9bmgPGXSzNCxELu+0+HQOapV/y+60gPXafR8e2g1Bifxzevaa+4L2ytCWm+CHqpELq4CSoN9ELiwCg==} - engines: {node: ^18.18.0 || >=20.0.0} - peerDependencies: - eslint: ^8.56.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/typescript-estree': 7.13.1(typescript@5.5.2) - '@typescript-eslint/utils': 7.13.1(eslint@8.57.0)(typescript@5.5.2) - debug: 4.3.4 - eslint: 8.57.0 - ts-api-utils: 1.3.0(typescript@5.5.2) - typescript: 5.5.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/types@5.57.1: - resolution: {integrity: sha512-bSs4LOgyV3bJ08F5RDqO2KXqg3WAdwHCu06zOqcQ6vqbTJizyBhuh1o1ImC69X4bV2g1OJxbH71PJqiO7Y1RuA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: true - - /@typescript-eslint/types@7.13.1: - resolution: {integrity: sha512-7K7HMcSQIAND6RBL4kDl24sG/xKM13cA85dc7JnmQXw2cBDngg7c19B++JzvJHRG3zG36n9j1i451GBzRuHchw==} - engines: {node: ^18.18.0 || >=20.0.0} - dev: true - - /@typescript-eslint/typescript-estree@5.57.1(typescript@5.5.2): - resolution: {integrity: sha512-A2MZqD8gNT0qHKbk2wRspg7cHbCDCk2tcqt6ScCFLr5Ru8cn+TCfM786DjPhqwseiS+PrYwcXht5ztpEQ6TFTw==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/types': 5.57.1 - '@typescript-eslint/visitor-keys': 5.57.1 - debug: 4.3.4 - globby: 11.1.0 - is-glob: 4.0.3 - semver: 7.5.4 - tsutils: 3.21.0(typescript@5.5.2) - typescript: 5.5.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/typescript-estree@7.13.1(typescript@5.5.2): - resolution: {integrity: sha512-uxNr51CMV7npU1BxZzYjoVz9iyjckBduFBP0S5sLlh1tXYzHzgZ3BR9SVsNed+LmwKrmnqN3Kdl5t7eZ5TS1Yw==} - engines: {node: ^18.18.0 || >=20.0.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/types': 7.13.1 - '@typescript-eslint/visitor-keys': 7.13.1 - debug: 4.3.4 - globby: 11.1.0 - is-glob: 4.0.3 - minimatch: 9.0.4 - semver: 7.6.2 - ts-api-utils: 1.3.0(typescript@5.5.2) - typescript: 5.5.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/utils@5.57.1(eslint@8.57.0)(typescript@5.5.2): - resolution: {integrity: sha512-kN6vzzf9NkEtawECqze6v99LtmDiUJCVpvieTFA1uL7/jDghiJGubGZ5csicYHU1Xoqb3oH/R5cN5df6W41Nfg==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@types/json-schema': 7.0.15 - '@types/semver': 7.5.8 - '@typescript-eslint/scope-manager': 5.57.1 - '@typescript-eslint/types': 5.57.1 - '@typescript-eslint/typescript-estree': 5.57.1(typescript@5.5.2) - eslint: 8.57.0 - eslint-scope: 5.1.1 - semver: 7.5.4 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /@typescript-eslint/utils@7.13.1(eslint@8.57.0)(typescript@5.5.2): - resolution: {integrity: sha512-h5MzFBD5a/Gh/fvNdp9pTfqJAbuQC4sCN2WzuXme71lqFJsZtLbjxfSk4r3p02WIArOF9N94pdsLiGutpDbrXQ==} - engines: {node: ^18.18.0 || >=20.0.0} - peerDependencies: - eslint: ^8.56.0 - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@typescript-eslint/scope-manager': 7.13.1 - '@typescript-eslint/types': 7.13.1 - '@typescript-eslint/typescript-estree': 7.13.1(typescript@5.5.2) - eslint: 8.57.0 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /@typescript-eslint/visitor-keys@5.57.1: - resolution: {integrity: sha512-RjQrAniDU0CEk5r7iphkm731zKlFiUjvcBS2yHAg8WWqFMCaCrD0rKEVOMUyMMcbGPZ0bPp56srkGWrgfZqLRA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - '@typescript-eslint/types': 5.57.1 - eslint-visitor-keys: 3.4.3 - dev: true - - /@typescript-eslint/visitor-keys@7.13.1: - resolution: {integrity: sha512-k/Bfne7lrP7hcb7m9zSsgcBmo+8eicqqfNAJ7uUY+jkTFpKeH2FSkWpFRtimBxgkyvqfu9jTPRbYOvud6isdXA==} - engines: {node: ^18.18.0 || >=20.0.0} - dependencies: - '@typescript-eslint/types': 7.13.1 - eslint-visitor-keys: 3.4.3 - dev: true - - /@ungap/structured-clone@1.2.0: - resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} - dev: true - - /@videojs/vhs-utils@3.0.5: - resolution: {integrity: sha512-PKVgdo8/GReqdx512F+ombhS+Bzogiofy1LgAj4tN8PfdBx3HSS7V5WfJotKTqtOWGwVfSWsrYN/t09/DSryrw==} - engines: {node: '>=8', npm: '>=5'} - dependencies: - '@babel/runtime': 7.21.0 - global: 4.4.0 - url-toolkit: 2.2.5 - dev: false - - /@videojs/vhs-utils@4.0.0: - resolution: {integrity: sha512-xJp7Yd4jMLwje2vHCUmi8MOUU76nxiwII3z4Eg3Ucb+6rrkFVGosrXlMgGnaLjq724j3wzNElRZ71D/CKrTtxg==} - engines: {node: '>=8', npm: '>=5'} - dependencies: - '@babel/runtime': 7.21.0 - global: 4.4.0 - url-toolkit: 2.2.5 - dev: false - - /@xmldom/xmldom@0.8.10: - resolution: {integrity: sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==} - engines: {node: '>=10.0.0'} - dev: false - - /@yao-pkg/pkg-fetch@3.5.9: - resolution: {integrity: sha512-usMwwqFCd2B7k+V87u6kiTesyDSlw+3LpiuYBWe+UgryvSOk/NXjx3XVCub8hQoi0bCREbdQ6NDBqminyHJJrg==} - hasBin: true - dependencies: - chalk: 4.1.2 - fs-extra: 9.1.0 - https-proxy-agent: 5.0.1 - node-fetch: 2.7.0 - progress: 2.0.3 - semver: 7.5.4 - tar-fs: 2.1.1 - yargs: 16.2.0 - transitivePeerDependencies: - - encoding - - supports-color - dev: false - - /@yao-pkg/pkg@5.12.0: - resolution: {integrity: sha512-KZVpiDKRi2gtrVtKwhz/ZUKBOicVNggxaYQzPBjULuOLJ/UypTmAz5a2g+utLMn+WogbLE3vLfmC+TWp8v3+aQ==} - hasBin: true - dependencies: - '@babel/generator': 7.23.0 - '@babel/parser': 7.23.0 - '@babel/types': 7.23.0 - '@yao-pkg/pkg-fetch': 3.5.9 - chalk: 4.1.2 - fs-extra: 9.1.0 - globby: 11.1.0 - into-stream: 6.0.0 - is-core-module: 2.9.0 - minimatch: 9.0.4 - minimist: 1.2.8 - multistream: 4.1.0 - prebuild-install: 7.1.1 - resolve: 1.22.2 - stream-meter: 1.0.4 - transitivePeerDependencies: - - encoding - - supports-color - dev: false - - /JSONStream@1.3.5: - resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==} - hasBin: true - dependencies: - jsonparse: 1.3.1 - through: 2.3.8 - dev: false - - /accepts@1.3.8: - resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} - engines: {node: '>= 0.6'} - dependencies: - mime-types: 2.1.35 - negotiator: 0.6.3 - dev: false - - /acorn-jsx@5.3.2(acorn@8.10.0): - resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - dependencies: - acorn: 8.10.0 - dev: true - - /acorn-walk@8.2.0: - resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==} - engines: {node: '>=0.4.0'} - dev: true - - /acorn@8.10.0: - resolution: {integrity: sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==} - engines: {node: '>=0.4.0'} - hasBin: true - dev: true - - /agent-base@6.0.2: - resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} - engines: {node: '>= 6.0.0'} - dependencies: - debug: 4.3.4 - transitivePeerDependencies: - - supports-color - dev: false - - /ajv@6.12.6: - resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - dependencies: - fast-deep-equal: 3.1.3 - fast-json-stable-stringify: 2.1.0 - json-schema-traverse: 0.4.1 - uri-js: 4.4.1 - dev: true - - /ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - - /ansi-styles@3.2.1: - resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} - engines: {node: '>=4'} - dependencies: - color-convert: 1.9.3 - dev: true - - /ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} - dependencies: - color-convert: 2.0.1 - - /arg@4.1.3: - resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} - dev: true - - /argparse@2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - dev: true - - /aria-query@5.1.3: - resolution: {integrity: sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==} - dependencies: - deep-equal: 2.2.0 - dev: true - - /array-buffer-byte-length@1.0.1: - resolution: {integrity: sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - is-array-buffer: 3.0.4 - dev: true - - /array-flatten@1.1.1: - resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} - dev: false - - /array-includes@3.1.8: - resolution: {integrity: sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-object-atoms: 1.0.0 - get-intrinsic: 1.2.4 - is-string: 1.0.7 - dev: true - - /array-union@2.1.0: - resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} - engines: {node: '>=8'} - - /array.prototype.findlast@1.2.5: - resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-errors: 1.3.0 - es-object-atoms: 1.0.0 - es-shim-unscopables: 1.0.2 - dev: true - - /array.prototype.flat@1.3.1: - resolution: {integrity: sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-shim-unscopables: 1.0.2 - dev: true - - /array.prototype.flatmap@1.3.2: - resolution: {integrity: sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-shim-unscopables: 1.0.2 - dev: true - - /array.prototype.toreversed@1.1.2: - resolution: {integrity: sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA==} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-shim-unscopables: 1.0.2 - dev: true - - /array.prototype.tosorted@1.1.4: - resolution: {integrity: sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-errors: 1.3.0 - es-shim-unscopables: 1.0.2 - dev: true - - /arraybuffer.prototype.slice@1.0.3: - resolution: {integrity: sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==} - engines: {node: '>= 0.4'} - dependencies: - array-buffer-byte-length: 1.0.1 - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-errors: 1.3.0 - get-intrinsic: 1.2.4 - is-array-buffer: 3.0.4 - is-shared-array-buffer: 1.0.3 - dev: true - - /ast-types-flow@0.0.7: - resolution: {integrity: sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==} - dev: true - - /at-least-node@1.0.0: - resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==} - engines: {node: '>= 4.0.0'} - dev: false - - /available-typed-arrays@1.0.5: - resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} - engines: {node: '>= 0.4'} - dev: true - - /available-typed-arrays@1.0.7: - resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} - engines: {node: '>= 0.4'} - dependencies: - possible-typed-array-names: 1.0.0 - dev: true - - /axe-core@4.6.3: - resolution: {integrity: sha512-/BQzOX780JhsxDnPpH4ZiyrJAzcd8AfzFPkv+89veFSr1rcMjuq2JDCwypKaPeB6ljHp9KjXhPpjgCvQlWYuqg==} - engines: {node: '>=4'} - dev: true - - /axobject-query@3.1.1: - resolution: {integrity: sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==} - dependencies: - deep-equal: 2.2.0 - dev: true - - /babel-plugin-macros@3.1.0: - resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==} - engines: {node: '>=10', npm: '>=6'} - dependencies: - '@babel/runtime': 7.21.0 - cosmiconfig: 7.1.0 - resolve: 1.22.2 - dev: true - - /babel-plugin-polyfill-corejs2@0.3.3(@babel/core@7.22.9): - resolution: {integrity: sha512-8hOdmFYFSZhqg2C/JgLUQ+t52o5nirNwaWM2B9LWteozwIvM14VSwdsCAUET10qT+kmySAlseadmfeeSWFCy+Q==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/compat-data': 7.21.4 - '@babel/core': 7.22.9 - '@babel/helper-define-polyfill-provider': 0.3.3(@babel/core@7.22.9) - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - dev: true - - /babel-plugin-polyfill-corejs3@0.6.0(@babel/core@7.22.9): - resolution: {integrity: sha512-+eHqR6OPcBhJOGgsIar7xoAB1GcSwVUA3XjAd7HJNzOXT4wv6/H7KIdA/Nc60cvUlDbKApmqNvD1B1bzOt4nyA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-define-polyfill-provider': 0.3.3(@babel/core@7.22.9) - core-js-compat: 3.30.0 - transitivePeerDependencies: - - supports-color - dev: true - - /babel-plugin-polyfill-regenerator@0.4.1(@babel/core@7.22.9): - resolution: {integrity: sha512-NtQGmyQDXjQqQ+IzRkBVwEOz9lQ4zxAQZgoAYEtU9dJjnl1Oc98qnN7jcp+bE7O7aYzVpavXE3/VKXNzUbh7aw==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.9 - '@babel/helper-define-polyfill-provider': 0.3.3(@babel/core@7.22.9) - transitivePeerDependencies: - - supports-color - dev: true - - /babel-plugin-transform-react-remove-prop-types@0.4.24: - resolution: {integrity: sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA==} - dev: true - - /babel-preset-react-app@10.0.1: - resolution: {integrity: sha512-b0D9IZ1WhhCWkrTXyFuIIgqGzSkRIH5D5AmB0bXbzYAB1OBAwHcUeyWW2LorutLWF5btNo/N7r/cIdmvvKJlYg==} - dependencies: - '@babel/core': 7.22.9 - '@babel/plugin-proposal-class-properties': 7.18.6(@babel/core@7.22.9) - '@babel/plugin-proposal-decorators': 7.21.0(@babel/core@7.22.9) - '@babel/plugin-proposal-nullish-coalescing-operator': 7.18.6(@babel/core@7.22.9) - '@babel/plugin-proposal-numeric-separator': 7.18.6(@babel/core@7.22.9) - '@babel/plugin-proposal-optional-chaining': 7.21.0(@babel/core@7.22.9) - '@babel/plugin-proposal-private-methods': 7.18.6(@babel/core@7.22.9) - '@babel/plugin-proposal-private-property-in-object': 7.21.0(@babel/core@7.22.9) - '@babel/plugin-transform-flow-strip-types': 7.21.0(@babel/core@7.22.9) - '@babel/plugin-transform-react-display-name': 7.18.6(@babel/core@7.22.9) - '@babel/plugin-transform-runtime': 7.21.4(@babel/core@7.22.9) - '@babel/preset-env': 7.21.4(@babel/core@7.22.9) - '@babel/preset-react': 7.18.6(@babel/core@7.22.9) - '@babel/preset-typescript': 7.21.4(@babel/core@7.22.9) - '@babel/runtime': 7.21.0 - babel-plugin-macros: 3.1.0 - babel-plugin-transform-react-remove-prop-types: 0.4.24 - transitivePeerDependencies: - - supports-color - dev: true - - /balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - - /base64-js@1.5.1: - resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - dev: false - - /big-integer@1.6.52: - resolution: {integrity: sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==} - engines: {node: '>=0.6'} - dev: true - - /binary@0.3.0: - resolution: {integrity: sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg==} - dependencies: - buffers: 0.1.1 - chainsaw: 0.1.0 - dev: true - - /bl@4.1.0: - resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} - dependencies: - buffer: 5.7.1 - inherits: 2.0.4 - readable-stream: 3.6.2 - dev: false - - /bluebird@3.4.7: - resolution: {integrity: sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==} - dev: true - - /body-parser@1.20.2: - resolution: {integrity: sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==} - engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} - dependencies: - bytes: 3.1.2 - content-type: 1.0.5 - debug: 2.6.9 - depd: 2.0.0 - destroy: 1.2.0 - http-errors: 2.0.0 - iconv-lite: 0.4.24 - on-finished: 2.4.1 - qs: 6.11.0 - raw-body: 2.5.2 - type-is: 1.6.18 - unpipe: 1.0.0 - transitivePeerDependencies: - - supports-color - dev: false - - /brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - dev: true - - /brace-expansion@2.0.1: - resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} - dependencies: - balanced-match: 1.0.2 - - /braces@3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} - engines: {node: '>=8'} - dependencies: - fill-range: 7.0.1 - - /browserslist@4.21.5: - resolution: {integrity: sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} - hasBin: true - dependencies: - caniuse-lite: 1.0.30001474 - electron-to-chromium: 1.4.356 - node-releases: 2.0.10 - update-browserslist-db: 1.0.10(browserslist@4.21.5) - dev: true - - /browserslist@4.21.9: - resolution: {integrity: sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} - hasBin: true - dependencies: - caniuse-lite: 1.0.30001516 - electron-to-chromium: 1.4.461 - node-releases: 2.0.13 - update-browserslist-db: 1.0.11(browserslist@4.21.9) - dev: true - - /buffer-indexof-polyfill@1.0.2: - resolution: {integrity: sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==} - engines: {node: '>=0.10'} - dev: true - - /buffer@5.7.1: - resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} - dependencies: - base64-js: 1.5.1 - ieee754: 1.2.1 - dev: false - - /buffers@0.1.1: - resolution: {integrity: sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ==} - engines: {node: '>=0.2.0'} - dev: true - - /bytes@3.1.2: - resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} - engines: {node: '>= 0.8'} - dev: false - - /cacheable-lookup@5.0.4: - resolution: {integrity: sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==} - engines: {node: '>=10.6.0'} - dev: false - - /cacheable-request@7.0.2: - resolution: {integrity: sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==} - engines: {node: '>=8'} - dependencies: - clone-response: 1.0.3 - get-stream: 5.2.0 - http-cache-semantics: 4.1.1 - keyv: 4.5.2 - lowercase-keys: 2.0.0 - normalize-url: 6.1.0 - responselike: 2.0.1 - dev: false - - /call-bind@1.0.7: - resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} - engines: {node: '>= 0.4'} - dependencies: - es-define-property: 1.0.0 - es-errors: 1.3.0 - function-bind: 1.1.2 - get-intrinsic: 1.2.4 - set-function-length: 1.2.2 - - /callsites@3.1.0: - resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} - engines: {node: '>=6'} - dev: true - - /caniuse-lite@1.0.30001474: - resolution: {integrity: sha512-iaIZ8gVrWfemh5DG3T9/YqarVZoYf0r188IjaGwx68j4Pf0SGY6CQkmJUIE+NZHkkecQGohzXmBGEwWDr9aM3Q==} - dev: true - - /caniuse-lite@1.0.30001516: - resolution: {integrity: sha512-Wmec9pCBY8CWbmI4HsjBeQLqDTqV91nFVR83DnZpYyRnPI1wePDsTg0bGLPC5VU/3OIZV1fmxEea1b+tFKe86g==} - dev: true - - /case-anything@2.1.13: - resolution: {integrity: sha512-zlOQ80VrQ2Ue+ymH5OuM/DlDq64mEm+B9UTdHULv5osUMD6HalNTblf2b1u/m6QecjsnOkBpqVZ+XPwIVsy7Ng==} - engines: {node: '>=12.13'} - dev: true - - /chainsaw@0.1.0: - resolution: {integrity: sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ==} - dependencies: - traverse: 0.3.9 - dev: true - - /chalk@2.4.2: - resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} - engines: {node: '>=4'} - dependencies: - ansi-styles: 3.2.1 - escape-string-regexp: 1.0.5 - supports-color: 5.5.0 - dev: true - - /chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - - /chownr@1.1.4: - resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} - dev: false - - /cliui@7.0.4: - resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - dev: false - - /cliui@8.0.1: - resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} - engines: {node: '>=12'} - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - dev: false - - /clone-buffer@1.0.0: - resolution: {integrity: sha512-KLLTJWrvwIP+OPfMn0x2PheDEP20RPUcGXj/ERegTgdmPEZylALQldygiqrPPu8P45uNuPs7ckmReLY6v/iA5g==} - engines: {node: '>= 0.10'} - dev: true - - /clone-response@1.0.3: - resolution: {integrity: sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==} - dependencies: - mimic-response: 1.0.1 - dev: false - - /clone-stats@1.0.0: - resolution: {integrity: sha512-au6ydSpg6nsrigcZ4m8Bc9hxjeW+GJ8xh5G3BJCMt4WXe1H10UNaVOamqQTmrx1kjVuxAHIQSNU6hY4Nsn9/ag==} - dev: true - - /clone@2.1.2: - resolution: {integrity: sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==} - engines: {node: '>=0.8'} - dev: true - - /cloneable-readable@1.1.3: - resolution: {integrity: sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==} - dependencies: - inherits: 2.0.4 - process-nextick-args: 2.0.1 - readable-stream: 2.3.8 - dev: true - - /color-convert@1.9.3: - resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} - dependencies: - color-name: 1.1.3 - dev: true - - /color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} - dependencies: - color-name: 1.1.4 - - /color-name@1.1.3: - resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} - dev: true - - /color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - - /concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - dev: true - - /confusing-browser-globals@1.0.11: - resolution: {integrity: sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==} - dev: true - - /content-disposition@0.5.4: - resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} - engines: {node: '>= 0.6'} - dependencies: - safe-buffer: 5.2.1 - dev: false - - /content-type@1.0.5: - resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} - engines: {node: '>= 0.6'} - dev: false - - /convert-source-map@1.9.0: - resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} - dev: true - - /cookie-signature@1.0.6: - resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} - dev: false - - /cookie@0.6.0: - resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} - engines: {node: '>= 0.6'} - dev: false - - /core-js-compat@3.30.0: - resolution: {integrity: sha512-P5A2h/9mRYZFIAP+5Ab8ns6083IyVpSclU74UNvbGVQ8VM7n3n3/g2yF3AkKQ9NXz2O+ioxLbEWKnDtgsFamhg==} - dependencies: - browserslist: 4.21.5 - dev: true - - /core-util-is@1.0.3: - resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} - - /cors@2.8.5: - resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} - engines: {node: '>= 0.10'} - dependencies: - object-assign: 4.1.1 - vary: 1.1.2 - dev: false - - /cosmiconfig@7.1.0: - resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==} - engines: {node: '>=10'} - dependencies: - '@types/parse-json': 4.0.0 - import-fresh: 3.3.0 - parse-json: 5.2.0 - path-type: 4.0.0 - yaml: 1.10.2 - dev: true - - /create-require@1.1.1: - resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} - dev: true - - /cross-spawn@7.0.3: - resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} - engines: {node: '>= 8'} - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - dev: true - - /damerau-levenshtein@1.0.8: - resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} - dev: true - - /data-uri-to-buffer@4.0.1: - resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==} - engines: {node: '>= 12'} - dev: true - - /data-view-buffer@1.0.1: - resolution: {integrity: sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - is-data-view: 1.0.1 - dev: true - - /data-view-byte-length@1.0.1: - resolution: {integrity: sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - is-data-view: 1.0.1 - dev: true - - /data-view-byte-offset@1.0.0: - resolution: {integrity: sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - is-data-view: 1.0.1 - dev: true - - /date-format@4.0.14: - resolution: {integrity: sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg==} - engines: {node: '>=4.0'} - dev: false - - /debug@2.6.9: - resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.0.0 - dev: false - - /debug@3.2.7: - resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.3 - dev: true - - /debug@4.3.4: - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.2 - - /decompress-response@6.0.0: - resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} - engines: {node: '>=10'} - dependencies: - mimic-response: 3.1.0 - dev: false - - /deep-equal@2.2.0: - resolution: {integrity: sha512-RdpzE0Hv4lhowpIUKKMJfeH6C1pXdtT1/it80ubgWqwI3qpuxUBpC1S4hnHg+zjnuOoDkzUtUCEEkG+XG5l3Mw==} - dependencies: - call-bind: 1.0.7 - es-get-iterator: 1.1.3 - get-intrinsic: 1.2.4 - is-arguments: 1.1.1 - is-array-buffer: 3.0.2 - is-date-object: 1.0.5 - is-regex: 1.1.4 - is-shared-array-buffer: 1.0.2 - isarray: 2.0.5 - object-is: 1.1.5 - object-keys: 1.1.1 - object.assign: 4.1.5 - regexp.prototype.flags: 1.4.3 - side-channel: 1.0.6 - which-boxed-primitive: 1.0.2 - which-collection: 1.0.1 - which-typed-array: 1.1.9 - dev: true - - /deep-extend@0.6.0: - resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} - engines: {node: '>=4.0.0'} - dev: false - - /deep-is@0.1.4: - resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - dev: true - - /defer-to-connect@2.0.1: - resolution: {integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==} - engines: {node: '>=10'} - dev: false - - /deferential@1.0.0: - resolution: {integrity: sha512-QyFNvptDP8bypD6WK6ZOXFSBHN6CFLZmQ59QyvRGDvN9+DoX01mxw28QrJwSVPrrwnMWqHgTRiXybH6Y0cBbWw==} - dependencies: - native-promise-only: 0.8.1 - dev: false - - /define-data-property@1.1.4: - resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} - engines: {node: '>= 0.4'} - dependencies: - es-define-property: 1.0.0 - es-errors: 1.3.0 - gopd: 1.0.1 - - /define-lazy-prop@2.0.0: - resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} - engines: {node: '>=8'} - dev: false - - /define-properties@1.2.1: - resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} - engines: {node: '>= 0.4'} - dependencies: - define-data-property: 1.1.4 - has-property-descriptors: 1.0.2 - object-keys: 1.1.1 - dev: true - - /depd@2.0.0: - resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} - engines: {node: '>= 0.8'} - dev: false - - /destroy@1.2.0: - resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} - engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} - dev: false - - /detect-libc@1.0.3: - resolution: {integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==} - engines: {node: '>=0.10'} - hasBin: true - dev: true - - /detect-libc@2.0.2: - resolution: {integrity: sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==} - engines: {node: '>=8'} - dev: false - - /diff@4.0.2: - resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} - engines: {node: '>=0.3.1'} - dev: true - - /dir-glob@3.0.1: - resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} - engines: {node: '>=8'} - dependencies: - path-type: 4.0.0 - - /doctrine@2.1.0: - resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} - engines: {node: '>=0.10.0'} - dependencies: - esutils: 2.0.3 - dev: true - - /doctrine@3.0.0: - resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} - engines: {node: '>=6.0.0'} - dependencies: - esutils: 2.0.3 - dev: true - - /dom-walk@0.1.2: - resolution: {integrity: sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==} - dev: false - - /dprint-node@1.0.8: - resolution: {integrity: sha512-iVKnUtYfGrYcW1ZAlfR/F59cUVL8QIhWoBJoSjkkdua/dkWIgjZfiLMeTjiB06X0ZLkQ0M2C1VbUj/CxkIf1zg==} - dependencies: - detect-libc: 1.0.3 - dev: true - - /duplexer2@0.1.4: - resolution: {integrity: sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==} - dependencies: - readable-stream: 2.3.8 - dev: true - - /ee-first@1.1.1: - resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - dev: false - - /electron-to-chromium@1.4.356: - resolution: {integrity: sha512-nEftV1dRX3omlxAj42FwqRZT0i4xd2dIg39sog/CnCJeCcL1TRd2Uh0i9Oebgv8Ou0vzTPw++xc+Z20jzS2B6A==} - dev: true - - /electron-to-chromium@1.4.461: - resolution: {integrity: sha512-1JkvV2sgEGTDXjdsaQCeSwYYuhLRphRpc+g6EHTFELJXEiznLt3/0pZ9JuAOQ5p2rI3YxKTbivtvajirIfhrEQ==} - dev: true - - /emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - dev: false - - /emoji-regex@9.2.2: - resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - dev: true - - /encodeurl@1.0.2: - resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} - engines: {node: '>= 0.8'} - dev: false - - /end-of-stream@1.4.4: - resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} - dependencies: - once: 1.4.0 - dev: false - - /error-ex@1.3.2: - resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} - dependencies: - is-arrayish: 0.2.1 - dev: true - - /es-abstract@1.23.3: - resolution: {integrity: sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==} - engines: {node: '>= 0.4'} - dependencies: - array-buffer-byte-length: 1.0.1 - arraybuffer.prototype.slice: 1.0.3 - available-typed-arrays: 1.0.7 - call-bind: 1.0.7 - data-view-buffer: 1.0.1 - data-view-byte-length: 1.0.1 - data-view-byte-offset: 1.0.0 - es-define-property: 1.0.0 - es-errors: 1.3.0 - es-object-atoms: 1.0.0 - es-set-tostringtag: 2.0.3 - es-to-primitive: 1.2.1 - function.prototype.name: 1.1.6 - get-intrinsic: 1.2.4 - get-symbol-description: 1.0.2 - globalthis: 1.0.3 - gopd: 1.0.1 - has-property-descriptors: 1.0.2 - has-proto: 1.0.3 - has-symbols: 1.0.3 - hasown: 2.0.2 - internal-slot: 1.0.7 - is-array-buffer: 3.0.4 - is-callable: 1.2.7 - is-data-view: 1.0.1 - is-negative-zero: 2.0.3 - is-regex: 1.1.4 - is-shared-array-buffer: 1.0.3 - is-string: 1.0.7 - is-typed-array: 1.1.13 - is-weakref: 1.0.2 - object-inspect: 1.13.1 - object-keys: 1.1.1 - object.assign: 4.1.5 - regexp.prototype.flags: 1.5.2 - safe-array-concat: 1.1.2 - safe-regex-test: 1.0.3 - string.prototype.trim: 1.2.9 - string.prototype.trimend: 1.0.8 - string.prototype.trimstart: 1.0.8 - typed-array-buffer: 1.0.2 - typed-array-byte-length: 1.0.1 - typed-array-byte-offset: 1.0.2 - typed-array-length: 1.0.6 - unbox-primitive: 1.0.2 - which-typed-array: 1.1.15 - dev: true - - /es-define-property@1.0.0: - resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} - engines: {node: '>= 0.4'} - dependencies: - get-intrinsic: 1.2.4 - - /es-errors@1.3.0: - resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} - engines: {node: '>= 0.4'} - - /es-get-iterator@1.1.3: - resolution: {integrity: sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==} - dependencies: - call-bind: 1.0.7 - get-intrinsic: 1.2.4 - has-symbols: 1.0.3 - is-arguments: 1.1.1 - is-map: 2.0.2 - is-set: 2.0.2 - is-string: 1.0.7 - isarray: 2.0.5 - stop-iteration-iterator: 1.0.0 - dev: true - - /es-iterator-helpers@1.0.19: - resolution: {integrity: sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-errors: 1.3.0 - es-set-tostringtag: 2.0.3 - function-bind: 1.1.2 - get-intrinsic: 1.2.4 - globalthis: 1.0.3 - has-property-descriptors: 1.0.2 - has-proto: 1.0.3 - has-symbols: 1.0.3 - internal-slot: 1.0.7 - iterator.prototype: 1.1.2 - safe-array-concat: 1.1.2 - dev: true - - /es-object-atoms@1.0.0: - resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==} - engines: {node: '>= 0.4'} - dependencies: - es-errors: 1.3.0 - dev: true - - /es-set-tostringtag@2.0.3: - resolution: {integrity: sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==} - engines: {node: '>= 0.4'} - dependencies: - get-intrinsic: 1.2.4 - has-tostringtag: 1.0.2 - hasown: 2.0.2 - dev: true - - /es-shim-unscopables@1.0.2: - resolution: {integrity: sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==} - dependencies: - hasown: 2.0.2 - dev: true - - /es-to-primitive@1.2.1: - resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} - engines: {node: '>= 0.4'} - dependencies: - is-callable: 1.2.7 - is-date-object: 1.0.5 - is-symbol: 1.0.4 - dev: true - - /esbuild@0.21.5: - resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} - engines: {node: '>=12'} - hasBin: true - requiresBuild: true - optionalDependencies: - '@esbuild/aix-ppc64': 0.21.5 - '@esbuild/android-arm': 0.21.5 - '@esbuild/android-arm64': 0.21.5 - '@esbuild/android-x64': 0.21.5 - '@esbuild/darwin-arm64': 0.21.5 - '@esbuild/darwin-x64': 0.21.5 - '@esbuild/freebsd-arm64': 0.21.5 - '@esbuild/freebsd-x64': 0.21.5 - '@esbuild/linux-arm': 0.21.5 - '@esbuild/linux-arm64': 0.21.5 - '@esbuild/linux-ia32': 0.21.5 - '@esbuild/linux-loong64': 0.21.5 - '@esbuild/linux-mips64el': 0.21.5 - '@esbuild/linux-ppc64': 0.21.5 - '@esbuild/linux-riscv64': 0.21.5 - '@esbuild/linux-s390x': 0.21.5 - '@esbuild/linux-x64': 0.21.5 - '@esbuild/netbsd-x64': 0.21.5 - '@esbuild/openbsd-x64': 0.21.5 - '@esbuild/sunos-x64': 0.21.5 - '@esbuild/win32-arm64': 0.21.5 - '@esbuild/win32-ia32': 0.21.5 - '@esbuild/win32-x64': 0.21.5 - dev: false - - /escalade@3.1.1: - resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} - engines: {node: '>=6'} - - /escape-html@1.0.3: - resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} - dev: false - - /escape-string-regexp@1.0.5: - resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} - engines: {node: '>=0.8.0'} - dev: true - - /escape-string-regexp@4.0.0: - resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} - engines: {node: '>=10'} - dev: true - - /eslint-config-react-app@7.0.1(@babel/plugin-syntax-flow@7.22.5)(@babel/plugin-transform-react-jsx@7.22.5)(eslint@8.57.0)(typescript@5.5.2): - resolution: {integrity: sha512-K6rNzvkIeHaTd8m/QEh1Zko0KI7BACWkkneSs6s9cKZC/J27X3eZR6Upt1jkmZ/4FK+XUOPPxMEN7+lbUXfSlA==} - engines: {node: '>=14.0.0'} - peerDependencies: - eslint: ^8.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@babel/core': 7.22.9 - '@babel/eslint-parser': 7.21.3(@babel/core@7.22.9)(eslint@8.57.0) - '@rushstack/eslint-patch': 1.2.0 - '@typescript-eslint/eslint-plugin': 5.57.1(@typescript-eslint/parser@5.57.1)(eslint@8.57.0)(typescript@5.5.2) - '@typescript-eslint/parser': 5.57.1(eslint@8.57.0)(typescript@5.5.2) - babel-preset-react-app: 10.0.1 - confusing-browser-globals: 1.0.11 - eslint: 8.57.0 - eslint-plugin-flowtype: 8.0.3(@babel/plugin-syntax-flow@7.22.5)(@babel/plugin-transform-react-jsx@7.22.5)(eslint@8.57.0) - eslint-plugin-import: 2.27.5(@typescript-eslint/parser@5.57.1)(eslint@8.57.0) - eslint-plugin-jest: 25.7.0(@typescript-eslint/eslint-plugin@5.57.1)(eslint@8.57.0)(typescript@5.5.2) - eslint-plugin-jsx-a11y: 6.7.1(eslint@8.57.0) - eslint-plugin-react: 7.34.3(eslint@8.57.0) - eslint-plugin-react-hooks: 4.6.0(eslint@8.57.0) - eslint-plugin-testing-library: 5.10.2(eslint@8.57.0)(typescript@5.5.2) - typescript: 5.5.2 - transitivePeerDependencies: - - '@babel/plugin-syntax-flow' - - '@babel/plugin-transform-react-jsx' - - eslint-import-resolver-typescript - - eslint-import-resolver-webpack - - jest - - supports-color - dev: true - - /eslint-import-resolver-node@0.3.7: - resolution: {integrity: sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==} - dependencies: - debug: 3.2.7 - is-core-module: 2.13.1 - resolve: 1.22.2 - transitivePeerDependencies: - - supports-color - dev: true - - /eslint-module-utils@2.7.4(@typescript-eslint/parser@5.57.1)(eslint-import-resolver-node@0.3.7)(eslint@8.57.0): - resolution: {integrity: sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==} - engines: {node: '>=4'} - peerDependencies: - '@typescript-eslint/parser': '*' - eslint: '*' - eslint-import-resolver-node: '*' - eslint-import-resolver-typescript: '*' - eslint-import-resolver-webpack: '*' - peerDependenciesMeta: - '@typescript-eslint/parser': - optional: true - eslint: - optional: true - eslint-import-resolver-node: - optional: true - eslint-import-resolver-typescript: - optional: true - eslint-import-resolver-webpack: - optional: true - dependencies: - '@typescript-eslint/parser': 5.57.1(eslint@8.57.0)(typescript@5.5.2) - debug: 3.2.7 - eslint: 8.57.0 - eslint-import-resolver-node: 0.3.7 - transitivePeerDependencies: - - supports-color - dev: true - - /eslint-plugin-flowtype@8.0.3(@babel/plugin-syntax-flow@7.22.5)(@babel/plugin-transform-react-jsx@7.22.5)(eslint@8.57.0): - resolution: {integrity: sha512-dX8l6qUL6O+fYPtpNRideCFSpmWOUVx5QcaGLVqe/vlDiBSe4vYljDWDETwnyFzpl7By/WVIu6rcrniCgH9BqQ==} - engines: {node: '>=12.0.0'} - peerDependencies: - '@babel/plugin-syntax-flow': ^7.14.5 - '@babel/plugin-transform-react-jsx': ^7.14.9 - eslint: ^8.1.0 - dependencies: - '@babel/plugin-syntax-flow': 7.22.5(@babel/core@7.22.9) - '@babel/plugin-transform-react-jsx': 7.22.5(@babel/core@7.22.9) - eslint: 8.57.0 - lodash: 4.17.21 - string-natural-compare: 3.0.1 - dev: true - - /eslint-plugin-import@2.27.5(@typescript-eslint/parser@5.57.1)(eslint@8.57.0): - resolution: {integrity: sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==} - engines: {node: '>=4'} - peerDependencies: - '@typescript-eslint/parser': '*' - eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 - peerDependenciesMeta: - '@typescript-eslint/parser': - optional: true - dependencies: - '@typescript-eslint/parser': 5.57.1(eslint@8.57.0)(typescript@5.5.2) - array-includes: 3.1.8 - array.prototype.flat: 1.3.1 - array.prototype.flatmap: 1.3.2 - debug: 3.2.7 - doctrine: 2.1.0 - eslint: 8.57.0 - eslint-import-resolver-node: 0.3.7 - eslint-module-utils: 2.7.4(@typescript-eslint/parser@5.57.1)(eslint-import-resolver-node@0.3.7)(eslint@8.57.0) - has: 1.0.3 - is-core-module: 2.13.1 - is-glob: 4.0.3 - minimatch: 3.1.2 - object.values: 1.2.0 - resolve: 1.22.2 - semver: 6.3.1 - tsconfig-paths: 3.14.2 - transitivePeerDependencies: - - eslint-import-resolver-typescript - - eslint-import-resolver-webpack - - supports-color - dev: true - - /eslint-plugin-jest@25.7.0(@typescript-eslint/eslint-plugin@5.57.1)(eslint@8.57.0)(typescript@5.5.2): - resolution: {integrity: sha512-PWLUEXeeF7C9QGKqvdSbzLOiLTx+bno7/HC9eefePfEb257QFHg7ye3dh80AZVkaa/RQsBB1Q/ORQvg2X7F0NQ==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - peerDependencies: - '@typescript-eslint/eslint-plugin': ^4.0.0 || ^5.0.0 - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - jest: '*' - peerDependenciesMeta: - '@typescript-eslint/eslint-plugin': - optional: true - jest: - optional: true - dependencies: - '@typescript-eslint/eslint-plugin': 5.57.1(@typescript-eslint/parser@5.57.1)(eslint@8.57.0)(typescript@5.5.2) - '@typescript-eslint/experimental-utils': 5.57.1(eslint@8.57.0)(typescript@5.5.2) - eslint: 8.57.0 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /eslint-plugin-jsx-a11y@6.7.1(eslint@8.57.0): - resolution: {integrity: sha512-63Bog4iIethyo8smBklORknVjB0T2dwB8Mr/hIC+fBS0uyHdYYpzM/Ed+YC8VxTjlXHEWFOdmgwcDn1U2L9VCA==} - engines: {node: '>=4.0'} - peerDependencies: - eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 - dependencies: - '@babel/runtime': 7.21.0 - aria-query: 5.1.3 - array-includes: 3.1.8 - array.prototype.flatmap: 1.3.2 - ast-types-flow: 0.0.7 - axe-core: 4.6.3 - axobject-query: 3.1.1 - damerau-levenshtein: 1.0.8 - emoji-regex: 9.2.2 - eslint: 8.57.0 - has: 1.0.3 - jsx-ast-utils: 3.3.3 - language-tags: 1.0.5 - minimatch: 3.1.2 - object.entries: 1.1.8 - object.fromentries: 2.0.8 - semver: 6.3.1 - dev: true - - /eslint-plugin-react-hooks@4.6.0(eslint@8.57.0): - resolution: {integrity: sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==} - engines: {node: '>=10'} - peerDependencies: - eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 - dependencies: - eslint: 8.57.0 - dev: true - - /eslint-plugin-react@7.34.3(eslint@8.57.0): - resolution: {integrity: sha512-aoW4MV891jkUulwDApQbPYTVZmeuSyFrudpbTAQuj5Fv8VL+o6df2xIGpw8B0hPjAaih1/Fb0om9grCdyFYemA==} - engines: {node: '>=4'} - peerDependencies: - eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 - dependencies: - array-includes: 3.1.8 - array.prototype.findlast: 1.2.5 - array.prototype.flatmap: 1.3.2 - array.prototype.toreversed: 1.1.2 - array.prototype.tosorted: 1.1.4 - doctrine: 2.1.0 - es-iterator-helpers: 1.0.19 - eslint: 8.57.0 - estraverse: 5.3.0 - jsx-ast-utils: 3.3.3 - minimatch: 3.1.2 - object.entries: 1.1.8 - object.fromentries: 2.0.8 - object.hasown: 1.1.4 - object.values: 1.2.0 - prop-types: 15.8.1 - resolve: 2.0.0-next.5 - semver: 6.3.1 - string.prototype.matchall: 4.0.11 - dev: true - - /eslint-plugin-testing-library@5.10.2(eslint@8.57.0)(typescript@5.5.2): - resolution: {integrity: sha512-f1DmDWcz5SDM+IpCkEX0lbFqrrTs8HRsEElzDEqN/EBI0hpRj8Cns5+IVANXswE8/LeybIJqPAOQIFu2j5Y5sw==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0, npm: '>=6'} - peerDependencies: - eslint: ^7.5.0 || ^8.0.0 - dependencies: - '@typescript-eslint/utils': 5.57.1(eslint@8.57.0)(typescript@5.5.2) - eslint: 8.57.0 - transitivePeerDependencies: - - supports-color - - typescript - dev: true - - /eslint-scope@5.1.1: - resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} - engines: {node: '>=8.0.0'} - dependencies: - esrecurse: 4.3.0 - estraverse: 4.3.0 - dev: true - - /eslint-scope@7.2.2: - resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - esrecurse: 4.3.0 - estraverse: 5.3.0 - dev: true - - /eslint-visitor-keys@2.1.0: - resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==} - engines: {node: '>=10'} - dev: true - - /eslint-visitor-keys@3.4.3: - resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: true - - /eslint@8.57.0: - resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - hasBin: true - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@eslint-community/regexpp': 4.10.0 - '@eslint/eslintrc': 2.1.4 - '@eslint/js': 8.57.0 - '@humanwhocodes/config-array': 0.11.14 - '@humanwhocodes/module-importer': 1.0.1 - '@nodelib/fs.walk': 1.2.8 - '@ungap/structured-clone': 1.2.0 - ajv: 6.12.6 - chalk: 4.1.2 - cross-spawn: 7.0.3 - debug: 4.3.4 - doctrine: 3.0.0 - escape-string-regexp: 4.0.0 - eslint-scope: 7.2.2 - eslint-visitor-keys: 3.4.3 - espree: 9.6.1 - esquery: 1.5.0 - esutils: 2.0.3 - fast-deep-equal: 3.1.3 - file-entry-cache: 6.0.1 - find-up: 5.0.0 - glob-parent: 6.0.2 - globals: 13.20.0 - graphemer: 1.4.0 - ignore: 5.2.4 - imurmurhash: 0.1.4 - is-glob: 4.0.3 - is-path-inside: 3.0.3 - js-yaml: 4.1.0 - json-stable-stringify-without-jsonify: 1.0.1 - levn: 0.4.1 - lodash.merge: 4.6.2 - minimatch: 3.1.2 - natural-compare: 1.4.0 - optionator: 0.9.3 - strip-ansi: 6.0.1 - text-table: 0.2.0 - transitivePeerDependencies: - - supports-color - dev: true - - /espree@9.6.1: - resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dependencies: - acorn: 8.10.0 - acorn-jsx: 5.3.2(acorn@8.10.0) - eslint-visitor-keys: 3.4.3 - dev: true - - /esquery@1.5.0: - resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} - engines: {node: '>=0.10'} - dependencies: - estraverse: 5.3.0 - dev: true - - /esrecurse@4.3.0: - resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} - engines: {node: '>=4.0'} - dependencies: - estraverse: 5.3.0 - dev: true - - /estraverse@4.3.0: - resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} - engines: {node: '>=4.0'} - dev: true - - /estraverse@5.3.0: - resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} - engines: {node: '>=4.0'} - dev: true - - /esutils@2.0.3: - resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} - engines: {node: '>=0.10.0'} - dev: true - - /etag@1.8.1: - resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} - engines: {node: '>= 0.6'} - dev: false - - /expand-template@2.0.3: - resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} - engines: {node: '>=6'} - dev: false - - /express@4.19.2: - resolution: {integrity: sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==} - engines: {node: '>= 0.10.0'} - dependencies: - accepts: 1.3.8 - array-flatten: 1.1.1 - body-parser: 1.20.2 - content-disposition: 0.5.4 - content-type: 1.0.5 - cookie: 0.6.0 - cookie-signature: 1.0.6 - debug: 2.6.9 - depd: 2.0.0 - encodeurl: 1.0.2 - escape-html: 1.0.3 - etag: 1.8.1 - finalhandler: 1.2.0 - fresh: 0.5.2 - http-errors: 2.0.0 - merge-descriptors: 1.0.1 - methods: 1.1.2 - on-finished: 2.4.1 - parseurl: 1.3.3 - path-to-regexp: 0.1.7 - proxy-addr: 2.0.7 - qs: 6.11.0 - range-parser: 1.2.1 - safe-buffer: 5.2.1 - send: 0.18.0 - serve-static: 1.15.0 - setprototypeof: 1.2.0 - statuses: 2.0.1 - type-is: 1.6.18 - utils-merge: 1.0.1 - vary: 1.1.2 - transitivePeerDependencies: - - supports-color - dev: false - - /fast-deep-equal@3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - dev: true - - /fast-glob@3.2.12: - resolution: {integrity: sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==} - engines: {node: '>=8.6.0'} - dependencies: - '@nodelib/fs.stat': 2.0.5 - '@nodelib/fs.walk': 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.5 - - /fast-json-stable-stringify@2.1.0: - resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - dev: true - - /fast-levenshtein@2.0.6: - resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - dev: true - - /fastq@1.15.0: - resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} - dependencies: - reusify: 1.0.4 - - /fetch-blob@3.2.0: - resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} - engines: {node: ^12.20 || >= 14.13} - dependencies: - node-domexception: 1.0.0 - web-streams-polyfill: 3.3.3 - dev: true - - /ffprobe@1.1.2: - resolution: {integrity: sha512-a+oTbhyeM7Z8PRy+mpzmVUAnATZT7z4BO94HSKeqHupdmjiKZ1djzcZkyoyXA21zCOCG7oVRrsBMmvvtmzoz4g==} - dependencies: - JSONStream: 1.3.5 - bl: 4.1.0 - deferential: 1.0.0 - dev: false - - /file-entry-cache@6.0.1: - resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} - engines: {node: ^10.12.0 || >=12.0.0} - dependencies: - flat-cache: 3.0.4 - dev: true - - /fill-range@7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} - engines: {node: '>=8'} - dependencies: - to-regex-range: 5.0.1 - - /finalhandler@1.2.0: - resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==} - engines: {node: '>= 0.8'} - dependencies: - debug: 2.6.9 - encodeurl: 1.0.2 - escape-html: 1.0.3 - on-finished: 2.4.1 - parseurl: 1.3.3 - statuses: 2.0.1 - unpipe: 1.0.0 - transitivePeerDependencies: - - supports-color - dev: false - - /find-up@5.0.0: - resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} - engines: {node: '>=10'} - dependencies: - locate-path: 6.0.0 - path-exists: 4.0.0 - dev: true - - /flat-cache@3.0.4: - resolution: {integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==} - engines: {node: ^10.12.0 || >=12.0.0} - dependencies: - flatted: 3.2.7 - rimraf: 3.0.2 - dev: true - - /flatted@3.2.7: - resolution: {integrity: sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==} - - /for-each@0.3.3: - resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} - dependencies: - is-callable: 1.2.7 - dev: true - - /formdata-polyfill@4.0.10: - resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} - engines: {node: '>=12.20.0'} - dependencies: - fetch-blob: 3.2.0 - dev: true - - /forwarded@0.2.0: - resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} - engines: {node: '>= 0.6'} - dev: false - - /fresh@0.5.2: - resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} - engines: {node: '>= 0.6'} - dev: false - - /from2@2.3.0: - resolution: {integrity: sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==} - dependencies: - inherits: 2.0.4 - readable-stream: 2.3.8 - dev: false - - /fs-constants@1.0.0: - resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} - dev: false - - /fs-extra@11.2.0: - resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==} - engines: {node: '>=14.14'} - dependencies: - graceful-fs: 4.2.11 - jsonfile: 6.1.0 - universalify: 2.0.0 - dev: false - - /fs-extra@8.1.0: - resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} - engines: {node: '>=6 <7 || >=8'} - dependencies: - graceful-fs: 4.2.11 - jsonfile: 4.0.0 - universalify: 0.1.2 - dev: false - - /fs-extra@9.1.0: - resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==} - engines: {node: '>=10'} - dependencies: - at-least-node: 1.0.0 - graceful-fs: 4.2.11 - jsonfile: 6.1.0 - universalify: 2.0.0 - dev: false - - /fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - dev: true - - /fstream@1.0.12: - resolution: {integrity: sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==} - engines: {node: '>=0.6'} - dependencies: - graceful-fs: 4.2.11 - inherits: 2.0.4 - mkdirp: 0.5.6 - rimraf: 2.7.1 - dev: true - - /function-bind@1.1.2: - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - - /function.prototype.name@1.1.6: - resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - functions-have-names: 1.2.3 - dev: true - - /functions-have-names@1.2.3: - resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} - dev: true - - /gensync@1.0.0-beta.2: - resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} - engines: {node: '>=6.9.0'} - dev: true - - /get-caller-file@2.0.5: - resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} - engines: {node: 6.* || 8.* || >= 10.*} - dev: false - - /get-intrinsic@1.2.4: - resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} - engines: {node: '>= 0.4'} - dependencies: - es-errors: 1.3.0 - function-bind: 1.1.2 - has-proto: 1.0.3 - has-symbols: 1.0.3 - hasown: 2.0.2 - - /get-stream@5.2.0: - resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} - engines: {node: '>=8'} - dependencies: - pump: 3.0.0 - dev: false - - /get-symbol-description@1.0.2: - resolution: {integrity: sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - get-intrinsic: 1.2.4 - dev: true - - /github-from-package@0.0.0: - resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==} - dev: false - - /glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} - dependencies: - is-glob: 4.0.3 - - /glob-parent@6.0.2: - resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} - engines: {node: '>=10.13.0'} - dependencies: - is-glob: 4.0.3 - dev: true - - /glob@7.2.3: - resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - dev: true - - /global@4.4.0: - resolution: {integrity: sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==} - dependencies: - min-document: 2.19.0 - process: 0.11.10 - dev: false - - /globals@11.12.0: - resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} - engines: {node: '>=4'} - dev: true - - /globals@13.20.0: - resolution: {integrity: sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==} - engines: {node: '>=8'} - dependencies: - type-fest: 0.20.2 - dev: true - - /globalthis@1.0.3: - resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} - engines: {node: '>= 0.4'} - dependencies: - define-properties: 1.2.1 - dev: true - - /globby@11.1.0: - resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} - engines: {node: '>=10'} - dependencies: - array-union: 2.1.0 - dir-glob: 3.0.1 - fast-glob: 3.2.12 - ignore: 5.2.4 - merge2: 1.4.1 - slash: 3.0.0 - - /gopd@1.0.1: - resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} - dependencies: - get-intrinsic: 1.2.4 - - /got@11.8.6: - resolution: {integrity: sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==} - engines: {node: '>=10.19.0'} - dependencies: - '@sindresorhus/is': 4.6.0 - '@szmarczak/http-timer': 4.0.6 - '@types/cacheable-request': 6.0.3 - '@types/responselike': 1.0.0 - cacheable-lookup: 5.0.4 - cacheable-request: 7.0.2 - decompress-response: 6.0.0 - http2-wrapper: 1.0.3 - lowercase-keys: 2.0.0 - p-cancelable: 2.1.1 - responselike: 2.0.1 - dev: false - - /graceful-fs@4.2.11: - resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - - /grapheme-splitter@1.0.4: - resolution: {integrity: sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==} - dev: true - - /graphemer@1.4.0: - resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - dev: true - - /has-bigints@1.0.2: - resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} - dev: true - - /has-flag@3.0.0: - resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} - engines: {node: '>=4'} - dev: true - - /has-flag@4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} - - /has-property-descriptors@1.0.2: - resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} - dependencies: - es-define-property: 1.0.0 - - /has-proto@1.0.3: - resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} - engines: {node: '>= 0.4'} - - /has-symbols@1.0.3: - resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} - engines: {node: '>= 0.4'} - - /has-tostringtag@1.0.0: - resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} - engines: {node: '>= 0.4'} - dependencies: - has-symbols: 1.0.3 - dev: true - - /has-tostringtag@1.0.2: - resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} - engines: {node: '>= 0.4'} - dependencies: - has-symbols: 1.0.3 - dev: true - - /has@1.0.3: - resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} - engines: {node: '>= 0.4.0'} - dependencies: - function-bind: 1.1.2 - - /hasown@2.0.2: - resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} - engines: {node: '>= 0.4'} - dependencies: - function-bind: 1.1.2 - - /http-cache-semantics@4.1.1: - resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} - dev: false - - /http-errors@2.0.0: - resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} - engines: {node: '>= 0.8'} - dependencies: - depd: 2.0.0 - inherits: 2.0.4 - setprototypeof: 1.2.0 - statuses: 2.0.1 - toidentifier: 1.0.1 - dev: false - - /http2-wrapper@1.0.3: - resolution: {integrity: sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==} - engines: {node: '>=10.19.0'} - dependencies: - quick-lru: 5.1.1 - resolve-alpn: 1.2.1 - dev: false - - /https-proxy-agent@5.0.1: - resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} - engines: {node: '>= 6'} - dependencies: - agent-base: 6.0.2 - debug: 4.3.4 - transitivePeerDependencies: - - supports-color - dev: false - - /iconv-lite@0.4.24: - resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} - engines: {node: '>=0.10.0'} - dependencies: - safer-buffer: 2.1.2 - dev: false - - /ieee754@1.2.1: - resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} - dev: false - - /ignore@5.2.4: - resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==} - engines: {node: '>= 4'} - - /ignore@5.3.1: - resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} - engines: {node: '>= 4'} - dev: true - - /import-fresh@3.3.0: - resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} - engines: {node: '>=6'} - dependencies: - parent-module: 1.0.1 - resolve-from: 4.0.0 - dev: true - - /imurmurhash@0.1.4: - resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} - engines: {node: '>=0.8.19'} - dev: true - - /inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - dev: true - - /inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - - /ini@1.3.8: - resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} - dev: false - - /internal-slot@1.0.7: - resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==} - engines: {node: '>= 0.4'} - dependencies: - es-errors: 1.3.0 - hasown: 2.0.2 - side-channel: 1.0.6 - dev: true - - /into-stream@6.0.0: - resolution: {integrity: sha512-XHbaOAvP+uFKUFsOgoNPRjLkwB+I22JFPFe5OjTkQ0nwgj6+pSjb4NmB6VMxaPshLiOf+zcpOCBQuLwC1KHhZA==} - engines: {node: '>=10'} - dependencies: - from2: 2.3.0 - p-is-promise: 3.0.0 - dev: false - - /ipaddr.js@1.9.1: - resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} - engines: {node: '>= 0.10'} - dev: false - - /is-arguments@1.1.1: - resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - has-tostringtag: 1.0.0 - dev: true - - /is-array-buffer@3.0.2: - resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==} - dependencies: - call-bind: 1.0.7 - get-intrinsic: 1.2.4 - is-typed-array: 1.1.10 - dev: true - - /is-array-buffer@3.0.4: - resolution: {integrity: sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - get-intrinsic: 1.2.4 - dev: true - - /is-arrayish@0.2.1: - resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - dev: true - - /is-async-function@2.0.0: - resolution: {integrity: sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.2 - dev: true - - /is-bigint@1.0.4: - resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} - dependencies: - has-bigints: 1.0.2 - dev: true - - /is-boolean-object@1.1.2: - resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - has-tostringtag: 1.0.2 - dev: true - - /is-callable@1.2.7: - resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} - engines: {node: '>= 0.4'} - dev: true - - /is-core-module@2.13.1: - resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} - dependencies: - hasown: 2.0.2 - - /is-core-module@2.9.0: - resolution: {integrity: sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==} - dependencies: - has: 1.0.3 - dev: false - - /is-data-view@1.0.1: - resolution: {integrity: sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==} - engines: {node: '>= 0.4'} - dependencies: - is-typed-array: 1.1.13 - dev: true - - /is-date-object@1.0.5: - resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.0 - dev: true - - /is-docker@2.2.1: - resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} - engines: {node: '>=8'} - hasBin: true - dev: false - - /is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - - /is-finalizationregistry@1.0.2: - resolution: {integrity: sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==} - dependencies: - call-bind: 1.0.7 - dev: true - - /is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - dev: false - - /is-generator-function@1.0.10: - resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.2 - dev: true - - /is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} - dependencies: - is-extglob: 2.1.1 - - /is-map@2.0.2: - resolution: {integrity: sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==} - dev: true - - /is-negative-zero@2.0.3: - resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} - engines: {node: '>= 0.4'} - dev: true - - /is-number-object@1.0.7: - resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.2 - dev: true - - /is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - - /is-path-inside@3.0.3: - resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} - engines: {node: '>=8'} - dev: true - - /is-regex@1.1.4: - resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - has-tostringtag: 1.0.0 - dev: true - - /is-set@2.0.2: - resolution: {integrity: sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==} - dev: true - - /is-shared-array-buffer@1.0.2: - resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==} - dependencies: - call-bind: 1.0.7 - dev: true - - /is-shared-array-buffer@1.0.3: - resolution: {integrity: sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - dev: true - - /is-string@1.0.7: - resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.2 - dev: true - - /is-symbol@1.0.4: - resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} - engines: {node: '>= 0.4'} - dependencies: - has-symbols: 1.0.3 - dev: true - - /is-typed-array@1.1.10: - resolution: {integrity: sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==} - engines: {node: '>= 0.4'} - dependencies: - available-typed-arrays: 1.0.7 - call-bind: 1.0.7 - for-each: 0.3.3 - gopd: 1.0.1 - has-tostringtag: 1.0.2 - dev: true - - /is-typed-array@1.1.13: - resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==} - engines: {node: '>= 0.4'} - dependencies: - which-typed-array: 1.1.15 - dev: true - - /is-weakmap@2.0.1: - resolution: {integrity: sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==} - dev: true - - /is-weakref@1.0.2: - resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} - dependencies: - call-bind: 1.0.7 - dev: true - - /is-weakset@2.0.2: - resolution: {integrity: sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==} - dependencies: - call-bind: 1.0.7 - get-intrinsic: 1.2.4 - dev: true - - /is-wsl@2.2.0: - resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} - engines: {node: '>=8'} - dependencies: - is-docker: 2.2.1 - dev: false - - /isarray@1.0.0: - resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} - - /isarray@2.0.5: - resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} - dev: true - - /isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - dev: true - - /iso-639@0.2.2: - resolution: {integrity: sha512-t1ZNgV1kLZ4dBQGxtY4z5oysRFPANt0kqHjomasflQW0w+YdDRF+Wsl0gFftIeUiP508KhZxG3MXQ31Swd643Q==} - dev: false - - /iterator.prototype@1.1.2: - resolution: {integrity: sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==} - dependencies: - define-properties: 1.2.1 - get-intrinsic: 1.2.4 - has-symbols: 1.0.3 - reflect.getprototypeof: 1.0.6 - set-function-name: 2.0.2 - dev: true - - /js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - dev: true - - /js-yaml@4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} - hasBin: true - dependencies: - argparse: 2.0.1 - dev: true - - /jsesc@0.5.0: - resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} - hasBin: true - dev: true - - /jsesc@2.5.2: - resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} - engines: {node: '>=4'} - hasBin: true - - /json-buffer@3.0.1: - resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} - dev: false - - /json-parse-even-better-errors@2.3.1: - resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - dev: true - - /json-schema-traverse@0.4.1: - resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - dev: true - - /json-stable-stringify-without-jsonify@1.0.1: - resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} - dev: true - - /json5@1.0.2: - resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} - hasBin: true - dependencies: - minimist: 1.2.8 - dev: true - - /json5@2.2.3: - resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} - engines: {node: '>=6'} - hasBin: true - dev: true - - /jsonfile@4.0.0: - resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} - optionalDependencies: - graceful-fs: 4.2.11 - dev: false - - /jsonfile@6.1.0: - resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} - dependencies: - universalify: 2.0.0 - optionalDependencies: - graceful-fs: 4.2.11 - dev: false - - /jsonparse@1.3.1: - resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==} - engines: {'0': node >= 0.2.0} - dev: false - - /jsx-ast-utils@3.3.3: - resolution: {integrity: sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==} - engines: {node: '>=4.0'} - dependencies: - array-includes: 3.1.8 - object.assign: 4.1.5 - dev: true - - /keyv@4.5.2: - resolution: {integrity: sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g==} - dependencies: - json-buffer: 3.0.1 - dev: false - - /language-subtag-registry@0.3.22: - resolution: {integrity: sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==} - dev: true - - /language-tags@1.0.5: - resolution: {integrity: sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==} - dependencies: - language-subtag-registry: 0.3.22 - dev: true - - /leven@3.1.0: - resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} - engines: {node: '>=6'} - dev: false - - /levn@0.4.1: - resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} - engines: {node: '>= 0.8.0'} - dependencies: - prelude-ls: 1.2.1 - type-check: 0.4.0 - dev: true - - /lines-and-columns@1.2.4: - resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - dev: true - - /listenercount@1.0.1: - resolution: {integrity: sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ==} - dev: true - - /locate-path@6.0.0: - resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} - engines: {node: '>=10'} - dependencies: - p-locate: 5.0.0 - dev: true - - /lodash.debounce@4.0.8: - resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} - dev: true - - /lodash.merge@4.6.2: - resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - dev: true - - /lodash@4.17.21: - resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - dev: true - - /log4js@6.9.1: - resolution: {integrity: sha512-1somDdy9sChrr9/f4UlzhdaGfDR2c/SaD2a4T7qEkG4jTS57/B3qmnjLYePwQ8cqWnUHZI0iAKxMBpCZICiZ2g==} - engines: {node: '>=8.0'} - dependencies: - date-format: 4.0.14 - debug: 4.3.4 - flatted: 3.2.7 - rfdc: 1.3.0 - streamroller: 3.1.5 - transitivePeerDependencies: - - supports-color - dev: false - - /long@5.2.3: - resolution: {integrity: sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==} - - /lookpath@1.2.2: - resolution: {integrity: sha512-k2Gmn8iV6qdME3ztZC2spubmQISimFOPLuQKiPaLcVdRz0IpdxrNClVepMlyTJlhodm/zG/VfbkWERm3kUIh+Q==} - engines: {npm: '>=6.13.4'} - hasBin: true - dev: false - - /loose-envify@1.4.0: - resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} - hasBin: true - dependencies: - js-tokens: 4.0.0 - dev: true - - /lowercase-keys@2.0.0: - resolution: {integrity: sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==} - engines: {node: '>=8'} - dev: false - - /lru-cache@5.1.1: - resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} - dependencies: - yallist: 3.1.1 - dev: true - - /lru-cache@6.0.0: - resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} - engines: {node: '>=10'} - dependencies: - yallist: 4.0.0 - - /m3u8-parsed@1.3.0: - resolution: {integrity: sha512-bGIFjhSFrLJq9u6O/ooaIMMOTKZr92Z2bUgDWerN/C6h44MriXQxrvAGtKsT7OlJCp7sC/7+Hv0KruNYce85uw==} - dependencies: - m3u8-parser: 4.8.0 - dev: false - - /m3u8-parser@4.8.0: - resolution: {integrity: sha512-UqA2a/Pw3liR6Df3gwxrqghCP17OpPlQj6RBPLYygf/ZSQ4MoSgvdvhvt35qV+3NaaA0FSZx93Ix+2brT1U7cA==} - dependencies: - '@babel/runtime': 7.21.0 - '@videojs/vhs-utils': 3.0.5 - global: 4.4.0 - dev: false - - /make-error@1.3.6: - resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} - dev: true - - /media-typer@0.3.0: - resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} - engines: {node: '>= 0.6'} - dev: false - - /merge-descriptors@1.0.1: - resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==} - dev: false - - /merge2@1.4.1: - resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} - engines: {node: '>= 8'} - - /methods@1.1.2: - resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} - engines: {node: '>= 0.6'} - dev: false - - /micromatch@4.0.5: - resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} - engines: {node: '>=8.6'} - dependencies: - braces: 3.0.2 - picomatch: 2.3.1 - - /mime-db@1.52.0: - resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} - engines: {node: '>= 0.6'} - dev: false - - /mime-types@2.1.35: - resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} - engines: {node: '>= 0.6'} - dependencies: - mime-db: 1.52.0 - dev: false - - /mime@1.6.0: - resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} - engines: {node: '>=4'} - hasBin: true - dev: false - - /mimic-response@1.0.1: - resolution: {integrity: sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==} - engines: {node: '>=4'} - dev: false - - /mimic-response@3.1.0: - resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} - engines: {node: '>=10'} - dev: false - - /min-document@2.19.0: - resolution: {integrity: sha512-9Wy1B3m3f66bPPmU5hdA4DR4PB2OfDU/+GS3yAB7IQozE3tqXaVv2zOjgla7MEGSRv95+ILmOuvhLkOK6wJtCQ==} - dependencies: - dom-walk: 0.1.2 - dev: false - - /minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - dependencies: - brace-expansion: 1.1.11 - dev: true - - /minimatch@9.0.4: - resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==} - engines: {node: '>=16 || 14 >=14.17'} - dependencies: - brace-expansion: 2.0.1 - - /minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - - /mkdirp-classic@0.5.3: - resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} - dev: false - - /mkdirp@0.5.6: - resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} - hasBin: true - dependencies: - minimist: 1.2.8 - dev: true - - /mpd-parser@1.3.0: - resolution: {integrity: sha512-WgeIwxAqkmb9uTn4ClicXpEQYCEduDqRKfmUdp4X8vmghKfBNXZLYpREn9eqrDx/Tf5LhzRcJLSpi4ohfV742Q==} - hasBin: true - dependencies: - '@babel/runtime': 7.21.0 - '@videojs/vhs-utils': 4.0.0 - '@xmldom/xmldom': 0.8.10 - global: 4.4.0 - dev: false - - /ms@2.0.0: - resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} - dev: false - - /ms@2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - - /ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - - /multistream@4.1.0: - resolution: {integrity: sha512-J1XDiAmmNpRCBfIWJv+n0ymC4ABcf/Pl+5YvC5B/D2f/2+8PtHvCNxMPKiQcZyi922Hq69J2YOpb1pTywfifyw==} - dependencies: - once: 1.4.0 - readable-stream: 3.6.2 - dev: false - - /napi-build-utils@1.0.2: - resolution: {integrity: sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==} - dev: false - - /native-promise-only@0.8.1: - resolution: {integrity: sha512-zkVhZUA3y8mbz652WrL5x0fB0ehrBkulWT3TomAQ9iDtyXZvzKeEA6GPxAItBYeNYl5yngKRX612qHOhvMkDeg==} - dev: false - - /natural-compare-lite@1.4.0: - resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==} - dev: true - - /natural-compare@1.4.0: - resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - dev: true - - /negotiator@0.6.3: - resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} - engines: {node: '>= 0.6'} - dev: false - - /node-abi@3.54.0: - resolution: {integrity: sha512-p7eGEiQil0YUV3ItH4/tBb781L5impVmmx2E9FRKF7d18XXzp4PGT2tdYMFY6wQqgxD0IwNZOiSJ0/K0fSi/OA==} - engines: {node: '>=10'} - dependencies: - semver: 7.5.4 - dev: false - - /node-domexception@1.0.0: - resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} - engines: {node: '>=10.5.0'} - dev: true - - /node-fetch@2.7.0: - resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} - engines: {node: 4.x || >=6.0.0} - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true - dependencies: - whatwg-url: 5.0.0 - dev: false - - /node-fetch@3.3.2: - resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - data-uri-to-buffer: 4.0.1 - fetch-blob: 3.2.0 - formdata-polyfill: 4.0.10 - dev: true - - /node-releases@2.0.10: - resolution: {integrity: sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==} - dev: true - - /node-releases@2.0.13: - resolution: {integrity: sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==} - dev: true - - /normalize-url@6.1.0: - resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==} - engines: {node: '>=10'} - dev: false - - /object-assign@4.1.1: - resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} - engines: {node: '>=0.10.0'} - - /object-inspect@1.13.1: - resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} - - /object-is@1.1.5: - resolution: {integrity: sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - dev: true - - /object-keys@1.1.1: - resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} - engines: {node: '>= 0.4'} - dev: true - - /object.assign@4.1.5: - resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - has-symbols: 1.0.3 - object-keys: 1.1.1 - dev: true - - /object.entries@1.1.8: - resolution: {integrity: sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-object-atoms: 1.0.0 - dev: true - - /object.fromentries@2.0.8: - resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-object-atoms: 1.0.0 - dev: true - - /object.hasown@1.1.4: - resolution: {integrity: sha512-FZ9LZt9/RHzGySlBARE3VF+gE26TxR38SdmqOqliuTnl9wrKulaQs+4dee1V+Io8VfxqzAfHu6YuRgUy8OHoTg==} - engines: {node: '>= 0.4'} - dependencies: - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-object-atoms: 1.0.0 - dev: true - - /object.values@1.2.0: - resolution: {integrity: sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-object-atoms: 1.0.0 - dev: true - - /on-finished@2.4.1: - resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} - engines: {node: '>= 0.8'} - dependencies: - ee-first: 1.1.1 - dev: false - - /once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - dependencies: - wrappy: 1.0.2 - - /open@8.4.2: - resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} - engines: {node: '>=12'} - dependencies: - define-lazy-prop: 2.0.0 - is-docker: 2.2.1 - is-wsl: 2.2.0 - dev: false - - /optionator@0.9.3: - resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} - engines: {node: '>= 0.8.0'} - dependencies: - '@aashutoshrathi/word-wrap': 1.2.6 - deep-is: 0.1.4 - fast-levenshtein: 2.0.6 - levn: 0.4.1 - prelude-ls: 1.2.1 - type-check: 0.4.0 - dev: true - - /p-cancelable@2.1.1: - resolution: {integrity: sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==} - engines: {node: '>=8'} - dev: false - - /p-is-promise@3.0.0: - resolution: {integrity: sha512-Wo8VsW4IRQSKVXsJCn7TomUaVtyfjVDn3nUP7kE967BQk0CwFpdbZs0X0uk5sW9mkBa9eNM7hCMaG93WUAwxYQ==} - engines: {node: '>=8'} - dev: false - - /p-limit@3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} - dependencies: - yocto-queue: 0.1.0 - dev: true - - /p-locate@5.0.0: - resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} - engines: {node: '>=10'} - dependencies: - p-limit: 3.1.0 - dev: true - - /parent-module@1.0.1: - resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} - engines: {node: '>=6'} - dependencies: - callsites: 3.1.0 - dev: true - - /parse-json@5.2.0: - resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} - engines: {node: '>=8'} - dependencies: - '@babel/code-frame': 7.21.4 - error-ex: 1.3.2 - json-parse-even-better-errors: 2.3.1 - lines-and-columns: 1.2.4 - dev: true - - /parseurl@1.3.3: - resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} - engines: {node: '>= 0.8'} - dev: false - - /path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} - dev: true - - /path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - dev: true - - /path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - dev: true - - /path-parse@1.0.7: - resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - - /path-to-regexp@0.1.7: - resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} - dev: false - - /path-type@4.0.0: - resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} - engines: {node: '>=8'} - - /picocolors@1.0.0: - resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} - dev: true - - /picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - - /possible-typed-array-names@1.0.0: - resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} - engines: {node: '>= 0.4'} - dev: true - - /prebuild-install@7.1.1: - resolution: {integrity: sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==} - engines: {node: '>=10'} - hasBin: true - dependencies: - detect-libc: 2.0.2 - expand-template: 2.0.3 - github-from-package: 0.0.0 - minimist: 1.2.8 - mkdirp-classic: 0.5.3 - napi-build-utils: 1.0.2 - node-abi: 3.54.0 - pump: 3.0.0 - rc: 1.2.8 - simple-get: 4.0.1 - tar-fs: 2.1.1 - tunnel-agent: 0.6.0 - dev: false - - /prelude-ls@1.2.1: - resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} - engines: {node: '>= 0.8.0'} - dev: true - - /process-nextick-args@2.0.1: - resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} - - /process@0.11.10: - resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} - engines: {node: '>= 0.6.0'} - dev: false - - /progress@2.0.3: - resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} - engines: {node: '>=0.4.0'} - dev: false - - /prop-types@15.8.1: - resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} - dependencies: - loose-envify: 1.4.0 - object-assign: 4.1.1 - react-is: 16.13.1 - dev: true - - /protobufjs@7.3.2: - resolution: {integrity: sha512-RXyHaACeqXeqAKGLDl68rQKbmObRsTIn4TYVUUug1KfS47YWCo5MacGITEryugIgZqORCvJWEk4l449POg5Txg==} - engines: {node: '>=12.0.0'} - requiresBuild: true - dependencies: - '@protobufjs/aspromise': 1.1.2 - '@protobufjs/base64': 1.1.2 - '@protobufjs/codegen': 2.0.4 - '@protobufjs/eventemitter': 1.1.0 - '@protobufjs/fetch': 1.1.0 - '@protobufjs/float': 1.0.2 - '@protobufjs/inquire': 1.1.0 - '@protobufjs/path': 1.1.2 - '@protobufjs/pool': 1.1.0 - '@protobufjs/utf8': 1.1.0 - '@types/node': 20.14.6 - long: 5.2.3 - - /protoc@1.1.3: - resolution: {integrity: sha512-Vy4OBxCcF0W38YrZZRFix659gFu8ujIxVDP1SUBK9ELzyeMSBe8m8tYyYlX1PI5j9gse9hWu4c4nzQaHesAf8Q==} - hasBin: true - requiresBuild: true - dependencies: - glob: 7.2.3 - mkdirp: 0.5.6 - node-fetch: 3.3.2 - rimraf: 3.0.2 - unzipper: 0.10.14 - uuid: 9.0.1 - vinyl: 2.2.1 - dev: true - - /proxy-addr@2.0.7: - resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} - engines: {node: '>= 0.10'} - dependencies: - forwarded: 0.2.0 - ipaddr.js: 1.9.1 - dev: false - - /pump@3.0.0: - resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==} - dependencies: - end-of-stream: 1.4.4 - once: 1.4.0 - dev: false - - /punycode@2.3.0: - resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==} - engines: {node: '>=6'} - dev: true - - /qs@6.11.0: - resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==} - engines: {node: '>=0.6'} - dependencies: - side-channel: 1.0.6 - dev: false - - /queue-microtask@1.2.3: - resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - - /quick-lru@5.1.1: - resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} - engines: {node: '>=10'} - dev: false - - /range-parser@1.2.1: - resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} - engines: {node: '>= 0.6'} - dev: false - - /raw-body@2.5.2: - resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} - engines: {node: '>= 0.8'} - dependencies: - bytes: 3.1.2 - http-errors: 2.0.0 - iconv-lite: 0.4.24 - unpipe: 1.0.0 - dev: false - - /rc@1.2.8: - resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} - hasBin: true - dependencies: - deep-extend: 0.6.0 - ini: 1.3.8 - minimist: 1.2.8 - strip-json-comments: 2.0.1 - dev: false - - /react-is@16.13.1: - resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} - dev: true - - /readable-stream@2.3.8: - resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} - dependencies: - core-util-is: 1.0.3 - inherits: 2.0.4 - isarray: 1.0.0 - process-nextick-args: 2.0.1 - safe-buffer: 5.1.2 - string_decoder: 1.1.1 - util-deprecate: 1.0.2 - - /readable-stream@3.6.2: - resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} - engines: {node: '>= 6'} - dependencies: - inherits: 2.0.4 - string_decoder: 1.3.0 - util-deprecate: 1.0.2 - dev: false - - /reflect.getprototypeof@1.0.6: - resolution: {integrity: sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-errors: 1.3.0 - get-intrinsic: 1.2.4 - globalthis: 1.0.3 - which-builtin-type: 1.1.3 - dev: true - - /regenerate-unicode-properties@10.1.0: - resolution: {integrity: sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==} - engines: {node: '>=4'} - dependencies: - regenerate: 1.4.2 - dev: true - - /regenerate@1.4.2: - resolution: {integrity: sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==} - dev: true - - /regenerator-runtime@0.13.11: - resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==} - - /regenerator-transform@0.15.1: - resolution: {integrity: sha512-knzmNAcuyxV+gQCufkYcvOqX/qIIfHLv0u5x79kRxuGojfYVky1f15TzZEu2Avte8QGepvUNTnLskf8E6X6Vyg==} - dependencies: - '@babel/runtime': 7.21.0 - dev: true - - /regexp.prototype.flags@1.4.3: - resolution: {integrity: sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - functions-have-names: 1.2.3 - dev: true - - /regexp.prototype.flags@1.5.2: - resolution: {integrity: sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-errors: 1.3.0 - set-function-name: 2.0.2 - dev: true - - /regexpu-core@5.3.2: - resolution: {integrity: sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==} - engines: {node: '>=4'} - dependencies: - '@babel/regjsgen': 0.8.0 - regenerate: 1.4.2 - regenerate-unicode-properties: 10.1.0 - regjsparser: 0.9.1 - unicode-match-property-ecmascript: 2.0.0 - unicode-match-property-value-ecmascript: 2.1.0 - dev: true - - /regjsparser@0.9.1: - resolution: {integrity: sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==} - hasBin: true - dependencies: - jsesc: 0.5.0 - dev: true - - /remove-trailing-separator@1.1.0: - resolution: {integrity: sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==} - dev: true - - /removeNPMAbsolutePaths@3.0.1: - resolution: {integrity: sha512-rJc1aHu5LT4rncs7gga/asiyQG+G1TkweO7L27D/oMBtfbHmSFSp7RgUtrfuZzk9c/4P2xHjHnD+cUNzWRFB4A==} - engines: {node: '>=4.0.0'} - hasBin: true - dev: true - - /replace-ext@1.0.1: - resolution: {integrity: sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==} - engines: {node: '>= 0.10'} - dev: true - - /require-directory@2.1.1: - resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} - engines: {node: '>=0.10.0'} - dev: false - - /resolve-alpn@1.2.1: - resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==} - dev: false - - /resolve-from@4.0.0: - resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} - engines: {node: '>=4'} - dev: true - - /resolve@1.22.2: - resolution: {integrity: sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==} - hasBin: true - dependencies: - is-core-module: 2.13.1 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - - /resolve@2.0.0-next.5: - resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==} - hasBin: true - dependencies: - is-core-module: 2.13.1 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - dev: true - - /responselike@2.0.1: - resolution: {integrity: sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==} - dependencies: - lowercase-keys: 2.0.0 - dev: false - - /reusify@1.0.4: - resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} - engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - - /rfdc@1.3.0: - resolution: {integrity: sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==} - dev: false - - /rimraf@2.7.1: - resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==} - hasBin: true - dependencies: - glob: 7.2.3 - dev: true - - /rimraf@3.0.2: - resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} - hasBin: true - dependencies: - glob: 7.2.3 - dev: true - - /run-parallel@1.2.0: - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - dependencies: - queue-microtask: 1.2.3 - - /safe-array-concat@1.1.2: - resolution: {integrity: sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==} - engines: {node: '>=0.4'} - dependencies: - call-bind: 1.0.7 - get-intrinsic: 1.2.4 - has-symbols: 1.0.3 - isarray: 2.0.5 - dev: true - - /safe-buffer@5.1.2: - resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} - - /safe-buffer@5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - dev: false - - /safe-regex-test@1.0.3: - resolution: {integrity: sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - is-regex: 1.1.4 - dev: true - - /safer-buffer@2.1.2: - resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - dev: false - - /sei-helper@3.3.0: - resolution: {integrity: sha512-tHKNxiY5H5YayQ0QkxOvDZl35bH5OW2ptjk04j887hHA/pbj8ggsIKs7tb+wI7zViHOOY4JQorpQ8Jnj4LMitQ==} - dev: false - - /semver@6.3.1: - resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} - hasBin: true - dev: true - - /semver@7.5.4: - resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} - engines: {node: '>=10'} - hasBin: true - dependencies: - lru-cache: 6.0.0 - - /semver@7.6.2: - resolution: {integrity: sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==} - engines: {node: '>=10'} - hasBin: true - dev: true - - /send@0.18.0: - resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==} - engines: {node: '>= 0.8.0'} - dependencies: - debug: 2.6.9 - depd: 2.0.0 - destroy: 1.2.0 - encodeurl: 1.0.2 - escape-html: 1.0.3 - etag: 1.8.1 - fresh: 0.5.2 - http-errors: 2.0.0 - mime: 1.6.0 - ms: 2.1.3 - on-finished: 2.4.1 - range-parser: 1.2.1 - statuses: 2.0.1 - transitivePeerDependencies: - - supports-color - dev: false - - /serve-static@1.15.0: - resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==} - engines: {node: '>= 0.8.0'} - dependencies: - encodeurl: 1.0.2 - escape-html: 1.0.3 - parseurl: 1.3.3 - send: 0.18.0 - transitivePeerDependencies: - - supports-color - dev: false - - /set-function-length@1.2.2: - resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} - engines: {node: '>= 0.4'} - dependencies: - define-data-property: 1.1.4 - es-errors: 1.3.0 - function-bind: 1.1.2 - get-intrinsic: 1.2.4 - gopd: 1.0.1 - has-property-descriptors: 1.0.2 - - /set-function-name@2.0.2: - resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} - engines: {node: '>= 0.4'} - dependencies: - define-data-property: 1.1.4 - es-errors: 1.3.0 - functions-have-names: 1.2.3 - has-property-descriptors: 1.0.2 - dev: true - - /setimmediate@1.0.5: - resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} - dev: true - - /setprototypeof@1.2.0: - resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} - dev: false - - /shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} - dependencies: - shebang-regex: 3.0.0 - dev: true - - /shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} - dev: true - - /side-channel@1.0.6: - resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - get-intrinsic: 1.2.4 - object-inspect: 1.13.1 - - /simple-concat@1.0.1: - resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==} - dev: false - - /simple-get@4.0.1: - resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==} - dependencies: - decompress-response: 6.0.0 - once: 1.4.0 - simple-concat: 1.0.1 - dev: false - - /slash@3.0.0: - resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} - engines: {node: '>=8'} - - /statuses@2.0.1: - resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} - engines: {node: '>= 0.8'} - dev: false - - /stop-iteration-iterator@1.0.0: - resolution: {integrity: sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==} - engines: {node: '>= 0.4'} - dependencies: - internal-slot: 1.0.7 - dev: true - - /stream-meter@1.0.4: - resolution: {integrity: sha512-4sOEtrbgFotXwnEuzzsQBYEV1elAeFSO8rSGeTwabuX1RRn/kEq9JVH7I0MRBhKVRR0sJkr0M0QCH7yOLf9fhQ==} - dependencies: - readable-stream: 2.3.8 - dev: false - - /streamroller@3.1.5: - resolution: {integrity: sha512-KFxaM7XT+irxvdqSP1LGLgNWbYN7ay5owZ3r/8t77p+EtSUAfUgtl7be3xtqtOmGUl9K9YPO2ca8133RlTjvKw==} - engines: {node: '>=8.0'} - dependencies: - date-format: 4.0.14 - debug: 4.3.4 - fs-extra: 8.1.0 - transitivePeerDependencies: - - supports-color - dev: false - - /string-natural-compare@3.0.1: - resolution: {integrity: sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw==} - dev: true - - /string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} - dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 - dev: false - - /string.prototype.matchall@4.0.11: - resolution: {integrity: sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-errors: 1.3.0 - es-object-atoms: 1.0.0 - get-intrinsic: 1.2.4 - gopd: 1.0.1 - has-symbols: 1.0.3 - internal-slot: 1.0.7 - regexp.prototype.flags: 1.5.2 - set-function-name: 2.0.2 - side-channel: 1.0.6 - dev: true - - /string.prototype.trim@1.2.9: - resolution: {integrity: sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-abstract: 1.23.3 - es-object-atoms: 1.0.0 - dev: true - - /string.prototype.trimend@1.0.8: - resolution: {integrity: sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-object-atoms: 1.0.0 - dev: true - - /string.prototype.trimstart@1.0.8: - resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - define-properties: 1.2.1 - es-object-atoms: 1.0.0 - dev: true - - /string_decoder@1.1.1: - resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} - dependencies: - safe-buffer: 5.1.2 - - /string_decoder@1.3.0: - resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} - dependencies: - safe-buffer: 5.2.1 - dev: false - - /strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} - dependencies: - ansi-regex: 5.0.1 - - /strip-bom@3.0.0: - resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} - engines: {node: '>=4'} - dev: true - - /strip-json-comments@2.0.1: - resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} - engines: {node: '>=0.10.0'} - dev: false - - /strip-json-comments@3.1.1: - resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} - engines: {node: '>=8'} - dev: true - - /supports-color@5.5.0: - resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} - engines: {node: '>=4'} - dependencies: - has-flag: 3.0.0 - dev: true - - /supports-color@7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} - dependencies: - has-flag: 4.0.0 - - /supports-preserve-symlinks-flag@1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} - - /tar-fs@2.1.1: - resolution: {integrity: sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==} - dependencies: - chownr: 1.1.4 - mkdirp-classic: 0.5.3 - pump: 3.0.0 - tar-stream: 2.2.0 - dev: false - - /tar-stream@2.2.0: - resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} - engines: {node: '>=6'} - dependencies: - bl: 4.1.0 - end-of-stream: 1.4.4 - fs-constants: 1.0.0 - inherits: 2.0.4 - readable-stream: 3.6.2 - dev: false - - /text-table@0.2.0: - resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} - dev: true - - /through@2.3.8: - resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} - dev: false - - /to-fast-properties@2.0.0: - resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} - engines: {node: '>=4'} - - /to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} - dependencies: - is-number: 7.0.0 - - /toidentifier@1.0.1: - resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} - engines: {node: '>=0.6'} - dev: false - - /tr46@0.0.3: - resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - dev: false - - /traverse@0.3.9: - resolution: {integrity: sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ==} - dev: true - - /ts-api-utils@1.3.0(typescript@5.5.2): - resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} - engines: {node: '>=16'} - peerDependencies: - typescript: '>=4.2.0' - dependencies: - typescript: 5.5.2 - dev: true - - /ts-node@10.9.2(@types/node@20.14.6)(typescript@5.5.2): - resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} - hasBin: true - peerDependencies: - '@swc/core': '>=1.2.50' - '@swc/wasm': '>=1.2.50' - '@types/node': '*' - typescript: '>=2.7' - peerDependenciesMeta: - '@swc/core': - optional: true - '@swc/wasm': - optional: true - dependencies: - '@cspotcode/source-map-support': 0.8.1 - '@tsconfig/node10': 1.0.9 - '@tsconfig/node12': 1.0.11 - '@tsconfig/node14': 1.0.3 - '@tsconfig/node16': 1.0.3 - '@types/node': 20.14.6 - acorn: 8.10.0 - acorn-walk: 8.2.0 - arg: 4.1.3 - create-require: 1.1.1 - diff: 4.0.2 - make-error: 1.3.6 - typescript: 5.5.2 - v8-compile-cache-lib: 3.0.1 - yn: 3.1.1 - dev: true - - /ts-poet@6.7.0: - resolution: {integrity: sha512-A0wvFtpkTCWPw7ftTIwbEH+L+7ul4CU0x3jXKQ+kCnmEQIAOwhpUaBmcAYKxZCxHae9/MUl4LbyTqw25BpzW5Q==} - dependencies: - dprint-node: 1.0.8 - dev: true - - /ts-proto-descriptors@1.16.0: - resolution: {integrity: sha512-3yKuzMLpltdpcyQji1PJZRfoo4OJjNieKTYkQY8pF7xGKsYz/RHe3aEe4KiRxcinoBmnEhmuI+yJTxLb922ULA==} - dependencies: - long: 5.2.3 - protobufjs: 7.3.2 - dev: true - - /ts-proto@1.180.0: - resolution: {integrity: sha512-Gx+y1ohKNitnBpoA4ELRPl2nHBa4zUkedj3kHKuwYn0THpLiLVLuzYidlqJVZBDooI+l/EROGGqlCt95FItI9g==} - hasBin: true - dependencies: - case-anything: 2.1.13 - protobufjs: 7.3.2 - ts-poet: 6.7.0 - ts-proto-descriptors: 1.16.0 - dev: true - - /tsconfig-paths@3.14.2: - resolution: {integrity: sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==} - dependencies: - '@types/json5': 0.0.29 - json5: 1.0.2 - minimist: 1.2.8 - strip-bom: 3.0.0 - dev: true - - /tslib@1.14.1: - resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} - dev: true - - /tsutils@3.21.0(typescript@5.5.2): - resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} - engines: {node: '>= 6'} - peerDependencies: - typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' - dependencies: - tslib: 1.14.1 - typescript: 5.5.2 - dev: true - - /tunnel-agent@0.6.0: - resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} - dependencies: - safe-buffer: 5.2.1 - dev: false - - /type-check@0.4.0: - resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} - engines: {node: '>= 0.8.0'} - dependencies: - prelude-ls: 1.2.1 - dev: true - - /type-fest@0.20.2: - resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} - engines: {node: '>=10'} - dev: true - - /type-is@1.6.18: - resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} - engines: {node: '>= 0.6'} - dependencies: - media-typer: 0.3.0 - mime-types: 2.1.35 - dev: false - - /typed-array-buffer@1.0.2: - resolution: {integrity: sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - is-typed-array: 1.1.13 - dev: true - - /typed-array-byte-length@1.0.1: - resolution: {integrity: sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - for-each: 0.3.3 - gopd: 1.0.1 - has-proto: 1.0.3 - is-typed-array: 1.1.13 - dev: true - - /typed-array-byte-offset@1.0.2: - resolution: {integrity: sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==} - engines: {node: '>= 0.4'} - dependencies: - available-typed-arrays: 1.0.7 - call-bind: 1.0.7 - for-each: 0.3.3 - gopd: 1.0.1 - has-proto: 1.0.3 - is-typed-array: 1.1.13 - dev: true - - /typed-array-length@1.0.6: - resolution: {integrity: sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - for-each: 0.3.3 - gopd: 1.0.1 - has-proto: 1.0.3 - is-typed-array: 1.1.13 - possible-typed-array-names: 1.0.0 - dev: true - - /typescript-eslint@7.13.1(eslint@8.57.0)(typescript@5.5.2): - resolution: {integrity: sha512-pvLEuRs8iS9s3Cnp/Wt//hpK8nKc8hVa3cLljHqzaJJQYP8oys8GUyIFqtlev+2lT/fqMPcyQko+HJ6iYK3nFA==} - engines: {node: ^18.18.0 || >=20.0.0} - peerDependencies: - eslint: ^8.56.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/eslint-plugin': 7.13.1(@typescript-eslint/parser@7.13.1)(eslint@8.57.0)(typescript@5.5.2) - '@typescript-eslint/parser': 7.13.1(eslint@8.57.0)(typescript@5.5.2) - '@typescript-eslint/utils': 7.13.1(eslint@8.57.0)(typescript@5.5.2) - eslint: 8.57.0 - typescript: 5.5.2 - transitivePeerDependencies: - - supports-color - dev: true - - /typescript@5.5.2: - resolution: {integrity: sha512-NcRtPEOsPFFWjobJEtfihkLCZCXZt/os3zf8nTxjVH3RvTSxjrCamJpbExGvYOF+tFHc3pA65qpdwPbzjohhew==} - engines: {node: '>=14.17'} - hasBin: true - dev: true - - /unbox-primitive@1.0.2: - resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} - dependencies: - call-bind: 1.0.7 - has-bigints: 1.0.2 - has-symbols: 1.0.3 - which-boxed-primitive: 1.0.2 - dev: true - - /undici-types@5.26.5: - resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} - - /unicode-canonical-property-names-ecmascript@2.0.0: - resolution: {integrity: sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==} - engines: {node: '>=4'} - dev: true - - /unicode-match-property-ecmascript@2.0.0: - resolution: {integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==} - engines: {node: '>=4'} - dependencies: - unicode-canonical-property-names-ecmascript: 2.0.0 - unicode-property-aliases-ecmascript: 2.1.0 - dev: true - - /unicode-match-property-value-ecmascript@2.1.0: - resolution: {integrity: sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==} - engines: {node: '>=4'} - dev: true - - /unicode-property-aliases-ecmascript@2.1.0: - resolution: {integrity: sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==} - engines: {node: '>=4'} - dev: true - - /universalify@0.1.2: - resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} - engines: {node: '>= 4.0.0'} - dev: false - - /universalify@2.0.0: - resolution: {integrity: sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==} - engines: {node: '>= 10.0.0'} - dev: false - - /unpipe@1.0.0: - resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} - engines: {node: '>= 0.8'} - dev: false - - /unzipper@0.10.14: - resolution: {integrity: sha512-ti4wZj+0bQTiX2KmKWuwj7lhV+2n//uXEotUmGuQqrbVZSEGFMbI68+c6JCQ8aAmUWYvtHEz2A8K6wXvueR/6g==} - dependencies: - big-integer: 1.6.52 - binary: 0.3.0 - bluebird: 3.4.7 - buffer-indexof-polyfill: 1.0.2 - duplexer2: 0.1.4 - fstream: 1.0.12 - graceful-fs: 4.2.11 - listenercount: 1.0.1 - readable-stream: 2.3.8 - setimmediate: 1.0.5 - dev: true - - /update-browserslist-db@1.0.10(browserslist@4.21.5): - resolution: {integrity: sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==} - hasBin: true - peerDependencies: - browserslist: '>= 4.21.0' - dependencies: - browserslist: 4.21.5 - escalade: 3.1.1 - picocolors: 1.0.0 - dev: true - - /update-browserslist-db@1.0.11(browserslist@4.21.9): - resolution: {integrity: sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==} - hasBin: true - peerDependencies: - browserslist: '>= 4.21.0' - dependencies: - browserslist: 4.21.9 - escalade: 3.1.1 - picocolors: 1.0.0 - dev: true - - /uri-js@4.4.1: - resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - dependencies: - punycode: 2.3.0 - dev: true - - /url-toolkit@2.2.5: - resolution: {integrity: sha512-mtN6xk+Nac+oyJ/PrI7tzfmomRVNFIWKUbG8jdYFt52hxbiReFAXIjYskvu64/dvuW71IcB7lV8l0HvZMac6Jg==} - dev: false - - /util-deprecate@1.0.2: - resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - - /utils-merge@1.0.1: - resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} - engines: {node: '>= 0.4.0'} - dev: false - - /uuid@9.0.1: - resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} - hasBin: true - dev: true - - /v8-compile-cache-lib@3.0.1: - resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} - dev: true - - /vary@1.1.2: - resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} - engines: {node: '>= 0.8'} - dev: false - - /vinyl@2.2.1: - resolution: {integrity: sha512-LII3bXRFBZLlezoG5FfZVcXflZgWP/4dCwKtxd5ky9+LOtM4CS3bIRQsmR1KMnMW07jpE8fqR2lcxPZ+8sJIcw==} - engines: {node: '>= 0.10'} - dependencies: - clone: 2.1.2 - clone-buffer: 1.0.0 - clone-stats: 1.0.0 - cloneable-readable: 1.1.3 - remove-trailing-separator: 1.1.0 - replace-ext: 1.0.1 - dev: true - - /web-streams-polyfill@3.3.3: - resolution: {integrity: sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==} - engines: {node: '>= 8'} - dev: true - - /webidl-conversions@3.0.1: - resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} - dev: false - - /whatwg-url@5.0.0: - resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} - dependencies: - tr46: 0.0.3 - webidl-conversions: 3.0.1 - dev: false - - /which-boxed-primitive@1.0.2: - resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} - dependencies: - is-bigint: 1.0.4 - is-boolean-object: 1.1.2 - is-number-object: 1.0.7 - is-string: 1.0.7 - is-symbol: 1.0.4 - dev: true - - /which-builtin-type@1.1.3: - resolution: {integrity: sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==} - engines: {node: '>= 0.4'} - dependencies: - function.prototype.name: 1.1.6 - has-tostringtag: 1.0.2 - is-async-function: 2.0.0 - is-date-object: 1.0.5 - is-finalizationregistry: 1.0.2 - is-generator-function: 1.0.10 - is-regex: 1.1.4 - is-weakref: 1.0.2 - isarray: 2.0.5 - which-boxed-primitive: 1.0.2 - which-collection: 1.0.1 - which-typed-array: 1.1.15 - dev: true - - /which-collection@1.0.1: - resolution: {integrity: sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==} - dependencies: - is-map: 2.0.2 - is-set: 2.0.2 - is-weakmap: 2.0.1 - is-weakset: 2.0.2 - dev: true - - /which-typed-array@1.1.15: - resolution: {integrity: sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==} - engines: {node: '>= 0.4'} - dependencies: - available-typed-arrays: 1.0.7 - call-bind: 1.0.7 - for-each: 0.3.3 - gopd: 1.0.1 - has-tostringtag: 1.0.2 - dev: true - - /which-typed-array@1.1.9: - resolution: {integrity: sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==} - engines: {node: '>= 0.4'} - dependencies: - available-typed-arrays: 1.0.5 - call-bind: 1.0.7 - for-each: 0.3.3 - gopd: 1.0.1 - has-tostringtag: 1.0.0 - is-typed-array: 1.1.10 - dev: true - - /which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true - dependencies: - isexe: 2.0.0 - dev: true - - /wrap-ansi@7.0.0: - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} - engines: {node: '>=10'} - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - dev: false - - /wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - - /ws@8.17.1: - resolution: {integrity: sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: '>=5.0.2' - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - dev: false - - /y18n@5.0.8: - resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} - engines: {node: '>=10'} - dev: false - - /yallist@3.1.1: - resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - dev: true - - /yallist@4.0.0: - resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - - /yaml@1.10.2: - resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} - engines: {node: '>= 6'} - dev: true - - /yaml@2.4.5: - resolution: {integrity: sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==} - engines: {node: '>= 14'} - hasBin: true - dev: false - - /yargs-parser@20.2.9: - resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} - engines: {node: '>=10'} - dev: false - - /yargs-parser@21.1.1: - resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} - engines: {node: '>=12'} - dev: false - - /yargs@16.2.0: - resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} - engines: {node: '>=10'} - dependencies: - cliui: 7.0.4 - escalade: 3.1.1 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - string-width: 4.2.3 - y18n: 5.0.8 - yargs-parser: 20.2.9 - dev: false - - /yargs@17.7.2: - resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} - engines: {node: '>=12'} - dependencies: - cliui: 8.0.1 - escalade: 3.1.1 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - string-width: 4.2.3 - y18n: 5.0.8 - yargs-parser: 21.1.1 - dev: false - - /yn@3.1.1: - resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} - engines: {node: '>=6'} - dev: true - - /yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} - dev: true diff --git a/tsc.ts b/tsc.ts deleted file mode 100644 index 3c1ee1a..0000000 --- a/tsc.ts +++ /dev/null @@ -1,164 +0,0 @@ -import { ChildProcess, exec } from 'child_process'; -import fs from 'fs-extra'; -import path from 'path'; -import { removeSync, copyFileSync } from 'fs-extra'; - -const argv = process.argv.slice(2); -let buildIgnore: string[] = []; - -const isTest = argv.length > 0 && argv[0] === 'test'; -const isGUI = !(argv.length > 1 && argv[1] === 'false'); - -if (!isTest) - buildIgnore = [ - '*/\\.env', - './config/setup.json' - ]; - -if (!isGUI) - buildIgnore = buildIgnore.concat([ - './gui*', - './build*', - 'gui.ts' - ]); - - -const ignore = [ - ...buildIgnore, - '*/\\.git*', - './lib*', - '*/@types*', - './out*', - './bin/mkvtoolnix*', - './config/token.yml$', - './config/updates.json$', - './config/*_token.yml$', - './config/*_sess.yml$', - './config/*_profile.yml$', - '*/\\.eslint*', - '*/*\\.tsx?$', - './fonts*', - './gui/react*', - './dev.js$', - '*/node_modules/*', - './widevine/*', - './videos/*', - './logs/*', -].map(a => a.replace(/\*/g, '[^]*').replace(/\.\//g, escapeRegExp(__dirname) + '/').replace(/\//g, path.sep === '\\' ? '\\\\' : '/')).map(a => new RegExp(a, 'i')); - -export { ignore }; - -(async () => { - - const waitForProcess = async (proc: ChildProcess) => { - return new Promise((resolve, reject) => { - proc.stdout?.on('data', console.log); - proc.stderr?.on('data', console.error); - proc.on('close', resolve); - proc.on('error', reject); - }); - }; - - process.stdout.write('Removing lib dir... '); - removeSync('lib'); - process.stdout.write('✓\nRunning tsc... '); - const tsc = exec('npx tsc'); - - await waitForProcess(tsc); - - if (!isGUI) { - fs.emptyDirSync(path.join('lib', 'gui')); - fs.rmdirSync(path.join('lib', 'gui')); - } - - if (!isTest && isGUI) { - process.stdout.write('✓\nBuilding react... '); - - const installReactDependencies = exec('pnpm install', { - cwd: path.join(__dirname, 'gui', 'react'), - }); - - await waitForProcess(installReactDependencies); - - const react = exec('pnpm run build', { - cwd: path.join(__dirname, 'gui', 'react'), - env: { - ...process.env, - CI: 'false' - } - }); - - await waitForProcess(react); - } - - process.stdout.write('✓\nCopying files... '); - if (!isTest && isGUI) { - copyDir(path.join(__dirname, 'gui', 'react', 'build'), path.join(__dirname, 'lib', 'gui', 'server', 'build')); - } - - const files = readDir(__dirname); - files.forEach(item => { - const itemPath = path.join(__dirname, 'lib', item.path.replace(__dirname, '')); - if (item.stats.isDirectory()) { - if (!fs.existsSync(itemPath)) - fs.mkdirSync(itemPath); - } else { - copyFileSync(item.path, itemPath); - } - }); - - process.stdout.write('✓\nInstalling dependencies... '); - if (!isTest) { - const dependencies = exec(`pnpm install ${isGUI ? '' : '-P'}`, { - cwd: path.join(__dirname, 'lib') - }); - await waitForProcess(dependencies); - } - - process.stdout.write('✓\n'); -})(); - -function readDir (dir: string): { - path: string, - stats: fs.Stats -}[] { - const items: { - path: string, - stats: fs.Stats - }[] = []; - const content = fs.readdirSync(dir); - itemLoop: for (const item of content) { - const itemPath = path.join(dir, item); - for (const ignoreItem of ignore) { - if (ignoreItem.test(itemPath)) - continue itemLoop; - } - const stats = fs.statSync(itemPath); - items.push({ - path: itemPath, - stats - }); - if (stats.isDirectory()) { - items.push(...readDir(itemPath)); - } - } - return items; -} - -async function copyDir(src: string, dest: string) { - await fs.promises.mkdir(dest, { recursive: true }); - const entries = await fs.promises.readdir(src, { withFileTypes: true }); - - for (const entry of entries) { - const srcPath = path.join(src, entry.name); - const destPath = path.join(dest, entry.name); - - entry.isDirectory() ? - await copyDir(srcPath, destPath) : - await fs.promises.copyFile(srcPath, destPath); - } -} - -function escapeRegExp(string: string): string { - return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string -} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json deleted file mode 100644 index 1625e86..0000000 --- a/tsconfig.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "compilerOptions": { - "target": "ES6", - "module": "commonjs", - "outDir": "./lib", - "strict": true, - "esModuleInterop": true, - "resolveJsonModule": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "downlevelIteration": true, - "jsx": "react" - }, - "exclude": [ - "./videos", - "./tsc.ts", - "lib/**/*", - "gui/react/**/*" - ] -} \ No newline at end of file diff --git a/videos/.gitkeep b/videos/.gitkeep deleted file mode 100644 index 8b13789..0000000 --- a/videos/.gitkeep +++ /dev/null @@ -1 +0,0 @@ - diff --git a/videos/_trash/.gitkeep b/videos/_trash/.gitkeep new file mode 100644 index 0000000..e69de29