From d9b49bd6bcddad793280b3492342ae4fc72f5cb0 Mon Sep 17 00:00:00 2001 From: sim0n00ps Date: Sat, 3 May 2025 00:17:19 +0100 Subject: [PATCH] Add project files. --- .editorconfig | 9 + .gitattributes | 63 + .github/workflows/publish-docker.yml | 43 + .github/workflows/publish-docs.yml | 66 + .github/workflows/publish-release.yml | 64 + .gitignore | 367 + Dockerfile | 66 + OF DL.sln | 25 + OF DL/CDMApi.cs | 28 + OF DL/Crypto/CryptoUtils.cs | 33 + OF DL/Crypto/Padding.cs | 121 + OF DL/Entities/Archived/Archived.cs | 275 + OF DL/Entities/Archived/ArchivedCollection.cs | 15 + OF DL/Entities/Auth.cs | 19 + OF DL/Entities/CDRMProjectRequest.cs | 27 + OF DL/Entities/Config.cs | 110 + OF DL/Entities/DynamicRules.cs | 28 + OF DL/Entities/FileNameFormatConfig.cs | 11 + OF DL/Entities/Highlights/HighlightMedia.cs | 108 + OF DL/Entities/Highlights/Highlights.cs | 24 + OF DL/Entities/IDownloadConfig.cs | 54 + OF DL/Entities/IFileNameFormatConfig.cs | 11 + OF DL/Entities/Lists/UserList.cs | 41 + OF DL/Entities/Lists/UsersList.cs | 171 + OF DL/Entities/Messages/MessageCollection.cs | 15 + OF DL/Entities/Messages/Messages.cs | 184 + OF DL/Entities/Messages/SingleMessage.cs | 119 + OF DL/Entities/OFDLRequest.cs | 21 + OF DL/Entities/Post/Post.cs | 213 + OF DL/Entities/Post/PostCollection.cs | 15 + OF DL/Entities/Post/SinglePost.cs | 197 + OF DL/Entities/Post/SinglePostCollection.cs | 15 + .../Purchased/PaidMessageCollection.cs | 16 + .../Entities/Purchased/PaidPostCollection.cs | 11 + OF DL/Entities/Purchased/Purchased.cs | 90 + .../Purchased/PurchasedTabCollection.cs | 16 + .../Purchased/SinglePaidMessageCollection.cs | 18 + OF DL/Entities/ShortDateConverter.cs | 13 + OF DL/Entities/Stories/Stories.cs | 96 + OF DL/Entities/Streams/Streams.cs | 216 + OF DL/Entities/Streams/StreamsCollection.cs | 15 + OF DL/Entities/Subscriptions.cs | 165 + OF DL/Entities/ToggleableConfigAttribute.cs | 8 + OF DL/Entities/User.cs | 191 + OF DL/Enumerations/CustomFileNameOption.cs | 13 + OF DL/Enumerations/DownloadDateSelection.cs | 14 + OF DL/Enumerations/LoggingLevel.cs | 36 + OF DL/Enumerations/MediaType.cs | 19 + OF DL/Helpers/APIHelper.cs | 2839 +++ OF DL/Helpers/AuthHelper.cs | 166 + OF DL/Helpers/Constants.cs | 6 + OF DL/Helpers/DBHelper.cs | 531 + OF DL/Helpers/DownloadContext.cs | 36 + OF DL/Helpers/DownloadHelper.cs | 1790 ++ OF DL/Helpers/FileNameHelper.cs | 188 + OF DL/Helpers/Interfaces/IAPIHelper.cs | 38 + OF DL/Helpers/Interfaces/IDBHelper.cs | 17 + OF DL/Helpers/Interfaces/IDownloadHelper.cs | 36 + OF DL/Helpers/Interfaces/IFileNameHelper.cs | 8 + OF DL/HttpUtil.cs | 99 + OF DL/Icon/download.ico | Bin 0 -> 1150 bytes OF DL/OF DL.csproj | 50 + OF DL/Program.cs | 3233 ++++ OF DL/References/Spectre.Console.deps.json | 112 + OF DL/References/Spectre.Console.dll | Bin 0 -> 694272 bytes OF DL/Utils.cs | 189 + OF DL/Utils/ThrottledStream.cs | 159 + OF DL/Utils/XmlUtils.cs | 25 + OF DL/Widevine/CDM.cs | 581 + OF DL/Widevine/CDMDevice.cs | 93 + OF DL/Widevine/Constants.cs | 9 + OF DL/Widevine/ContentKey.cs | 42 + OF DL/Widevine/DerivedKeys.cs | 9 + OF DL/Widevine/PSSHBox.cs | 63 + OF DL/Widevine/Session.cs | 27 + OF DL/Widevine/WvProto2.cs | 2257 +++ OF DL/rules.json | 8 + README.md | 39 + docker/entrypoint.sh | 25 + docker/supervisord.conf | 25 + docs/.gitignore | 20 + docs/.nvmrc | 1 + docs/README.md | 41 + docs/babel.config.js | 3 + docs/docs/config/_category_.json | 8 + docs/docs/config/auth.md | 78 + docs/docs/config/cdm.md | 32 + docs/docs/config/configuration.md | 516 + docs/docs/config/custom-filename-formats.md | 94 + docs/docs/installation/_category_.json | 8 + docs/docs/installation/docker.md | 48 + docs/docs/installation/linux.md | 48 + docs/docs/installation/macos.md | 9 + docs/docs/installation/windows.md | 26 + docs/docs/running-the-program.md | 54 + docs/docusaurus.config.js | 123 + docs/package-lock.json | 15550 ++++++++++++++++ docs/package.json | 44 + docs/sidebars.js | 33 + docs/src/pages/index.js | 39 + docs/src/pages/index.module.css | 23 + docs/static/.nojekyll | 0 docs/static/img/cli_menu.png | Bin 0 -> 22758 bytes docs/static/img/logo.png | Bin 0 -> 769 bytes docs/static/img/network_tab.png | Bin 0 -> 18685 bytes docs/static/img/request_headers.png | Bin 0 -> 60208 bytes docs/static/img/welcome_banner.png | Bin 0 -> 1740 bytes 107 files changed, 32993 insertions(+) create mode 100644 .editorconfig create mode 100644 .gitattributes create mode 100644 .github/workflows/publish-docker.yml create mode 100644 .github/workflows/publish-docs.yml create mode 100644 .github/workflows/publish-release.yml create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 OF DL.sln create mode 100644 OF DL/CDMApi.cs create mode 100644 OF DL/Crypto/CryptoUtils.cs create mode 100644 OF DL/Crypto/Padding.cs create mode 100644 OF DL/Entities/Archived/Archived.cs create mode 100644 OF DL/Entities/Archived/ArchivedCollection.cs create mode 100644 OF DL/Entities/Auth.cs create mode 100644 OF DL/Entities/CDRMProjectRequest.cs create mode 100644 OF DL/Entities/Config.cs create mode 100644 OF DL/Entities/DynamicRules.cs create mode 100644 OF DL/Entities/FileNameFormatConfig.cs create mode 100644 OF DL/Entities/Highlights/HighlightMedia.cs create mode 100644 OF DL/Entities/Highlights/Highlights.cs create mode 100644 OF DL/Entities/IDownloadConfig.cs create mode 100644 OF DL/Entities/IFileNameFormatConfig.cs create mode 100644 OF DL/Entities/Lists/UserList.cs create mode 100644 OF DL/Entities/Lists/UsersList.cs create mode 100644 OF DL/Entities/Messages/MessageCollection.cs create mode 100644 OF DL/Entities/Messages/Messages.cs create mode 100644 OF DL/Entities/Messages/SingleMessage.cs create mode 100644 OF DL/Entities/OFDLRequest.cs create mode 100644 OF DL/Entities/Post/Post.cs create mode 100644 OF DL/Entities/Post/PostCollection.cs create mode 100644 OF DL/Entities/Post/SinglePost.cs create mode 100644 OF DL/Entities/Post/SinglePostCollection.cs create mode 100644 OF DL/Entities/Purchased/PaidMessageCollection.cs create mode 100644 OF DL/Entities/Purchased/PaidPostCollection.cs create mode 100644 OF DL/Entities/Purchased/Purchased.cs create mode 100644 OF DL/Entities/Purchased/PurchasedTabCollection.cs create mode 100644 OF DL/Entities/Purchased/SinglePaidMessageCollection.cs create mode 100644 OF DL/Entities/ShortDateConverter.cs create mode 100644 OF DL/Entities/Stories/Stories.cs create mode 100644 OF DL/Entities/Streams/Streams.cs create mode 100644 OF DL/Entities/Streams/StreamsCollection.cs create mode 100644 OF DL/Entities/Subscriptions.cs create mode 100644 OF DL/Entities/ToggleableConfigAttribute.cs create mode 100644 OF DL/Entities/User.cs create mode 100644 OF DL/Enumerations/CustomFileNameOption.cs create mode 100644 OF DL/Enumerations/DownloadDateSelection.cs create mode 100644 OF DL/Enumerations/LoggingLevel.cs create mode 100644 OF DL/Enumerations/MediaType.cs create mode 100644 OF DL/Helpers/APIHelper.cs create mode 100644 OF DL/Helpers/AuthHelper.cs create mode 100644 OF DL/Helpers/Constants.cs create mode 100644 OF DL/Helpers/DBHelper.cs create mode 100644 OF DL/Helpers/DownloadContext.cs create mode 100644 OF DL/Helpers/DownloadHelper.cs create mode 100644 OF DL/Helpers/FileNameHelper.cs create mode 100644 OF DL/Helpers/Interfaces/IAPIHelper.cs create mode 100644 OF DL/Helpers/Interfaces/IDBHelper.cs create mode 100644 OF DL/Helpers/Interfaces/IDownloadHelper.cs create mode 100644 OF DL/Helpers/Interfaces/IFileNameHelper.cs create mode 100644 OF DL/HttpUtil.cs create mode 100644 OF DL/Icon/download.ico create mode 100644 OF DL/OF DL.csproj create mode 100644 OF DL/Program.cs create mode 100644 OF DL/References/Spectre.Console.deps.json create mode 100644 OF DL/References/Spectre.Console.dll create mode 100644 OF DL/Utils.cs create mode 100644 OF DL/Utils/ThrottledStream.cs create mode 100644 OF DL/Utils/XmlUtils.cs create mode 100644 OF DL/Widevine/CDM.cs create mode 100644 OF DL/Widevine/CDMDevice.cs create mode 100644 OF DL/Widevine/Constants.cs create mode 100644 OF DL/Widevine/ContentKey.cs create mode 100644 OF DL/Widevine/DerivedKeys.cs create mode 100644 OF DL/Widevine/PSSHBox.cs create mode 100644 OF DL/Widevine/Session.cs create mode 100644 OF DL/Widevine/WvProto2.cs create mode 100644 OF DL/rules.json create mode 100644 README.md create mode 100644 docker/entrypoint.sh create mode 100644 docker/supervisord.conf create mode 100644 docs/.gitignore create mode 100644 docs/.nvmrc create mode 100644 docs/README.md create mode 100644 docs/babel.config.js create mode 100644 docs/docs/config/_category_.json create mode 100644 docs/docs/config/auth.md create mode 100644 docs/docs/config/cdm.md create mode 100644 docs/docs/config/configuration.md create mode 100644 docs/docs/config/custom-filename-formats.md create mode 100644 docs/docs/installation/_category_.json create mode 100644 docs/docs/installation/docker.md create mode 100644 docs/docs/installation/linux.md create mode 100644 docs/docs/installation/macos.md create mode 100644 docs/docs/installation/windows.md create mode 100644 docs/docs/running-the-program.md create mode 100644 docs/docusaurus.config.js create mode 100644 docs/package-lock.json create mode 100644 docs/package.json create mode 100644 docs/sidebars.js create mode 100644 docs/src/pages/index.js create mode 100644 docs/src/pages/index.module.css create mode 100644 docs/static/.nojekyll create mode 100644 docs/static/img/cli_menu.png create mode 100644 docs/static/img/logo.png create mode 100644 docs/static/img/network_tab.png create mode 100644 docs/static/img/request_headers.png create mode 100644 docs/static/img/welcome_banner.png diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..b3672fd --- /dev/null +++ b/.editorconfig @@ -0,0 +1,9 @@ +# Editor configuration, see https://editorconfig.org +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 4 +insert_final_newline = true +trim_trailing_whitespace = true diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1ff0c42 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/.github/workflows/publish-docker.yml b/.github/workflows/publish-docker.yml new file mode 100644 index 0000000..15a01f9 --- /dev/null +++ b/.github/workflows/publish-docker.yml @@ -0,0 +1,43 @@ +name: Publish Docker image + +on: + push: + tags: + - 'OFDLV*' + +jobs: + push_to_registry: + name: Push docker image to registry + runs-on: ubuntu-latest + steps: + - name: Extract version + id: version + run: | + VERSION="${GITHUB_REF_NAME#OFDLV}" + echo "Version: $VERSION" + echo "version=$VERSION" >> "$GITHUB_OUTPUT" + + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to ghcr + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and push Docker image + uses: docker/build-push-action@v6 + with: + context: . + platforms: linux/amd64,linux/arm64 + push: true + tags: | + ghcr.io/${{ github.actor }}/of-dl:latest + ghcr.io/${{ github.actor }}/of-dl:${{ steps.version.outputs.version }} + build-args: | + VERSION=${{ steps.version.outputs.version }} diff --git a/.github/workflows/publish-docs.yml b/.github/workflows/publish-docs.yml new file mode 100644 index 0000000..1cf2bc3 --- /dev/null +++ b/.github/workflows/publish-docs.yml @@ -0,0 +1,66 @@ +name: Publish docs + +on: + workflow_dispatch: + push: + tags: + - 'OFDLV*' + paths: + - 'docs/**' + - '.github/workflows/publish-docs.yml' + +# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages +permissions: + contents: read + pages: write + id-token: write + +# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. +# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. +concurrency: + group: "pages" + cancel-in-progress: false + +jobs: + # Build job + build: + runs-on: ubuntu-latest + defaults: + run: + working-directory: ./docs + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Pages + uses: actions/configure-pages@v5 + + - name: Setup node + uses: actions/setup-node@v4 + with: + node-version-file: './docs/.nvmrc' + + - name: Install dependencies + run: npm ci + + - name: Build with docusaurus + run: npm run build + + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 + with: + path: './docs/build' + + # Deployment job + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + needs: build + + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml new file mode 100644 index 0000000..c18d680 --- /dev/null +++ b/.github/workflows/publish-release.yml @@ -0,0 +1,64 @@ +name: Publish release zip + +on: + push: + tags: + - 'OFDLV*' + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Setup dotnet 8.x + uses: actions/setup-dotnet@v3 + with: + dotnet-version: 8.x + + - name: Display dotnet version + run: dotnet --version + + - name: Extract version + id: version + run: | + VERSION="${GITHUB_REF_NAME#OFDLV}" + echo "Version: $VERSION" + echo "version=$VERSION" >> "$GITHUB_OUTPUT" + + - name: Run build + run: | + dotnet publish -p:Version=${{ steps.version.outputs.version }} -p:WarningLevel=0 -c Release -r win-x86 --self-contained true -p:PublishSingleFile=true -o outwin + dotnet publish -p:Version=${{ steps.version.outputs.version }} -p:WarningLevel=0 -c Release -r linux-x64 --self-contained true -p:PublishSingleFile=true -o outlin + cp ./OF\ DL/rules.json outwin/ + chmod +x ./outlin/OF\ DL + cd outwin + ../outlin/OF\ DL --non-interactive || true + mkdir -p cdm/devices/chrome_1610 + wget https://www.gyan.dev/ffmpeg/builds/ffmpeg-release-essentials.zip + unzip ffmpeg-release-essentials.zip ffmpeg\*/bin/ffmpeg.exe ffmpeg\*/LICENSE + mv ffmpeg*/bin/ffmpeg.exe . + mv ffmpeg*/LICENSE LICENSE.ffmpeg + zip ../OFDLV${{ steps.version.outputs.version }}.zip OF\ DL.exe e_sqlite3.dll rules.json config.conf cdm ffmpeg.exe LICENSE.ffmpeg + cd .. + + - name: Create release + uses: actions/create-release@v1 + id: create_release + with: + draft: true + prerelease: false + release_name: ${{ steps.version.outputs.version }} + tag_name: ${{ github.ref }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Upload Windows zip + uses: actions/upload-release-asset@v1 + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} + asset_path: ./OFDLV${{ steps.version.outputs.version }}.zip + asset_name: OFDLV${{ steps.version.outputs.version }}.zip + asset_content_type: application/zip + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..61c2e8e --- /dev/null +++ b/.gitignore @@ -0,0 +1,367 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Oo]ut/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd +/OF DL/auth.json +/OF DL/config.json +/OF DL/device_client_id_blob +/OF DL/device_private_key diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..9044f8c --- /dev/null +++ b/Dockerfile @@ -0,0 +1,66 @@ +FROM alpine:3.20 AS build + +ARG VERSION + +RUN apk --no-cache --repository community add \ + dotnet8-sdk + +# Copy source code +COPY ["OF DL.sln", "/src/OF DL.sln"] +COPY ["OF DL", "/src/OF DL"] + +WORKDIR "/src" + +# Build release +RUN dotnet publish -p:WarningLevel=0 -p:Version=$VERSION -c Release --self-contained true -p:PublishSingleFile=true -o out + +# Generate default config.conf files +RUN /src/out/OF\ DL --non-interactive || true && \ +# Set download path in default config.conf to /data + sed -e 's/DownloadPath = ""/DownloadPath = "\/data"/' /src/config.conf > /src/updated_config.conf && \ + mv /src/updated_config.conf /src/config.conf + + +FROM alpine:3.20 AS final + +# Install dependencies +RUN apk --no-cache --repository community add \ + bash \ + tini \ + dotnet8-runtime \ + ffmpeg \ + udev \ + ttf-freefont \ + chromium \ + supervisor \ + xvfb \ + x11vnc \ + novnc + +# Redirect webroot to vnc.html instead of displaying directory listing +RUN echo "" > /usr/share/novnc/index.html + +# Create directories for configuration and downloaded files +RUN mkdir /data /config /config/logs /default-config + +# Copy release +COPY --from=build /src/out /app + +# Copy default configuration files +COPY --from=build /src/config.conf /default-config +COPY --from=build ["/src/OF DL/rules.json", "/default-config"] + +COPY docker/supervisord.conf /etc/supervisor/conf.d/supervisord.conf +COPY docker/entrypoint.sh /app/entrypoint.sh +RUN chmod +x /app/entrypoint.sh + +ENV DISPLAY=:0.0 \ + DISPLAY_WIDTH=1024 \ + DISPLAY_HEIGHT=768 \ + OFDL_PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium \ + OFDL_DOCKER=true + +EXPOSE 8080 +WORKDIR /config +ENTRYPOINT ["/sbin/tini", "--"] +CMD ["/app/entrypoint.sh"] diff --git a/OF DL.sln b/OF DL.sln new file mode 100644 index 0000000..2434220 --- /dev/null +++ b/OF DL.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.33516.290 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OF DL", "OF DL\OF DL.csproj", "{318B2CE3-D046-4276-A2CF-89E6DF32F1B3}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {318B2CE3-D046-4276-A2CF-89E6DF32F1B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {318B2CE3-D046-4276-A2CF-89E6DF32F1B3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {318B2CE3-D046-4276-A2CF-89E6DF32F1B3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {318B2CE3-D046-4276-A2CF-89E6DF32F1B3}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {54D0035A-5593-4A55-AD35-A319DB9B7232} + EndGlobalSection +EndGlobal diff --git a/OF DL/CDMApi.cs b/OF DL/CDMApi.cs new file mode 100644 index 0000000..e01eae2 --- /dev/null +++ b/OF DL/CDMApi.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; + +namespace WidevineClient.Widevine +{ + public class CDMApi + { + string SessionId { get; set; } + + public byte[] GetChallenge(string initDataB64, string certDataB64, bool offline = false, bool raw = false) + { + SessionId = CDM.OpenSession(initDataB64, Constants.DEVICE_NAME, offline, raw); + CDM.SetServiceCertificate(SessionId, Convert.FromBase64String(certDataB64)); + return CDM.GetLicenseRequest(SessionId); + } + + public bool ProvideLicense(string licenseB64) + { + CDM.ProvideLicense(SessionId, Convert.FromBase64String(licenseB64)); + return true; + } + + public List GetKeys() + { + return CDM.GetKeys(SessionId); + } + } +} diff --git a/OF DL/Crypto/CryptoUtils.cs b/OF DL/Crypto/CryptoUtils.cs new file mode 100644 index 0000000..d433133 --- /dev/null +++ b/OF DL/Crypto/CryptoUtils.cs @@ -0,0 +1,33 @@ +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Macs; +using Org.BouncyCastle.Crypto.Parameters; +using System.Security.Cryptography; + +namespace WidevineClient.Crypto +{ + public class CryptoUtils + { + public static byte[] GetHMACSHA256Digest(byte[] data, byte[] key) + { + return new HMACSHA256(key).ComputeHash(data); + } + + public static byte[] GetCMACDigest(byte[] data, byte[] key) + { + IBlockCipher cipher = new AesEngine(); + IMac mac = new CMac(cipher, 128); + + KeyParameter keyParam = new KeyParameter(key); + + mac.Init(keyParam); + + mac.BlockUpdate(data, 0, data.Length); + + byte[] outBytes = new byte[16]; + + mac.DoFinal(outBytes, 0); + return outBytes; + } + } +} diff --git a/OF DL/Crypto/Padding.cs b/OF DL/Crypto/Padding.cs new file mode 100644 index 0000000..4701c1c --- /dev/null +++ b/OF DL/Crypto/Padding.cs @@ -0,0 +1,121 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Cryptography; + +namespace WidevineClient.Crypto +{ + public class Padding + { + public static byte[] AddPKCS7Padding(byte[] data, int k) + { + int m = k - (data.Length % k); + + byte[] padding = new byte[m]; + Array.Fill(padding, (byte)m); + + byte[] paddedBytes = new byte[data.Length + padding.Length]; + Buffer.BlockCopy(data, 0, paddedBytes, 0, data.Length); + Buffer.BlockCopy(padding, 0, paddedBytes, data.Length, padding.Length); + + return paddedBytes; + } + + public static byte[] RemovePKCS7Padding(byte[] paddedByteArray) + { + var last = paddedByteArray[^1]; + if (paddedByteArray.Length <= last) + { + return paddedByteArray; + } + + return SubArray(paddedByteArray, 0, (paddedByteArray.Length - last)); + } + + public static T[] SubArray(T[] arr, int start, int length) + { + var result = new T[length]; + Buffer.BlockCopy(arr, start, result, 0, length); + + return result; + } + + public static byte[] AddPSSPadding(byte[] hash) + { + int modBits = 2048; + int hLen = 20; + int emLen = 256; + + int lmask = 0; + for (int i = 0; i < 8 * emLen - (modBits - 1); i++) + lmask = lmask >> 1 | 0x80; + + if (emLen < hLen + hLen + 2) + { + return null; + } + + byte[] salt = new byte[hLen]; + new Random().NextBytes(salt); + + byte[] m_prime = Enumerable.Repeat((byte)0, 8).ToArray().Concat(hash).Concat(salt).ToArray(); + byte[] h = SHA1.Create().ComputeHash(m_prime); + + byte[] ps = Enumerable.Repeat((byte)0, emLen - hLen - hLen - 2).ToArray(); + byte[] db = ps.Concat(new byte[] { 0x01 }).Concat(salt).ToArray(); + + byte[] dbMask = MGF1(h, emLen - hLen - 1); + + byte[] maskedDb = new byte[dbMask.Length]; + for (int i = 0; i < dbMask.Length; i++) + maskedDb[i] = (byte)(db[i] ^ dbMask[i]); + + maskedDb[0] = (byte)(maskedDb[0] & ~lmask); + + byte[] padded = maskedDb.Concat(h).Concat(new byte[] { 0xBC }).ToArray(); + + return padded; + } + + public static byte[] RemoveOAEPPadding(byte[] data) + { + int k = 256; + int hLen = 20; + + byte[] maskedSeed = data[1..(hLen + 1)]; + byte[] maskedDB = data[(hLen + 1)..]; + + byte[] seedMask = MGF1(maskedDB, hLen); + + byte[] seed = new byte[maskedSeed.Length]; + for (int i = 0; i < maskedSeed.Length; i++) + seed[i] = (byte)(maskedSeed[i] ^ seedMask[i]); + + byte[] dbMask = MGF1(seed, k - hLen - 1); + + byte[] db = new byte[maskedDB.Length]; + for (int i = 0; i < maskedDB.Length; i++) + db[i] = (byte)(maskedDB[i] ^ dbMask[i]); + + int onePos = BitConverter.ToString(db[hLen..]).Replace("-", "").IndexOf("01") / 2; + byte[] unpadded = db[(hLen + onePos + 1)..]; + + return unpadded; + } + + static byte[] MGF1(byte[] seed, int maskLen) + { + SHA1 hobj = SHA1.Create(); + int hLen = hobj.HashSize / 8; + List T = new List(); + for (int i = 0; i < (int)Math.Ceiling(((double)maskLen / (double)hLen)); i++) + { + byte[] c = BitConverter.GetBytes(i); + Array.Reverse(c); + byte[] digest = hobj.ComputeHash(seed.Concat(c).ToArray()); + T.AddRange(digest); + } + return T.GetRange(0, maskLen).ToArray(); + } + } +} diff --git a/OF DL/Entities/Archived/Archived.cs b/OF DL/Entities/Archived/Archived.cs new file mode 100644 index 0000000..49658e9 --- /dev/null +++ b/OF DL/Entities/Archived/Archived.cs @@ -0,0 +1,275 @@ +using Newtonsoft.Json; +using OF_DL.Utils; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace OF_DL.Entities.Archived +{ + public class Archived + { + public List list { get; set; } + public bool hasMore { get; set; } + public string headMarker { get; set; } + public string tailMarker { get; set; } + public Counters counters { get; set; } + public class Author + { + public int id { get; set; } + public string _view { get; set; } + } + + public class Counters + { + public int? audiosCount { get; set; } + public int? photosCount { get; set; } + public int? videosCount { get; set; } + public int? mediasCount { get; set; } + public int? postsCount { get; set; } + public int? streamsCount { get; set; } + public int? archivedPostsCount { get; set; } + } + + public class Dash + { + [JsonProperty("CloudFront-Policy")] + public string CloudFrontPolicy { get; set; } + + [JsonProperty("CloudFront-Signature")] + public string CloudFrontSignature { get; set; } + + [JsonProperty("CloudFront-Key-Pair-Id")] + public string CloudFrontKeyPairId { get; set; } + } + + public class Drm + { + public Manifest manifest { get; set; } + public Signature signature { get; set; } + } + + public class Files + { + public Full full { get; set; } + public Thumb thumb { get; set; } + public Preview preview { get; set; } + public SquarePreview squarePreview { get; set; } + public Drm drm { get; set; } + } + + public class Full + { + public string url { get; set; } + public int width { get; set; } + public int height { get; set; } + public int size { get; set; } + public List sources { get; set; } + } + + public class SquarePreview + { + public string url { get; set; } + public int width { get; set; } + public int height { get; set; } + public int size { get; set; } + } + + public class Thumb + { + public string url { get; set; } + public int width { get; set; } + public int height { get; set; } + public int size { get; set; } + } + + public class Hls + { + [JsonProperty("CloudFront-Policy")] + public string CloudFrontPolicy { get; set; } + + [JsonProperty("CloudFront-Signature")] + public string CloudFrontSignature { get; set; } + + [JsonProperty("CloudFront-Key-Pair-Id")] + public string CloudFrontKeyPairId { get; set; } + } + + public class Info + { + public Source source { get; set; } + public Preview preview { get; set; } + } + + public class LinkedPost + { + public string responseType { get; set; } + public int? id { get; set; } + public DateTime? postedAt { get; set; } + public string postedAtPrecise { get; set; } + public object expiredAt { get; set; } + public Author author { get; set; } + public string text { get; set; } + private string _rawText; + public string rawText + { + get + { + if (string.IsNullOrEmpty(_rawText)) + { + _rawText = XmlUtils.EvaluateInnerText(text); + } + + return _rawText; + } + set + { + _rawText = value; + } + } + public bool? lockedText { get; set; } + public bool? isFavorite { get; set; } + public bool? canReport { get; set; } + public bool? canDelete { get; set; } + public bool? canComment { get; set; } + public bool? canEdit { get; set; } + public bool? isPinned { get; set; } + public int? favoritesCount { get; set; } + public int? mediaCount { get; set; } + public bool? isMediaReady { get; set; } + public object voting { get; set; } + public bool? isOpened { get; set; } + public bool? canToggleFavorite { get; set; } + public object streamId { get; set; } + public string? price { get; set; } + public bool? hasVoting { get; set; } + public bool? isAddedToBookmarks { get; set; } + public bool? isArchived { get; set; } + public bool? isPrivateArchived { get; set; } + public bool? isDeleted { get; set; } + public bool? hasUrl { get; set; } + public bool? isCouplePeopleMedia { get; set; } + public string cantCommentReason { get; set; } + public int? commentsCount { get; set; } + public List mentionedUsers { get; set; } + public List linkedUsers { get; set; } + public List media { get; set; } + public bool? canViewMedia { get; set; } + public List preview { get; set; } + } + + public class List + { + public string responseType { get; set; } + public long id { get; set; } + public DateTime postedAt { get; set; } + public string postedAtPrecise { get; set; } + public object expiredAt { get; set; } + public Author author { get; set; } + public string text { get; set; } + private string _rawText; + public string rawText + { + get + { + if (string.IsNullOrEmpty(_rawText)) + { + _rawText = XmlUtils.EvaluateInnerText(text); + } + + return _rawText; + } + set + { + _rawText = value; + } + } + public bool? lockedText { get; set; } + public bool? isFavorite { get; set; } + public bool? canReport { get; set; } + public bool? canDelete { get; set; } + public bool? canComment { get; set; } + public bool? canEdit { get; set; } + public bool? isPinned { get; set; } + public int? favoritesCount { get; set; } + public int? mediaCount { get; set; } + public bool? isMediaReady { get; set; } + public object voting { get; set; } + public bool isOpened { get; set; } + public bool? canToggleFavorite { get; set; } + public object streamId { get; set; } + public string price { get; set; } + public bool? hasVoting { get; set; } + public bool? isAddedToBookmarks { get; set; } + public bool isArchived { get; set; } + public bool? isPrivateArchived { get; set; } + public bool? isDeleted { get; set; } + public bool? hasUrl { get; set; } + public bool? isCouplePeopleMedia { get; set; } + public int? commentsCount { get; set; } + public List mentionedUsers { get; set; } + public List linkedUsers { get; set; } + public List media { get; set; } + public bool? canViewMedia { get; set; } + public List preview { get; set; } + public string cantCommentReason { get; set; } + } + + public class Manifest + { + public string hls { get; set; } + public string dash { get; set; } + } + + public class Medium + { + public long id { get; set; } + public string type { get; set; } + public bool? convertedToVideo { get; set; } + public bool canView { get; set; } + public bool? hasError { get; set; } + public DateTime? createdAt { get; set; } + public Info info { get; set; } + public Source source { get; set; } + public string squarePreview { get; set; } + public string full { get; set; } + public string preview { get; set; } + public string thumb { get; set; } + public Files files { get; set; } + public VideoSources videoSources { get; set; } + } + + public class Preview + { + public int? width { get; set; } + public int? height { get; set; } + public int? size { get; set; } + public string url { get; set; } + } + + public class Signature + { + public Hls hls { get; set; } + public Dash dash { get; set; } + } + + public class Source + { + public string source { get; set; } + public int? width { get; set; } + public int? height { get; set; } + public int? size { get; set; } + public int? duration { get; set; } + } + + public class VideoSources + { + [JsonProperty("720")] + public string _720 { get; set; } + + [JsonProperty("240")] + public string _240 { get; set; } + } + } +} diff --git a/OF DL/Entities/Archived/ArchivedCollection.cs b/OF DL/Entities/Archived/ArchivedCollection.cs new file mode 100644 index 0000000..2eb56fb --- /dev/null +++ b/OF DL/Entities/Archived/ArchivedCollection.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace OF_DL.Entities.Archived +{ + public class ArchivedCollection + { + public Dictionary ArchivedPosts = new Dictionary(); + public List ArchivedPostObjects = new List(); + public List ArchivedPostMedia = new List(); + } +} diff --git a/OF DL/Entities/Auth.cs b/OF DL/Entities/Auth.cs new file mode 100644 index 0000000..86d9f83 --- /dev/null +++ b/OF DL/Entities/Auth.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Newtonsoft.Json; + +namespace OF_DL.Entities +{ + public class Auth + { + public string? USER_ID { get; set; } = string.Empty; + public string? USER_AGENT { get; set; } = string.Empty; + public string? X_BC { get; set; } = string.Empty; + public string? COOKIE { get; set; } = string.Empty; + [JsonIgnore] + public string? FFMPEG_PATH { get; set; } = string.Empty; + } +} diff --git a/OF DL/Entities/CDRMProjectRequest.cs b/OF DL/Entities/CDRMProjectRequest.cs new file mode 100644 index 0000000..b48279b --- /dev/null +++ b/OF DL/Entities/CDRMProjectRequest.cs @@ -0,0 +1,27 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace OF_DL.Entities +{ + public class CDRMProjectRequest + { + [JsonProperty("pssh")] + public string PSSH { get; set; } = ""; + + [JsonProperty("licurl")] + public string LicenseURL { get; set; } = ""; + + [JsonProperty("headers")] + public string Headers { get; set; } = ""; + + [JsonProperty("cookies")] + public string Cookies { get; set; } = ""; + + [JsonProperty("data")] + public string Data { get; set; } = ""; + } +} diff --git a/OF DL/Entities/Config.cs b/OF DL/Entities/Config.cs new file mode 100644 index 0000000..0919d74 --- /dev/null +++ b/OF DL/Entities/Config.cs @@ -0,0 +1,110 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using OF_DL.Enumerations; + +namespace OF_DL.Entities +{ + + public class Config : IDownloadConfig, IFileNameFormatConfig + { + [ToggleableConfig] + public bool DownloadAvatarHeaderPhoto { get; set; } = true; + [ToggleableConfig] + public bool DownloadPaidPosts { get; set; } = true; + [ToggleableConfig] + public bool DownloadPosts { get; set; } = true; + [ToggleableConfig] + public bool DownloadArchived { get; set; } = true; + [ToggleableConfig] + public bool DownloadStreams { get; set; } = true; + [ToggleableConfig] + public bool DownloadStories { get; set; } = true; + [ToggleableConfig] + public bool DownloadHighlights { get; set; } = true; + [ToggleableConfig] + public bool DownloadMessages { get; set; } = true; + [ToggleableConfig] + public bool DownloadPaidMessages { get; set; } = true; + [ToggleableConfig] + public bool DownloadImages { get; set; } = true; + [ToggleableConfig] + public bool DownloadVideos { get; set; } = true; + [ToggleableConfig] + public bool DownloadAudios { get; set; } = true; + [ToggleableConfig] + public bool IncludeExpiredSubscriptions { get; set; } = false; + [ToggleableConfig] + public bool IncludeRestrictedSubscriptions { get; set; } = false; + [ToggleableConfig] + public bool SkipAds { get; set; } = false; + + public string? DownloadPath { get; set; } = string.Empty; + public string? PaidPostFileNameFormat { get; set; } = string.Empty; + public string? PostFileNameFormat { get; set; } = string.Empty; + public string? PaidMessageFileNameFormat { get; set; } = string.Empty; + public string? MessageFileNameFormat { get; set; } = string.Empty; + [ToggleableConfig] + public bool RenameExistingFilesWhenCustomFormatIsSelected { get; set; } = false; + public int? Timeout { get; set; } = -1; + [ToggleableConfig] + public bool FolderPerPaidPost { get; set; } = false; + [ToggleableConfig] + public bool FolderPerPost { get; set; } = false; + [ToggleableConfig] + public bool FolderPerPaidMessage { get; set; } = false; + [ToggleableConfig] + public bool FolderPerMessage { get; set; } = false; + [ToggleableConfig] + public bool LimitDownloadRate { get; set; } = false; + public int DownloadLimitInMbPerSec { get; set; } = 4; + + // Indicates if you want to download only on specific dates. + [ToggleableConfig] + public bool DownloadOnlySpecificDates { get; set; } = false; + + // This enum will define if we want data from before or after the CustomDate. + [JsonConverter(typeof(StringEnumConverter))] + public DownloadDateSelection DownloadDateSelection { get; set; } = DownloadDateSelection.before; + // This is the specific date used in combination with the above enum. + + [JsonConverter(typeof(ShortDateConverter))] + public DateTime? CustomDate { get; set; } = null; + + [ToggleableConfig] + public bool ShowScrapeSize { get; set; } = false; + + [ToggleableConfig] + public bool DownloadPostsIncrementally { get; set; } = false; + + public bool NonInteractiveMode { get; set; } = false; + public string NonInteractiveModeListName { get; set; } = string.Empty; + [ToggleableConfig] + public bool NonInteractiveModePurchasedTab { get; set; } = false; + public string? FFmpegPath { get; set; } = string.Empty; + + [ToggleableConfig] + public bool BypassContentForCreatorsWhoNoLongerExist { get; set; } = false; + + public Dictionary CreatorConfigs { get; set; } = new Dictionary(); + + [ToggleableConfig] + public bool DownloadDuplicatedMedia { get; set; } = false; + + public string IgnoredUsersListName { get; set; } = string.Empty; + + [JsonConverter(typeof(StringEnumConverter))] + public LoggingLevel LoggingLevel { get; set; } = LoggingLevel.Error; + + [ToggleableConfig] + public bool IgnoreOwnMessages { get; set; } = false; + } + + public class CreatorConfig : IFileNameFormatConfig + { + public string? PaidPostFileNameFormat { get; set; } + public string? PostFileNameFormat { get; set; } + public string? PaidMessageFileNameFormat { get; set; } + public string? MessageFileNameFormat { get; set; } + } + +} diff --git a/OF DL/Entities/DynamicRules.cs b/OF DL/Entities/DynamicRules.cs new file mode 100644 index 0000000..eb41a7c --- /dev/null +++ b/OF DL/Entities/DynamicRules.cs @@ -0,0 +1,28 @@ +using Newtonsoft.Json; + +namespace OF_DL.Entities +{ + public class DynamicRules + { + [JsonProperty(PropertyName="app-token")] + public string? AppToken { get; set; } + + [JsonProperty(PropertyName="app_token")] + private string AppToken2 { set { AppToken = value; } } + + [JsonProperty(PropertyName="static_param")] + public string? StaticParam { get; set; } + + [JsonProperty(PropertyName="prefix")] + public string? Prefix { get; set; } + + [JsonProperty(PropertyName="suffix")] + public string? Suffix { get; set; } + + [JsonProperty(PropertyName="checksum_constant")] + public int? ChecksumConstant { get; set; } + + [JsonProperty(PropertyName = "checksum_indexes")] + public List ChecksumIndexes { get; set; } + } +} diff --git a/OF DL/Entities/FileNameFormatConfig.cs b/OF DL/Entities/FileNameFormatConfig.cs new file mode 100644 index 0000000..73b7b73 --- /dev/null +++ b/OF DL/Entities/FileNameFormatConfig.cs @@ -0,0 +1,11 @@ +namespace OF_DL.Entities +{ + public class FileNameFormatConfig : IFileNameFormatConfig + { + public string? PaidPostFileNameFormat { get; set; } + public string? PostFileNameFormat { get; set; } + public string? PaidMessageFileNameFormat { get; set; } + public string? MessageFileNameFormat { get; set; } + } + +} diff --git a/OF DL/Entities/Highlights/HighlightMedia.cs b/OF DL/Entities/Highlights/HighlightMedia.cs new file mode 100644 index 0000000..d4b141a --- /dev/null +++ b/OF DL/Entities/Highlights/HighlightMedia.cs @@ -0,0 +1,108 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace OF_DL.Entities.Highlights +{ + public class HighlightMedia + { + public int id { get; set; } + public int userId { get; set; } + public string title { get; set; } + public int coverStoryId { get; set; } + public string cover { get; set; } + public int storiesCount { get; set; } + public DateTime? createdAt { get; set; } + public List stories { get; set; } + public class Files + { + public Full full { get; set; } + public Thumb thumb { get; set; } + public Preview preview { get; set; } + public SquarePreview squarePreview { get; set; } + } + + public class Full + { + public string url { get; set; } + public int width { get; set; } + public int height { get; set; } + public int size { get; set; } + public List sources { get; set; } + } + + public class Medium + { + public long id { get; set; } + public string type { get; set; } + public bool convertedToVideo { get; set; } + public bool canView { get; set; } + public bool hasError { get; set; } + public DateTime? createdAt { get; set; } + public Files files { get; set; } + } + + public class Preview + { + public string url { get; set; } + public int width { get; set; } + public int height { get; set; } + public int size { get; set; } + public Sources sources { get; set; } + } + + public class Source + { + public string url { get; set; } + public int width { get; set; } + public int height { get; set; } + public int duration { get; set; } + public int size { get; set; } + public Sources sources { get; set; } + } + + public class Sources + { + [JsonProperty("720")] + public string _720 { get; set; } + + [JsonProperty("240")] + public string _240 { get; set; } + public string w150 { get; set; } + public string w480 { get; set; } + } + + public class SquarePreview + { + public string url { get; set; } + public int width { get; set; } + public int height { get; set; } + public int size { get; set; } + public Sources sources { get; set; } + } + + public class Story + { + public int id { get; set; } + public int userId { get; set; } + public bool isWatched { get; set; } + public bool isReady { get; set; } + public List media { get; set; } + public DateTime? createdAt { get; set; } + public object question { get; set; } + public bool canLike { get; set; } + public bool isLiked { get; set; } + } + + public class Thumb + { + public string url { get; set; } + public int width { get; set; } + public int height { get; set; } + public int size { get; set; } + } + } +} diff --git a/OF DL/Entities/Highlights/Highlights.cs b/OF DL/Entities/Highlights/Highlights.cs new file mode 100644 index 0000000..fc29ff7 --- /dev/null +++ b/OF DL/Entities/Highlights/Highlights.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace OF_DL.Entities.Highlights +{ + public class Highlights + { + public List list { get; set; } + public bool hasMore { get; set; } + public class List + { + public int id { get; set; } + public int userId { get; set; } + public string title { get; set; } + public int coverStoryId { get; set; } + public string cover { get; set; } + public int storiesCount { get; set; } + public DateTime? createdAt { get; set; } + } + } +} diff --git a/OF DL/Entities/IDownloadConfig.cs b/OF DL/Entities/IDownloadConfig.cs new file mode 100644 index 0000000..2072220 --- /dev/null +++ b/OF DL/Entities/IDownloadConfig.cs @@ -0,0 +1,54 @@ +using OF_DL.Enumerations; + +namespace OF_DL.Entities +{ + public interface IDownloadConfig + { + bool DownloadAvatarHeaderPhoto { get; set; } + bool DownloadPaidPosts { get; set; } + bool DownloadPosts { get; set; } + bool DownloadArchived { get; set; } + bool DownloadStreams { get; set; } + bool DownloadStories { get; set; } + bool DownloadHighlights { get; set; } + bool DownloadMessages { get; set; } + bool DownloadPaidMessages { get; set; } + bool DownloadImages { get; set; } + bool DownloadVideos { get; set; } + bool DownloadAudios { get; set; } + + int? Timeout { get; set; } + bool FolderPerPaidPost { get; set; } + bool FolderPerPost { get; set; } + bool FolderPerPaidMessage { get; set; } + bool FolderPerMessage { get; set; } + + bool RenameExistingFilesWhenCustomFormatIsSelected { get; set; } + bool ShowScrapeSize { get; set; } + bool LimitDownloadRate { get; set; } + int DownloadLimitInMbPerSec { get; set; } + string? FFmpegPath { get; set; } + + bool SkipAds { get; set; } + bool BypassContentForCreatorsWhoNoLongerExist { get; set; } + + #region Download Date Configurations + + bool DownloadOnlySpecificDates { get; set; } + + // This enum will define if we want data from before or after the CustomDate. + DownloadDateSelection DownloadDateSelection { get; set; } + + // This is the specific date used in combination with the above enum. + DateTime? CustomDate { get; set; } + #endregion + + bool DownloadPostsIncrementally { get; set; } + + bool DownloadDuplicatedMedia { get; set; } + public LoggingLevel LoggingLevel { get; set; } + + bool IgnoreOwnMessages { get; set; } + } + +} diff --git a/OF DL/Entities/IFileNameFormatConfig.cs b/OF DL/Entities/IFileNameFormatConfig.cs new file mode 100644 index 0000000..1c3bc3f --- /dev/null +++ b/OF DL/Entities/IFileNameFormatConfig.cs @@ -0,0 +1,11 @@ +namespace OF_DL.Entities +{ + public interface IFileNameFormatConfig + { + string? PaidPostFileNameFormat { get; set; } + string? PostFileNameFormat { get; set; } + string? PaidMessageFileNameFormat { get; set; } + string? MessageFileNameFormat { get; set; } + } + +} diff --git a/OF DL/Entities/Lists/UserList.cs b/OF DL/Entities/Lists/UserList.cs new file mode 100644 index 0000000..0a2c067 --- /dev/null +++ b/OF DL/Entities/Lists/UserList.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace OF_DL.Entities.Lists +{ + public class UserList + { + public List list { get; set; } + public bool? hasMore { get; set; } + public class List + { + public string id { get; set; } + public string type { get; set; } + public string name { get; set; } + public int? usersCount { get; set; } + public int? postsCount { get; set; } + public bool? canUpdate { get; set; } + public bool? canDelete { get; set; } + public bool? canManageUsers { get; set; } + public bool? canAddUsers { get; set; } + public bool? canPinnedToFeed { get; set; } + public bool? isPinnedToFeed { get; set; } + public bool? canPinnedToChat { get; set; } + public bool? isPinnedToChat { get; set; } + public string order { get; set; } + public string direction { get; set; } + public List users { get; set; } + public List customOrderUsersIds { get; set; } + public List posts { get; set; } + } + + public class User + { + public int? id { get; set; } + public string _view { get; set; } + } + } +} diff --git a/OF DL/Entities/Lists/UsersList.cs b/OF DL/Entities/Lists/UsersList.cs new file mode 100644 index 0000000..3b77dfa --- /dev/null +++ b/OF DL/Entities/Lists/UsersList.cs @@ -0,0 +1,171 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace OF_DL.Entities.Lists +{ + public class UsersList + { + public string view { get; set; } + public string avatar { get; set; } + public AvatarThumbs avatarThumbs { get; set; } + public string header { get; set; } + public HeaderSize headerSize { get; set; } + public HeaderThumbs headerThumbs { get; set; } + public int? id { get; set; } + public string name { get; set; } + public string username { get; set; } + public bool? canLookStory { get; set; } + public bool? canCommentStory { get; set; } + public bool? hasNotViewedStory { get; set; } + public bool? isVerified { get; set; } + public bool? canPayInternal { get; set; } + public bool? hasScheduledStream { get; set; } + public bool? hasStream { get; set; } + public bool? hasStories { get; set; } + public bool? tipsEnabled { get; set; } + public bool? tipsTextEnabled { get; set; } + public int? tipsMin { get; set; } + public int? tipsMinInternal { get; set; } + public int? tipsMax { get; set; } + public bool? canEarn { get; set; } + public bool? canAddSubscriber { get; set; } + public string? subscribePrice { get; set; } + public List subscriptionBundles { get; set; } + public string displayName { get; set; } + public string notice { get; set; } + public bool? isPaywallRequired { get; set; } + public bool? unprofitable { get; set; } + public List listsStates { get; set; } + public bool? isMuted { get; set; } + public bool? isRestricted { get; set; } + public bool? canRestrict { get; set; } + public bool? subscribedBy { get; set; } + public bool? subscribedByExpire { get; set; } + public DateTime? subscribedByExpireDate { get; set; } + public bool? subscribedByAutoprolong { get; set; } + public bool? subscribedIsExpiredNow { get; set; } + public string? currentSubscribePrice { get; set; } + public bool? subscribedOn { get; set; } + public bool? subscribedOnExpiredNow { get; set; } + public string subscribedOnDuration { get; set; } + public bool? canReport { get; set; } + public bool? canReceiveChatMessage { get; set; } + public bool? hideChat { get; set; } + public DateTime? lastSeen { get; set; } + public bool? isPerformer { get; set; } + public bool? isRealPerformer { get; set; } + public SubscribedByData subscribedByData { get; set; } + public SubscribedOnData subscribedOnData { get; set; } + public bool? canTrialSend { get; set; } + public bool? isBlocked { get; set; } + public List promoOffers { get; set; } + public class AvatarThumbs + { + public string c50 { get; set; } + public string c144 { get; set; } + } + + public class HeaderSize + { + public int? width { get; set; } + public int? height { get; set; } + } + + public class HeaderThumbs + { + public string w480 { get; set; } + public string w760 { get; set; } + } + + public class ListsState + { + public string id { get; set; } + public string type { get; set; } + public string name { get; set; } + public bool hasUser { get; set; } + public bool canAddUser { get; set; } + } + + public class Subscribe + { + public object id { get; set; } + public int? userId { get; set; } + public int? subscriberId { get; set; } + public DateTime? date { get; set; } + public int? duration { get; set; } + public DateTime? startDate { get; set; } + public DateTime? expireDate { get; set; } + public object cancelDate { get; set; } + public string? price { get; set; } + public string? regularPrice { get; set; } + public string? discount { get; set; } + public string action { get; set; } + public string type { get; set; } + public object offerStart { get; set; } + public object offerEnd { get; set; } + public bool? isCurrent { get; set; } + } + + public class SubscribedByData + { + public string? price { get; set; } + public string? newPrice { get; set; } + public string? regularPrice { get; set; } + public string? subscribePrice { get; set; } + public string? discountPercent { get; set; } + public string? discountPeriod { get; set; } + public DateTime? subscribeAt { get; set; } + public DateTime? expiredAt { get; set; } + public object renewedAt { get; set; } + public object discountFinishedAt { get; set; } + public object discountStartedAt { get; set; } + public string status { get; set; } + public bool? isMuted { get; set; } + public string unsubscribeReason { get; set; } + public string duration { get; set; } + public bool? showPostsInFeed { get; set; } + public List subscribes { get; set; } + } + + public class SubscribedOnData + { + public string? price { get; set; } + public string? newPrice { get; set; } + public string? regularPrice { get; set; } + public string? subscribePrice { get; set; } + public string? discountPercent { get; set; } + public string? discountPeriod { get; set; } + public DateTime? subscribeAt { get; set; } + public DateTime? expiredAt { get; set; } + public object renewedAt { get; set; } + public object discountFinishedAt { get; set; } + public object discountStartedAt { get; set; } + public object status { get; set; } + public bool? isMuted { get; set; } + public string unsubscribeReason { get; set; } + public string duration { get; set; } + public string? tipsSumm { get; set; } + public string? subscribesSumm { get; set; } + public string? messagesSumm { get; set; } + public string? postsSumm { get; set; } + public string? streamsSumm { get; set; } + public string? totalSumm { get; set; } + public DateTime? lastActivity { get; set; } + public int? recommendations { get; set; } + public List subscribes { get; set; } + } + + public class SubscriptionBundle + { + public int? id { get; set; } + public string? discount { get; set; } + public string? duration { get; set; } + public string? price { get; set; } + public bool? canBuy { get; set; } + } + + } +} diff --git a/OF DL/Entities/Messages/MessageCollection.cs b/OF DL/Entities/Messages/MessageCollection.cs new file mode 100644 index 0000000..dd01461 --- /dev/null +++ b/OF DL/Entities/Messages/MessageCollection.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace OF_DL.Entities.Messages +{ + public class MessageCollection + { + public Dictionary Messages = new Dictionary(); + public List MessageObjects = new List(); + public List MessageMedia = new List(); + } +} diff --git a/OF DL/Entities/Messages/Messages.cs b/OF DL/Entities/Messages/Messages.cs new file mode 100644 index 0000000..1f17f70 --- /dev/null +++ b/OF DL/Entities/Messages/Messages.cs @@ -0,0 +1,184 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace OF_DL.Entities.Messages +{ + public class Messages + { + public List list { get; set; } + public bool hasMore { get; set; } + public class Dash + { + [JsonProperty("CloudFront-Policy")] + public string CloudFrontPolicy { get; set; } + + [JsonProperty("CloudFront-Signature")] + public string CloudFrontSignature { get; set; } + + [JsonProperty("CloudFront-Key-Pair-Id")] + public string CloudFrontKeyPairId { get; set; } + } + + public class Drm + { + public Manifest manifest { get; set; } + public Signature signature { get; set; } + } + + public class Files + { + public Full full { get; set; } + public Thumb thumb { get; set; } + public Preview preview { get; set; } + public SquarePreview squarePreview { get; set; } + public Drm drm { get; set; } + } + + public class Full + { + public string url { get; set; } + public int width { get; set; } + public int height { get; set; } + public int size { get; set; } + public List sources { get; set; } + } + + public class SquarePreview + { + public string url { get; set; } + public int width { get; set; } + public int height { get; set; } + public int size { get; set; } + } + + public class Thumb + { + public string url { get; set; } + public int width { get; set; } + public int height { get; set; } + public int size { get; set; } + } + + public class FromUser + { + public int? id { get; set; } + public string _view { get; set; } + } + + public class Hls + { + [JsonProperty("CloudFront-Policy")] + public string CloudFrontPolicy { get; set; } + + [JsonProperty("CloudFront-Signature")] + public string CloudFrontSignature { get; set; } + + [JsonProperty("CloudFront-Key-Pair-Id")] + public string CloudFrontKeyPairId { get; set; } + } + + public class Info + { + public Source source { get; set; } + public Preview preview { get; set; } + } + + public class List + { + public string responseType { get; set; } + public string text { get; set; } + public object giphyId { get; set; } + public bool? lockedText { get; set; } + public bool? isFree { get; set; } + public string? price { get; set; } + public bool? isMediaReady { get; set; } + public int? mediaCount { get; set; } + public List media { get; set; } + public List previews { get; set; } + public bool? isTip { get; set; } + public bool? isReportedByMe { get; set; } + public bool? isCouplePeopleMedia { get; set; } + public object queueId { get; set; } + public FromUser fromUser { get; set; } + public bool? isFromQueue { get; set; } + public bool? canUnsendQueue { get; set; } + public int? unsendSecondsQueue { get; set; } + public long id { get; set; } + public bool? isOpened { get; set; } + public bool? isNew { get; set; } + public DateTime? createdAt { get; set; } + public DateTime? changedAt { get; set; } + public int? cancelSeconds { get; set; } + public bool? isLiked { get; set; } + public bool? canPurchase { get; set; } + public string canPurchaseReason { get; set; } + public bool? canReport { get; set; } + public bool? canBePinned { get; set; } + public bool? isPinned { get; set; } + } + + public class Manifest + { + public string hls { get; set; } + public string dash { get; set; } + } + + public class Medium + { + public long id { get; set; } + public bool canView { get; set; } + public string type { get; set; } + public string src { get; set; } + public string preview { get; set; } + public string thumb { get; set; } + public object locked { get; set; } + public int? duration { get; set; } + public bool? hasError { get; set; } + public string squarePreview { get; set; } + public Video video { get; set; } + public VideoSources videoSources { get; set; } + public Source source { get; set; } + public Info info { get; set; } + public Files files { get; set; } + } + + public class Preview + { + public int? width { get; set; } + public int? height { get; set; } + public int? size { get; set; } + } + + public class Signature + { + public Hls hls { get; set; } + public Dash dash { get; set; } + } + + public class Source + { + public string source { get; set; } + public int? width { get; set; } + public int? height { get; set; } + public int? size { get; set; } + } + + public class Video + { + public string mp4 { get; set; } + } + + public class VideoSources + { + [JsonProperty("720")] + public string _720 { get; set; } + + [JsonProperty("240")] + public string _240 { get; set; } + } + } +} diff --git a/OF DL/Entities/Messages/SingleMessage.cs b/OF DL/Entities/Messages/SingleMessage.cs new file mode 100644 index 0000000..f6231fb --- /dev/null +++ b/OF DL/Entities/Messages/SingleMessage.cs @@ -0,0 +1,119 @@ +using Newtonsoft.Json; +using static OF_DL.Entities.Messages.Messages; + +namespace OF_DL.Entities.Messages +{ + public class AvatarThumbs + { + public string c50 { get; set; } + public string c144 { get; set; } + } + + public class FromUser + { + public string view { get; set; } + public string avatar { get; set; } + public AvatarThumbs avatarThumbs { get; set; } + public string header { get; set; } + public HeaderSize headerSize { get; set; } + public HeaderThumbs headerThumbs { get; set; } + public int? id { get; set; } + public string name { get; set; } + public string username { get; set; } + public bool canLookStory { get; set; } + public bool canCommentStory { get; set; } + public bool hasNotViewedStory { get; set; } + public bool isVerified { get; set; } + public bool canPayInternal { get; set; } + public bool hasScheduledStream { get; set; } + public bool hasStream { get; set; } + public bool hasStories { get; set; } + public bool tipsEnabled { get; set; } + public bool tipsTextEnabled { get; set; } + public int tipsMin { get; set; } + public int tipsMinInternal { get; set; } + public int tipsMax { get; set; } + public bool canEarn { get; set; } + public bool canAddSubscriber { get; set; } + public string? subscribePrice { get; set; } + public List subscriptionBundles { get; set; } + public bool isPaywallRequired { get; set; } + public List listsStates { get; set; } + public bool isRestricted { get; set; } + public bool canRestrict { get; set; } + public object subscribedBy { get; set; } + public object subscribedByExpire { get; set; } + public DateTime subscribedByExpireDate { get; set; } + public object subscribedByAutoprolong { get; set; } + public bool subscribedIsExpiredNow { get; set; } + public object currentSubscribePrice { get; set; } + public object subscribedOn { get; set; } + public object subscribedOnExpiredNow { get; set; } + public object subscribedOnDuration { get; set; } + public int callPrice { get; set; } + public DateTime? lastSeen { get; set; } + public bool canReport { get; set; } + } + + public class HeaderSize + { + public int width { get; set; } + public int height { get; set; } + } + + public class HeaderThumbs + { + public string w480 { get; set; } + public string w760 { get; set; } + } + + public class ListsState + { + public string id { get; set; } + public string type { get; set; } + public string name { get; set; } + public bool hasUser { get; set; } + public bool canAddUser { get; set; } + public string cannotAddUserReason { get; set; } + } + + public class Preview + { + public int width { get; set; } + public int height { get; set; } + public int size { get; set; } + } + + public class SingleMessage + { + public string responseType { get; set; } + public string text { get; set; } + public object giphyId { get; set; } + public bool lockedText { get; set; } + public bool isFree { get; set; } + public double price { get; set; } + public bool isMediaReady { get; set; } + public int mediaCount { get; set; } + public List media { get; set; } + public List previews { get; set; } + public bool isTip { get; set; } + public bool isReportedByMe { get; set; } + public bool isCouplePeopleMedia { get; set; } + public long queueId { get; set; } + public FromUser fromUser { get; set; } + public bool isFromQueue { get; set; } + public bool canUnsendQueue { get; set; } + public int unsendSecondsQueue { get; set; } + public long id { get; set; } + public bool isOpened { get; set; } + public bool isNew { get; set; } + public DateTime? createdAt { get; set; } + public DateTime? changedAt { get; set; } + public int cancelSeconds { get; set; } + public bool isLiked { get; set; } + public bool canPurchase { get; set; } + public bool canReport { get; set; } + } + +} + diff --git a/OF DL/Entities/OFDLRequest.cs b/OF DL/Entities/OFDLRequest.cs new file mode 100644 index 0000000..56060b9 --- /dev/null +++ b/OF DL/Entities/OFDLRequest.cs @@ -0,0 +1,21 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace OF_DL.Entities +{ + public class OFDLRequest + { + [JsonProperty("pssh")] + public string PSSH { get; set; } = ""; + + [JsonProperty("licenceURL")] + public string LicenseURL { get; set; } = ""; + + [JsonProperty("headers")] + public string Headers { get; set; } = ""; + } +} diff --git a/OF DL/Entities/Post/Post.cs b/OF DL/Entities/Post/Post.cs new file mode 100644 index 0000000..5078f95 --- /dev/null +++ b/OF DL/Entities/Post/Post.cs @@ -0,0 +1,213 @@ +using Newtonsoft.Json; +using OF_DL.Utils; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using static OF_DL.Entities.Messages.Messages; + +namespace OF_DL.Entities.Post; + +#pragma warning disable IDE1006 // Naming Styles +public class Post +{ + public List list { get; set; } + public bool hasMore { get; set; } + + public string headMarker { get; set; } + + public string tailMarker { get; set; } + public class Author + { + public int id { get; set; } + public string _view { get; set; } + } + + public class Dash + { + [JsonProperty("CloudFront-Policy")] + public string CloudFrontPolicy { get; set; } + + [JsonProperty("CloudFront-Signature")] + public string CloudFrontSignature { get; set; } + + [JsonProperty("CloudFront-Key-Pair-Id")] + public string CloudFrontKeyPairId { get; set; } + } + + public class Drm + { + public Manifest manifest { get; set; } + public Signature signature { get; set; } + } + + public class Files + { + public Full full { get; set; } + public Thumb thumb { get; set; } + public Preview preview { get; set; } + public SquarePreview squarePreview { get; set; } + public Drm drm { get; set; } + } + + public class Full + { + public string url { get; set; } + public int width { get; set; } + public int height { get; set; } + public int size { get; set; } + public List sources { get; set; } + } + + public class SquarePreview + { + public string url { get; set; } + public int width { get; set; } + public int height { get; set; } + public int size { get; set; } + } + + public class Thumb + { + public string url { get; set; } + public int width { get; set; } + public int height { get; set; } + public int size { get; set; } + } + + public class Hls + { + [JsonProperty("CloudFront-Policy")] + public string CloudFrontPolicy { get; set; } + + [JsonProperty("CloudFront-Signature")] + public string CloudFrontSignature { get; set; } + + [JsonProperty("CloudFront-Key-Pair-Id")] + public string CloudFrontKeyPairId { get; set; } + } + + public class Info + { + public Source source { get; set; } + public Preview preview { get; set; } + } + + public class List + { + public string responseType { get; set; } + public long id { get; set; } + public DateTime postedAt { get; set; } + public string postedAtPrecise { get; set; } + public object expiredAt { get; set; } + public Author author { get; set; } + public string text { get; set; } + + private string _rawText; + public string rawText + { + get + { + if(string.IsNullOrEmpty(_rawText)) + { + _rawText = XmlUtils.EvaluateInnerText(text); + } + + return _rawText; + } + set + { + _rawText = value; + } + } + public bool? lockedText { get; set; } + public bool? isFavorite { get; set; } + public bool? canReport { get; set; } + public bool? canDelete { get; set; } + public bool? canComment { get; set; } + public bool? canEdit { get; set; } + public bool? isPinned { get; set; } + public int? favoritesCount { get; set; } + public int? mediaCount { get; set; } + public bool? isMediaReady { get; set; } + public object voting { get; set; } + public bool isOpened { get; set; } + public bool? canToggleFavorite { get; set; } + public object streamId { get; set; } + public string? price { get; set; } + public bool? hasVoting { get; set; } + public bool? isAddedToBookmarks { get; set; } + public bool isArchived { get; set; } + public bool? isPrivateArchived { get; set; } + public bool? isDeleted { get; set; } + public bool? hasUrl { get; set; } + public bool? isCouplePeopleMedia { get; set; } + public string cantCommentReason { get; set; } + public int? votingType { get; set; } + public int? commentsCount { get; set; } + public List mentionedUsers { get; set; } + public List linkedUsers { get; set; } + public bool? canVote { get; set; } + public List media { get; set; } + public bool? canViewMedia { get; set; } + public List preview { get; set; } + } + + public class Manifest + { + public string? hls { get; set; } + public string? dash { get; set; } + } + + public class Medium + { + public long id { get; set; } + public string type { get; set; } + public bool? convertedToVideo { get; set; } + public bool canView { get; set; } + public bool? hasError { get; set; } + public DateTime? createdAt { get; set; } + public Info info { get; set; } + public Source source { get; set; } + public string squarePreview { get; set; } + public string full { get; set; } + public string preview { get; set; } + public string thumb { get; set; } + public Files files { get; set; } + public VideoSources videoSources { get; set; } + } + + public class Preview + { + public int? width { get; set; } + public int? height { get; set; } + public int? size { get; set; } + public string url { get; set; } + } + + public class Signature + { + public Hls hls { get; set; } + public Dash dash { get; set; } + } + + public class Source + { + public string? source { get; set; } + public int? width { get; set; } + public int? height { get; set; } + public int? size { get; set; } + public int? duration { get; set; } + } + + public class VideoSources + { + [JsonProperty("720")] + public object _720 { get; set; } + + [JsonProperty("240")] + public object _240 { get; set; } + } +#pragma warning restore IDE1006 // Naming Styles +} diff --git a/OF DL/Entities/Post/PostCollection.cs b/OF DL/Entities/Post/PostCollection.cs new file mode 100644 index 0000000..1ed0478 --- /dev/null +++ b/OF DL/Entities/Post/PostCollection.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace OF_DL.Entities.Post +{ + public class PostCollection + { + public Dictionary Posts = new Dictionary(); + public List PostObjects = new List(); + public List PostMedia = new List(); + } +} diff --git a/OF DL/Entities/Post/SinglePost.cs b/OF DL/Entities/Post/SinglePost.cs new file mode 100644 index 0000000..98e68f0 --- /dev/null +++ b/OF DL/Entities/Post/SinglePost.cs @@ -0,0 +1,197 @@ +using Newtonsoft.Json; +using OF_DL.Utils; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using static OF_DL.Entities.Post.Post; + +namespace OF_DL.Entities.Post +{ + public class SinglePost + { + public string responseType { get; set; } + public int id { get; set; } + public DateTime postedAt { get; set; } + public string postedAtPrecise { get; set; } + public object expiredAt { get; set; } + public Author author { get; set; } + public string text { get; set; } + private string _rawText; + public string rawText + { + get + { + if (string.IsNullOrEmpty(_rawText)) + { + _rawText = XmlUtils.EvaluateInnerText(text); + } + + return _rawText; + } + set + { + _rawText = value; + } + } + public bool lockedText { get; set; } + public bool isFavorite { get; set; } + public bool canReport { get; set; } + public bool canDelete { get; set; } + public bool canComment { get; set; } + public bool canEdit { get; set; } + public bool isPinned { get; set; } + public int favoritesCount { get; set; } + public int mediaCount { get; set; } + public bool isMediaReady { get; set; } + public object voting { get; set; } + public bool isOpened { get; set; } + public bool canToggleFavorite { get; set; } + public string streamId { get; set; } + public string price { get; set; } + public bool hasVoting { get; set; } + public bool isAddedToBookmarks { get; set; } + public bool isArchived { get; set; } + public bool isPrivateArchived { get; set; } + public bool isDeleted { get; set; } + public bool hasUrl { get; set; } + public bool isCouplePeopleMedia { get; set; } + public int commentsCount { get; set; } + public List mentionedUsers { get; set; } + public List linkedUsers { get; set; } + public string tipsAmount { get; set; } + public string tipsAmountRaw { get; set; } + public List media { get; set; } + public bool canViewMedia { get; set; } + public List preview { get; set; } + public class Author + { + public int id { get; set; } + public string _view { get; set; } + } + + public class Files + { + public Full full { get; set; } + public Thumb thumb { get; set; } + public Preview preview { get; set; } + public SquarePreview squarePreview { get; set; } + public Drm drm { get; set; } + } + + public class Full + { + public string url { get; set; } + public int width { get; set; } + public int height { get; set; } + public int size { get; set; } + public List sources { get; set; } + } + + public class SquarePreview + { + public string url { get; set; } + public int width { get; set; } + public int height { get; set; } + public int size { get; set; } + } + + public class Thumb + { + public string url { get; set; } + public int width { get; set; } + public int height { get; set; } + public int size { get; set; } + } + + public class Info + { + public Source source { get; set; } + public Preview preview { get; set; } + } + + public class Medium + { + public long id { get; set; } + public string type { get; set; } + public bool convertedToVideo { get; set; } + public bool canView { get; set; } + public bool hasError { get; set; } + public DateTime? createdAt { get; set; } + public Info info { get; set; } + public Source source { get; set; } + public string squarePreview { get; set; } + public string full { get; set; } + public string preview { get; set; } + public string thumb { get; set; } + public bool hasCustomPreview { get; set; } + public Files files { get; set; } + public VideoSources videoSources { get; set; } + } + + public class Preview + { + public int width { get; set; } + public int height { get; set; } + public int size { get; set; } + public string url { get; set; } + } + + public class Source + { + public string source { get; set; } + public int width { get; set; } + public int height { get; set; } + public int size { get; set; } + public int duration { get; set; } + } + + public class VideoSources + { + [JsonProperty("720")] + public object _720 { get; set; } + + [JsonProperty("240")] + public object _240 { get; set; } + } + public class Dash + { + [JsonProperty("CloudFront-Policy")] + public string CloudFrontPolicy { get; set; } + + [JsonProperty("CloudFront-Signature")] + public string CloudFrontSignature { get; set; } + + [JsonProperty("CloudFront-Key-Pair-Id")] + public string CloudFrontKeyPairId { get; set; } + } + + public class Drm + { + public Manifest manifest { get; set; } + public Signature signature { get; set; } + } + public class Hls + { + [JsonProperty("CloudFront-Policy")] + public string CloudFrontPolicy { get; set; } + + [JsonProperty("CloudFront-Signature")] + public string CloudFrontSignature { get; set; } + + [JsonProperty("CloudFront-Key-Pair-Id")] + public string CloudFrontKeyPairId { get; set; } + } + public class Manifest + { + public string? hls { get; set; } + public string? dash { get; set; } + } + public class Signature + { + public Hls hls { get; set; } + public Dash dash { get; set; } + } + } +} diff --git a/OF DL/Entities/Post/SinglePostCollection.cs b/OF DL/Entities/Post/SinglePostCollection.cs new file mode 100644 index 0000000..aceedb5 --- /dev/null +++ b/OF DL/Entities/Post/SinglePostCollection.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace OF_DL.Entities.Post +{ + public class SinglePostCollection + { + public Dictionary SinglePosts = new Dictionary(); + public List SinglePostObjects = new List(); + public List SinglePostMedia = new List(); + } +} diff --git a/OF DL/Entities/Purchased/PaidMessageCollection.cs b/OF DL/Entities/Purchased/PaidMessageCollection.cs new file mode 100644 index 0000000..1222ba0 --- /dev/null +++ b/OF DL/Entities/Purchased/PaidMessageCollection.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using static OF_DL.Entities.Messages.Messages; + +namespace OF_DL.Entities.Purchased +{ + public class PaidMessageCollection + { + public Dictionary PaidMessages = new Dictionary(); + public List PaidMessageObjects = new List(); + public List PaidMessageMedia = new List(); + } +} diff --git a/OF DL/Entities/Purchased/PaidPostCollection.cs b/OF DL/Entities/Purchased/PaidPostCollection.cs new file mode 100644 index 0000000..2e86d97 --- /dev/null +++ b/OF DL/Entities/Purchased/PaidPostCollection.cs @@ -0,0 +1,11 @@ +using static OF_DL.Entities.Messages.Messages; + +namespace OF_DL.Entities.Purchased +{ + public class PaidPostCollection + { + public Dictionary PaidPosts = new Dictionary(); + public List PaidPostObjects = new List(); + public List PaidPostMedia = new List(); + } +} diff --git a/OF DL/Entities/Purchased/Purchased.cs b/OF DL/Entities/Purchased/Purchased.cs new file mode 100644 index 0000000..11fddda --- /dev/null +++ b/OF DL/Entities/Purchased/Purchased.cs @@ -0,0 +1,90 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using static OF_DL.Entities.Messages.Messages; + +namespace OF_DL.Entities.Purchased +{ + public class Purchased + { + public List list { get; set; } + public bool hasMore { get; set; } + + + + + public class FromUser + { + public int id { get; set; } + public string _view { get; set; } + } + public class Author + { + public int id { get; set; } + public string _view { get; set; } + } + + public class Hls + { + [JsonProperty("CloudFront-Policy")] + public string CloudFrontPolicy { get; set; } + + [JsonProperty("CloudFront-Signature")] + public string CloudFrontSignature { get; set; } + + [JsonProperty("CloudFront-Key-Pair-Id")] + public string CloudFrontKeyPairId { get; set; } + } + + + public class List + { + public string responseType { get; set; } + public string text { get; set; } + public object giphyId { get; set; } + public bool? lockedText { get; set; } + public bool? isFree { get; set; } + public string? price { get; set; } + public bool? isMediaReady { get; set; } + public int? mediaCount { get; set; } + public List media { get; set; } + public List previews { get; set; } + public List preview { get; set; } + public bool? isTip { get; set; } + public bool? isReportedByMe { get; set; } + public bool? isCouplePeopleMedia { get; set; } + public object queueId { get; set; } + public FromUser fromUser { get; set; } + public Author author { get; set; } + public bool? isFromQueue { get; set; } + public bool? canUnsendQueue { get; set; } + public int? unsendSecondsQueue { get; set; } + public long id { get; set; } + public bool isOpened { get; set; } + public bool? isNew { get; set; } + public DateTime? createdAt { get; set; } + public DateTime? postedAt { get; set; } + public DateTime? changedAt { get; set; } + public int? cancelSeconds { get; set; } + public bool? isLiked { get; set; } + public bool? canPurchase { get; set; } + public bool? canReport { get; set; } + public bool? isCanceled { get; set; } + public bool? isArchived { get; set; } + } + + public class Manifest + { + public string hls { get; set; } + public string dash { get; set; } + } + + + + + + } +} diff --git a/OF DL/Entities/Purchased/PurchasedTabCollection.cs b/OF DL/Entities/Purchased/PurchasedTabCollection.cs new file mode 100644 index 0000000..f3af333 --- /dev/null +++ b/OF DL/Entities/Purchased/PurchasedTabCollection.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace OF_DL.Entities.Purchased +{ + public class PurchasedTabCollection + { + public long UserId { get; set; } + public string Username { get; set; } = string.Empty; + public PaidPostCollection PaidPosts { get; set; } = new PaidPostCollection(); + public PaidMessageCollection PaidMessages { get; set; } = new PaidMessageCollection(); + } +} diff --git a/OF DL/Entities/Purchased/SinglePaidMessageCollection.cs b/OF DL/Entities/Purchased/SinglePaidMessageCollection.cs new file mode 100644 index 0000000..703530b --- /dev/null +++ b/OF DL/Entities/Purchased/SinglePaidMessageCollection.cs @@ -0,0 +1,18 @@ +using OF_DL.Entities.Messages; +using OF_DL.Entities.Post; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using static OF_DL.Entities.Messages.Messages; + +namespace OF_DL.Entities.Purchased +{ + public class SinglePaidMessageCollection + { + public Dictionary SingleMessages = new Dictionary(); + public List SingleMessageObjects = new List(); + public List SingleMessageMedia = new List(); + } +} diff --git a/OF DL/Entities/ShortDateConverter.cs b/OF DL/Entities/ShortDateConverter.cs new file mode 100644 index 0000000..2ba2cbd --- /dev/null +++ b/OF DL/Entities/ShortDateConverter.cs @@ -0,0 +1,13 @@ +using Newtonsoft.Json.Converters; +using System.Runtime.Serialization; + +namespace OF_DL.Entities +{ + public class ShortDateConverter : IsoDateTimeConverter + { + public ShortDateConverter() + { + DateTimeFormat = "yyyy-MM-dd"; + } + } +} diff --git a/OF DL/Entities/Stories/Stories.cs b/OF DL/Entities/Stories/Stories.cs new file mode 100644 index 0000000..0d8961d --- /dev/null +++ b/OF DL/Entities/Stories/Stories.cs @@ -0,0 +1,96 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace OF_DL.Entities.Stories +{ + public class Stories + { + public int id { get; set; } + public int userId { get; set; } + public bool isWatched { get; set; } + public bool isReady { get; set; } + public List media { get; set; } + public DateTime? createdAt { get; set; } + public object question { get; set; } + public bool canLike { get; set; } + public bool isLiked { get; set; } + public class Files + { + public Full full { get; set; } + public Thumb thumb { get; set; } + public Preview preview { get; set; } + public SquarePreview squarePreview { get; set; } + } + + public class Full + { + public string url { get; set; } + public int width { get; set; } + public int height { get; set; } + public int size { get; set; } + public List sources { get; set; } + } + + public class Medium + { + public long id { get; set; } + public string type { get; set; } + public bool convertedToVideo { get; set; } + public bool canView { get; set; } + public bool hasError { get; set; } + public DateTime? createdAt { get; set; } + public Files files { get; set; } + } + + public class Preview + { + public string url { get; set; } + public int width { get; set; } + public int height { get; set; } + public int size { get; set; } + public Sources sources { get; set; } + } + + public class Source + { + public string url { get; set; } + public int width { get; set; } + public int height { get; set; } + public int duration { get; set; } + public int size { get; set; } + public Sources sources { get; set; } + } + + public class Sources + { + [JsonProperty("720")] + public object _720 { get; set; } + + [JsonProperty("240")] + public object _240 { get; set; } + public string w150 { get; set; } + public string w480 { get; set; } + } + + public class SquarePreview + { + public string url { get; set; } + public int width { get; set; } + public int height { get; set; } + public int size { get; set; } + public Sources sources { get; set; } + } + + public class Thumb + { + public string url { get; set; } + public int width { get; set; } + public int height { get; set; } + public int size { get; set; } + } + } +} diff --git a/OF DL/Entities/Streams/Streams.cs b/OF DL/Entities/Streams/Streams.cs new file mode 100644 index 0000000..a822e97 --- /dev/null +++ b/OF DL/Entities/Streams/Streams.cs @@ -0,0 +1,216 @@ +using Newtonsoft.Json; +using OF_DL.Utils; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace OF_DL.Entities.Streams +{ + public class Streams + { + public List list { get; set; } + public bool hasMore { get; set; } + public string headMarker { get; set; } + public string tailMarker { get; set; } + public Counters counters { get; set; } + public class Author + { + public int id { get; set; } + public string _view { get; set; } + } + + public class Counters + { + public int audiosCount { get; set; } + public int photosCount { get; set; } + public int videosCount { get; set; } + public int mediasCount { get; set; } + public int postsCount { get; set; } + public int streamsCount { get; set; } + public int archivedPostsCount { get; set; } + } + + public class Files + { + public Full full { get; set; } + public Thumb thumb { get; set; } + public Preview preview { get; set; } + public SquarePreview squarePreview { get; set; } + public Drm drm { get; set; } + } + + public class Full + { + public string url { get; set; } + public int width { get; set; } + public int height { get; set; } + public int size { get; set; } + public List sources { get; set; } + } + + public class SquarePreview + { + public string url { get; set; } + public int width { get; set; } + public int height { get; set; } + public int size { get; set; } + } + + public class Thumb + { + public string url { get; set; } + public int width { get; set; } + public int height { get; set; } + public int size { get; set; } + } + + public class Info + { + public Source source { get; set; } + public Preview preview { get; set; } + } + + public class List + { + public string responseType { get; set; } + public long id { get; set; } + public DateTime postedAt { get; set; } + public string postedAtPrecise { get; set; } + public object expiredAt { get; set; } + public Author author { get; set; } + public string text { get; set; } + private string _rawText; + public string rawText + { + get + { + if (string.IsNullOrEmpty(_rawText)) + { + _rawText = XmlUtils.EvaluateInnerText(text); + } + + return _rawText; + } + set + { + _rawText = value; + } + } + public bool lockedText { get; set; } + public bool isFavorite { get; set; } + public bool canReport { get; set; } + public bool canDelete { get; set; } + public bool canComment { get; set; } + public bool canEdit { get; set; } + public bool isPinned { get; set; } + public int favoritesCount { get; set; } + public int mediaCount { get; set; } + public bool isMediaReady { get; set; } + public object voting { get; set; } + public bool isOpened { get; set; } + public bool canToggleFavorite { get; set; } + public int streamId { get; set; } + public string price { get; set; } + public bool hasVoting { get; set; } + public bool isAddedToBookmarks { get; set; } + public bool isArchived { get; set; } + public bool isPrivateArchived { get; set; } + public bool isDeleted { get; set; } + public bool hasUrl { get; set; } + public bool isCouplePeopleMedia { get; set; } + public string cantCommentReason { get; set; } + public int commentsCount { get; set; } + public List mentionedUsers { get; set; } + public List linkedUsers { get; set; } + public string tipsAmount { get; set; } + public string tipsAmountRaw { get; set; } + public List media { get; set; } + public bool canViewMedia { get; set; } + public List preview { get; set; } + } + + public class Medium + { + public long id { get; set; } + public string type { get; set; } + public bool convertedToVideo { get; set; } + public bool canView { get; set; } + public bool hasError { get; set; } + public DateTime? createdAt { get; set; } + public Info info { get; set; } + public Source source { get; set; } + public string squarePreview { get; set; } + public string full { get; set; } + public string preview { get; set; } + public string thumb { get; set; } + public bool hasCustomPreview { get; set; } + public Files files { get; set; } + public VideoSources videoSources { get; set; } + } + + public class Preview + { + public int width { get; set; } + public int height { get; set; } + public int size { get; set; } + public string url { get; set; } + } + + public class Source + { + public string source { get; set; } + public int width { get; set; } + public int height { get; set; } + public int size { get; set; } + public int duration { get; set; } + } + + public class VideoSources + { + [JsonProperty("720")] + public object _720 { get; set; } + + [JsonProperty("240")] + public object _240 { get; set; } + } + public class Drm + { + public Manifest manifest { get; set; } + public Signature signature { get; set; } + } + public class Manifest + { + public string? hls { get; set; } + public string? dash { get; set; } + } + public class Signature + { + public Hls hls { get; set; } + public Dash dash { get; set; } + } + public class Hls + { + [JsonProperty("CloudFront-Policy")] + public string CloudFrontPolicy { get; set; } + + [JsonProperty("CloudFront-Signature")] + public string CloudFrontSignature { get; set; } + + [JsonProperty("CloudFront-Key-Pair-Id")] + public string CloudFrontKeyPairId { get; set; } + } + public class Dash + { + [JsonProperty("CloudFront-Policy")] + public string CloudFrontPolicy { get; set; } + + [JsonProperty("CloudFront-Signature")] + public string CloudFrontSignature { get; set; } + + [JsonProperty("CloudFront-Key-Pair-Id")] + public string CloudFrontKeyPairId { get; set; } + } + } +} diff --git a/OF DL/Entities/Streams/StreamsCollection.cs b/OF DL/Entities/Streams/StreamsCollection.cs new file mode 100644 index 0000000..247a13b --- /dev/null +++ b/OF DL/Entities/Streams/StreamsCollection.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace OF_DL.Entities.Streams +{ + public class StreamsCollection + { + public Dictionary Streams = new Dictionary(); + public List StreamObjects = new List(); + public List StreamMedia = new List(); + } +} diff --git a/OF DL/Entities/Subscriptions.cs b/OF DL/Entities/Subscriptions.cs new file mode 100644 index 0000000..06cf9b0 --- /dev/null +++ b/OF DL/Entities/Subscriptions.cs @@ -0,0 +1,165 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace OF_DL.Entities +{ + public class Subscriptions + { + public List list { get; set; } + public bool hasMore { get; set; } + public class AvatarThumbs + { + public string c50 { get; set; } + public string c144 { get; set; } + } + + public class HeaderSize + { + public int? width { get; set; } + public int? height { get; set; } + } + + public class HeaderThumbs + { + public string w480 { get; set; } + public string w760 { get; set; } + } + + public class List + { + public string view { get; set; } + public string avatar { get; set; } + public AvatarThumbs avatarThumbs { get; set; } + public string header { get; set; } + public HeaderSize headerSize { get; set; } + public HeaderThumbs headerThumbs { get; set; } + public int id { get; set; } + public string name { get; set; } + public string username { get; set; } + public bool? canLookStory { get; set; } + public bool? canCommentStory { get; set; } + public bool? hasNotViewedStory { get; set; } + public bool? isVerified { get; set; } + public bool? canPayInternal { get; set; } + public bool? hasScheduledStream { get; set; } + public bool? hasStream { get; set; } + public bool? hasStories { get; set; } + public bool? tipsEnabled { get; set; } + public bool? tipsTextEnabled { get; set; } + public int? tipsMin { get; set; } + public int? tipsMinInternal { get; set; } + public int? tipsMax { get; set; } + public bool? canEarn { get; set; } + public bool? canAddSubscriber { get; set; } + public string? subscribePrice { get; set; } + public bool? isPaywallRequired { get; set; } + public bool? unprofitable { get; set; } + public List listsStates { get; set; } + public bool? isMuted { get; set; } + public bool? isRestricted { get; set; } + public bool? canRestrict { get; set; } + public bool? subscribedBy { get; set; } + public bool? subscribedByExpire { get; set; } + public DateTime? subscribedByExpireDate { get; set; } + public bool? subscribedByAutoprolong { get; set; } + public bool? subscribedIsExpiredNow { get; set; } + public string? currentSubscribePrice { get; set; } + public bool? subscribedOn { get; set; } + public bool? subscribedOnExpiredNow { get; set; } + public string subscribedOnDuration { get; set; } + public bool? canReport { get; set; } + public bool? canReceiveChatMessage { get; set; } + public bool? hideChat { get; set; } + public DateTime? lastSeen { get; set; } + public bool? isPerformer { get; set; } + public bool? isRealPerformer { get; set; } + public SubscribedByData subscribedByData { get; set; } + public SubscribedOnData subscribedOnData { get; set; } + public bool? canTrialSend { get; set; } + public bool? isBlocked { get; set; } + public string displayName { get; set; } + public string notice { get; set; } + } + + public class ListsState + { + public object id { get; set; } + public string type { get; set; } + public string name { get; set; } + public bool? hasUser { get; set; } + public bool? canAddUser { get; set; } + } + + public class Subscribe + { + public object id { get; set; } + public int? userId { get; set; } + public int? subscriberId { get; set; } + public DateTime? date { get; set; } + public int? duration { get; set; } + public DateTime? startDate { get; set; } + public DateTime? expireDate { get; set; } + public object cancelDate { get; set; } + public string? price { get; set; } + public string? regularPrice { get; set; } + public string? discount { get; set; } + public string action { get; set; } + public string type { get; set; } + public object offerStart { get; set; } + public object offerEnd { get; set; } + public bool? isCurrent { get; set; } + } + + public class SubscribedByData + { + public string? price { get; set; } + public string? newPrice { get; set; } + public string? regularPrice { get; set; } + public string? subscribePrice { get; set; } + public int? discountPercent { get; set; } + public int? discountPeriod { get; set; } + public DateTime? subscribeAt { get; set; } + public DateTime? expiredAt { get; set; } + public DateTime? renewedAt { get; set; } + public object discountFinishedAt { get; set; } + public object discountStartedAt { get; set; } + public string status { get; set; } + public bool? isMuted { get; set; } + public string unsubscribeReason { get; set; } + public string duration { get; set; } + public bool? showPostsInFeed { get; set; } + public List subscribes { get; set; } + public bool? hasActivePaidSubscriptions { get; set; } + } + + public class SubscribedOnData + { + public string? price { get; set; } + public string? newPrice { get; set; } + public string? regularPrice { get; set; } + public string? subscribePrice { get; set; } + public int? discountPercent { get; set; } + public int? discountPeriod { get; set; } + public DateTime? subscribeAt { get; set; } + public DateTime? expiredAt { get; set; } + public DateTime? renewedAt { get; set; } + public object discountFinishedAt { get; set; } + public object discountStartedAt { get; set; } + public object status { get; set; } + public bool? isMuted { get; set; } + public string unsubscribeReason { get; set; } + public string duration { get; set; } + public string? tipsSumm { get; set; } + public string? subscribesSumm { get; set; } + public string? messagesSumm { get; set; } + public string? postsSumm { get; set; } + public string? streamsSumm { get; set; } + public string? totalSumm { get; set; } + public List subscribes { get; set; } + public bool? hasActivePaidSubscriptions { get; set; } + } + } +} diff --git a/OF DL/Entities/ToggleableConfigAttribute.cs b/OF DL/Entities/ToggleableConfigAttribute.cs new file mode 100644 index 0000000..ff0a4e8 --- /dev/null +++ b/OF DL/Entities/ToggleableConfigAttribute.cs @@ -0,0 +1,8 @@ +namespace OF_DL.Entities +{ + [AttributeUsage(AttributeTargets.Property)] + internal class ToggleableConfigAttribute : Attribute + { + } + +} diff --git a/OF DL/Entities/User.cs b/OF DL/Entities/User.cs new file mode 100644 index 0000000..ff95c8f --- /dev/null +++ b/OF DL/Entities/User.cs @@ -0,0 +1,191 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace OF_DL.Entities +{ + public class User + { + public string view { get; set; } + public string? avatar { get; set; } + public AvatarThumbs avatarThumbs { get; set; } + public string? header { get; set; } + public HeaderSize headerSize { get; set; } + public HeaderThumbs headerThumbs { get; set; } + public int? id { get; set; } + public string name { get; set; } + public string username { get; set; } + public bool? canLookStory { get; set; } + public bool? canCommentStory { get; set; } + public bool? hasNotViewedStory { get; set; } + public bool? isVerified { get; set; } + public bool? canPayInternal { get; set; } + public bool? hasScheduledStream { get; set; } + public bool? hasStream { get; set; } + public bool? hasStories { get; set; } + public bool? tipsEnabled { get; set; } + public bool? tipsTextEnabled { get; set; } + public int? tipsMin { get; set; } + public int? tipsMinInternal { get; set; } + public int? tipsMax { get; set; } + public bool? canEarn { get; set; } + public bool? canAddSubscriber { get; set; } + public string? subscribePrice { get; set; } + public string displayName { get; set; } + public string notice { get; set; } + public bool? isPaywallRequired { get; set; } + public bool? unprofitable { get; set; } + public List listsStates { get; set; } + public bool? isMuted { get; set; } + public bool? isRestricted { get; set; } + public bool? canRestrict { get; set; } + public bool? subscribedBy { get; set; } + public bool? subscribedByExpire { get; set; } + public DateTime? subscribedByExpireDate { get; set; } + public bool? subscribedByAutoprolong { get; set; } + public bool? subscribedIsExpiredNow { get; set; } + public string? currentSubscribePrice { get; set; } + public bool? subscribedOn { get; set; } + public bool? subscribedOnExpiredNow { get; set; } + public string subscribedOnDuration { get; set; } + public DateTime? joinDate { get; set; } + public bool? isReferrerAllowed { get; set; } + public string about { get; set; } + public string rawAbout { get; set; } + public object website { get; set; } + public object wishlist { get; set; } + public object location { get; set; } + public int? postsCount { get; set; } + public int? archivedPostsCount { get; set; } + public int? privateArchivedPostsCount { get; set; } + public int? photosCount { get; set; } + public int? videosCount { get; set; } + public int? audiosCount { get; set; } + public int? mediasCount { get; set; } + public DateTime? lastSeen { get; set; } + public int? favoritesCount { get; set; } + public int? favoritedCount { get; set; } + public bool? showPostsInFeed { get; set; } + public bool? canReceiveChatMessage { get; set; } + public bool? isPerformer { get; set; } + public bool? isRealPerformer { get; set; } + public bool? isSpotifyConnected { get; set; } + public int? subscribersCount { get; set; } + public bool? hasPinnedPosts { get; set; } + public bool? hasLabels { get; set; } + public bool? canChat { get; set; } + public string? callPrice { get; set; } + public bool? isPrivateRestriction { get; set; } + public bool? showSubscribersCount { get; set; } + public bool? showMediaCount { get; set; } + public SubscribedByData subscribedByData { get; set; } + public SubscribedOnData subscribedOnData { get; set; } + public bool? canPromotion { get; set; } + public bool? canCreatePromotion { get; set; } + public bool? canCreateTrial { get; set; } + public bool? isAdultContent { get; set; } + public bool? canTrialSend { get; set; } + public bool? hadEnoughLastPhotos { get; set; } + public bool? hasLinks { get; set; } + public DateTime? firstPublishedPostDate { get; set; } + public bool? isSpringConnected { get; set; } + public bool? isFriend { get; set; } + public bool? isBlocked { get; set; } + public bool? canReport { get; set; } + public class AvatarThumbs + { + public string c50 { get; set; } + public string c144 { get; set; } + } + + public class HeaderSize + { + public int? width { get; set; } + public int? height { get; set; } + } + + public class HeaderThumbs + { + public string w480 { get; set; } + public string w760 { get; set; } + } + + public class ListsState + { + public string id { get; set; } + public string type { get; set; } + public string name { get; set; } + public bool hasUser { get; set; } + public bool canAddUser { get; set; } + } + + public class Subscribe + { + public long? id { get; set; } + public int? userId { get; set; } + public int? subscriberId { get; set; } + public DateTime? date { get; set; } + public int? duration { get; set; } + public DateTime? startDate { get; set; } + public DateTime? expireDate { get; set; } + public object cancelDate { get; set; } + public string? price { get; set; } + public string? regularPrice { get; set; } + public int? discount { get; set; } + public string action { get; set; } + public string type { get; set; } + public object offerStart { get; set; } + public object offerEnd { get; set; } + public bool? isCurrent { get; set; } + } + + public class SubscribedByData + { + public string? price { get; set; } + public string? newPrice { get; set; } + public string? regularPrice { get; set; } + public string? subscribePrice { get; set; } + public int? discountPercent { get; set; } + public int? discountPeriod { get; set; } + public DateTime? subscribeAt { get; set; } + public DateTime? expiredAt { get; set; } + public object? renewedAt { get; set; } + public object? discountFinishedAt { get; set; } + public object? discountStartedAt { get; set; } + public string? status { get; set; } + public bool? isMuted { get; set; } + public string? unsubscribeReason { get; set; } + public string? duration { get; set; } + public bool? showPostsInFeed { get; set; } + public List? subscribes { get; set; } + } + + public class SubscribedOnData + { + public string? price { get; set; } + public string? newPrice { get; set; } + public string? regularPrice { get; set; } + public string? subscribePrice { get; set; } + public int? discountPercent { get; set; } + public int? discountPeriod { get; set; } + public DateTime? subscribeAt { get; set; } + public DateTime? expiredAt { get; set; } + public DateTime? renewedAt { get; set; } + public object? discountFinishedAt { get; set; } + public object? discountStartedAt { get; set; } + public object? status { get; set; } + public bool? isMuted { get; set; } + public string? unsubscribeReason { get; set; } + public string? duration { get; set; } + public string? tipsSumm { get; set; } + public string? subscribesSumm { get; set; } + public string? messagesSumm { get; set; } + public string? postsSumm { get; set; } + public string? streamsSumm { get; set; } + public string? totalSumm { get; set; } + public List? subscribes { get; set; } + } + } +} diff --git a/OF DL/Enumerations/CustomFileNameOption.cs b/OF DL/Enumerations/CustomFileNameOption.cs new file mode 100644 index 0000000..eecd762 --- /dev/null +++ b/OF DL/Enumerations/CustomFileNameOption.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace OF_DL.Enumerations; + +public enum CustomFileNameOption +{ + ReturnOriginal, + ReturnEmpty, +} diff --git a/OF DL/Enumerations/DownloadDateSelection.cs b/OF DL/Enumerations/DownloadDateSelection.cs new file mode 100644 index 0000000..926c7bd --- /dev/null +++ b/OF DL/Enumerations/DownloadDateSelection.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace OF_DL.Enumerations +{ + public enum DownloadDateSelection + { + before, + after, + } +} diff --git a/OF DL/Enumerations/LoggingLevel.cs b/OF DL/Enumerations/LoggingLevel.cs new file mode 100644 index 0000000..6757262 --- /dev/null +++ b/OF DL/Enumerations/LoggingLevel.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace OF_DL.Enumerations +{ + public enum LoggingLevel + { + // + // Summary: + // Anything and everything you might want to know about a running block of code. + Verbose, + // + // Summary: + // Internal system events that aren't necessarily observable from the outside. + Debug, + // + // Summary: + // The lifeblood of operational intelligence - things happen. + Information, + // + // Summary: + // Service is degraded or endangered. + Warning, + // + // Summary: + // Functionality is unavailable, invariants are broken or data is lost. + Error, + // + // Summary: + // If you have a pager, it goes off when one of these occurs. + Fatal + } +} diff --git a/OF DL/Enumerations/MediaType.cs b/OF DL/Enumerations/MediaType.cs new file mode 100644 index 0000000..86078e8 --- /dev/null +++ b/OF DL/Enumerations/MediaType.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace OF_DL.Enumurations +{ + public enum MediaType + { + PaidPosts = 10, + Posts = 20, + Archived = 30, + Stories = 40, + Highlights = 50, + Messages = 60, + PaidMessages = 70 + } +} diff --git a/OF DL/Helpers/APIHelper.cs b/OF DL/Helpers/APIHelper.cs new file mode 100644 index 0000000..bef4db8 --- /dev/null +++ b/OF DL/Helpers/APIHelper.cs @@ -0,0 +1,2839 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using OF_DL.Entities; +using OF_DL.Entities.Archived; +using OF_DL.Entities.Highlights; +using OF_DL.Entities.Lists; +using OF_DL.Entities.Messages; +using OF_DL.Entities.Post; +using OF_DL.Entities.Purchased; +using OF_DL.Entities.Stories; +using OF_DL.Entities.Streams; +using OF_DL.Enumurations; +using Serilog; +using Spectre.Console; +using System.Globalization; +using System.Security.Cryptography; +using System.Text; +using System.Text.Json; +using System.Xml.Linq; +using WidevineClient.Widevine; +using static WidevineClient.HttpUtil; + +namespace OF_DL.Helpers; + +public class APIHelper : IAPIHelper +{ + private static readonly JsonSerializerSettings m_JsonSerializerSettings; + private readonly IDBHelper m_DBHelper; + private readonly Auth auth; + private static DateTime? cachedDynamicRulesExpiration; + private static DynamicRules? cachedDynamicRules; + + static APIHelper() + { + m_JsonSerializerSettings = new() + { + MissingMemberHandling = MissingMemberHandling.Ignore + }; + } + + public APIHelper(Auth auth, IDownloadConfig downloadConfig) + { + this.auth = auth; + m_DBHelper = new DBHelper(downloadConfig); + } + + + public Dictionary GetDynamicHeaders(string path, string queryParams) + { + Log.Debug("Calling GetDynamicHeaders"); + Log.Debug($"Path: {path}"); + Log.Debug($"Query Params: {queryParams}"); + + DynamicRules? root; + + //Check if we have a cached version of the dynamic rules + if (cachedDynamicRules != null && cachedDynamicRulesExpiration.HasValue && + DateTime.UtcNow < cachedDynamicRulesExpiration) + { + Log.Debug("Using cached dynamic rules"); + root = cachedDynamicRules; + } + else + { + //Get rules from GitHub and fallback to local file + string? dynamicRulesJSON = GetDynamicRules(); + if (!string.IsNullOrEmpty(dynamicRulesJSON)) + { + Log.Debug("Using dynamic rules from GitHub"); + root = JsonConvert.DeserializeObject(dynamicRulesJSON); + + // Cache the GitHub response for 15 minutes + cachedDynamicRules = root; + cachedDynamicRulesExpiration = DateTime.UtcNow.AddMinutes(15); + } + else + { + Log.Debug("Using dynamic rules from local file"); + root = JsonConvert.DeserializeObject(File.ReadAllText("rules.json")); + + // Cache the dynamic rules from local file to prevent unnecessary disk + // operations and frequent call to GitHub. Since the GitHub dynamic rules + // are preferred to the local file, the cache time is shorter than when dynamic rules + // are successfully retrieved from GitHub. + cachedDynamicRules = root; + cachedDynamicRulesExpiration = DateTime.UtcNow.AddMinutes(5); + } + } + + DateTimeOffset dto = (DateTimeOffset)DateTime.UtcNow; + long timestamp = dto.ToUnixTimeMilliseconds(); + + string input = $"{root!.StaticParam}\n{timestamp}\n{path + queryParams}\n{auth.USER_ID}"; + byte[] inputBytes = Encoding.UTF8.GetBytes(input); + byte[] hashBytes = SHA1.HashData(inputBytes); + string hashString = BitConverter.ToString(hashBytes).Replace("-", "").ToLower(); + + var checksum = root.ChecksumIndexes.Aggregate(0, (current, number) => current + hashString[number]) + root.ChecksumConstant!.Value; + var sign = $"{root.Prefix}:{hashString}:{checksum.ToString("X").ToLower()}:{root.Suffix}"; + + Dictionary headers = new() + { + { "accept", "application/json, text/plain" }, + { "app-token", root.AppToken! }, + { "cookie", auth!.COOKIE! }, + { "sign", sign }, + { "time", timestamp.ToString() }, + { "user-id", auth!.USER_ID! }, + { "user-agent", auth!.USER_AGENT! }, + { "x-bc", auth!.X_BC! } + }; + return headers; + } + + + private async Task BuildHeaderAndExecuteRequests(Dictionary getParams, string endpoint, HttpClient client) + { + Log.Debug("Calling BuildHeaderAndExecuteRequests"); + + HttpRequestMessage request = await BuildHttpRequestMessage(getParams, endpoint); + using var response = await client.SendAsync(request); + response.EnsureSuccessStatusCode(); + string body = await response.Content.ReadAsStringAsync(); + + Log.Debug(body); + + return body; + } + + + private async Task BuildHttpRequestMessage(Dictionary getParams, string endpoint) + { + Log.Debug("Calling BuildHttpRequestMessage"); + + string queryParams = "?" + string.Join("&", getParams.Select(kvp => $"{kvp.Key}={kvp.Value}")); + + Dictionary headers = GetDynamicHeaders($"/api2/v2{endpoint}", queryParams); + + HttpRequestMessage request = new(HttpMethod.Get, $"{Constants.API_URL}{endpoint}{queryParams}"); + + Log.Debug($"Full request URL: {Constants.API_URL}{endpoint}{queryParams}"); + + foreach (KeyValuePair keyValuePair in headers) + { + request.Headers.Add(keyValuePair.Key, keyValuePair.Value); + } + + return request; + } + + private static double ConvertToUnixTimestampWithMicrosecondPrecision(DateTime date) + { + DateTime origin = new(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); + TimeSpan diff = date.ToUniversalTime() - origin; + + return diff.TotalSeconds; // This gives the number of seconds. If you need milliseconds, use diff.TotalMilliseconds + } + + public static bool IsStringOnlyDigits(string input) + { + return input.All(char.IsDigit); + } + + + private static HttpClient GetHttpClient(IDownloadConfig? config = null) + { + var client = new HttpClient(); + if (config?.Timeout != null && config.Timeout > 0) + { + client.Timeout = TimeSpan.FromSeconds(config.Timeout.Value); + } + return client; + } + + + /// + /// this one is used during initialization only + /// if the config option is not available then no modificatiotns will be done on the getParams + /// + /// + /// + /// + private static void UpdateGetParamsForDateSelection(Enumerations.DownloadDateSelection downloadDateSelection, ref Dictionary getParams, DateTime? dt) + { + //if (config.DownloadOnlySpecificDates && dt.HasValue) + //{ + if (dt.HasValue) + { + UpdateGetParamsForDateSelection( + downloadDateSelection, + ref getParams, + ConvertToUnixTimestampWithMicrosecondPrecision(dt.Value).ToString("0.000000", CultureInfo.InvariantCulture) + ); + } + //} + } + + private static void UpdateGetParamsForDateSelection(Enumerations.DownloadDateSelection downloadDateSelection, ref Dictionary getParams, string unixTimeStampInMicrosec) + { + switch (downloadDateSelection) + { + case Enumerations.DownloadDateSelection.before: + getParams["beforePublishTime"] = unixTimeStampInMicrosec; + break; + case Enumerations.DownloadDateSelection.after: + getParams["order"] = "publish_date_asc"; + getParams["afterPublishTime"] = unixTimeStampInMicrosec; + break; + } + } + + + public async Task GetUserInfo(string endpoint) + { + Log.Debug($"Calling GetUserInfo: {endpoint}"); + + try + { + Entities.User? user = new(); + int post_limit = 50; + Dictionary getParams = new() + { + { "limit", post_limit.ToString() }, + { "order", "publish_date_asc" } + }; + + HttpClient client = new(); + HttpRequestMessage request = await BuildHttpRequestMessage(getParams, endpoint); + + using var response = await client.SendAsync(request); + + if (!response.IsSuccessStatusCode) + { + return user; + } + + response.EnsureSuccessStatusCode(); + var body = await response.Content.ReadAsStringAsync(); + user = JsonConvert.DeserializeObject(body, m_JsonSerializerSettings); + return user; + } + catch (Exception ex) + { + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + Log.Error("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + if (ex.InnerException != null) + { + Console.WriteLine("\nInner Exception:"); + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + Log.Error("Inner Exception: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + } + } + return null; + } + + public async Task GetUserInfoById(string endpoint) + { + try + { + HttpClient client = new(); + HttpRequestMessage request = await BuildHttpRequestMessage(new Dictionary(), endpoint); + + using var response = await client.SendAsync(request); + + response.EnsureSuccessStatusCode(); + var body = await response.Content.ReadAsStringAsync(); + + //if the content creator doesnt exist, we get a 200 response, but the content isnt usable + //so let's not throw an exception, since "content creator no longer exists" is handled elsewhere + //which means we wont get loads of exceptions + if (body.Equals("[]")) + return null; + + JObject jObject = JObject.Parse(body); + + return jObject; + } + catch (Exception ex) + { + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + Log.Error("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + if (ex.InnerException != null) + { + Console.WriteLine("\nInner Exception:"); + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + Log.Error("Inner Exception: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + } + } + return null; + } + + + public async Task?> GetAllSubscriptions(Dictionary getParams, string endpoint, bool includeRestricted, IDownloadConfig config) + { + try + { + Dictionary users = new(); + Subscriptions subscriptions = new(); + + Log.Debug("Calling GetAllSubscrptions"); + + string? body = await BuildHeaderAndExecuteRequests(getParams, endpoint, new HttpClient()); + + subscriptions = JsonConvert.DeserializeObject(body); + if (subscriptions != null && subscriptions.hasMore) + { + getParams["offset"] = subscriptions.list.Count.ToString(); + + while (true) + { + Subscriptions newSubscriptions = new(); + string? loopbody = await BuildHeaderAndExecuteRequests(getParams, endpoint, new HttpClient()); + + if (!string.IsNullOrEmpty(loopbody) && (!loopbody.Contains("[]") || loopbody.Trim() != "[]")) + { + newSubscriptions = JsonConvert.DeserializeObject(loopbody, m_JsonSerializerSettings); + } + else + { + break; + } + + subscriptions.list.AddRange(newSubscriptions.list); + if (!newSubscriptions.hasMore) + { + break; + } + getParams["offset"] = subscriptions.list.Count.ToString(); + } + } + + foreach (Subscriptions.List subscription in subscriptions.list) + { + if ((!(subscription.isRestricted ?? false) || ((subscription.isRestricted ?? false) && includeRestricted)) + && !users.ContainsKey(subscription.username)) + { + users.Add(subscription.username, subscription.id); + } + } + + return users; + } + catch (Exception ex) + { + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + Log.Error("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + if (ex.InnerException != null) + { + Console.WriteLine("\nInner Exception:"); + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + Log.Error("Inner Exception: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + } + } + return null; + } + + public async Task?> GetActiveSubscriptions(string endpoint, bool includeRestricted, IDownloadConfig config) + { + Dictionary getParams = new() + { + { "offset", "0" }, + { "limit", "50" }, + { "type", "active" }, + { "format", "infinite"} + }; + + return await GetAllSubscriptions(getParams, endpoint, includeRestricted, config); + } + + + public async Task?> GetExpiredSubscriptions(string endpoint, bool includeRestricted, IDownloadConfig config) + { + + Dictionary getParams = new() + { + { "offset", "0" }, + { "limit", "50" }, + { "type", "expired" }, + { "format", "infinite"} + }; + + Log.Debug("Calling GetExpiredSubscriptions"); + + return await GetAllSubscriptions(getParams, endpoint, includeRestricted, config); + } + + + public async Task> GetLists(string endpoint, IDownloadConfig config) + { + Log.Debug("Calling GetLists"); + + try + { + int offset = 0; + Dictionary getParams = new() + { + { "offset", offset.ToString() }, + { "skip_users", "all" }, + { "limit", "50" }, + { "format", "infinite" } + }; + Dictionary lists = new(); + while (true) + { + string? body = await BuildHeaderAndExecuteRequests(getParams, endpoint, new HttpClient()); + + if (body == null) + { + break; + } + + UserList userList = JsonConvert.DeserializeObject(body); + if (userList == null) + { + break; + } + + foreach (UserList.List l in userList.list) + { + if (IsStringOnlyDigits(l.id) && !lists.ContainsKey(l.name)) + { + lists.Add(l.name, Convert.ToInt32(l.id)); + } + } + + if (userList.hasMore.Value) + { + offset += 50; + getParams["offset"] = Convert.ToString(offset); + } + else + { + break; + } + + } + return lists; + } + catch (Exception ex) + { + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + Log.Error("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + if (ex.InnerException != null) + { + Console.WriteLine("\nInner Exception:"); + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + Log.Error("Inner Exception: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + } + } + return null; + } + + + public async Task?> GetListUsers(string endpoint, IDownloadConfig config) + { + Log.Debug($"Calling GetListUsers - {endpoint}"); + + try + { + int offset = 0; + Dictionary getParams = new() + { + { "offset", offset.ToString() }, + { "limit", "50" } + }; + List users = new(); + + while (true) + { + var body = await BuildHeaderAndExecuteRequests(getParams, endpoint, new HttpClient()); + if (body == null) + { + break; + } + + List? usersList = JsonConvert.DeserializeObject>(body); + + if (usersList == null || usersList.Count <= 0) + { + break; + } + + foreach (UsersList ul in usersList) + { + users.Add(ul.username); + } + + if (users.Count < 50) + { + break; + } + + offset += 50; + getParams["offset"] = Convert.ToString(offset); + + } + return users; + } + catch (Exception ex) + { + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + Log.Error("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + if (ex.InnerException != null) + { + Console.WriteLine("\nInner Exception:"); + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + Log.Error("Inner Exception: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + } + } + return null; + } + + + public async Task> GetMedia(MediaType mediatype, + string endpoint, + string? username, + string folder, + IDownloadConfig config, + List paid_post_ids) + { + + Log.Debug($"Calling GetMedia - {username}"); + + try + { + Dictionary return_urls = new(); + int post_limit = 50; + int limit = 5; + int offset = 0; + + Dictionary getParams = new(); + + switch (mediatype) + { + + case MediaType.Stories: + getParams = new Dictionary + { + { "limit", post_limit.ToString() }, + { "order", "publish_date_desc" } + }; + break; + + case MediaType.Highlights: + getParams = new Dictionary + { + { "limit", limit.ToString() }, + { "offset", offset.ToString() } + }; + break; + } + + var body = await BuildHeaderAndExecuteRequests(getParams, endpoint, new HttpClient()); + + + if (mediatype == MediaType.Stories) + { + Log.Debug("Media Stories - " + endpoint); + + var stories = JsonConvert.DeserializeObject>(body, m_JsonSerializerSettings) ?? new List(); + + foreach (Stories story in stories) + { + if (story.media[0].createdAt.HasValue) + { + await m_DBHelper.AddStory(folder, story.id, string.Empty, "0", false, false, story.media[0].createdAt.Value); + } + else if (story.createdAt.HasValue) + { + await m_DBHelper.AddStory(folder, story.id, string.Empty, "0", false, false, story.createdAt.Value); + } + else + { + await m_DBHelper.AddStory(folder, story.id, string.Empty, "0", false, false, DateTime.Now); + } + if (story.media != null && story.media.Count > 0) + { + foreach (Stories.Medium medium in story.media) + { + await m_DBHelper.AddMedia(folder, medium.id, story.id, medium.files.full.url, null, null, null, "Stories", medium.type == "photo" ? "Images" : (medium.type == "video" || medium.type == "gif" ? "Videos" : (medium.type == "audio" ? "Audios" : null)), false, false, null); + if (medium.type == "photo" && !config.DownloadImages) + { + continue; + } + if (medium.type == "video" && !config.DownloadVideos) + { + continue; + } + if (medium.type == "gif" && !config.DownloadVideos) + { + continue; + } + if (medium.type == "audio" && !config.DownloadAudios) + { + continue; + } + if (medium.canView && !medium.files.full.url.Contains("upload")) + { + if (!return_urls.ContainsKey(medium.id)) + { + return_urls.Add(medium.id, medium.files.full.url); + } + } + } + } + } + } + else if (mediatype == MediaType.Highlights) + { + List highlight_ids = new(); + var highlights = JsonConvert.DeserializeObject(body, m_JsonSerializerSettings) ?? new Highlights(); + + if (highlights.hasMore) + { + offset += 5; + getParams["offset"] = offset.ToString(); + while (true) + { + Highlights newhighlights = new(); + + Log.Debug("Media Highlights - " + endpoint); + + var loopbody = await BuildHeaderAndExecuteRequests(getParams, endpoint, GetHttpClient(config)); + newhighlights = JsonConvert.DeserializeObject(loopbody, m_JsonSerializerSettings); + + highlights.list.AddRange(newhighlights.list); + if (!newhighlights.hasMore) + { + break; + } + offset += 5; + getParams["offset"] = offset.ToString(); + } + } + foreach (Highlights.List list in highlights.list) + { + if (!highlight_ids.Contains(list.id.ToString())) + { + highlight_ids.Add(list.id.ToString()); + } + } + + foreach (string highlight_id in highlight_ids) + { + HighlightMedia highlightMedia = new(); + Dictionary highlight_headers = GetDynamicHeaders("/api2/v2/stories/highlights/" + highlight_id, string.Empty); + + HttpClient highlight_client = GetHttpClient(config); + + HttpRequestMessage highlight_request = new(HttpMethod.Get, $"https://onlyfans.com/api2/v2/stories/highlights/{highlight_id}"); + + foreach (KeyValuePair keyValuePair in highlight_headers) + { + highlight_request.Headers.Add(keyValuePair.Key, keyValuePair.Value); + } + + using var highlightResponse = await highlight_client.SendAsync(highlight_request); + highlightResponse.EnsureSuccessStatusCode(); + var highlightBody = await highlightResponse.Content.ReadAsStringAsync(); + highlightMedia = JsonConvert.DeserializeObject(highlightBody, m_JsonSerializerSettings); + if (highlightMedia != null) + { + foreach (HighlightMedia.Story item in highlightMedia.stories) + { + if (item.media[0].createdAt.HasValue) + { + await m_DBHelper.AddStory(folder, item.id, string.Empty, "0", false, false, item.media[0].createdAt.Value); + } + else if (item.createdAt.HasValue) + { + await m_DBHelper.AddStory(folder, item.id, string.Empty, "0", false, false, item.createdAt.Value); + } + else + { + await m_DBHelper.AddStory(folder, item.id, string.Empty, "0", false, false, DateTime.Now); + } + if (item.media.Count > 0 && item.media[0].canView) + { + foreach (HighlightMedia.Medium medium in item.media) + { + await m_DBHelper.AddMedia(folder, medium.id, item.id, item.media[0].files.full.url, null, null, null, "Stories", medium.type == "photo" ? "Images" : (medium.type == "video" || medium.type == "gif" ? "Videos" : (medium.type == "audio" ? "Audios" : null)), false, false, null); + if (medium.type == "photo" && !config.DownloadImages) + { + continue; + } + if (medium.type == "video" && !config.DownloadVideos) + { + continue; + } + if (medium.type == "gif" && !config.DownloadVideos) + { + continue; + } + if (medium.type == "audio" && !config.DownloadAudios) + { + continue; + } + if (!return_urls.ContainsKey(medium.id)) + { + return_urls.Add(medium.id, item.media[0].files.full.url); + } + } + } + } + } + } + } + + return return_urls; + } + catch (Exception ex) + { + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + Log.Error("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + if (ex.InnerException != null) + { + Console.WriteLine("\nInner Exception:"); + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + Log.Error("Inner Exception: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + } + } + return null; + } + + + public async Task GetPaidPosts(string endpoint, string folder, string username, IDownloadConfig config, List paid_post_ids, StatusContext ctx) + { + Log.Debug($"Calling GetPaidPosts - {username}"); + + try + { + Purchased paidPosts = new(); + PaidPostCollection paidPostCollection = new(); + int post_limit = 50; + Dictionary getParams = new() + { + { "limit", post_limit.ToString() }, + { "order", "publish_date_desc" }, + { "format", "infinite" }, + { "user_id", username } + }; + + var body = await BuildHeaderAndExecuteRequests(getParams, endpoint, GetHttpClient(config)); + paidPosts = JsonConvert.DeserializeObject(body, m_JsonSerializerSettings); + ctx.Status($"[red]Getting Paid Posts\n[/] [red]Found {paidPosts.list.Count}[/]"); + ctx.Spinner(Spinner.Known.Dots); + ctx.SpinnerStyle(Style.Parse("blue")); + if (paidPosts != null && paidPosts.hasMore) + { + getParams["offset"] = paidPosts.list.Count.ToString(); + while (true) + { + + Purchased newPaidPosts = new(); + + var loopbody = await BuildHeaderAndExecuteRequests(getParams, endpoint, GetHttpClient(config)); + newPaidPosts = JsonConvert.DeserializeObject(loopbody, m_JsonSerializerSettings); + + paidPosts.list.AddRange(newPaidPosts.list); + ctx.Status($"[red]Getting Paid Posts\n[/] [red]Found {paidPosts.list.Count}[/]"); + ctx.Spinner(Spinner.Known.Dots); + ctx.SpinnerStyle(Style.Parse("blue")); + if (!newPaidPosts.hasMore) + { + break; + } + getParams["offset"] = Convert.ToString(Convert.ToInt32(getParams["offset"]) + post_limit); + } + + } + + foreach (Purchased.List purchase in paidPosts.list) + { + if (purchase.responseType == "post" && purchase.media != null && purchase.media.Count > 0) + { + List previewids = new(); + if (purchase.previews != null) + { + for (int i = 0; i < purchase.previews.Count; i++) + { + if (purchase.previews[i] is long previewId) + { + if (!previewids.Contains(previewId)) + { + previewids.Add(previewId); + } + } + } + } + else if (purchase.preview != null) + { + for (int i = 0; i < purchase.preview.Count; i++) + { + if (purchase.preview[i] is long previewId) + { + if (!previewids.Contains(previewId)) + { + previewids.Add(previewId); + } + } + } + } + await m_DBHelper.AddPost(folder, purchase.id, purchase.text != null ? purchase.text : string.Empty, purchase.price != null ? purchase.price.ToString() : "0", purchase.price != null && purchase.isOpened ? true : false, purchase.isArchived.HasValue ? purchase.isArchived.Value : false, purchase.createdAt != null ? purchase.createdAt.Value : purchase.postedAt.Value); + paidPostCollection.PaidPostObjects.Add(purchase); + foreach (Messages.Medium medium in purchase.media) + { + if (!previewids.Contains(medium.id)) + { + paid_post_ids.Add(medium.id); + } + + if (medium.type == "photo" && !config.DownloadImages) + { + continue; + } + if (medium.type == "video" && !config.DownloadVideos) + { + continue; + } + if (medium.type == "gif" && !config.DownloadVideos) + { + continue; + } + if (medium.type == "audio" && !config.DownloadAudios) + { + continue; + } + if (previewids.Count > 0) + { + bool has = previewids.Any(cus => cus.Equals(medium.id)); + if (!has && medium.canView && medium.files != null && medium.files.full != null && !string.IsNullOrEmpty(medium.files.full.url) && !medium.files.full.url.Contains("upload")) + { + if (!paidPostCollection.PaidPosts.ContainsKey(medium.id)) + { + await m_DBHelper.AddMedia(folder, medium.id, purchase.id, medium.files.full.url, null, null, null, "Posts", medium.type == "photo" ? "Images" : (medium.type == "video" || medium.type == "gif" ? "Videos" : (medium.type == "audio" ? "Audios" : null)), previewids.Contains(medium.id) ? true : false, false, null); + paidPostCollection.PaidPosts.Add(medium.id, medium.files.full.url); + paidPostCollection.PaidPostMedia.Add(medium); + } + } + else if (!has && medium.canView && medium.files != null && medium.files.drm != null) + { + + if (!paidPostCollection.PaidPosts.ContainsKey(medium.id)) + { + await m_DBHelper.AddMedia(folder, medium.id, purchase.id, medium.files.drm.manifest.dash, null, null, null, "Posts", medium.type == "photo" ? "Images" : (medium.type == "video" || medium.type == "gif" ? "Videos" : (medium.type == "audio" ? "Audios" : null)), previewids.Contains(medium.id) ? true : false, false, null); + paidPostCollection.PaidPosts.Add(medium.id, $"{medium.files.drm.manifest.dash},{medium.files.drm.signature.dash.CloudFrontPolicy},{medium.files.drm.signature.dash.CloudFrontSignature},{medium.files.drm.signature.dash.CloudFrontKeyPairId},{medium.id},{purchase.id}"); + paidPostCollection.PaidPostMedia.Add(medium); + } + + } + } + else + { + if (medium.canView && medium.files != null && medium.files.full != null && !string.IsNullOrEmpty(medium.files.full.url) && !medium.files.full.url.Contains("upload")) + { + if (!paidPostCollection.PaidPosts.ContainsKey(medium.id)) + { + await m_DBHelper.AddMedia(folder, medium.id, purchase.id, medium.files.full.url, null, null, null, "Posts", medium.type == "photo" ? "Images" : (medium.type == "video" || medium.type == "gif" ? "Videos" : (medium.type == "audio" ? "Audios" : null)), previewids.Contains(medium.id) ? true : false, false, null); + paidPostCollection.PaidPosts.Add(medium.id, medium.files.full.url); + paidPostCollection.PaidPostMedia.Add(medium); + } + } + else if (medium.canView && medium.files != null && medium.files.drm != null) + { + if (!paidPostCollection.PaidPosts.ContainsKey(medium.id)) + { + await m_DBHelper.AddMedia(folder, medium.id, purchase.id, medium.files.drm.manifest.dash, null, null, null, "Posts", medium.type == "photo" ? "Images" : (medium.type == "video" || medium.type == "gif" ? "Videos" : (medium.type == "audio" ? "Audios" : null)), previewids.Contains(medium.id) ? true : false, false, null); + paidPostCollection.PaidPosts.Add(medium.id, $"{medium.files.drm.manifest.dash},{medium.files.drm.signature.dash.CloudFrontPolicy},{medium.files.drm.signature.dash.CloudFrontSignature},{medium.files.drm.signature.dash.CloudFrontKeyPairId},{medium.id},{purchase.id}"); + paidPostCollection.PaidPostMedia.Add(medium); + } + } + } + } + } + } + return paidPostCollection; + } + catch (Exception ex) + { + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + Log.Error("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + if (ex.InnerException != null) + { + Console.WriteLine("\nInner Exception:"); + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + Log.Error("Inner Exception: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + } + } + return null; + } + + + public async Task GetPosts(string endpoint, string folder, IDownloadConfig config, List paid_post_ids, StatusContext ctx) + { + Log.Debug($"Calling GetPosts - {endpoint}"); + + try + { + Post posts = new(); + PostCollection postCollection = new(); + int post_limit = 50; + Dictionary getParams = new() + { + { "limit", post_limit.ToString() }, + { "order", "publish_date_desc" }, + { "format", "infinite" } + }; + + Enumerations.DownloadDateSelection downloadDateSelection = Enumerations.DownloadDateSelection.before; + DateTime? downloadAsOf = null; + + if (config.DownloadOnlySpecificDates && config.CustomDate.HasValue) + { + downloadDateSelection = config.DownloadDateSelection; + downloadAsOf = config.CustomDate; + } + else if (config.DownloadPostsIncrementally) + { + var mostRecentPostDate = await m_DBHelper.GetMostRecentPostDate(folder); + if (mostRecentPostDate.HasValue) + { + downloadDateSelection = Enumerations.DownloadDateSelection.after; + downloadAsOf = mostRecentPostDate.Value.AddMinutes(-5); // Back track a little for a margin of error + } + } + + UpdateGetParamsForDateSelection( + downloadDateSelection, + ref getParams, + downloadAsOf); + + var body = await BuildHeaderAndExecuteRequests(getParams, endpoint, new HttpClient()); + posts = JsonConvert.DeserializeObject(body, m_JsonSerializerSettings); + ctx.Status($"[red]Getting Posts (this may take a long time, depending on the number of Posts the creator has)\n[/] [red]Found {posts.list.Count}[/]"); + ctx.Spinner(Spinner.Known.Dots); + ctx.SpinnerStyle(Style.Parse("blue")); + if (posts != null && posts.hasMore) + { + UpdateGetParamsForDateSelection( + downloadDateSelection, + ref getParams, + posts.tailMarker); + + while (true) + { + Post newposts = new(); + + var loopbody = await BuildHeaderAndExecuteRequests(getParams, endpoint, GetHttpClient(config)); + newposts = JsonConvert.DeserializeObject(loopbody, m_JsonSerializerSettings); + + posts.list.AddRange(newposts.list); + ctx.Status($"[red]Getting Posts (this may take a long time, depending on the number of Posts the creator has)\n[/] [red]Found {posts.list.Count}[/]"); + ctx.Spinner(Spinner.Known.Dots); + ctx.SpinnerStyle(Style.Parse("blue")); + if (!newposts.hasMore) + { + break; + } + + UpdateGetParamsForDateSelection( + downloadDateSelection, + ref getParams, + newposts.tailMarker); + } + } + + foreach (Post.List post in posts.list) + { + if (config.SkipAds) + { + if (post.rawText != null && (post.rawText.Contains("#ad") || post.rawText.Contains("/trial/") || post.rawText.Contains("#announcement"))) + { + continue; + } + + if (post.text != null && (post.text.Contains("#ad") || post.text.Contains("/trial/") || post.text.Contains("#announcement"))) + { + continue; + } + } + List postPreviewIds = new(); + if (post.preview != null && post.preview.Count > 0) + { + for (int i = 0; i < post.preview.Count; i++) + { + if (post.preview[i] is long previewId) + { + if (!postPreviewIds.Contains(previewId)) + { + postPreviewIds.Add(previewId); + } + } + } + } + await m_DBHelper.AddPost(folder, post.id, post.rawText != null ? post.rawText : string.Empty, post.price != null ? post.price.ToString() : "0", post.price != null && post.isOpened ? true : false, post.isArchived, post.postedAt); + postCollection.PostObjects.Add(post); + if (post.media != null && post.media.Count > 0) + { + foreach (Post.Medium medium in post.media) + { + if (medium.type == "photo" && !config.DownloadImages) + { + continue; + } + if (medium.type == "video" && !config.DownloadVideos) + { + continue; + } + if (medium.type == "gif" && !config.DownloadVideos) + { + continue; + } + if (medium.type == "audio" && !config.DownloadAudios) + { + continue; + } + if (medium.canView && medium.files?.drm == null) + { + bool has = paid_post_ids.Any(cus => cus.Equals(medium.id)); + if (medium.files!.full != null && !string.IsNullOrEmpty(medium.files!.full.url)) + { + if (!has && !medium.files!.full.url.Contains("upload")) + { + if (!postCollection.Posts.ContainsKey(medium.id)) + { + await m_DBHelper.AddMedia(folder, medium.id, post.id, medium.files!.full.url, null, null, null, "Posts", medium.type == "photo" ? "Images" : (medium.type == "video" || medium.type == "gif" ? "Videos" : (medium.type == "audio" ? "Audios" : null)), postPreviewIds.Contains((long)medium.id) ? true : false, false, null); + postCollection.Posts.Add(medium.id, medium.files!.full.url); + postCollection.PostMedia.Add(medium); + } + } + } + else if (medium.files.preview != null && medium.files!.full == null) + { + if (!has && !medium.files.preview.url.Contains("upload")) + { + if (!postCollection.Posts.ContainsKey(medium.id)) + { + await m_DBHelper.AddMedia(folder, medium.id, post.id, medium.files.preview.url, null, null, null, "Posts", medium.type == "photo" ? "Images" : (medium.type == "video" || medium.type == "gif" ? "Videos" : (medium.type == "audio" ? "Audios" : null)), postPreviewIds.Contains((long)medium.id) ? true : false, false, null); + postCollection.Posts.Add(medium.id, medium.files.preview.url); + postCollection.PostMedia.Add(medium); + } + } + } + } + else if (medium.canView && medium.files != null && medium.files.drm != null) + { + bool has = paid_post_ids.Any(cus => cus.Equals(medium.id)); + if (!has && medium.files != null && medium.files.drm != null) + { + if (!postCollection.Posts.ContainsKey(medium.id)) + { + await m_DBHelper.AddMedia(folder, medium.id, post.id, medium.files.drm.manifest.dash, null, null, null, "Posts", medium.type == "photo" ? "Images" : (medium.type == "video" || medium.type == "gif" ? "Videos" : (medium.type == "audio" ? "Audios" : null)), postPreviewIds.Contains((long)medium.id) ? true : false, false, null); + postCollection.Posts.Add(medium.id, $"{medium.files.drm.manifest.dash},{medium.files.drm.signature.dash.CloudFrontPolicy},{medium.files.drm.signature.dash.CloudFrontSignature},{medium.files.drm.signature.dash.CloudFrontKeyPairId},{medium.id},{post.id}"); + postCollection.PostMedia.Add(medium); + } + } + } + } + } + } + + return postCollection; + } + catch (Exception ex) + { + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + Log.Error("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + if (ex.InnerException != null) + { + Console.WriteLine("\nInner Exception:"); + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + Log.Error("Inner Exception: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + } + } + return null; + } + public async Task GetPost(string endpoint, string folder, IDownloadConfig config) + { + Log.Debug($"Calling GetPost - {endpoint}"); + + try + { + SinglePost singlePost = new(); + SinglePostCollection singlePostCollection = new(); + Dictionary getParams = new() + { + { "skip_users", "all" } + }; + + var body = await BuildHeaderAndExecuteRequests(getParams, endpoint, new HttpClient()); + singlePost = JsonConvert.DeserializeObject(body, m_JsonSerializerSettings); + + if (singlePost != null) + { + List postPreviewIds = new(); + if (singlePost.preview != null && singlePost.preview.Count > 0) + { + for (int i = 0; i < singlePost.preview.Count; i++) + { + if (singlePost.preview[i] is long previewId) + { + if (!postPreviewIds.Contains(previewId)) + { + postPreviewIds.Add(previewId); + } + } + } + } + await m_DBHelper.AddPost(folder, singlePost.id, singlePost.text != null ? singlePost.text : string.Empty, singlePost.price != null ? singlePost.price.ToString() : "0", singlePost.price != null && singlePost.isOpened ? true : false, singlePost.isArchived, singlePost.postedAt); + singlePostCollection.SinglePostObjects.Add(singlePost); + if (singlePost.media != null && singlePost.media.Count > 0) + { + foreach (SinglePost.Medium medium in singlePost.media) + { + if (medium.type == "photo" && !config.DownloadImages) + { + continue; + } + if (medium.type == "video" && !config.DownloadVideos) + { + continue; + } + if (medium.type == "gif" && !config.DownloadVideos) + { + continue; + } + if (medium.type == "audio" && !config.DownloadAudios) + { + continue; + } + if (medium.canView && medium.files?.drm == null) + { + if (medium.files!.full != null && !string.IsNullOrEmpty(medium.files!.full.url)) + { + if (!medium.files!.full.url.Contains("upload")) + { + if (!singlePostCollection.SinglePosts.ContainsKey(medium.id)) + { + await m_DBHelper.AddMedia(folder, medium.id, singlePost.id, medium.files!.full.url, null, null, null, "Posts", medium.type == "photo" ? "Images" : (medium.type == "video" || medium.type == "gif" ? "Videos" : (medium.type == "audio" ? "Audios" : null)), postPreviewIds.Contains((long)medium.id) ? true : false, false, null); + singlePostCollection.SinglePosts.Add(medium.id, medium.files!.full.url); + singlePostCollection.SinglePostMedia.Add(medium); + } + } + } + else if (medium.files.preview != null && medium.files!.full == null) + { + if (!medium.files.preview.url.Contains("upload")) + { + if (!singlePostCollection.SinglePosts.ContainsKey(medium.id)) + { + await m_DBHelper.AddMedia(folder, medium.id, singlePost.id, medium.files.preview.url, null, null, null, "Posts", medium.type == "photo" ? "Images" : (medium.type == "video" || medium.type == "gif" ? "Videos" : (medium.type == "audio" ? "Audios" : null)), postPreviewIds.Contains((long)medium.id) ? true : false, false, null); + singlePostCollection.SinglePosts.Add(medium.id, medium.files.preview.url); + singlePostCollection.SinglePostMedia.Add(medium); + } + } + } + } + else if (medium.canView && medium.files != null && medium.files.drm != null) + { + if (medium.files != null && medium.files.drm != null) + { + if (!singlePostCollection.SinglePosts.ContainsKey(medium.id)) + { + await m_DBHelper.AddMedia(folder, medium.id, singlePost.id, medium.files.drm.manifest.dash, null, null, null, "Posts", medium.type == "photo" ? "Images" : (medium.type == "video" || medium.type == "gif" ? "Videos" : (medium.type == "audio" ? "Audios" : null)), postPreviewIds.Contains((long)medium.id) ? true : false, false, null); + singlePostCollection.SinglePosts.Add(medium.id, $"{medium.files.drm.manifest.dash},{medium.files.drm.signature.dash.CloudFrontPolicy},{medium.files.drm.signature.dash.CloudFrontSignature},{medium.files.drm.signature.dash.CloudFrontKeyPairId},{medium.id},{singlePost.id}"); + singlePostCollection.SinglePostMedia.Add(medium); + } + } + } + } + } + } + + return singlePostCollection; + } + catch (Exception ex) + { + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + Log.Error("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + if (ex.InnerException != null) + { + Console.WriteLine("\nInner Exception:"); + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + Log.Error("Inner Exception: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + } + } + return null; + } + + public async Task GetStreams(string endpoint, string folder, IDownloadConfig config, List paid_post_ids, StatusContext ctx) + { + Log.Debug($"Calling GetStreams - {endpoint}"); + + try + { + Streams streams = new(); + StreamsCollection streamsCollection = new(); + int post_limit = 50; + Dictionary getParams = new() + { + { "limit", post_limit.ToString() }, + { "order", "publish_date_desc" }, + { "format", "infinite" } + }; + + Enumerations.DownloadDateSelection downloadDateSelection = Enumerations.DownloadDateSelection.before; + if (config.DownloadOnlySpecificDates && config.CustomDate.HasValue) + { + downloadDateSelection = config.DownloadDateSelection; + } + + UpdateGetParamsForDateSelection( + downloadDateSelection, + ref getParams, + config.CustomDate); + + var body = await BuildHeaderAndExecuteRequests(getParams, endpoint, new HttpClient()); + streams = JsonConvert.DeserializeObject(body, m_JsonSerializerSettings); + ctx.Status($"[red]Getting Streams\n[/] [red]Found {streams.list.Count}[/]"); + ctx.Spinner(Spinner.Known.Dots); + ctx.SpinnerStyle(Style.Parse("blue")); + if (streams != null && streams.hasMore) + { + + UpdateGetParamsForDateSelection( + downloadDateSelection, + ref getParams, + streams.tailMarker); + + while (true) + { + Streams newstreams = new(); + + var loopbody = await BuildHeaderAndExecuteRequests(getParams, endpoint, GetHttpClient(config)); + newstreams = JsonConvert.DeserializeObject(loopbody, m_JsonSerializerSettings); + + streams.list.AddRange(newstreams.list); + ctx.Status($"[red]Getting Streams\n[/] [red]Found {streams.list.Count}[/]"); + ctx.Spinner(Spinner.Known.Dots); + ctx.SpinnerStyle(Style.Parse("blue")); + if (!newstreams.hasMore) + { + break; + } + + UpdateGetParamsForDateSelection( + downloadDateSelection, + ref getParams, + newstreams.tailMarker); + } + } + + foreach (Streams.List stream in streams.list) + { + List streamPreviewIds = new(); + if (stream.preview != null && stream.preview.Count > 0) + { + for (int i = 0; i < stream.preview.Count; i++) + { + if (stream.preview[i] is long previewId) + { + if (!streamPreviewIds.Contains(previewId)) + { + streamPreviewIds.Add(previewId); + } + } + } + } + await m_DBHelper.AddPost(folder, stream.id, stream.text != null ? stream.text : string.Empty, stream.price != null ? stream.price.ToString() : "0", stream.price != null && stream.isOpened ? true : false, stream.isArchived, stream.postedAt); + streamsCollection.StreamObjects.Add(stream); + if (stream.media != null && stream.media.Count > 0) + { + foreach (Streams.Medium medium in stream.media) + { + if (medium.type == "photo" && !config.DownloadImages) + { + continue; + } + if (medium.type == "video" && !config.DownloadVideos) + { + continue; + } + if (medium.type == "gif" && !config.DownloadVideos) + { + continue; + } + if (medium.type == "audio" && !config.DownloadAudios) + { + continue; + } + if (medium.canView && medium.files?.drm == null) + { + bool has = paid_post_ids.Any(cus => cus.Equals(medium.id)); + if (!has && medium.canView && medium.files != null && medium.files.full != null && !string.IsNullOrEmpty(medium.files.full.url) && !medium.files.full.url.Contains("upload")) + { + if (!streamsCollection.Streams.ContainsKey(medium.id)) + { + await m_DBHelper.AddMedia(folder, medium.id, stream.id, medium.files.full.url, null, null, null, "Posts", medium.type == "photo" ? "Images" : (medium.type == "video" || medium.type == "gif" ? "Videos" : (medium.type == "audio" ? "Audios" : null)), streamPreviewIds.Contains((long)medium.id) ? true : false, false, null); + streamsCollection.Streams.Add(medium.id, medium.files.full.url); + streamsCollection.StreamMedia.Add(medium); + } + } + } + else if (medium.canView && medium.files != null && medium.files.drm != null) + { + bool has = paid_post_ids.Any(cus => cus.Equals(medium.id)); + if (!has && medium.files != null && medium.files.drm != null) + { + if (!streamsCollection.Streams.ContainsKey(medium.id)) + { + await m_DBHelper.AddMedia(folder, medium.id, stream.id, medium.files.drm.manifest.dash, null, null, null, "Posts", medium.type == "photo" ? "Images" : (medium.type == "video" || medium.type == "gif" ? "Videos" : (medium.type == "audio" ? "Audios" : null)), streamPreviewIds.Contains((long)medium.id) ? true : false, false, null); + streamsCollection.Streams.Add(medium.id, $"{medium.files.drm.manifest.dash},{medium.files.drm.signature.dash.CloudFrontPolicy},{medium.files.drm.signature.dash.CloudFrontSignature},{medium.files.drm.signature.dash.CloudFrontKeyPairId},{medium.id},{stream.id}"); + streamsCollection.StreamMedia.Add(medium); + } + } + } + } + } + } + + return streamsCollection; + } + catch (Exception ex) + { + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + Log.Error("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + if (ex.InnerException != null) + { + Console.WriteLine("\nInner Exception:"); + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + Log.Error("Inner Exception: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + } + } + return null; + } + + + public async Task GetArchived(string endpoint, string folder, IDownloadConfig config, StatusContext ctx) + { + Log.Debug($"Calling GetArchived - {endpoint}"); + + try + { + Archived archived = new(); + ArchivedCollection archivedCollection = new(); + int post_limit = 50; + Dictionary getParams = new() + { + { "limit", post_limit.ToString() }, + { "order", "publish_date_desc" }, + { "skip_users", "all" }, + { "format", "infinite" }, + { "label", "archived" }, + { "counters", "1" } + }; + + Enumerations.DownloadDateSelection downloadDateSelection = Enumerations.DownloadDateSelection.before; + if (config.DownloadOnlySpecificDates && config.CustomDate.HasValue) + { + downloadDateSelection = config.DownloadDateSelection; + } + + UpdateGetParamsForDateSelection( + downloadDateSelection, + ref getParams, + config.CustomDate); + + var body = await BuildHeaderAndExecuteRequests(getParams, endpoint, GetHttpClient(config)); + archived = JsonConvert.DeserializeObject(body, m_JsonSerializerSettings); + ctx.Status($"[red]Getting Archived Posts\n[/] [red]Found {archived.list.Count}[/]"); + ctx.Spinner(Spinner.Known.Dots); + ctx.SpinnerStyle(Style.Parse("blue")); + if (archived != null && archived.hasMore) + { + UpdateGetParamsForDateSelection( + downloadDateSelection, + ref getParams, + archived.tailMarker); + while (true) + { + Archived newarchived = new(); + + var loopbody = await BuildHeaderAndExecuteRequests(getParams, endpoint, GetHttpClient(config)); + newarchived = JsonConvert.DeserializeObject(loopbody, m_JsonSerializerSettings); + + archived.list.AddRange(newarchived.list); + ctx.Status($"[red]Getting Archived Posts\n[/] [red]Found {archived.list.Count}[/]"); + ctx.Spinner(Spinner.Known.Dots); + ctx.SpinnerStyle(Style.Parse("blue")); + if (!newarchived.hasMore) + { + break; + } + UpdateGetParamsForDateSelection( + downloadDateSelection, + ref getParams, + newarchived.tailMarker); + } + } + + foreach (Archived.List archive in archived.list) + { + List previewids = new(); + if (archive.preview != null) + { + for (int i = 0; i < archive.preview.Count; i++) + { + if (archive.preview[i] is long previewId) + { + if (!previewids.Contains(previewId)) + { + previewids.Add(previewId); + } + } + } + } + await m_DBHelper.AddPost(folder, archive.id, archive.text != null ? archive.text : string.Empty, archive.price != null ? archive.price.ToString() : "0", archive.price != null && archive.isOpened ? true : false, archive.isArchived, archive.postedAt); + archivedCollection.ArchivedPostObjects.Add(archive); + if (archive.media != null && archive.media.Count > 0) + { + foreach (Archived.Medium medium in archive.media) + { + if (medium.type == "photo" && !config.DownloadImages) + { + continue; + } + if (medium.type == "video" && !config.DownloadVideos) + { + continue; + } + if (medium.type == "gif" && !config.DownloadVideos) + { + continue; + } + if (medium.type == "audio" && !config.DownloadAudios) + { + continue; + } + if (medium.canView && medium.files != null && medium.files.full != null && !string.IsNullOrEmpty(medium.files.full.url) && !medium.files.full.url.Contains("upload")) + { + if (!archivedCollection.ArchivedPosts.ContainsKey(medium.id)) + { + await m_DBHelper.AddMedia(folder, medium.id, archive.id, medium.files.full.url, null, null, null, "Posts", medium.type == "photo" ? "Images" : (medium.type == "video" || medium.type == "gif" ? "Videos" : (medium.type == "audio" ? "Audios" : null)), previewids.Contains(medium.id) ? true : false, false, null); + archivedCollection.ArchivedPosts.Add(medium.id, medium.files.full.url); + archivedCollection.ArchivedPostMedia.Add(medium); + } + } + else if (medium.canView && medium.files != null && medium.files.drm != null) + { + if (!archivedCollection.ArchivedPosts.ContainsKey(medium.id)) + { + await m_DBHelper.AddMedia(folder, medium.id, archive.id, medium.files.drm.manifest.dash, null, null, null, "Posts", medium.type == "photo" ? "Images" : (medium.type == "video" || medium.type == "gif" ? "Videos" : (medium.type == "audio" ? "Audios" : null)), previewids.Contains(medium.id) ? true : false, false, null); + archivedCollection.ArchivedPosts.Add(medium.id, $"{medium.files.drm.manifest.dash},{medium.files.drm.signature.dash.CloudFrontPolicy},{medium.files.drm.signature.dash.CloudFrontSignature},{medium.files.drm.signature.dash.CloudFrontKeyPairId},{medium.id},{archive.id}"); + archivedCollection.ArchivedPostMedia.Add(medium); + } + } + } + } + } + + return archivedCollection; + } + catch (Exception ex) + { + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + Log.Error("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + if (ex.InnerException != null) + { + Console.WriteLine("\nInner Exception:"); + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + Log.Error("Inner Exception: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + } + } + return null; + } + + + public async Task GetMessages(string endpoint, string folder, IDownloadConfig config, StatusContext ctx) + { + Log.Debug($"Calling GetMessages - {endpoint}"); + + try + { + Messages messages = new(); + MessageCollection messageCollection = new(); + int post_limit = 50; + Dictionary getParams = new() + { + { "limit", post_limit.ToString() }, + { "order", "desc" } + }; + + var body = await BuildHeaderAndExecuteRequests(getParams, endpoint, GetHttpClient(config)); + messages = JsonConvert.DeserializeObject(body, m_JsonSerializerSettings); + ctx.Status($"[red]Getting Messages\n[/] [red]Found {messages.list.Count}[/]"); + ctx.Spinner(Spinner.Known.Dots); + ctx.SpinnerStyle(Style.Parse("blue")); + if (messages.hasMore) + { + getParams["id"] = messages.list[^1].id.ToString(); + while (true) + { + Messages newmessages = new(); + + var loopbody = await BuildHeaderAndExecuteRequests(getParams, endpoint, GetHttpClient(config)); + newmessages = JsonConvert.DeserializeObject(loopbody, m_JsonSerializerSettings); + + messages.list.AddRange(newmessages.list); + ctx.Status($"[red]Getting Messages\n[/] [red]Found {messages.list.Count}[/]"); + ctx.Spinner(Spinner.Known.Dots); + ctx.SpinnerStyle(Style.Parse("blue")); + if (!newmessages.hasMore) + { + break; + } + getParams["id"] = newmessages.list[newmessages.list.Count - 1].id.ToString(); + } + } + + foreach (Messages.List list in messages.list) + { + if (config.SkipAds) + { + if (list.text != null && (list.text.Contains("#ad") || list.text.Contains("/trial/"))) + { + continue; + } + } + List messagePreviewIds = new(); + if (list.previews != null && list.previews.Count > 0) + { + for (int i = 0; i < list.previews.Count; i++) + { + if (list.previews[i] is long previewId) + { + if (!messagePreviewIds.Contains(previewId)) + { + messagePreviewIds.Add(previewId); + } + } + } + } + if (!config.IgnoreOwnMessages || list.fromUser.id != Convert.ToInt32(auth.USER_ID)) + { + await m_DBHelper.AddMessage(folder, list.id, list.text != null ? list.text : string.Empty, list.price != null ? list.price.ToString() : "0", list.canPurchaseReason == "opened" ? true : list.canPurchaseReason != "opened" ? false : (bool?)null ?? false, false, list.createdAt.HasValue ? list.createdAt.Value : DateTime.Now, list.fromUser != null && list.fromUser.id != null ? list.fromUser.id.Value : int.MinValue); + messageCollection.MessageObjects.Add(list); + if (list.canPurchaseReason != "opened" && list.media != null && list.media.Count > 0) + { + foreach (Messages.Medium medium in list.media) + { + if (medium.canView && medium.files != null && medium.files.full != null && !string.IsNullOrEmpty(medium.files.full.url) && !medium.files.full.url.Contains("upload")) + { + if (medium.type == "photo" && !config.DownloadImages) + { + continue; + } + if (medium.type == "video" && !config.DownloadVideos) + { + continue; + } + if (medium.type == "gif" && !config.DownloadVideos) + { + continue; + } + if (medium.type == "audio" && !config.DownloadAudios) + { + continue; + } + if (!messageCollection.Messages.ContainsKey(medium.id)) + { + await m_DBHelper.AddMedia(folder, medium.id, list.id, medium.files.full.url, null, null, null, "Messages", medium.type == "photo" ? "Images" : (medium.type == "video" || medium.type == "gif" ? "Videos" : (medium.type == "audio" ? "Audios" : null)), messagePreviewIds.Contains(medium.id) ? true : false, false, null); + messageCollection.Messages.Add(medium.id, medium.files.full.url); + messageCollection.MessageMedia.Add(medium); + } + } + else if (medium.canView && medium.files != null && medium.files.drm != null) + { + if (medium.type == "photo" && !config.DownloadImages) + { + continue; + } + if (medium.type == "video" && !config.DownloadVideos) + { + continue; + } + if (medium.type == "gif" && !config.DownloadVideos) + { + continue; + } + if (medium.type == "audio" && !config.DownloadAudios) + { + continue; + } + if (!messageCollection.Messages.ContainsKey(medium.id)) + { + await m_DBHelper.AddMedia(folder, medium.id, list.id, medium.files.drm.manifest.dash, null, null, null, "Messages", medium.type == "photo" ? "Images" : (medium.type == "video" || medium.type == "gif" ? "Videos" : (medium.type == "audio" ? "Audios" : null)), messagePreviewIds.Contains(medium.id) ? true : false, false, null); + messageCollection.Messages.Add(medium.id, $"{medium.files.drm.manifest.dash},{medium.files.drm.signature.dash.CloudFrontPolicy},{medium.files.drm.signature.dash.CloudFrontSignature},{medium.files.drm.signature.dash.CloudFrontKeyPairId},{medium.id},{list.id}"); + messageCollection.MessageMedia.Add(medium); + } + } + } + } + else if (messagePreviewIds.Count > 0) + { + foreach (Messages.Medium medium in list.media) + { + if (medium.canView && medium.files != null && medium.files.full != null && !string.IsNullOrEmpty(medium.files.full.url) && !medium.files.full.url.Contains("upload") && messagePreviewIds.Contains(medium.id)) + { + if (medium.type == "photo" && !config.DownloadImages) + { + continue; + } + if (medium.type == "video" && !config.DownloadVideos) + { + continue; + } + if (medium.type == "gif" && !config.DownloadVideos) + { + continue; + } + if (medium.type == "audio" && !config.DownloadAudios) + { + continue; + } + if (!messageCollection.Messages.ContainsKey(medium.id)) + { + await m_DBHelper.AddMedia(folder, medium.id, list.id, medium.files.full.url, null, null, null, "Messages", medium.type == "photo" ? "Images" : (medium.type == "video" || medium.type == "gif" ? "Videos" : (medium.type == "audio" ? "Audios" : null)), messagePreviewIds.Contains(medium.id) ? true : false, false, null); + messageCollection.Messages.Add(medium.id, medium.files.full.url); + messageCollection.MessageMedia.Add(medium); + } + } + else if (medium.canView && medium.files != null && medium.files.drm != null && messagePreviewIds.Contains(medium.id)) + { + if (medium.type == "photo" && !config.DownloadImages) + { + continue; + } + if (medium.type == "video" && !config.DownloadVideos) + { + continue; + } + if (medium.type == "gif" && !config.DownloadVideos) + { + continue; + } + if (medium.type == "audio" && !config.DownloadAudios) + { + continue; + } + if (!messageCollection.Messages.ContainsKey(medium.id)) + { + await m_DBHelper.AddMedia(folder, medium.id, list.id, medium.files.drm.manifest.dash, null, null, null, "Messages", medium.type == "photo" ? "Images" : (medium.type == "video" || medium.type == "gif" ? "Videos" : (medium.type == "audio" ? "Audios" : null)), messagePreviewIds.Contains(medium.id) ? true : false, false, null); + messageCollection.Messages.Add(medium.id, $"{medium.files.drm.manifest.dash},{medium.files.drm.signature.dash.CloudFrontPolicy},{medium.files.drm.signature.dash.CloudFrontSignature},{medium.files.drm.signature.dash.CloudFrontKeyPairId},{medium.id},{list.id}"); + messageCollection.MessageMedia.Add(medium); + } + } + } + } + } + } + + return messageCollection; + } + catch (Exception ex) + { + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + Log.Error("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + if (ex.InnerException != null) + { + Console.WriteLine("\nInner Exception:"); + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + Log.Error("Inner Exception: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + } + } + return null; + } + + public async Task GetPaidMessage(string endpoint, string folder, IDownloadConfig config) + { + Log.Debug($"Calling GetPaidMessage - {endpoint}"); + + try + { + SingleMessage message = new(); + SinglePaidMessageCollection singlePaidMessageCollection = new(); + int post_limit = 50; + Dictionary getParams = new() + { + { "limit", post_limit.ToString() }, + { "order", "desc" } + }; + + var body = await BuildHeaderAndExecuteRequests(getParams, endpoint, GetHttpClient(config)); + message = JsonConvert.DeserializeObject(body, m_JsonSerializerSettings); + + if (!config.IgnoreOwnMessages || message.fromUser.id != Convert.ToInt32(auth.USER_ID)) + { + await m_DBHelper.AddMessage(folder, message.id, message.text != null ? message.text : string.Empty, message.price != null ? message.price.ToString() : "0", true, false, message.createdAt.HasValue ? message.createdAt.Value : DateTime.Now, message.fromUser != null && message.fromUser.id != null ? message.fromUser.id.Value : int.MinValue); + singlePaidMessageCollection.SingleMessageObjects.Add(message); + List messagePreviewIds = new(); + if (message.previews != null && message.previews.Count > 0) + { + for (int i = 0; i < message.previews.Count; i++) + { + if (message.previews[i] is long previewId) + { + if (!messagePreviewIds.Contains(previewId)) + { + messagePreviewIds.Add(previewId); + } + } + } + } + + if (message.media != null && message.media.Count > 0) + { + foreach (Messages.Medium medium in message.media) + { + if (!messagePreviewIds.Contains(medium.id) && medium.canView && medium.files != null && medium.files.full != null && !string.IsNullOrEmpty(medium.files.full.url) && !medium.files.full.url.Contains("upload")) + { + if (medium.type == "photo" && !config.DownloadImages) + { + continue; + } + if (medium.type == "video" && !config.DownloadVideos) + { + continue; + } + if (medium.type == "gif" && !config.DownloadVideos) + { + continue; + } + if (medium.type == "audio" && !config.DownloadAudios) + { + continue; + } + + if (!singlePaidMessageCollection.SingleMessages.ContainsKey(medium.id)) + { + await m_DBHelper.AddMedia(folder, medium.id, message.id, medium.files.full.url, null, null, null, "Messages", medium.type == "photo" ? "Images" : (medium.type == "video" || medium.type == "gif" ? "Videos" : (medium.type == "audio" ? "Audios" : null)), messagePreviewIds.Contains(medium.id) ? true : false, false, null); + singlePaidMessageCollection.SingleMessages.Add(medium.id, medium.files.full.url.ToString()); + singlePaidMessageCollection.SingleMessageMedia.Add(medium); + } + } + else if (!messagePreviewIds.Contains(medium.id) && medium.canView && medium.files != null && medium.files.drm != null) + { + if (medium.type == "photo" && !config.DownloadImages) + { + continue; + } + if (medium.type == "video" && !config.DownloadVideos) + { + continue; + } + if (medium.type == "gif" && !config.DownloadVideos) + { + continue; + } + if (medium.type == "audio" && !config.DownloadAudios) + { + continue; + } + + if (!singlePaidMessageCollection.SingleMessages.ContainsKey(medium.id)) + { + await m_DBHelper.AddMedia(folder, medium.id, message.id, medium.files.drm.manifest.dash, null, null, null, "Messages", medium.type == "photo" ? "Images" : (medium.type == "video" || medium.type == "gif" ? "Videos" : (medium.type == "audio" ? "Audios" : null)), messagePreviewIds.Contains(medium.id) ? true : false, false, null); + singlePaidMessageCollection.SingleMessages.Add(medium.id, $"{medium.files.drm.manifest.dash},{medium.files.drm.signature.dash.CloudFrontPolicy},{medium.files.drm.signature.dash.CloudFrontSignature},{medium.files.drm.signature.dash.CloudFrontKeyPairId},{medium.id},{message.id}"); + singlePaidMessageCollection.SingleMessageMedia.Add(medium); + } + } + } + } + } + + return singlePaidMessageCollection; + } + catch (Exception ex) + { + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + Log.Error("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + if (ex.InnerException != null) + { + Console.WriteLine("\nInner Exception:"); + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + Log.Error("Inner Exception: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + } + } + return null; + } + + + public async Task GetPaidMessages(string endpoint, string folder, string username, IDownloadConfig config, StatusContext ctx) + { + Log.Debug($"Calling GetPaidMessages - {username}"); + + try + { + Purchased paidMessages = new(); + PaidMessageCollection paidMessageCollection = new(); + int post_limit = 50; + Dictionary getParams = new() + { + { "limit", post_limit.ToString() }, + { "order", "publish_date_desc" }, + { "format", "infinite" }, + { "user_id", username } + }; + + var body = await BuildHeaderAndExecuteRequests(getParams, endpoint, GetHttpClient(config)); + paidMessages = JsonConvert.DeserializeObject(body, m_JsonSerializerSettings); + ctx.Status($"[red]Getting Paid Messages\n[/] [red]Found {paidMessages.list.Count}[/]"); + ctx.Spinner(Spinner.Known.Dots); + ctx.SpinnerStyle(Style.Parse("blue")); + if (paidMessages != null && paidMessages.hasMore) + { + getParams["offset"] = paidMessages.list.Count.ToString(); + while (true) + { + string loopqueryParams = "?" + string.Join("&", getParams.Select(kvp => $"{kvp.Key}={kvp.Value}")); + Purchased newpaidMessages = new(); + Dictionary loopheaders = GetDynamicHeaders("/api2/v2" + endpoint, loopqueryParams); + HttpClient loopclient = GetHttpClient(config); + + HttpRequestMessage looprequest = new(HttpMethod.Get, $"{Constants.API_URL}{endpoint}{loopqueryParams}"); + + foreach (KeyValuePair keyValuePair in loopheaders) + { + looprequest.Headers.Add(keyValuePair.Key, keyValuePair.Value); + } + using (var loopresponse = await loopclient.SendAsync(looprequest)) + { + loopresponse.EnsureSuccessStatusCode(); + var loopbody = await loopresponse.Content.ReadAsStringAsync(); + newpaidMessages = JsonConvert.DeserializeObject(loopbody, m_JsonSerializerSettings); + } + paidMessages.list.AddRange(newpaidMessages.list); + ctx.Status($"[red]Getting Paid Messages\n[/] [red]Found {paidMessages.list.Count}[/]"); + ctx.Spinner(Spinner.Known.Dots); + ctx.SpinnerStyle(Style.Parse("blue")); + if (!newpaidMessages.hasMore) + { + break; + } + getParams["offset"] = Convert.ToString(Convert.ToInt32(getParams["offset"]) + post_limit); + } + } + + if (paidMessages.list != null && paidMessages.list.Count > 0) + { + foreach (Purchased.List purchase in paidMessages.list.Where(p => p.responseType == "message").OrderByDescending(p => p.postedAt ?? p.createdAt)) + { + if (!config.IgnoreOwnMessages || purchase.fromUser.id != Convert.ToInt32(auth.USER_ID)) + { + if (purchase.postedAt != null) + { + await m_DBHelper.AddMessage(folder, purchase.id, purchase.text != null ? purchase.text : string.Empty, purchase.price != null ? purchase.price : "0", true, false, purchase.postedAt.Value, purchase.fromUser.id); + } + else + { + await m_DBHelper.AddMessage(folder, purchase.id, purchase.text != null ? purchase.text : string.Empty, purchase.price != null ? purchase.price : "0", true, false, purchase.createdAt.Value, purchase.fromUser.id); + } + paidMessageCollection.PaidMessageObjects.Add(purchase); + if (purchase.media != null && purchase.media.Count > 0) + { + List previewids = new(); + if (purchase.previews != null) + { + for (int i = 0; i < purchase.previews.Count; i++) + { + if (purchase.previews[i] is long previewId) + { + if (!previewids.Contains(previewId)) + { + previewids.Add(previewId); + } + } + } + } + else if (purchase.preview != null) + { + for (int i = 0; i < purchase.preview.Count; i++) + { + if (purchase.preview[i] is long previewId) + { + if (!previewids.Contains(previewId)) + { + previewids.Add(previewId); + } + } + } + } + + foreach (Messages.Medium medium in purchase.media) + { + if (previewids.Count > 0) + { + bool has = previewids.Any(cus => cus.Equals(medium.id)); + if (!has && medium.canView && medium.files != null && medium.files.full != null && !string.IsNullOrEmpty(medium.files.full.url) && !medium.files.full.url.Contains("upload")) + { + if (medium.type == "photo" && !config.DownloadImages) + { + continue; + } + if (medium.type == "video" && !config.DownloadVideos) + { + continue; + } + if (medium.type == "gif" && !config.DownloadVideos) + { + continue; + } + if (medium.type == "audio" && !config.DownloadAudios) + { + continue; + } + if (!paidMessageCollection.PaidMessages.ContainsKey(medium.id)) + { + await m_DBHelper.AddMedia(folder, medium.id, purchase.id, medium.files.full.url, null, null, null, "Messages", medium.type == "photo" ? "Images" : (medium.type == "video" || medium.type == "gif" ? "Videos" : (medium.type == "audio" ? "Audios" : null)), previewids.Contains(medium.id) ? true : false, false, null); + paidMessageCollection.PaidMessages.Add(medium.id, medium.files.full.url); + paidMessageCollection.PaidMessageMedia.Add(medium); + } + } + else if (!has && medium.canView && medium.files != null && medium.files.drm != null) + { + if (medium.type == "photo" && !config.DownloadImages) + { + continue; + } + if (medium.type == "video" && !config.DownloadVideos) + { + continue; + } + if (medium.type == "gif" && !config.DownloadVideos) + { + continue; + } + if (medium.type == "audio" && !config.DownloadAudios) + { + continue; + } + if (!paidMessageCollection.PaidMessages.ContainsKey(medium.id)) + { + await m_DBHelper.AddMedia(folder, medium.id, purchase.id, medium.files.drm.manifest.dash, null, null, null, "Messages", medium.type == "photo" ? "Images" : (medium.type == "video" || medium.type == "gif" ? "Videos" : (medium.type == "audio" ? "Audios" : null)), previewids.Contains(medium.id) ? true : false, false, null); + paidMessageCollection.PaidMessages.Add(medium.id, $"{medium.files.drm.manifest.dash},{medium.files.drm.signature.dash.CloudFrontPolicy},{medium.files.drm.signature.dash.CloudFrontSignature},{medium.files.drm.signature.dash.CloudFrontKeyPairId},{medium.id},{purchase.id}"); + paidMessageCollection.PaidMessageMedia.Add(medium); + } + } + } + else + { + if (medium.canView && medium.files != null && medium.files.full != null && !string.IsNullOrEmpty(medium.files.full.url) && !medium.files.full.url.Contains("upload")) + { + if (medium.type == "photo" && !config.DownloadImages) + { + continue; + } + if (medium.type == "video" && !config.DownloadVideos) + { + continue; + } + if (medium.type == "gif" && !config.DownloadVideos) + { + continue; + } + if (medium.type == "audio" && !config.DownloadAudios) + { + continue; + } + if (!paidMessageCollection.PaidMessages.ContainsKey(medium.id)) + { + await m_DBHelper.AddMedia(folder, medium.id, purchase.id, medium.files.full.url, null, null, null, "Messages", medium.type == "photo" ? "Images" : (medium.type == "video" || medium.type == "gif" ? "Videos" : (medium.type == "audio" ? "Audios" : null)), previewids.Contains(medium.id) ? true : false, false, null); + paidMessageCollection.PaidMessages.Add(medium.id, medium.files.full.url); + paidMessageCollection.PaidMessageMedia.Add(medium); + } + } + else if (medium.canView && medium.files != null && medium.files.drm != null) + { + if (medium.type == "photo" && !config.DownloadImages) + { + continue; + } + if (medium.type == "video" && !config.DownloadVideos) + { + continue; + } + if (medium.type == "gif" && !config.DownloadVideos) + { + continue; + } + if (medium.type == "audio" && !config.DownloadAudios) + { + continue; + } + if (!paidMessageCollection.PaidMessages.ContainsKey(medium.id)) + { + await m_DBHelper.AddMedia(folder, medium.id, purchase.id, medium.files.drm.manifest.dash, null, null, null, "Messages", medium.type == "photo" ? "Images" : (medium.type == "video" || medium.type == "gif" ? "Videos" : (medium.type == "audio" ? "Audios" : null)), previewids.Contains(medium.id) ? true : false, false, null); + paidMessageCollection.PaidMessages.Add(medium.id, $"{medium.files.drm.manifest.dash},{medium.files.drm.signature.dash.CloudFrontPolicy},{medium.files.drm.signature.dash.CloudFrontSignature},{medium.files.drm.signature.dash.CloudFrontKeyPairId},{medium.id},{purchase.id}"); + paidMessageCollection.PaidMessageMedia.Add(medium); + } + } + } + } + } + } + } + } + + return paidMessageCollection; + } + catch (Exception ex) + { + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + Log.Error("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + if (ex.InnerException != null) + { + Console.WriteLine("\nInner Exception:"); + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + Log.Error("Inner Exception: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + } + } + return null; + } + + public async Task> GetPurchasedTabUsers(string endpoint, IDownloadConfig config, Dictionary users) + { + Log.Debug($"Calling GetPurchasedTabUsers - {endpoint}"); + + try + { + Dictionary purchasedTabUsers = new(); + Purchased purchased = new(); + int post_limit = 50; + Dictionary getParams = new() + { + { "limit", post_limit.ToString() }, + { "order", "publish_date_desc" }, + { "format", "infinite" } + }; + + var body = await BuildHeaderAndExecuteRequests(getParams, endpoint, GetHttpClient(config)); + purchased = JsonConvert.DeserializeObject(body, m_JsonSerializerSettings); + if (purchased != null && purchased.hasMore) + { + getParams["offset"] = purchased.list.Count.ToString(); + while (true) + { + string loopqueryParams = "?" + string.Join("&", getParams.Select(kvp => $"{kvp.Key}={kvp.Value}")); + Purchased newPurchased = new(); + Dictionary loopheaders = GetDynamicHeaders("/api2/v2" + endpoint, loopqueryParams); + HttpClient loopclient = GetHttpClient(config); + + HttpRequestMessage looprequest = new(HttpMethod.Get, $"{Constants.API_URL}{endpoint}{loopqueryParams}"); + + foreach (KeyValuePair keyValuePair in loopheaders) + { + looprequest.Headers.Add(keyValuePair.Key, keyValuePair.Value); + } + using (var loopresponse = await loopclient.SendAsync(looprequest)) + { + loopresponse.EnsureSuccessStatusCode(); + var loopbody = await loopresponse.Content.ReadAsStringAsync(); + newPurchased = JsonConvert.DeserializeObject(loopbody, m_JsonSerializerSettings); + } + purchased.list.AddRange(newPurchased.list); + if (!newPurchased.hasMore) + { + break; + } + getParams["offset"] = Convert.ToString(Convert.ToInt32(getParams["offset"]) + post_limit); + } + } + + if (purchased.list != null && purchased.list.Count > 0) + { + foreach (Purchased.List purchase in purchased.list.OrderByDescending(p => p.postedAt ?? p.createdAt)) + { + if (purchase.fromUser != null) + { + if (users.Values.Contains(purchase.fromUser.id)) + { + if (!string.IsNullOrEmpty(users.FirstOrDefault(x => x.Value == purchase.fromUser.id).Key)) + { + if (!purchasedTabUsers.ContainsKey(users.FirstOrDefault(x => x.Value == purchase.fromUser.id).Key)) + { + purchasedTabUsers.Add(users.FirstOrDefault(x => x.Value == purchase.fromUser.id).Key, purchase.fromUser.id); + } + } + else + { + if (!purchasedTabUsers.ContainsKey($"Deleted User - {purchase.fromUser.id}")) + { + purchasedTabUsers.Add($"Deleted User - {purchase.fromUser.id}", purchase.fromUser.id); + } + } + } + else + { + JObject user = await GetUserInfoById($"/users/list?x[]={purchase.fromUser.id}"); + + if(user is null) + { + if (!config.BypassContentForCreatorsWhoNoLongerExist) + { + if(!purchasedTabUsers.ContainsKey($"Deleted User - {purchase.fromUser.id}")) + { + purchasedTabUsers.Add($"Deleted User - {purchase.fromUser.id}", purchase.fromUser.id); + } + } + Log.Debug("Content creator not longer exists - {0}", purchase.fromUser.id); + } + else if (!string.IsNullOrEmpty(user[purchase.fromUser.id.ToString()]["username"].ToString())) + { + if (!purchasedTabUsers.ContainsKey(user[purchase.fromUser.id.ToString()]["username"].ToString())) + { + purchasedTabUsers.Add(user[purchase.fromUser.id.ToString()]["username"].ToString(), purchase.fromUser.id); + } + } + else + { + if (!purchasedTabUsers.ContainsKey($"Deleted User - {purchase.fromUser.id}")) + { + purchasedTabUsers.Add($"Deleted User - {purchase.fromUser.id}", purchase.fromUser.id); + } + } + } + } + else if (purchase.author != null) + { + if (users.Values.Contains(purchase.author.id)) + { + if (!string.IsNullOrEmpty(users.FirstOrDefault(x => x.Value == purchase.author.id).Key)) + { + if (!purchasedTabUsers.ContainsKey(users.FirstOrDefault(x => x.Value == purchase.author.id).Key) && users.ContainsKey(users.FirstOrDefault(x => x.Value == purchase.author.id).Key)) + { + purchasedTabUsers.Add(users.FirstOrDefault(x => x.Value == purchase.author.id).Key, purchase.author.id); + } + } + else + { + if (!purchasedTabUsers.ContainsKey($"Deleted User - {purchase.author.id}")) + { + purchasedTabUsers.Add($"Deleted User - {purchase.author.id}", purchase.author.id); + } + } + } + else + { + JObject user = await GetUserInfoById($"/users/list?x[]={purchase.author.id}"); + + if (user is null) + { + if (!config.BypassContentForCreatorsWhoNoLongerExist) + { + if(!purchasedTabUsers.ContainsKey($"Deleted User - {purchase.author.id}")) + { + purchasedTabUsers.Add($"Deleted User - {purchase.author.id}", purchase.author.id); + } + } + Log.Debug("Content creator not longer exists - {0}", purchase.author.id); + } + else if (!string.IsNullOrEmpty(user[purchase.author.id.ToString()]["username"].ToString())) + { + if (!purchasedTabUsers.ContainsKey(user[purchase.author.id.ToString()]["username"].ToString()) && users.ContainsKey(user[purchase.author.id.ToString()]["username"].ToString())) + { + purchasedTabUsers.Add(user[purchase.author.id.ToString()]["username"].ToString(), purchase.author.id); + } + } + else + { + if (!purchasedTabUsers.ContainsKey($"Deleted User - {purchase.author.id}")) + { + purchasedTabUsers.Add($"Deleted User - {purchase.author.id}", purchase.author.id); + } + } + } + } + } + } + + return purchasedTabUsers; + } + catch (Exception ex) + { + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + Log.Error("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + if (ex.InnerException != null) + { + Console.WriteLine("\nInner Exception:"); + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + Log.Error("Inner Exception: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + } + } + return null; + } + + public async Task> GetPurchasedTab(string endpoint, string folder, IDownloadConfig config, Dictionary users) + { + Log.Debug($"Calling GetPurchasedTab - {endpoint}"); + + try + { + Dictionary> userPurchases = new Dictionary>(); + List purchasedTabCollections = new(); + Purchased purchased = new(); + int post_limit = 50; + Dictionary getParams = new() + { + { "limit", post_limit.ToString() }, + { "order", "publish_date_desc" }, + { "format", "infinite" } + }; + + var body = await BuildHeaderAndExecuteRequests(getParams, endpoint, GetHttpClient(config)); + purchased = JsonConvert.DeserializeObject(body, m_JsonSerializerSettings); + if (purchased != null && purchased.hasMore) + { + getParams["offset"] = purchased.list.Count.ToString(); + while (true) + { + string loopqueryParams = "?" + string.Join("&", getParams.Select(kvp => $"{kvp.Key}={kvp.Value}")); + Purchased newPurchased = new(); + Dictionary loopheaders = GetDynamicHeaders("/api2/v2" + endpoint, loopqueryParams); + HttpClient loopclient = GetHttpClient(config); + + HttpRequestMessage looprequest = new(HttpMethod.Get, $"{Constants.API_URL}{endpoint}{loopqueryParams}"); + + foreach (KeyValuePair keyValuePair in loopheaders) + { + looprequest.Headers.Add(keyValuePair.Key, keyValuePair.Value); + } + using (var loopresponse = await loopclient.SendAsync(looprequest)) + { + loopresponse.EnsureSuccessStatusCode(); + var loopbody = await loopresponse.Content.ReadAsStringAsync(); + newPurchased = JsonConvert.DeserializeObject(loopbody, m_JsonSerializerSettings); + } + purchased.list.AddRange(newPurchased.list); + if (!newPurchased.hasMore) + { + break; + } + getParams["offset"] = Convert.ToString(Convert.ToInt32(getParams["offset"]) + post_limit); + } + } + + if (purchased.list != null && purchased.list.Count > 0) + { + foreach (Purchased.List purchase in purchased.list.OrderByDescending(p => p.postedAt ?? p.createdAt)) + { + if (purchase.fromUser != null) + { + if (!userPurchases.ContainsKey(purchase.fromUser.id)) + { + userPurchases.Add(purchase.fromUser.id, new List()); + } + userPurchases[purchase.fromUser.id].Add(purchase); + } + else if (purchase.author != null) + { + if (!userPurchases.ContainsKey(purchase.author.id)) + { + userPurchases.Add(purchase.author.id, new List()); + } + userPurchases[purchase.author.id].Add(purchase); + } + } + } + + foreach (KeyValuePair> user in userPurchases) + { + PurchasedTabCollection purchasedTabCollection = new PurchasedTabCollection(); + JObject userObject = await GetUserInfoById($"/users/list?x[]={user.Key}"); + purchasedTabCollection.UserId = user.Key; + purchasedTabCollection.Username = userObject is not null && !string.IsNullOrEmpty(userObject[user.Key.ToString()]["username"].ToString()) ? userObject[user.Key.ToString()]["username"].ToString() : $"Deleted User - {user.Key}"; + string path = System.IO.Path.Combine(folder, purchasedTabCollection.Username); + if (Path.Exists(path)) + { + foreach (Purchased.List purchase in user.Value) + { + switch (purchase.responseType) + { + case "post": + List previewids = new(); + if (purchase.previews != null) + { + for (int i = 0; i < purchase.previews.Count; i++) + { + if (purchase.previews[i] is long previewId) + { + if (!previewids.Contains(previewId)) + { + previewids.Add(previewId); + } + } + } + } + else if (purchase.preview != null) + { + for (int i = 0; i < purchase.preview.Count; i++) + { + if (purchase.preview[i] is long previewId) + { + if (!previewids.Contains(previewId)) + { + previewids.Add(previewId); + } + } + } + } + await m_DBHelper.AddPost(path, purchase.id, purchase.text != null ? purchase.text : string.Empty, purchase.price != null ? purchase.price.ToString() : "0", purchase.price != null && purchase.isOpened ? true : false, purchase.isArchived.HasValue ? purchase.isArchived.Value : false, purchase.createdAt != null ? purchase.createdAt.Value : purchase.postedAt.Value); + purchasedTabCollection.PaidPosts.PaidPostObjects.Add(purchase); + foreach (Messages.Medium medium in purchase.media) + { + if (medium.type == "photo" && !config.DownloadImages) + { + continue; + } + if (medium.type == "video" && !config.DownloadVideos) + { + continue; + } + if (medium.type == "gif" && !config.DownloadVideos) + { + continue; + } + if (medium.type == "audio" && !config.DownloadAudios) + { + continue; + } + if (previewids.Count > 0) + { + bool has = previewids.Any(cus => cus.Equals(medium.id)); + if (!has && medium.canView && medium.files != null && medium.files.full != null && !string.IsNullOrEmpty(medium.files.full.url) && !medium.files.full.url.Contains("upload")) + { + + if (!purchasedTabCollection.PaidPosts.PaidPosts.ContainsKey(medium.id)) + { + await m_DBHelper.AddMedia(path, medium.id, purchase.id, medium.files.full.url, null, null, null, "Posts", medium.type == "photo" ? "Images" : (medium.type == "video" || medium.type == "gif" ? "Videos" : (medium.type == "audio" ? "Audios" : null)), previewids.Contains(medium.id) ? true : false, false, null); + purchasedTabCollection.PaidPosts.PaidPosts.Add(medium.id, medium.files.full.url); + purchasedTabCollection.PaidPosts.PaidPostMedia.Add(medium); + } + } + else if (!has && medium.canView && medium.files != null && medium.files.drm != null) + { + + if (!purchasedTabCollection.PaidPosts.PaidPosts.ContainsKey(medium.id)) + { + await m_DBHelper.AddMedia(path, medium.id, purchase.id, medium.files.drm.manifest.dash, null, null, null, "Posts", medium.type == "photo" ? "Images" : (medium.type == "video" || medium.type == "gif" ? "Videos" : (medium.type == "audio" ? "Audios" : null)), previewids.Contains(medium.id) ? true : false, false, null); + purchasedTabCollection.PaidPosts.PaidPosts.Add(medium.id, $"{medium.files.drm.manifest.dash},{medium.files.drm.signature.dash.CloudFrontPolicy},{medium.files.drm.signature.dash.CloudFrontSignature},{medium.files.drm.signature.dash.CloudFrontKeyPairId},{medium.id},{purchase.id}"); + purchasedTabCollection.PaidPosts.PaidPostMedia.Add(medium); + } + + } + } + else + { + if (medium.canView && medium.files != null && medium.files.full != null && !string.IsNullOrEmpty(medium.files.full.url) && !medium.files.full.url.Contains("upload")) + { + if (!purchasedTabCollection.PaidPosts.PaidPosts.ContainsKey(medium.id)) + { + await m_DBHelper.AddMedia(path, medium.id, purchase.id, medium.files.full.url, null, null, null, "Posts", medium.type == "photo" ? "Images" : (medium.type == "video" || medium.type == "gif" ? "Videos" : (medium.type == "audio" ? "Audios" : null)), previewids.Contains(medium.id) ? true : false, false, null); + purchasedTabCollection.PaidPosts.PaidPosts.Add(medium.id, medium.files.full.url); + purchasedTabCollection.PaidPosts.PaidPostMedia.Add(medium); + } + } + else if (medium.canView && medium.files != null && medium.files.drm != null) + { + if (!purchasedTabCollection.PaidPosts.PaidPosts.ContainsKey(medium.id)) + { + await m_DBHelper.AddMedia(path, medium.id, purchase.id, medium.files.drm.manifest.dash, null, null, null, "Posts", medium.type == "photo" ? "Images" : (medium.type == "video" || medium.type == "gif" ? "Videos" : (medium.type == "audio" ? "Audios" : null)), previewids.Contains(medium.id) ? true : false, false, null); + purchasedTabCollection.PaidPosts.PaidPosts.Add(medium.id, $"{medium.files.drm.manifest.dash},{medium.files.drm.signature.dash.CloudFrontPolicy},{medium.files.drm.signature.dash.CloudFrontSignature},{medium.files.drm.signature.dash.CloudFrontKeyPairId},{medium.id},{purchase.id}"); + purchasedTabCollection.PaidPosts.PaidPostMedia.Add(medium); + } + } + } + } + break; + case "message": + if (purchase.postedAt != null) + { + await m_DBHelper.AddMessage(path, purchase.id, purchase.text != null ? purchase.text : string.Empty, purchase.price != null ? purchase.price : "0", true, false, purchase.postedAt.Value, purchase.fromUser.id); + } + else + { + await m_DBHelper.AddMessage(path, purchase.id, purchase.text != null ? purchase.text : string.Empty, purchase.price != null ? purchase.price : "0", true, false, purchase.createdAt.Value, purchase.fromUser.id); + } + purchasedTabCollection.PaidMessages.PaidMessageObjects.Add(purchase); + if (purchase.media != null && purchase.media.Count > 0) + { + List paidMessagePreviewids = new(); + if (purchase.previews != null) + { + for (int i = 0; i < purchase.previews.Count; i++) + { + if (purchase.previews[i] is long previewId) + { + if (!paidMessagePreviewids.Contains(previewId)) + { + paidMessagePreviewids.Add(previewId); + } + } + } + } + else if (purchase.preview != null) + { + for (int i = 0; i < purchase.preview.Count; i++) + { + if (purchase.preview[i] is long previewId) + { + if (!paidMessagePreviewids.Contains(previewId)) + { + paidMessagePreviewids.Add(previewId); + } + } + } + } + + foreach (Messages.Medium medium in purchase.media) + { + if (paidMessagePreviewids.Count > 0) + { + bool has = paidMessagePreviewids.Any(cus => cus.Equals(medium.id)); + if (!has && medium.canView && medium.files != null && medium.files.full != null && !string.IsNullOrEmpty(medium.files.full.url) && !medium.files.full.url.Contains("upload")) + { + if (medium.type == "photo" && !config.DownloadImages) + { + continue; + } + if (medium.type == "video" && !config.DownloadVideos) + { + continue; + } + if (medium.type == "gif" && !config.DownloadVideos) + { + continue; + } + if (medium.type == "audio" && !config.DownloadAudios) + { + continue; + } + if (!purchasedTabCollection.PaidMessages.PaidMessages.ContainsKey(medium.id)) + { + await m_DBHelper.AddMedia(path, medium.id, purchase.id, medium.files.full.url, null, null, null, "Messages", medium.type == "photo" ? "Images" : (medium.type == "video" || medium.type == "gif" ? "Videos" : (medium.type == "audio" ? "Audios" : null)), paidMessagePreviewids.Contains(medium.id) ? true : false, false, null); + purchasedTabCollection.PaidMessages.PaidMessages.Add(medium.id, medium.files.full.url); + purchasedTabCollection.PaidMessages.PaidMessageMedia.Add(medium); + } + } + else if (!has && medium.canView && medium.files != null && medium.files.drm != null) + { + if (medium.type == "photo" && !config.DownloadImages) + { + continue; + } + if (medium.type == "video" && !config.DownloadVideos) + { + continue; + } + if (medium.type == "gif" && !config.DownloadVideos) + { + continue; + } + if (medium.type == "audio" && !config.DownloadAudios) + { + continue; + } + if (!purchasedTabCollection.PaidMessages.PaidMessages.ContainsKey(medium.id)) + { + await m_DBHelper.AddMedia(path, medium.id, purchase.id, medium.files.drm.manifest.dash, null, null, null, "Messages", medium.type == "photo" ? "Images" : (medium.type == "video" || medium.type == "gif" ? "Videos" : (medium.type == "audio" ? "Audios" : null)), paidMessagePreviewids.Contains(medium.id) ? true : false, false, null); + purchasedTabCollection.PaidMessages.PaidMessages.Add(medium.id, $"{medium.files.drm.manifest.dash},{medium.files.drm.signature.dash.CloudFrontPolicy},{medium.files.drm.signature.dash.CloudFrontSignature},{medium.files.drm.signature.dash.CloudFrontKeyPairId},{medium.id},{purchase.id}"); + purchasedTabCollection.PaidMessages.PaidMessageMedia.Add(medium); + } + } + } + else + { + if (medium.canView && medium.files != null && medium.files.full != null && !string.IsNullOrEmpty(medium.files.full.url) && !medium.files.full.url.Contains("upload")) + { + if (medium.type == "photo" && !config.DownloadImages) + { + continue; + } + if (medium.type == "video" && !config.DownloadVideos) + { + continue; + } + if (medium.type == "gif" && !config.DownloadVideos) + { + continue; + } + if (medium.type == "audio" && !config.DownloadAudios) + { + continue; + } + if (!purchasedTabCollection.PaidMessages.PaidMessages.ContainsKey(medium.id)) + { + await m_DBHelper.AddMedia(path, medium.id, purchase.id, medium.files.full.url, null, null, null, "Messages", medium.type == "photo" ? "Images" : (medium.type == "video" || medium.type == "gif" ? "Videos" : (medium.type == "audio" ? "Audios" : null)), paidMessagePreviewids.Contains(medium.id) ? true : false, false, null); + purchasedTabCollection.PaidMessages.PaidMessages.Add(medium.id, medium.files.full.url); + purchasedTabCollection.PaidMessages.PaidMessageMedia.Add(medium); + } + } + else if (medium.canView && medium.files != null && medium.files.drm != null) + { + if (medium.type == "photo" && !config.DownloadImages) + { + continue; + } + if (medium.type == "video" && !config.DownloadVideos) + { + continue; + } + if (medium.type == "gif" && !config.DownloadVideos) + { + continue; + } + if (medium.type == "audio" && !config.DownloadAudios) + { + continue; + } + if (!purchasedTabCollection.PaidMessages.PaidMessages.ContainsKey(medium.id)) + { + await m_DBHelper.AddMedia(path, medium.id, purchase.id, medium.files.drm.manifest.dash, null, null, null, "Messages", medium.type == "photo" ? "Images" : (medium.type == "video" || medium.type == "gif" ? "Videos" : (medium.type == "audio" ? "Audios" : null)), paidMessagePreviewids.Contains(medium.id) ? true : false, false, null); + purchasedTabCollection.PaidMessages.PaidMessages.Add(medium.id, $"{medium.files.drm.manifest.dash},{medium.files.drm.signature.dash.CloudFrontPolicy},{medium.files.drm.signature.dash.CloudFrontSignature},{medium.files.drm.signature.dash.CloudFrontKeyPairId},{medium.id},{purchase.id}"); + purchasedTabCollection.PaidMessages.PaidMessageMedia.Add(medium); + } + } + } + } + } + break; + } + } + purchasedTabCollections.Add(purchasedTabCollection); + } + } + return purchasedTabCollections; + } + catch (Exception ex) + { + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + Log.Error("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + if (ex.InnerException != null) + { + Console.WriteLine("\nInner Exception:"); + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + Log.Error("Inner Exception: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + } + } + return null; + } + + + public async Task GetDRMMPDPSSH(string mpdUrl, string policy, string signature, string kvp) + { + try + { + string pssh = null; + + HttpClient client = new(); + HttpRequestMessage request = new(HttpMethod.Get, mpdUrl); + request.Headers.Add("user-agent", auth.USER_AGENT); + request.Headers.Add("Accept", "*/*"); + request.Headers.Add("Cookie", $"CloudFront-Policy={policy}; CloudFront-Signature={signature}; CloudFront-Key-Pair-Id={kvp}; {auth.COOKIE};"); + using (var response = await client.SendAsync(request)) + { + response.EnsureSuccessStatusCode(); + var body = await response.Content.ReadAsStringAsync(); + XNamespace ns = "urn:mpeg:dash:schema:mpd:2011"; + XNamespace cenc = "urn:mpeg:cenc:2013"; + XDocument xmlDoc = XDocument.Parse(body); + var psshElements = xmlDoc.Descendants(cenc + "pssh"); + pssh = psshElements.ElementAt(1).Value; + } + + return pssh; + } + catch (Exception ex) + { + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + Log.Error("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + if (ex.InnerException != null) + { + Console.WriteLine("\nInner Exception:"); + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + Log.Error("Inner Exception: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + } + } + return null; + } + + + public async Task GetDRMMPDLastModified(string mpdUrl, string policy, string signature, string kvp) + { + Log.Debug("Calling GetDRMMPDLastModified"); + Log.Debug($"mpdUrl: {mpdUrl}"); + Log.Debug($"policy: {policy}"); + Log.Debug($"signature: {signature}"); + Log.Debug($"kvp: {kvp}"); + + try + { + DateTime lastmodified; + + HttpClient client = new(); + HttpRequestMessage request = new(HttpMethod.Get, mpdUrl); + request.Headers.Add("user-agent", auth.USER_AGENT); + request.Headers.Add("Accept", "*/*"); + request.Headers.Add("Cookie", $"CloudFront-Policy={policy}; CloudFront-Signature={signature}; CloudFront-Key-Pair-Id={kvp}; {auth.COOKIE};"); + using (var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead)) + { + response.EnsureSuccessStatusCode(); + lastmodified = response.Content.Headers.LastModified?.LocalDateTime ?? DateTime.Now; + + Log.Debug($"Last modified: {lastmodified}"); + } + return lastmodified; + } + catch (Exception ex) + { + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + Log.Error("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + if (ex.InnerException != null) + { + Console.WriteLine("\nInner Exception:"); + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + Log.Error("Inner Exception: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + } + } + return DateTime.Now; + } + + + public async Task GetDecryptionKeyCDRMProject(Dictionary drmHeaders, string licenceURL, string pssh) + { + Log.Debug("Calling GetDecryptionKey"); + + const int maxAttempts = 30; + const int delayBetweenAttempts = 3000; + int attempt = 0; + + try + { + string dcValue = string.Empty; + HttpClient client = new(); + + CDRMProjectRequest cdrmProjectRequest = new CDRMProjectRequest + { + PSSH = pssh, + LicenseURL = licenceURL, + Headers = JsonConvert.SerializeObject(drmHeaders), + Cookies = "", + Data = "" + }; + + string json = JsonConvert.SerializeObject(cdrmProjectRequest); + + Log.Debug($"Posting to CDRM Project: {json}"); + + while (attempt < maxAttempts) + { + attempt++; + + HttpRequestMessage request = new(HttpMethod.Post, "https://cdrm-project.com/api/decrypt") + { + Content = new StringContent(json, Encoding.UTF8, "application/json") + }; + + using var response = await client.SendAsync(request); + + Log.Debug($"CDRM Project Response (Attempt {attempt}): {response.Content.ReadAsStringAsync().Result}"); + + response.EnsureSuccessStatusCode(); + var body = await response.Content.ReadAsStringAsync(); + var doc = JsonDocument.Parse(body); + + if (doc.RootElement.TryGetProperty("status", out JsonElement status)) + { + if (status.ToString().Trim().Equals("success", StringComparison.OrdinalIgnoreCase)) + { + dcValue = doc.RootElement.GetProperty("message").GetString().Trim(); + return dcValue; + } + else + { + Log.Debug($"CDRM response status not successful. Retrying... Attempt {attempt} of {maxAttempts}"); + if (attempt < maxAttempts) + { + await Task.Delay(delayBetweenAttempts); + } + } + } + else + { + Log.Debug($"Status not in CDRM response. Retrying... Attempt {attempt} of {maxAttempts}"); + if (attempt < maxAttempts) + { + await Task.Delay(delayBetweenAttempts); + } + } + } + + throw new Exception("Maximum retry attempts reached. Unable to get a valid decryption key."); + } + catch (Exception ex) + { + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + Log.Error("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + if (ex.InnerException != null) + { + Console.WriteLine("\nInner Exception:"); + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + Log.Error("Inner Exception: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + } + } + return null; + } + + public async Task GetDecryptionKeyOFDL(Dictionary drmHeaders, string licenceURL, string pssh) + { + Log.Debug("Calling GetDecryptionOFDL"); + + + try + { + string dcValue = string.Empty; + HttpClient client = new(); + + OFDLRequest ofdlRequest = new OFDLRequest + { + PSSH = pssh, + LicenseURL = licenceURL, + Headers = JsonConvert.SerializeObject(drmHeaders) + }; + + string json = JsonConvert.SerializeObject(ofdlRequest); + + Log.Debug($"Posting to ofdl.tools: {json}"); + + HttpRequestMessage request = new(HttpMethod.Post, "https://ofdl.tools/WV") + { + Content = new StringContent(json, Encoding.UTF8, "application/json") + }; + + using var response = await client.SendAsync(request); + + if (response.IsSuccessStatusCode) + { + string body = await response.Content.ReadAsStringAsync(); + return body; + } + } + catch (Exception ex) + { + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + Log.Error("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + if (ex.InnerException != null) + { + Console.WriteLine("\nInner Exception:"); + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + Log.Error("Inner Exception: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + } + } + return null; + } + + public async Task GetDecryptionKeyCDM(Dictionary drmHeaders, string licenceURL, string pssh) + { + Log.Debug("Calling GetDecryptionKeyCDM"); + + try + { + var resp1 = PostData(licenceURL, drmHeaders, new byte[] { 0x08, 0x04 }); + var certDataB64 = Convert.ToBase64String(resp1); + var cdm = new CDMApi(); + var challenge = cdm.GetChallenge(pssh, certDataB64, false, false); + var resp2 = PostData(licenceURL, drmHeaders, challenge); + var licenseB64 = Convert.ToBase64String(resp2); + Log.Debug($"resp1: {resp1}"); + Log.Debug($"certDataB64: {certDataB64}"); + Log.Debug($"challenge: {challenge}"); + Log.Debug($"resp2: {resp2}"); + Log.Debug($"licenseB64: {licenseB64}"); + cdm.ProvideLicense(licenseB64); + List keys = cdm.GetKeys(); + if (keys.Count > 0) + { + Log.Debug($"GetDecryptionKeyCDM Key: {keys[0].ToString()}"); + return keys[0].ToString(); + } + } + catch (Exception ex) + { + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + Log.Error("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + if (ex.InnerException != null) + { + Console.WriteLine("\nInner Exception:"); + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + Log.Error("Inner Exception: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + } + } + return null; + } + + public static string? GetDynamicRules() + { + Log.Debug("Calling GetDynamicRules"); + try + { + HttpClient client = new HttpClient(); + HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, "https://raw.githubusercontent.com/deviint/onlyfans-dynamic-rules/main/dynamicRules.json"); + using var response = client.Send(request); + + if (!response.IsSuccessStatusCode) + { + Log.Debug("GetDynamicRules did not return a Success Status Code"); + return null; + } + + var body = response.Content.ReadAsStringAsync().Result; + + Log.Debug("GetDynamicRules Response: "); + Log.Debug(body); + + return body; + } + catch (Exception ex) + { + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + Log.Error("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + if (ex.InnerException != null) + { + Console.WriteLine("\nInner Exception:"); + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + Log.Error("Inner Exception: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + } + } + return null; + } +} diff --git a/OF DL/Helpers/AuthHelper.cs b/OF DL/Helpers/AuthHelper.cs new file mode 100644 index 0000000..b8c47d9 --- /dev/null +++ b/OF DL/Helpers/AuthHelper.cs @@ -0,0 +1,166 @@ +using OF_DL.Entities; +using PuppeteerSharp; +using PuppeteerSharp.BrowserData; +using Serilog; + +namespace OF_DL.Helpers; + +public class AuthHelper +{ + private readonly LaunchOptions _options = new() + { + Headless = false, + Channel = ChromeReleaseChannel.Stable, + DefaultViewport = null, + Args = ["--no-sandbox", "--disable-setuid-sandbox"], + UserDataDir = Path.GetFullPath("chrome-data") + }; + + private readonly string[] _desiredCookies = + [ + "auth_id", + "sess" + ]; + + private const int LoginTimeout = 600000; // 10 minutes + private const int FeedLoadTimeout = 60000; // 1 minute + + public async Task SetupBrowser(bool runningInDocker) + { + string? executablePath = Environment.GetEnvironmentVariable("OFDL_PUPPETEER_EXECUTABLE_PATH"); + if (executablePath != null) + { + Log.Information("OFDL_PUPPETEER_EXECUTABLE_PATH environment variable found. Using browser executable path: {executablePath}", executablePath); + _options.ExecutablePath = executablePath; + } + else + { + var browserFetcher = new BrowserFetcher(); + var installedBrowsers = browserFetcher.GetInstalledBrowsers().ToList(); + if (installedBrowsers.Count == 0) + { + Log.Information("Downloading browser."); + var downloadedBrowser = await browserFetcher.DownloadAsync(); + Log.Information("Browser downloaded. Path: {executablePath}", + downloadedBrowser.GetExecutablePath()); + _options.ExecutablePath = downloadedBrowser.GetExecutablePath(); + } + else + { + _options.ExecutablePath = installedBrowsers.First().GetExecutablePath(); + } + } + + if (runningInDocker) + { + Log.Information("Running in Docker. Disabling sandbox and GPU."); + _options.Args = ["--no-sandbox", "--disable-setuid-sandbox", "--disable-gpu"]; + } + } + + private async Task GetBcToken(IPage page) + { + return await page.EvaluateExpressionAsync("window.localStorage.getItem('bcTokenSha') || ''"); + } + + public async Task GetAuthFromBrowser(bool isDocker = false) + { + try + { + IBrowser? browser; + try + { + browser = await Puppeteer.LaunchAsync(_options); + } + catch (ProcessException e) + { + if (e.Message.Contains("Failed to launch browser") && Directory.Exists(_options.UserDataDir)) + { + Log.Error("Failed to launch browser. Deleting chrome-data directory and trying again."); + Directory.Delete(_options.UserDataDir, true); + browser = await Puppeteer.LaunchAsync(_options); + } + else + { + throw; + } + } + + if (browser == null) + { + throw new Exception("Could not get browser"); + } + + IPage[]? pages = await browser.PagesAsync(); + IPage? page = pages.First(); + + if (page == null) + { + throw new Exception("Could not get page"); + } + + Log.Debug("Navigating to OnlyFans."); + await page.GoToAsync("https://onlyfans.com"); + + Log.Debug("Waiting for user to login"); + await page.WaitForSelectorAsync(".b-feed", new WaitForSelectorOptions { Timeout = LoginTimeout }); + Log.Debug("Feed element detected (user logged in)"); + + await page.ReloadAsync(); + + await page.WaitForNavigationAsync(new NavigationOptions { + WaitUntil = [WaitUntilNavigation.Networkidle2], + Timeout = FeedLoadTimeout + }); + Log.Debug("DOM loaded. Getting BC token and cookies ..."); + + string xBc; + try + { + xBc = await GetBcToken(page); + } + catch (Exception e) + { + throw new Exception("Error getting bcToken"); + } + + Dictionary mappedCookies = (await page.GetCookiesAsync()) + .Where(cookie => cookie.Domain.Contains("onlyfans.com")) + .ToDictionary(cookie => cookie.Name, cookie => cookie.Value); + + mappedCookies.TryGetValue("auth_id", out string? userId); + if (userId == null) + { + throw new Exception("Could not find 'auth_id' cookie"); + } + + mappedCookies.TryGetValue("sess", out string? sess); + if (sess == null) + { + throw new Exception("Could not find 'sess' cookie"); + } + + string? userAgent = await browser.GetUserAgentAsync(); + if (userAgent == null) + { + throw new Exception("Could not get user agent"); + } + + string cookies = string.Join(" ", mappedCookies.Keys.Where(key => _desiredCookies.Contains(key)) + .Select(key => $"${key}={mappedCookies[key]};")); + + return new Auth() + { + COOKIE = cookies, + USER_AGENT = userAgent, + USER_ID = userId, + X_BC = xBc + }; + } + catch (Exception e) + { + Log.Error(e, "Error getting auth from browser"); + return null; + } + } +} diff --git a/OF DL/Helpers/Constants.cs b/OF DL/Helpers/Constants.cs new file mode 100644 index 0000000..857d1e3 --- /dev/null +++ b/OF DL/Helpers/Constants.cs @@ -0,0 +1,6 @@ +namespace OF_DL.Helpers; + +public static class Constants +{ + public const string API_URL = "https://onlyfans.com/api2/v2"; +} diff --git a/OF DL/Helpers/DBHelper.cs b/OF DL/Helpers/DBHelper.cs new file mode 100644 index 0000000..21e63a5 --- /dev/null +++ b/OF DL/Helpers/DBHelper.cs @@ -0,0 +1,531 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using OF_DL.Enumurations; +using System.IO; +using Microsoft.Data.Sqlite; +using Serilog; +using OF_DL.Entities; + +namespace OF_DL.Helpers +{ + public class DBHelper : IDBHelper + { + private readonly IDownloadConfig downloadConfig; + + public DBHelper(IDownloadConfig downloadConfig) + { + this.downloadConfig = downloadConfig; + } + + public async Task CreateDB(string folder) + { + try + { + if (!Directory.Exists(folder + "/Metadata")) + { + Directory.CreateDirectory(folder + "/Metadata"); + } + + string dbFilePath = $"{folder}/Metadata/user_data.db"; + + // connect to the new database file + using SqliteConnection connection = new($"Data Source={dbFilePath}"); + // open the connection + connection.Open(); + + // create the 'medias' table + using (SqliteCommand cmd = new("CREATE TABLE IF NOT EXISTS medias (id INTEGER NOT NULL, media_id INTEGER, post_id INTEGER NOT NULL, link VARCHAR, directory VARCHAR, filename VARCHAR, size INTEGER, api_type VARCHAR, media_type VARCHAR, preview INTEGER, linked VARCHAR, downloaded INTEGER, created_at TIMESTAMP, record_created_at TIMESTAMP, PRIMARY KEY(id), UNIQUE(media_id));", connection)) + { + await cmd.ExecuteNonQueryAsync(); + } + + await EnsureCreatedAtColumnExists(connection, "medias"); + + // + // Alter existing databases to create unique constraint on `medias` + // + using (SqliteCommand cmd = new(@" + PRAGMA foreign_keys=off; + + BEGIN TRANSACTION; + + ALTER TABLE medias RENAME TO old_medias; + + CREATE TABLE medias ( + id INTEGER NOT NULL, + media_id INTEGER, + post_id INTEGER NOT NULL, + link VARCHAR, + directory VARCHAR, + filename VARCHAR, + size INTEGER, + api_type VARCHAR, + media_type VARCHAR, + preview INTEGER, + linked VARCHAR, + downloaded INTEGER, + created_at TIMESTAMP, + record_created_at TIMESTAMP, + PRIMARY KEY(id), + UNIQUE(media_id, api_type) + ); + + INSERT INTO medias SELECT * FROM old_medias; + + DROP TABLE old_medias; + + COMMIT; + + PRAGMA foreign_keys=on;", connection)) + { + await cmd.ExecuteNonQueryAsync(); + } + + // create the 'messages' table + using (SqliteCommand cmd = new("CREATE TABLE IF NOT EXISTS messages (id INTEGER NOT NULL, post_id INTEGER NOT NULL, text VARCHAR, price INTEGER, paid INTEGER, archived BOOLEAN, created_at TIMESTAMP, user_id INTEGER, record_created_at TIMESTAMP, PRIMARY KEY(id), UNIQUE(post_id));", connection)) + { + await cmd.ExecuteNonQueryAsync(); + } + + // create the 'posts' table + using (SqliteCommand cmd = new("CREATE TABLE IF NOT EXISTS posts (id INTEGER NOT NULL, post_id INTEGER NOT NULL, text VARCHAR, price INTEGER, paid INTEGER, archived BOOLEAN, created_at TIMESTAMP, record_created_at TIMESTAMP, PRIMARY KEY(id), UNIQUE(post_id));", connection)) + { + await cmd.ExecuteNonQueryAsync(); + } + + // create the 'stories' table + using (SqliteCommand cmd = new("CREATE TABLE IF NOT EXISTS stories (id INTEGER NOT NULL, post_id INTEGER NOT NULL, text VARCHAR, price INTEGER, paid INTEGER, archived BOOLEAN, created_at TIMESTAMP, record_created_at TIMESTAMP, PRIMARY KEY(id), UNIQUE(post_id));", connection)) + { + await cmd.ExecuteNonQueryAsync(); + } + + // create the 'others' table + using (SqliteCommand cmd = new("CREATE TABLE IF NOT EXISTS others (id INTEGER NOT NULL, post_id INTEGER NOT NULL, text VARCHAR, price INTEGER, paid INTEGER, archived BOOLEAN, created_at TIMESTAMP, record_created_at TIMESTAMP, PRIMARY KEY(id), UNIQUE(post_id));", connection)) + { + await cmd.ExecuteNonQueryAsync(); + } + + // create the 'products' table + using (SqliteCommand cmd = new("CREATE TABLE IF NOT EXISTS products (id INTEGER NOT NULL, post_id INTEGER NOT NULL, text VARCHAR, price INTEGER, paid INTEGER, archived BOOLEAN, created_at TIMESTAMP, title VARCHAR, record_created_at TIMESTAMP, PRIMARY KEY(id), UNIQUE(post_id));", connection)) + { + await cmd.ExecuteNonQueryAsync(); + } + + // create the 'profiles' table + using (SqliteCommand cmd = new("CREATE TABLE IF NOT EXISTS profiles (id INTEGER NOT NULL, user_id INTEGER NOT NULL, username VARCHAR NOT NULL, record_created_at TIMESTAMP, PRIMARY KEY(id), UNIQUE(username));", connection)) + { + await cmd.ExecuteNonQueryAsync(); + } + + connection.Close(); + } + catch (Exception ex) + { + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + Log.Error("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + if (ex.InnerException != null) + { + Console.WriteLine("\nInner Exception:"); + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + Log.Error("Inner Exception: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + } + } + } + + public async Task CreateUsersDB(Dictionary users) + { + try + { + using SqliteConnection connection = new($"Data Source={Directory.GetCurrentDirectory()}/users.db"); + Log.Debug("Database data source: " + connection.DataSource); + + connection.Open(); + + using (SqliteCommand cmd = new("CREATE TABLE IF NOT EXISTS users (id INTEGER NOT NULL, user_id INTEGER NOT NULL, username VARCHAR NOT NULL, PRIMARY KEY(id), UNIQUE(username));", connection)) + { + await cmd.ExecuteNonQueryAsync(); + } + + Log.Debug("Adding missing creators"); + foreach (KeyValuePair user in users) + { + using (SqliteCommand checkCmd = new($"SELECT user_id, username FROM users WHERE user_id = @userId;", connection)) + { + checkCmd.Parameters.AddWithValue("@userId", user.Value); + using (var reader = await checkCmd.ExecuteReaderAsync()) + { + if (!reader.Read()) + { + using (SqliteCommand insertCmd = new($"INSERT INTO users (user_id, username) VALUES (@userId, @username);", connection)) + { + insertCmd.Parameters.AddWithValue("@userId", user.Value); + insertCmd.Parameters.AddWithValue("@username", user.Key); + await insertCmd.ExecuteNonQueryAsync(); + Log.Debug("Inserted new creator: " + user.Key); + } + } + else + { + Log.Debug("Creator " + user.Key + " already exists"); + } + } + } + } + + connection.Close(); + } + catch (Exception ex) + { + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + Log.Error("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + if (ex.InnerException != null) + { + Console.WriteLine("\nInner Exception:"); + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + Log.Error("Inner Exception: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + } + } + } + + public async Task CheckUsername(KeyValuePair user, string path) + { + try + { + using SqliteConnection connection = new($"Data Source={Directory.GetCurrentDirectory()}/users.db"); + + connection.Open(); + + using (SqliteCommand checkCmd = new($"SELECT user_id, username FROM users WHERE user_id = @userId;", connection)) + { + checkCmd.Parameters.AddWithValue("@userId", user.Value); + using (var reader = await checkCmd.ExecuteReaderAsync()) + { + if (reader.Read()) + { + long storedUserId = reader.GetInt64(0); + string storedUsername = reader.GetString(1); + + if (storedUsername != user.Key) + { + using (SqliteCommand updateCmd = new($"UPDATE users SET username = @newUsername WHERE user_id = @userId;", connection)) + { + updateCmd.Parameters.AddWithValue("@newUsername", user.Key); + updateCmd.Parameters.AddWithValue("@userId", user.Value); + await updateCmd.ExecuteNonQueryAsync(); + } + + string oldPath = path.Replace(path.Split("/")[^1], storedUsername); + + if (Directory.Exists(oldPath)) + { + Directory.Move(path.Replace(path.Split("/")[^1], storedUsername), path); + } + } + } + } + } + + connection.Close(); + } + catch (Exception ex) + { + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + Log.Error("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + if (ex.InnerException != null) + { + Console.WriteLine("\nInner Exception:"); + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + Log.Error("Inner Exception: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + } + } + } + + public async Task AddMessage(string folder, long post_id, string message_text, string price, bool is_paid, bool is_archived, DateTime created_at, int user_id) + { + try + { + using SqliteConnection connection = new($"Data Source={folder}/Metadata/user_data.db"); + connection.Open(); + await EnsureCreatedAtColumnExists(connection, "messages"); + using SqliteCommand cmd = new($"SELECT COUNT(*) FROM messages WHERE post_id=@post_id", connection); + cmd.Parameters.AddWithValue("@post_id", post_id); + int count = Convert.ToInt32(await cmd.ExecuteScalarAsync()); + if (count == 0) + { + // If the record doesn't exist, insert a new one + using SqliteCommand insertCmd = new("INSERT INTO messages(post_id, text, price, paid, archived, created_at, user_id, record_created_at) VALUES(@post_id, @message_text, @price, @is_paid, @is_archived, @created_at, @user_id, @record_created_at)", connection); + insertCmd.Parameters.AddWithValue("@post_id", post_id); + insertCmd.Parameters.AddWithValue("@message_text", message_text ?? (object)DBNull.Value); + insertCmd.Parameters.AddWithValue("@price", price ?? (object)DBNull.Value); + insertCmd.Parameters.AddWithValue("@is_paid", is_paid); + insertCmd.Parameters.AddWithValue("@is_archived", is_archived); + insertCmd.Parameters.AddWithValue("@created_at", created_at); + insertCmd.Parameters.AddWithValue("@user_id", user_id); + insertCmd.Parameters.AddWithValue("@record_created_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); + await insertCmd.ExecuteNonQueryAsync(); + } + } + catch (Exception ex) + { + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + Log.Error("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + if (ex.InnerException != null) + { + Console.WriteLine("\nInner Exception:"); + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + Log.Error("Inner Exception: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + } + } + } + + + public async Task AddPost(string folder, long post_id, string message_text, string price, bool is_paid, bool is_archived, DateTime created_at) + { + try + { + using SqliteConnection connection = new($"Data Source={folder}/Metadata/user_data.db"); + connection.Open(); + await EnsureCreatedAtColumnExists(connection, "posts"); + using SqliteCommand cmd = new($"SELECT COUNT(*) FROM posts WHERE post_id=@post_id", connection); + cmd.Parameters.AddWithValue("@post_id", post_id); + int count = Convert.ToInt32(await cmd.ExecuteScalarAsync()); + if (count == 0) + { + // If the record doesn't exist, insert a new one + using SqliteCommand insertCmd = new("INSERT INTO posts(post_id, text, price, paid, archived, created_at, record_created_at) VALUES(@post_id, @message_text, @price, @is_paid, @is_archived, @created_at, @record_created_at)", connection); + insertCmd.Parameters.AddWithValue("@post_id", post_id); + insertCmd.Parameters.AddWithValue("@message_text", message_text ?? (object)DBNull.Value); + insertCmd.Parameters.AddWithValue("@price", price ?? (object)DBNull.Value); + insertCmd.Parameters.AddWithValue("@is_paid", is_paid); + insertCmd.Parameters.AddWithValue("@is_archived", is_archived); + insertCmd.Parameters.AddWithValue("@created_at", created_at); + insertCmd.Parameters.AddWithValue("@record_created_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); + await insertCmd.ExecuteNonQueryAsync(); + } + } + catch (Exception ex) + { + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + Log.Error("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + if (ex.InnerException != null) + { + Console.WriteLine("\nInner Exception:"); + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + Log.Error("Inner Exception: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + } + } + } + + + public async Task AddStory(string folder, long post_id, string message_text, string price, bool is_paid, bool is_archived, DateTime created_at) + { + try + { + using SqliteConnection connection = new($"Data Source={folder}/Metadata/user_data.db"); + connection.Open(); + await EnsureCreatedAtColumnExists(connection, "stories"); + using SqliteCommand cmd = new($"SELECT COUNT(*) FROM stories WHERE post_id=@post_id", connection); + cmd.Parameters.AddWithValue("@post_id", post_id); + int count = Convert.ToInt32(await cmd.ExecuteScalarAsync()); + if (count == 0) + { + // If the record doesn't exist, insert a new one + using SqliteCommand insertCmd = new("INSERT INTO stories(post_id, text, price, paid, archived, created_at, record_created_at) VALUES(@post_id, @message_text, @price, @is_paid, @is_archived, @created_at, @record_created_at)", connection); + insertCmd.Parameters.AddWithValue("@post_id", post_id); + insertCmd.Parameters.AddWithValue("@message_text", message_text ?? (object)DBNull.Value); + insertCmd.Parameters.AddWithValue("@price", price ?? (object)DBNull.Value); + insertCmd.Parameters.AddWithValue("@is_paid", is_paid); + insertCmd.Parameters.AddWithValue("@is_archived", is_archived); + insertCmd.Parameters.AddWithValue("@created_at", created_at); + insertCmd.Parameters.AddWithValue("@record_created_at", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); + await insertCmd.ExecuteNonQueryAsync(); + } + } + catch (Exception ex) + { + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + Log.Error("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + if (ex.InnerException != null) + { + Console.WriteLine("\nInner Exception:"); + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + Log.Error("Inner Exception: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + } + } + } + + + public async Task AddMedia(string folder, long media_id, long post_id, string link, string? directory, string? filename, long? size, string api_type, string media_type, bool preview, bool downloaded, DateTime? created_at) + { + try + { + using SqliteConnection connection = new($"Data Source={folder}/Metadata/user_data.db"); + connection.Open(); + await EnsureCreatedAtColumnExists(connection, "medias"); + StringBuilder sql = new StringBuilder("SELECT COUNT(*) FROM medias WHERE media_id=@media_id"); + if (downloadConfig.DownloadDuplicatedMedia) + { + sql.Append(" and api_type=@api_type"); + } + + using SqliteCommand cmd = new(sql.ToString(), connection); + cmd.Parameters.AddWithValue("@media_id", media_id); + cmd.Parameters.AddWithValue("@api_type", api_type); + int count = Convert.ToInt32(cmd.ExecuteScalar()); + if (count == 0) + { + // If the record doesn't exist, insert a new one + using SqliteCommand insertCmd = new($"INSERT INTO medias(media_id, post_id, link, directory, filename, size, api_type, media_type, preview, downloaded, created_at, record_created_at) VALUES({media_id}, {post_id}, '{link}', '{directory?.ToString() ?? "NULL"}', '{filename?.ToString() ?? "NULL"}', {size?.ToString() ?? "NULL"}, '{api_type}', '{media_type}', {Convert.ToInt32(preview)}, {Convert.ToInt32(downloaded)}, '{created_at?.ToString("yyyy-MM-dd HH:mm:ss")}', '{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}')", connection); + await insertCmd.ExecuteNonQueryAsync(); + } + } + catch (Exception ex) + { + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + Log.Error("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + if (ex.InnerException != null) + { + Console.WriteLine("\nInner Exception:"); + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + Log.Error("Inner Exception: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + } + } + } + + + public async Task CheckDownloaded(string folder, long media_id, string api_type) + { + try + { + bool downloaded = false; + + using (SqliteConnection connection = new($"Data Source={folder}/Metadata/user_data.db")) + { + StringBuilder sql = new StringBuilder("SELECT downloaded FROM medias WHERE media_id=@media_id"); + if(downloadConfig.DownloadDuplicatedMedia) + { + sql.Append(" and api_type=@api_type"); + } + + connection.Open(); + using SqliteCommand cmd = new (sql.ToString(), connection); + cmd.Parameters.AddWithValue("@media_id", media_id); + cmd.Parameters.AddWithValue("@api_type", api_type); + downloaded = Convert.ToBoolean(await cmd.ExecuteScalarAsync()); + } + return downloaded; + } + catch (Exception ex) + { + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + Log.Error("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + if (ex.InnerException != null) + { + Console.WriteLine("\nInner Exception:"); + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + Log.Error("Inner Exception: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + } + } + return false; + } + + + public async Task UpdateMedia(string folder, long media_id, string api_type, string directory, string filename, long size, bool downloaded, DateTime created_at) + { + using SqliteConnection connection = new($"Data Source={folder}/Metadata/user_data.db"); + connection.Open(); + + // Construct the update command + StringBuilder sql = new StringBuilder("UPDATE medias SET directory=@directory, filename=@filename, size=@size, downloaded=@downloaded, created_at=@created_at WHERE media_id=@media_id"); + if (downloadConfig.DownloadDuplicatedMedia) + { + sql.Append(" and api_type=@api_type"); + } + + // Create a new command object + using SqliteCommand command = new(sql.ToString(), connection); + // Add parameters to the command object + command.Parameters.AddWithValue("@directory", directory); + command.Parameters.AddWithValue("@filename", filename); + command.Parameters.AddWithValue("@size", size); + command.Parameters.AddWithValue("@downloaded", downloaded ? 1 : 0); + command.Parameters.AddWithValue("@created_at", created_at); + command.Parameters.AddWithValue("@media_id", media_id); + command.Parameters.AddWithValue("@api_type", api_type); + + // Execute the command + await command.ExecuteNonQueryAsync(); + } + + + public async Task GetStoredFileSize(string folder, long media_id, string api_type) + { + long size; + using (SqliteConnection connection = new($"Data Source={folder}/Metadata/user_data.db")) + { + connection.Open(); + using SqliteCommand cmd = new($"SELECT size FROM medias WHERE media_id=@media_id and api_type=@api_type", connection); + cmd.Parameters.AddWithValue("@media_id", media_id); + cmd.Parameters.AddWithValue("@api_type", api_type); + size = Convert.ToInt64(await cmd.ExecuteScalarAsync()); + } + return size; + } + + public async Task GetMostRecentPostDate(string folder) + { + DateTime? mostRecentDate = null; + using (SqliteConnection connection = new($"Data Source={folder}/Metadata/user_data.db")) + { + connection.Open(); + using SqliteCommand cmd = new(@" + SELECT + MIN(created_at) AS created_at + FROM ( + SELECT MAX(P.created_at) AS created_at + FROM posts AS P + LEFT OUTER JOIN medias AS m + ON P.post_id = m.post_id + AND m.downloaded = 1 + UNION + SELECT MIN(P.created_at) AS created_at + FROM posts AS P + INNER JOIN medias AS m + ON P.post_id = m.post_id + WHERE m.downloaded = 0 + )", connection); + var scalarValue = await cmd.ExecuteScalarAsync(); + if(scalarValue != null && scalarValue != DBNull.Value) + { + mostRecentDate = Convert.ToDateTime(scalarValue); + } + } + return mostRecentDate; + } + + private async Task EnsureCreatedAtColumnExists(SqliteConnection connection, string tableName) + { + using SqliteCommand cmd = new($"PRAGMA table_info({tableName});", connection); + using var reader = await cmd.ExecuteReaderAsync(); + bool columnExists = false; + + while (await reader.ReadAsync()) + { + if (reader["name"].ToString() == "record_created_at") + { + columnExists = true; + break; + } + } + + if (!columnExists) + { + using SqliteCommand alterCmd = new($"ALTER TABLE {tableName} ADD COLUMN record_created_at TIMESTAMP;", connection); + await alterCmd.ExecuteNonQueryAsync(); + } + } + } +} diff --git a/OF DL/Helpers/DownloadContext.cs b/OF DL/Helpers/DownloadContext.cs new file mode 100644 index 0000000..cc65dcb --- /dev/null +++ b/OF DL/Helpers/DownloadContext.cs @@ -0,0 +1,36 @@ +using OF_DL.Entities; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace OF_DL.Helpers +{ + internal interface IDownloadContext + { + public IDownloadConfig DownloadConfig { get; } + public IFileNameFormatConfig FileNameFormatConfig { get; } + public APIHelper ApiHelper { get; } + public DBHelper DBHelper { get; } + public DownloadHelper DownloadHelper { get; } + } + + internal class DownloadContext : IDownloadContext + { + public APIHelper ApiHelper { get; } + public DBHelper DBHelper { get; } + public DownloadHelper DownloadHelper { get; } + public IDownloadConfig DownloadConfig { get; } + public IFileNameFormatConfig FileNameFormatConfig { get; } + + public DownloadContext(Auth auth, IDownloadConfig downloadConfig, IFileNameFormatConfig fileNameFormatConfig, APIHelper apiHelper, DBHelper dBHelper) + { + ApiHelper = apiHelper; + DBHelper = dBHelper; + DownloadConfig = downloadConfig; + FileNameFormatConfig = fileNameFormatConfig; + DownloadHelper = new DownloadHelper(auth, downloadConfig, fileNameFormatConfig); + } + } +} diff --git a/OF DL/Helpers/DownloadHelper.cs b/OF DL/Helpers/DownloadHelper.cs new file mode 100644 index 0000000..1c2589e --- /dev/null +++ b/OF DL/Helpers/DownloadHelper.cs @@ -0,0 +1,1790 @@ +using FFmpeg.NET; +using FFmpeg.NET.Events; +using FFmpeg.NET.Services; +using OF_DL.Entities; +using OF_DL.Entities.Archived; +using OF_DL.Entities.Messages; +using OF_DL.Entities.Post; +using OF_DL.Entities.Purchased; +using OF_DL.Entities.Stories; +using OF_DL.Entities.Streams; +using OF_DL.Enumerations; +using OF_DL.Utils; +using Org.BouncyCastle.Asn1.Tsp; +using Org.BouncyCastle.Asn1.X509; +using Serilog; +using Spectre.Console; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Net; +using System.Security.Cryptography; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using static OF_DL.Entities.Lists.UserList; +using static OF_DL.Entities.Messages.Messages; + +namespace OF_DL.Helpers; + +public class DownloadHelper : IDownloadHelper +{ + private readonly Auth auth; + private readonly IDBHelper m_DBHelper; + private readonly IFileNameHelper _FileNameHelper; + private readonly IDownloadConfig downloadConfig; + private readonly IFileNameFormatConfig fileNameFormatConfig; + private TaskCompletionSource _completionSource; + + public DownloadHelper(Auth auth, IDownloadConfig downloadConfig, IFileNameFormatConfig fileNameFormatConfig) + { + this.auth = auth; + this.m_DBHelper = new DBHelper(downloadConfig); + this._FileNameHelper = new FileNameHelper(auth); + this.downloadConfig = downloadConfig; + this.fileNameFormatConfig = fileNameFormatConfig; + } + + #region common + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + protected async Task CreateDirectoriesAndDownloadMedia(string path, + string url, + string folder, + long media_id, + string api_type, + ProgressTask task, + string serverFileName, + string resolvedFileName) + { + try + { + string customFileName = string.Empty; + if (!Directory.Exists(folder + path)) + { + Directory.CreateDirectory(folder + path); + } + string extension = Path.GetExtension(url.Split("?")[0]); + + path = UpdatePathBasedOnExtension(folder, path, extension); + + return await ProcessMediaDownload(folder, media_id, api_type, url, path, serverFileName, resolvedFileName, extension, task); + } + catch (Exception ex) + { + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + + if (ex.InnerException != null) + { + Console.WriteLine("\nInner Exception:"); + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + } + } + return false; + } + + + /// + /// Updates the given path based on the file extension. + /// + /// The parent folder. + /// The initial relative path. + /// The file extension. + /// A string that represents the updated path based on the file extension. + private string UpdatePathBasedOnExtension(string folder, string path, string extension) + { + string subdirectory = string.Empty; + + switch (extension.ToLower()) + { + case ".jpg": + case ".jpeg": + case ".png": + subdirectory = "/Images"; + break; + case ".mp4": + case ".avi": + case ".wmv": + case ".gif": + case ".mov": + subdirectory = "/Videos"; + break; + case ".mp3": + case ".wav": + case ".ogg": + subdirectory = "/Audios"; + break; + } + + if (!string.IsNullOrEmpty(subdirectory)) + { + path += subdirectory; + string fullPath = folder + path; + + if (!Directory.Exists(fullPath)) + { + Directory.CreateDirectory(fullPath); + } + } + + return path; + } + + + /// + /// Generates a custom filename based on the given format and properties. + /// + /// The format string for the filename. + /// General information about the post. + /// Media associated with the post. + /// Author of the post. + /// Dictionary containing user-related data. + /// Helper class for filename operations. + /// A Task resulting in a string that represents the custom filename. + private async Task GenerateCustomFileName(string filename, + string? filenameFormat, + object? postInfo, + object? postMedia, + object? author, + string username, + Dictionary users, + IFileNameHelper fileNameHelper, + CustomFileNameOption option) + { + if (string.IsNullOrEmpty(filenameFormat) || postInfo == null || postMedia == null || author == null) + { + return option switch + { + CustomFileNameOption.ReturnOriginal => filename, + CustomFileNameOption.ReturnEmpty => string.Empty, + _ => filename, + }; + } + + List properties = new(); + string pattern = @"\{(.*?)\}"; + MatchCollection matches = Regex.Matches(filenameFormat, pattern); + properties.AddRange(matches.Select(match => match.Groups[1].Value)); + + Dictionary values = await fileNameHelper.GetFilename(postInfo, postMedia, author, properties, username, users); + return await fileNameHelper.BuildFilename(filenameFormat, values); + } + + + private async Task GetFileSizeAsync(string url, Auth auth) + { + long fileSize = 0; + + try + { + Uri uri = new(url); + + if (uri.Host == "cdn3.onlyfans.com" && uri.LocalPath.Contains("/dash/files")) + { + string[] messageUrlParsed = url.Split(','); + string mpdURL = messageUrlParsed[0]; + string policy = messageUrlParsed[1]; + string signature = messageUrlParsed[2]; + string kvp = messageUrlParsed[3]; + + mpdURL = mpdURL.Replace(".mpd", "_source.mp4"); + + using HttpClient client = new(); + client.DefaultRequestHeaders.Add("Cookie", $"CloudFront-Policy={policy}; CloudFront-Signature={signature}; CloudFront-Key-Pair-Id={kvp}; {auth.COOKIE}"); + client.DefaultRequestHeaders.Add("User-Agent", auth.USER_AGENT); + + using HttpResponseMessage response = await client.GetAsync(mpdURL, HttpCompletionOption.ResponseHeadersRead); + if (response.IsSuccessStatusCode) + { + fileSize = response.Content.Headers.ContentLength ?? 0; + } + } + else + { + using HttpClient client = new(); + client.DefaultRequestHeaders.Add("User-Agent", auth.USER_AGENT); + using HttpResponseMessage response = await client.GetAsync(uri, HttpCompletionOption.ResponseHeadersRead); + if (response.IsSuccessStatusCode) + { + fileSize = response.Content.Headers.ContentLength ?? 0; + } + } + } + catch (Exception ex) + { + Console.WriteLine($"Error getting file size for URL '{url}': {ex.Message}"); + } + + return fileSize; + } + + public static async Task GetDRMVideoLastModified(string url, Auth auth) + { + Uri uri = new(url); + + string[] messageUrlParsed = url.Split(','); + string mpdURL = messageUrlParsed[0]; + string policy = messageUrlParsed[1]; + string signature = messageUrlParsed[2]; + string kvp = messageUrlParsed[3]; + + mpdURL = mpdURL.Replace(".mpd", "_source.mp4"); + + using HttpClient client = new(); + client.DefaultRequestHeaders.Add("Cookie", $"CloudFront-Policy={policy}; CloudFront-Signature={signature}; CloudFront-Key-Pair-Id={kvp}; {auth.COOKIE}"); + client.DefaultRequestHeaders.Add("User-Agent", auth.USER_AGENT); + + using HttpResponseMessage response = await client.GetAsync(mpdURL, HttpCompletionOption.ResponseHeadersRead); + if (response.IsSuccessStatusCode) + { + return response.Content.Headers.LastModified.Value.DateTime; + } + return DateTime.Now; + } + public static async Task GetMediaLastModified(string url) + { + using HttpClient client = new(); + + using HttpResponseMessage response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead); + if (response.IsSuccessStatusCode) + { + return response.Content.Headers.LastModified.Value.DateTime; + } + return DateTime.Now; + } + + /// + /// Processes the download and database update of media. + /// + /// The folder where the media is stored. + /// The ID of the media. + /// The full path to the media. + /// The URL from where to download the media. + /// The relative path to the media. + /// The filename after any required manipulations. + /// The file extension. + /// The task object for tracking progress. + /// A Task resulting in a boolean indicating whether the media is newly downloaded or not. + public async Task ProcessMediaDownload(string folder, + long media_id, + string api_type, + string url, + string path, + string serverFilename, + string resolvedFilename, + string extension, + ProgressTask task) + { + + try + { + if (!await m_DBHelper.CheckDownloaded(folder, media_id, api_type)) + { + return await HandleNewMedia(folder: folder, + media_id: media_id, + api_type: api_type, + url: url, + path: path, + serverFilename: serverFilename, + resolvedFilename: resolvedFilename, + extension: extension, + task: task); + } + else + { + bool status = await HandlePreviouslyDownloadedMediaAsync(folder, media_id, api_type, task); + if (downloadConfig.RenameExistingFilesWhenCustomFormatIsSelected && (serverFilename != resolvedFilename)) + { + await HandleRenamingOfExistingFilesAsync(folder, media_id, api_type, path, serverFilename, resolvedFilename, extension); + } + return status; + } + } + catch (Exception ex) + { + // Handle exception (e.g., log it) + Console.WriteLine($"An error occurred: {ex.Message}"); + return false; + } + } + + + private async Task HandleRenamingOfExistingFilesAsync(string folder, + long media_id, + string api_type, + string path, + string serverFilename, + string resolvedFilename, + string extension) + { + string fullPathWithTheServerFileName = $"{folder}{path}/{serverFilename}{extension}"; + string fullPathWithTheNewFileName = $"{folder}{path}/{resolvedFilename}{extension}"; + if (!File.Exists(fullPathWithTheServerFileName)) + { + return false; + } + + try + { + File.Move(fullPathWithTheServerFileName, fullPathWithTheNewFileName); + } + catch (Exception ex) + { + Console.WriteLine($"An error occurred: {ex.Message}"); + return false; + } + + long size = await m_DBHelper.GetStoredFileSize(folder, media_id, api_type); + var lastModified = File.GetLastWriteTime(fullPathWithTheNewFileName); + await m_DBHelper.UpdateMedia(folder, media_id, api_type, folder + path, resolvedFilename + extension, size, true, lastModified); + return true; + } + + + /// + /// Handles new media by downloading and updating the database. + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// A Task resulting in a boolean indicating whether the media is newly downloaded or not. + private async Task HandleNewMedia(string folder, + long media_id, + string api_type, + string url, + string path, + string serverFilename, + string resolvedFilename, + string extension, + ProgressTask task) + { + long fileSizeInBytes; + DateTime lastModified; + bool status; + + string fullPathWithTheServerFileName = $"{folder}{path}/{serverFilename}{extension}"; + string fullPathWithTheNewFileName = $"{folder}{path}/{resolvedFilename}{extension}"; + + //there are a few possibilities here. + //1.file has been downloaded in the past but it has the server filename + // in that case it should be set as existing and it should be renamed + //2.file has been downloaded in the past but it has custom filename. + // it should be set as existing and nothing else. + // of coures 1 and 2 depends in the fact that there may be a difference in the resolved file name + // (ie user has selected a custom format. If he doesn't then the resolved name will be the same as the server filename + //3.file doesn't exist and it should be downloaded. + + // Handle the case where the file has been downloaded in the past with the server filename + //but it has downloaded outsite of this application so it doesn't exist in the database + if (File.Exists(fullPathWithTheServerFileName)) + { + string finalPath; + if (fullPathWithTheServerFileName != fullPathWithTheNewFileName) + { + finalPath = fullPathWithTheNewFileName; + //rename. + try + { + File.Move(fullPathWithTheServerFileName, fullPathWithTheNewFileName); + } + catch (Exception ex) + { + Console.WriteLine($"An error occurred: {ex.Message}"); + } + } + else + { + finalPath = fullPathWithTheServerFileName; + } + + fileSizeInBytes = GetLocalFileSize(finalPath); + lastModified = File.GetLastWriteTime(finalPath); + if (downloadConfig.ShowScrapeSize) + { + task.Increment(fileSizeInBytes); + } + else + { + task.Increment(1); + } + status = false; + } + // Handle the case where the file has been downloaded in the past with a custom filename. + //but it has downloaded outsite of this application so it doesn't exist in the database + // this is a bit improbable but we should check for that. + else if (File.Exists(fullPathWithTheNewFileName)) + { + fileSizeInBytes = GetLocalFileSize(fullPathWithTheNewFileName); + lastModified = File.GetLastWriteTime(fullPathWithTheNewFileName); + if (downloadConfig.ShowScrapeSize) + { + task.Increment(fileSizeInBytes); + } + else + { + task.Increment(1); + } + status = false; + } + else //file doesn't exist and we should download it. + { + lastModified = await DownloadFile(url, fullPathWithTheNewFileName, task); + fileSizeInBytes = GetLocalFileSize(fullPathWithTheNewFileName); + status = true; + } + + //finaly check which filename we should use. Custom or the server one. + //if a custom is used, then the servefilename will be different from the resolved filename. + string finalName = serverFilename == resolvedFilename ? serverFilename : resolvedFilename; + await m_DBHelper.UpdateMedia(folder, media_id, api_type, folder + path, finalName + extension, fileSizeInBytes, true, lastModified); + return status; + } + + + /// + /// Handles media that has been previously downloaded and updates the task accordingly. + /// + /// + /// + /// + /// + /// A boolean indicating whether the media is newly downloaded or not. + private async Task HandlePreviouslyDownloadedMediaAsync(string folder, long media_id, string api_type, ProgressTask task) + { + if (downloadConfig.ShowScrapeSize) + { + long size = await m_DBHelper.GetStoredFileSize(folder, media_id, api_type); + task.Increment(size); + } + else + { + task.Increment(1); + } + return false; + } + + + /// + /// Gets the file size of the media. + /// + /// The path to the file. + /// The file size in bytes. + private long GetLocalFileSize(string filePath) + { + return new FileInfo(filePath).Length; + } + + + /// + /// Downloads a file from the given URL and saves it to the specified destination path. + /// + /// The URL to download the file from. + /// The path where the downloaded file will be saved. + /// Progress tracking object. + /// A Task resulting in a DateTime indicating the last modified date of the downloaded file. + + private async Task DownloadFile(string url, string destinationPath, ProgressTask task) + { + using var client = new HttpClient(); + var request = new HttpRequestMessage + { + Method = HttpMethod.Get, + RequestUri = new Uri(url) + }; + + using var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead); + response.EnsureSuccessStatusCode(); + var body = await response.Content.ReadAsStreamAsync(); + + // Wrap the body stream with the ThrottledStream to limit read rate. + using (ThrottledStream throttledStream = new(body, downloadConfig.DownloadLimitInMbPerSec * 1_000_000, downloadConfig.LimitDownloadRate)) + { + using FileStream fileStream = new(destinationPath, FileMode.Create, FileAccess.Write, FileShare.None, 16384, true); + var buffer = new byte[16384]; + int read; + while ((read = await throttledStream.ReadAsync(buffer, CancellationToken.None)) > 0) + { + if (downloadConfig.ShowScrapeSize) + { + task.Increment(read); + } + await fileStream.WriteAsync(buffer.AsMemory(0, read), CancellationToken.None); + } + } + + File.SetLastWriteTime(destinationPath, response.Content.Headers.LastModified?.LocalDateTime ?? DateTime.Now); + if (!downloadConfig.ShowScrapeSize) + { + task.Increment(1); + } + return response.Content.Headers.LastModified?.LocalDateTime ?? DateTime.Now; + } + + public async Task CalculateTotalFileSize(List urls) + { + long totalFileSize = 0; + if (urls.Count > 250) + { + int batchSize = 250; + + var tasks = new List>(); + + for (int i = 0; i < urls.Count; i += batchSize) + { + var batchUrls = urls.Skip(i).Take(batchSize).ToList(); + + var batchTasks = batchUrls.Select(url => GetFileSizeAsync(url, auth)); + tasks.AddRange(batchTasks); + + await Task.WhenAll(batchTasks); + + await Task.Delay(5000); + } + + long[] fileSizes = await Task.WhenAll(tasks); + foreach (long fileSize in fileSizes) + { + totalFileSize += fileSize; + } + } + else + { + var tasks = new List>(); + + foreach (string url in urls) + { + tasks.Add(GetFileSizeAsync(url, auth)); + } + + long[] fileSizes = await Task.WhenAll(tasks); + foreach (long fileSize in fileSizes) + { + totalFileSize += fileSize; + } + } + + return totalFileSize; + } + #endregion + + #region drm common + + private async Task DownloadDrmMedia(string user_agent, string policy, string signature, string kvp, string sess, string url, string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, ProgressTask task, string customFileName, string filename, string path) + { + try + { + _completionSource = new TaskCompletionSource(); + + int pos1 = decryptionKey.IndexOf(':'); + string decKey = ""; + if (pos1 >= 0) + { + decKey = decryptionKey.Substring(pos1 + 1); + } + + string tempFilename = $"{folder}{path}/{filename}_source.mp4"; + + string parameters = $"-cenc_decryption_key {decKey} -headers \"Cookie:CloudFront-Policy={policy}; CloudFront-Signature={signature}; CloudFront-Key-Pair-Id={kvp}; {sess} Origin: https://onlyfans.com Referer: https://onlyfans.com User-Agent: {user_agent}\" -y -i \"{url}\" -codec copy \"{tempFilename}\""; + + Log.Debug($"Calling FFMPEG with Parameters: {parameters}"); + + Engine ffmpeg = new Engine(downloadConfig.FFmpegPath); + ffmpeg.Error += OnError; + ffmpeg.Complete += async (sender, args) => + { + _completionSource.TrySetResult(true); + await OnFFMPEGDownloadComplete(tempFilename, lastModified, folder, path, customFileName, filename, media_id, api_type, task); + }; + await ffmpeg.ExecuteAsync(parameters, CancellationToken.None); + + return await _completionSource.Task; + } + catch (Exception ex) + { + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + Log.Error("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + if (ex.InnerException != null) + { + Console.WriteLine("\nInner Exception:"); + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + Log.Error("Inner Exception: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + } + } + return false; + } + #endregion + + #region normal posts + public async Task DownloadPostMedia(string url, string folder, long media_id, string api_type, ProgressTask task, string? filenameFormat, Post.List? postInfo, Post.Medium? postMedia, Post.Author? author, Dictionary users) + { + string path; + if (downloadConfig.FolderPerPost && postInfo != null && postInfo?.id is not null && postInfo?.postedAt is not null) + { + path = $"/Posts/Free/{postInfo.id} {postInfo.postedAt:yyyy-MM-dd HH-mm-ss}"; + } + else + { + path = "/Posts/Free"; + } + + Uri uri = new(url); + string filename = System.IO.Path.GetFileNameWithoutExtension(uri.LocalPath); + string resolvedFilename = await GenerateCustomFileName(filename, filenameFormat, postInfo, postMedia, author, folder.Split("/")[^1], users, _FileNameHelper, CustomFileNameOption.ReturnOriginal); + + return await CreateDirectoriesAndDownloadMedia(path, url, folder, media_id, api_type, task, filename, resolvedFilename); + } + public async Task DownloadPostMedia(string url, string folder, long media_id, string api_type, ProgressTask task, string? filenameFormat, SinglePost? postInfo, SinglePost.Medium? postMedia, SinglePost.Author? author, Dictionary users) + { + string path; + if (downloadConfig.FolderPerPost && postInfo != null && postInfo?.id is not null && postInfo?.postedAt is not null) + { + path = $"/Posts/Free/{postInfo.id} {postInfo.postedAt:yyyy-MM-dd HH-mm-ss}"; + } + else + { + path = "/Posts/Free"; + } + + Uri uri = new(url); + string filename = System.IO.Path.GetFileNameWithoutExtension(uri.LocalPath); + string resolvedFilename = await GenerateCustomFileName(filename, filenameFormat, postInfo, postMedia, author, folder.Split("/")[^1], users, _FileNameHelper, CustomFileNameOption.ReturnOriginal); + + return await CreateDirectoriesAndDownloadMedia(path, url, folder, media_id, api_type, task, filename, resolvedFilename); + } + public async Task DownloadStreamMedia(string url, string folder, long media_id, string api_type, ProgressTask task, string? filenameFormat, Streams.List? streamInfo, Streams.Medium? streamMedia, Streams.Author? author, Dictionary users) + { + string path; + if (downloadConfig.FolderPerPost && streamInfo != null && streamInfo?.id is not null && streamInfo?.postedAt is not null) + { + path = $"/Posts/Free/{streamInfo.id} {streamInfo.postedAt:yyyy-MM-dd HH-mm-ss}"; + } + else + { + path = "/Posts/Free"; + } + + Uri uri = new(url); + string filename = System.IO.Path.GetFileNameWithoutExtension(uri.LocalPath); + string resolvedFilename = await GenerateCustomFileName(filename, filenameFormat, streamInfo, streamMedia, author, folder.Split("/")[^1], users, _FileNameHelper, CustomFileNameOption.ReturnOriginal); + + return await CreateDirectoriesAndDownloadMedia(path, url, folder, media_id, api_type, task, filename, resolvedFilename); + } + + + public async Task DownloadMessageMedia(string url, string folder, long media_id, string api_type, ProgressTask task, string? filenameFormat, Messages.List? messageInfo, Messages.Medium? messageMedia, Messages.FromUser? fromUser, Dictionary users) + { + string path; + if (downloadConfig.FolderPerMessage && messageInfo != null && messageInfo?.id is not null && messageInfo?.createdAt is not null) + { + path = $"/Messages/Free/{messageInfo.id} {messageInfo.createdAt.Value:yyyy-MM-dd HH-mm-ss}"; + } + else + { + path = "/Messages/Free"; + } + Uri uri = new(url); + string filename = System.IO.Path.GetFileNameWithoutExtension(uri.LocalPath); + string resolvedFilename = await GenerateCustomFileName(filename, filenameFormat, messageInfo, messageMedia, fromUser, folder.Split("/")[^1], users, _FileNameHelper, CustomFileNameOption.ReturnOriginal); + return await CreateDirectoriesAndDownloadMedia(path, url, folder, media_id, api_type, task, filename, resolvedFilename); + } + + + public async Task DownloadArchivedMedia(string url, string folder, long media_id, string api_type, ProgressTask task, string? filenameFormat, Archived.List? messageInfo, Archived.Medium? messageMedia, Archived.Author? author, Dictionary users) + { + string path = "/Archived/Posts/Free"; + Uri uri = new(url); + string filename = System.IO.Path.GetFileNameWithoutExtension(uri.LocalPath); + string resolvedFilename = await GenerateCustomFileName(filename, filenameFormat, messageInfo, messageMedia, author, folder.Split("/")[^1], users, _FileNameHelper, CustomFileNameOption.ReturnOriginal); + return await CreateDirectoriesAndDownloadMedia(path, url, folder, media_id, api_type, task, filename, resolvedFilename); + } + + + + public async Task DownloadStoryMedia(string url, string folder, long media_id, string api_type, ProgressTask task) + { + string path = "/Stories/Free"; + Uri uri = new(url); + string filename = System.IO.Path.GetFileNameWithoutExtension(uri.LocalPath); + return await CreateDirectoriesAndDownloadMedia(path, url, folder, media_id, api_type, task, filename, filename); + } + + public async Task DownloadPurchasedMedia(string url, string folder, long media_id, string api_type, ProgressTask task, string? filenameFormat, Purchased.List? messageInfo, Medium? messageMedia, Purchased.FromUser? fromUser, Dictionary users) + { + string path; + if (downloadConfig.FolderPerPaidMessage && messageInfo != null && messageInfo?.id is not null && messageInfo?.createdAt is not null) + { + path = $"/Messages/Paid/{messageInfo.id} {messageInfo.createdAt.Value:yyyy-MM-dd HH-mm-ss}"; + } + else + { + path = "/Messages/Paid"; + } + Uri uri = new(url); + string filename = System.IO.Path.GetFileNameWithoutExtension(uri.LocalPath); + string resolvedFilename = await GenerateCustomFileName(filename, filenameFormat, messageInfo, messageMedia, fromUser, folder.Split("/")[^1], users, _FileNameHelper, CustomFileNameOption.ReturnOriginal); + return await CreateDirectoriesAndDownloadMedia(path, url, folder, media_id, api_type, task, filename, resolvedFilename); + } + + public async Task DownloadSinglePurchasedMedia(string url, string folder, long media_id, string api_type, ProgressTask task, string? filenameFormat, SingleMessage? messageInfo, Medium? messageMedia, Entities.Messages.FromUser? fromUser, Dictionary users) + { + string path; + if (downloadConfig.FolderPerPaidMessage && messageInfo != null && messageInfo?.id is not null && messageInfo?.createdAt is not null) + { + path = $"/Messages/Paid/{messageInfo.id} {messageInfo.createdAt.Value:yyyy-MM-dd HH-mm-ss}"; + } + else + { + path = "/Messages/Paid"; + } + Uri uri = new(url); + string filename = System.IO.Path.GetFileNameWithoutExtension(uri.LocalPath); + string resolvedFilename = await GenerateCustomFileName(filename, filenameFormat, messageInfo, messageMedia, fromUser, folder.Split("/")[^1], users, _FileNameHelper, CustomFileNameOption.ReturnOriginal); + return await CreateDirectoriesAndDownloadMedia(path, url, folder, media_id, api_type, task, filename, resolvedFilename); + } + + public async Task DownloadPurchasedPostMedia(string url, + string folder, + long media_id, + string api_type, + ProgressTask task, + string? filenameFormat, + Purchased.List? messageInfo, + Medium? messageMedia, + Purchased.FromUser? fromUser, + Dictionary users) + { + string path; + if (downloadConfig.FolderPerPaidPost && messageInfo != null && messageInfo?.id is not null && messageInfo?.postedAt is not null) + { + path = $"/Posts/Paid/{messageInfo.id} {messageInfo.postedAt.Value:yyyy-MM-dd HH-mm-ss}"; + } + else + { + path = "/Posts/Paid"; + } + Uri uri = new(url); + string filename = System.IO.Path.GetFileNameWithoutExtension(uri.LocalPath); + string resolvedFilename = await GenerateCustomFileName(filename, filenameFormat, messageInfo, messageMedia, fromUser, folder.Split("/")[^1], users, _FileNameHelper, CustomFileNameOption.ReturnOriginal); + return await CreateDirectoriesAndDownloadMedia(path, url, folder, media_id, api_type, task, filename, resolvedFilename); + } + + #endregion + public async Task DownloadAvatarHeader(string? avatarUrl, string? headerUrl, string folder, string username) + { + try + { + string path = $"/Profile"; + + if (!Directory.Exists(folder + path)) + { + Directory.CreateDirectory(folder + path); + } + + if (!string.IsNullOrEmpty(avatarUrl)) + { + string avatarpath = $"{path}/Avatars"; + if (!Directory.Exists(folder + avatarpath)) + { + Directory.CreateDirectory(folder + avatarpath); + } + + List avatarMD5Hashes = WidevineClient.Utils.CalculateFolderMD5(folder + avatarpath); + + Uri uri = new(avatarUrl); + string destinationPath = $"{folder}{avatarpath}/"; + + var client = new HttpClient(); + + var request = new HttpRequestMessage + { + Method = HttpMethod.Get, + RequestUri = uri + + }; + using var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead); + response.EnsureSuccessStatusCode(); + + using var memoryStream = new MemoryStream(); + await response.Content.CopyToAsync(memoryStream); + memoryStream.Seek(0, SeekOrigin.Begin); + + MD5 md5 = MD5.Create(); + byte[] hash = md5.ComputeHash(memoryStream); + memoryStream.Seek(0, SeekOrigin.Begin); + if (!avatarMD5Hashes.Contains(BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant())) + { + destinationPath = destinationPath + string.Format("{0} {1}.jpg", username, response.Content.Headers.LastModified.HasValue ? response.Content.Headers.LastModified.Value.LocalDateTime.ToString("dd-MM-yyyy") : DateTime.Now.ToString("dd-MM-yyyy")); + + using (FileStream fileStream = File.Create(destinationPath)) + { + await memoryStream.CopyToAsync(fileStream); + } + File.SetLastWriteTime(destinationPath, response.Content.Headers.LastModified?.LocalDateTime ?? DateTime.Now); + } + } + + if (!string.IsNullOrEmpty(headerUrl)) + { + string headerpath = $"{path}/Headers"; + if (!Directory.Exists(folder + headerpath)) + { + Directory.CreateDirectory(folder + headerpath); + } + + List headerMD5Hashes = WidevineClient.Utils.CalculateFolderMD5(folder + headerpath); + + Uri uri = new(headerUrl); + string destinationPath = $"{folder}{headerpath}/"; + + var client = new HttpClient(); + + var request = new HttpRequestMessage + { + Method = HttpMethod.Get, + RequestUri = uri + + }; + using var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead); + response.EnsureSuccessStatusCode(); + + using var memoryStream = new MemoryStream(); + await response.Content.CopyToAsync(memoryStream); + memoryStream.Seek(0, SeekOrigin.Begin); + + MD5 md5 = MD5.Create(); + byte[] hash = md5.ComputeHash(memoryStream); + memoryStream.Seek(0, SeekOrigin.Begin); + if (!headerMD5Hashes.Contains(BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant())) + { + destinationPath = destinationPath + string.Format("{0} {1}.jpg", username, response.Content.Headers.LastModified.HasValue ? response.Content.Headers.LastModified.Value.LocalDateTime.ToString("dd-MM-yyyy") : DateTime.Now.ToString("dd-MM-yyyy")); + + using (FileStream fileStream = File.Create(destinationPath)) + { + await memoryStream.CopyToAsync(fileStream); + } + File.SetLastWriteTime(destinationPath, response.Content.Headers.LastModified?.LocalDateTime ?? DateTime.Now); + } + } + } + catch (Exception ex) + { + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + + if (ex.InnerException != null) + { + Console.WriteLine("\nInner Exception:"); + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + } + } + } + + private async Task OnFFMPEGDownloadComplete(string tempFilename, DateTime lastModified, string folder, string path, string customFileName, string filename, long media_id, string api_type, ProgressTask task) + { + try + { + if (File.Exists(tempFilename)) + { + File.SetLastWriteTime(tempFilename, lastModified); + } + if (!string.IsNullOrEmpty(customFileName)) + { + File.Move(tempFilename, $"{folder + path + "/" + customFileName + ".mp4"}"); + } + + // Cleanup Files + long fileSizeInBytes = new FileInfo(!string.IsNullOrEmpty(customFileName) ? folder + path + "/" + customFileName + ".mp4" : tempFilename).Length; + if (downloadConfig.ShowScrapeSize) + { + task.Increment(fileSizeInBytes); + } + else + { + task.Increment(1); + } + + await m_DBHelper.UpdateMedia(folder, media_id, api_type, folder + path, !string.IsNullOrEmpty(customFileName) ? customFileName + ".mp4" : filename + "_source.mp4", fileSizeInBytes, true, lastModified); + } + catch (Exception ex) + { + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + Log.Error("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + if (ex.InnerException != null) + { + Console.WriteLine("\nInner Exception:"); + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + Log.Error("Inner Exception: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + } + } + } + + private void OnError(object sender, ConversionErrorEventArgs e) + { + Log.Debug("[{0} => {1}]: Error: {2}\n{3}", e.Input.Name, e.Output.Name, e.Exception.ExitCode, e.Exception.InnerException); + _completionSource?.TrySetResult(false); + } + + #region drm posts + public async Task DownloadMessageDRMVideo(string policy, string signature, string kvp, string url, string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, ProgressTask task, string? filenameFormat, Messages.List? messageInfo, Messages.Medium? messageMedia, Messages.FromUser? fromUser, Dictionary users) + { + try + { + string customFileName = string.Empty; + string path; + Uri uri = new(url); + string filename = System.IO.Path.GetFileName(uri.LocalPath).Split(".")[0]; + if (downloadConfig.FolderPerMessage && messageInfo != null && messageInfo?.id is not null && messageInfo?.createdAt is not null) + { + path = $"/Messages/Free/{messageInfo.id} {messageInfo.createdAt.Value:yyyy-MM-dd HH-mm-ss}/Videos"; + } + else + { + path = "/Messages/Free/Videos"; + } + if (!Directory.Exists(folder + path)) + { + Directory.CreateDirectory(folder + path); + } + + + if (!string.IsNullOrEmpty(filenameFormat) && messageInfo != null && messageMedia != null) + { + List properties = new(); + string pattern = @"\{(.*?)\}"; + MatchCollection matches = Regex.Matches(filenameFormat, pattern); + foreach (Match match in matches) + { + properties.Add(match.Groups[1].Value); + } + Dictionary values = await _FileNameHelper.GetFilename(messageInfo, messageMedia, fromUser, properties, folder.Split("/")[^1],users); + customFileName = await _FileNameHelper.BuildFilename(filenameFormat, values); + } + + if (!await m_DBHelper.CheckDownloaded(folder, media_id, api_type)) + { + if (!string.IsNullOrEmpty(customFileName) ? !File.Exists(folder + path + "/" + customFileName + ".mp4") : !File.Exists(folder + path + "/" + filename + "_source.mp4")) + { + return await DownloadDrmMedia(auth.USER_AGENT, policy, signature, kvp, auth.COOKIE, url, decryptionKey, folder, lastModified, media_id, api_type, task, customFileName, filename, path); + } + else + { + long fileSizeInBytes = new FileInfo(!string.IsNullOrEmpty(customFileName) ? folder + path + "/" + customFileName + ".mp4" : folder + path + "/" + filename + "_source.mp4").Length; + if (downloadConfig.ShowScrapeSize) + { + task.Increment(fileSizeInBytes); + } + else + { + task.Increment(1); + } + await m_DBHelper.UpdateMedia(folder, media_id, api_type, folder + path, !string.IsNullOrEmpty(customFileName) ? customFileName + "mp4" : filename + "_source.mp4", fileSizeInBytes, true, lastModified); + } + } + else + { + if (!string.IsNullOrEmpty(customFileName)) + { + if (downloadConfig.RenameExistingFilesWhenCustomFormatIsSelected && (filename + "_source" != customFileName)) + { + string fullPathWithTheServerFileName = $"{folder}{path}/{filename}_source.mp4"; + string fullPathWithTheNewFileName = $"{folder}{path}/{customFileName}.mp4"; + if (!File.Exists(fullPathWithTheServerFileName)) + { + return false; + } + try + { + File.Move(fullPathWithTheServerFileName, fullPathWithTheNewFileName); + } + catch (Exception ex) + { + Console.WriteLine($"An error occurred: {ex.Message}"); + return false; + } + long size = await m_DBHelper.GetStoredFileSize(folder, media_id, api_type); + await m_DBHelper.UpdateMedia(folder, media_id, api_type, folder + path, customFileName + ".mp4", size, true, lastModified); + } + } + + if (downloadConfig.ShowScrapeSize) + { + long size = await m_DBHelper.GetStoredFileSize(folder, media_id, api_type); + task.Increment(size); + } + else + { + task.Increment(1); + } + } + return false; + } + catch (Exception ex) + { + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + Log.Error("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + if (ex.InnerException != null) + { + Console.WriteLine("\nInner Exception:"); + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + Log.Error("Inner Exception: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + } + } + return false; + } + + + public async Task DownloadPurchasedMessageDRMVideo(string policy, string signature, string kvp, string url, string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, ProgressTask task, string? filenameFormat, Purchased.List? messageInfo, Medium? messageMedia, Purchased.FromUser? fromUser, Dictionary users) + { + try + { + string customFileName = string.Empty; + string path; + Uri uri = new(url); + string filename = System.IO.Path.GetFileName(uri.LocalPath).Split(".")[0]; + if (downloadConfig.FolderPerPaidMessage && messageInfo != null && messageInfo?.id is not null && messageInfo?.createdAt is not null) + { + path = $"/Messages/Paid/{messageInfo.id} {messageInfo.createdAt.Value:yyyy-MM-dd HH-mm-ss}/Videos"; + } + else + { + path = "/Messages/Paid/Videos"; + } + if (!Directory.Exists(folder + path)) + { + Directory.CreateDirectory(folder + path); + } + + if (!string.IsNullOrEmpty(filenameFormat) && messageInfo != null && messageMedia != null) + { + List properties = new(); + string pattern = @"\{(.*?)\}"; + MatchCollection matches = Regex.Matches(filenameFormat, pattern); + foreach (Match match in matches) + { + properties.Add(match.Groups[1].Value); + } + Dictionary values = await _FileNameHelper.GetFilename(messageInfo, messageMedia, fromUser, properties, folder.Split("/")[^1], users); + customFileName = await _FileNameHelper.BuildFilename(filenameFormat, values); + } + + if (!await m_DBHelper.CheckDownloaded(folder, media_id, api_type)) + { + if (!string.IsNullOrEmpty(customFileName) ? !File.Exists(folder + path + "/" + customFileName + ".mp4") : !File.Exists(folder + path + "/" + filename + "_source.mp4")) + { + return await DownloadDrmMedia(auth.USER_AGENT, policy, signature, kvp, auth.COOKIE, url, decryptionKey, folder, lastModified, media_id, api_type, task, customFileName, filename, path); + } + else + { + long fileSizeInBytes = new FileInfo(!string.IsNullOrEmpty(customFileName) ? folder + path + "/" + customFileName + ".mp4" : folder + path + "/" + filename + "_source.mp4").Length; + if (downloadConfig.ShowScrapeSize) + { + task.Increment(fileSizeInBytes); + } + else + { + task.Increment(1); + } + await m_DBHelper.UpdateMedia(folder, media_id, api_type, folder + path, !string.IsNullOrEmpty(customFileName) ? customFileName + "mp4" : filename + "_source.mp4", fileSizeInBytes, true, lastModified); + } + } + else + { + if (!string.IsNullOrEmpty(customFileName)) + { + if (downloadConfig.RenameExistingFilesWhenCustomFormatIsSelected && (filename + "_source" != customFileName)) + { + string fullPathWithTheServerFileName = $"{folder}{path}/{filename}_source.mp4"; + string fullPathWithTheNewFileName = $"{folder}{path}/{customFileName}.mp4"; + if (!File.Exists(fullPathWithTheServerFileName)) + { + return false; + } + try + { + File.Move(fullPathWithTheServerFileName, fullPathWithTheNewFileName); + } + catch (Exception ex) + { + Console.WriteLine($"An error occurred: {ex.Message}"); + return false; + } + long size = await m_DBHelper.GetStoredFileSize(folder, media_id, api_type); + await m_DBHelper.UpdateMedia(folder, media_id, api_type, folder + path, customFileName + ".mp4", size, true, lastModified); + } + } + + if (downloadConfig.ShowScrapeSize) + { + long size = await m_DBHelper.GetStoredFileSize(folder, media_id, api_type); + task.Increment(size); + } + else + { + task.Increment(1); + } + } + return false; + } + catch (Exception ex) + { + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + Log.Error("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + if (ex.InnerException != null) + { + Console.WriteLine("\nInner Exception:"); + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + Log.Error("Inner Exception: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + } + } + return false; + } + + public async Task DownloadSinglePurchasedMessageDRMVideo(string policy, string signature, string kvp, string url, string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, ProgressTask task, string? filenameFormat, SingleMessage? messageInfo, Medium? messageMedia, Entities.Messages.FromUser? fromUser, Dictionary users) + { + try + { + string customFileName = string.Empty; + string path; + Uri uri = new(url); + string filename = System.IO.Path.GetFileName(uri.LocalPath).Split(".")[0]; + if (downloadConfig.FolderPerPaidMessage && messageInfo != null && messageInfo?.id is not null && messageInfo?.createdAt is not null) + { + path = $"/Messages/Paid/{messageInfo.id} {messageInfo.createdAt.Value:yyyy-MM-dd HH-mm-ss}/Videos"; + } + else + { + path = "/Messages/Paid/Videos"; + } + if (!Directory.Exists(folder + path)) + { + Directory.CreateDirectory(folder + path); + } + + if (!string.IsNullOrEmpty(filenameFormat) && messageInfo != null && messageMedia != null) + { + List properties = new(); + string pattern = @"\{(.*?)\}"; + MatchCollection matches = Regex.Matches(filenameFormat, pattern); + foreach (Match match in matches) + { + properties.Add(match.Groups[1].Value); + } + Dictionary values = await _FileNameHelper.GetFilename(messageInfo, messageMedia, fromUser, properties, folder.Split("/")[^1], users); + customFileName = await _FileNameHelper.BuildFilename(filenameFormat, values); + } + + if (!await m_DBHelper.CheckDownloaded(folder, media_id, api_type)) + { + if (!string.IsNullOrEmpty(customFileName) ? !File.Exists(folder + path + "/" + customFileName + ".mp4") : !File.Exists(folder + path + "/" + filename + "_source.mp4")) + { + return await DownloadDrmMedia(auth.USER_AGENT, policy, signature, kvp, auth.COOKIE, url, decryptionKey, folder, lastModified, media_id, api_type, task, customFileName, filename, path); + } + else + { + long fileSizeInBytes = new FileInfo(!string.IsNullOrEmpty(customFileName) ? folder + path + "/" + customFileName + ".mp4" : folder + path + "/" + filename + "_source.mp4").Length; + if (downloadConfig.ShowScrapeSize) + { + task.Increment(fileSizeInBytes); + } + else + { + task.Increment(1); + } + await m_DBHelper.UpdateMedia(folder, media_id, api_type, folder + path, !string.IsNullOrEmpty(customFileName) ? customFileName + "mp4" : filename + "_source.mp4", fileSizeInBytes, true, lastModified); + } + } + else + { + if (!string.IsNullOrEmpty(customFileName)) + { + if (downloadConfig.RenameExistingFilesWhenCustomFormatIsSelected && (filename + "_source" != customFileName)) + { + string fullPathWithTheServerFileName = $"{folder}{path}/{filename}_source.mp4"; + string fullPathWithTheNewFileName = $"{folder}{path}/{customFileName}.mp4"; + if (!File.Exists(fullPathWithTheServerFileName)) + { + return false; + } + try + { + File.Move(fullPathWithTheServerFileName, fullPathWithTheNewFileName); + } + catch (Exception ex) + { + Console.WriteLine($"An error occurred: {ex.Message}"); + return false; + } + long size = await m_DBHelper.GetStoredFileSize(folder, media_id, api_type); + await m_DBHelper.UpdateMedia(folder, media_id, api_type, folder + path, customFileName + ".mp4", size, true, lastModified); + } + } + + if (downloadConfig.ShowScrapeSize) + { + long size = await m_DBHelper.GetStoredFileSize(folder, media_id, api_type); + task.Increment(size); + } + else + { + task.Increment(1); + } + } + return false; + } + catch (Exception ex) + { + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + Log.Error("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + if (ex.InnerException != null) + { + Console.WriteLine("\nInner Exception:"); + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + Log.Error("Inner Exception: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + } + } + return false; + } + + + public async Task DownloadPostDRMVideo(string policy, string signature, string kvp, string url, string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, ProgressTask task, string? filenameFormat, Post.List? postInfo, Post.Medium? postMedia, Post.Author? author, Dictionary users) + { + try + { + string customFileName = string.Empty; + string path; + Uri uri = new(url); + string filename = System.IO.Path.GetFileName(uri.LocalPath).Split(".")[0]; + if (downloadConfig.FolderPerPost && postInfo != null && postInfo?.id is not null && postInfo?.postedAt is not null) + { + path = $"/Posts/Free/{postInfo.id} {postInfo.postedAt:yyyy-MM-dd HH-mm-ss}/Videos"; + } + else + { + path = "/Posts/Free/Videos"; + } + if (!Directory.Exists(folder + path)) + { + Directory.CreateDirectory(folder + path); + } + + if (!string.IsNullOrEmpty(filenameFormat) && postInfo != null && postMedia != null) + { + List properties = new(); + string pattern = @"\{(.*?)\}"; + MatchCollection matches = Regex.Matches(filenameFormat, pattern); + foreach (Match match in matches) + { + properties.Add(match.Groups[1].Value); + } + Dictionary values = await _FileNameHelper.GetFilename(postInfo, postMedia, author, properties, folder.Split("/")[^1], users); + customFileName = await _FileNameHelper.BuildFilename(filenameFormat, values); + } + + if (!await m_DBHelper.CheckDownloaded(folder, media_id, api_type)) + { + if (!string.IsNullOrEmpty(customFileName) ? !File.Exists(folder + path + "/" + customFileName + ".mp4") : !File.Exists(folder + path + "/" + filename + "_source.mp4")) + { + return await DownloadDrmMedia(auth.USER_AGENT, policy, signature, kvp, auth.COOKIE, url, decryptionKey, folder, lastModified, media_id, api_type, task, customFileName, filename, path); + } + else + { + long fileSizeInBytes = new FileInfo(!string.IsNullOrEmpty(customFileName) ? folder + path + "/" + customFileName + ".mp4" : folder + path + "/" + filename + "_source.mp4").Length; + if (downloadConfig.ShowScrapeSize) + { + task.Increment(fileSizeInBytes); + } + else + { + task.Increment(1); + } + await m_DBHelper.UpdateMedia(folder, media_id, api_type, folder + path, !string.IsNullOrEmpty(customFileName) ? customFileName + "mp4" : filename + "_source.mp4", fileSizeInBytes, true, lastModified); + } + } + else + { + if (!string.IsNullOrEmpty(customFileName)) + { + if (downloadConfig.RenameExistingFilesWhenCustomFormatIsSelected && (filename + "_source" != customFileName)) + { + string fullPathWithTheServerFileName = $"{folder}{path}/{filename}_source.mp4"; + string fullPathWithTheNewFileName = $"{folder}{path}/{customFileName}.mp4"; + if (!File.Exists(fullPathWithTheServerFileName)) + { + return false; + } + try + { + File.Move(fullPathWithTheServerFileName, fullPathWithTheNewFileName); + } + catch (Exception ex) + { + Console.WriteLine($"An error occurred: {ex.Message}"); + return false; + } + long size = await m_DBHelper.GetStoredFileSize(folder, media_id, api_type); + await m_DBHelper.UpdateMedia(folder, media_id, api_type, folder + path, customFileName + ".mp4", size, true, lastModified); + } + } + + if (downloadConfig.ShowScrapeSize) + { + long size = await m_DBHelper.GetStoredFileSize(folder, media_id, api_type); + task.Increment(size); + } + else + { + task.Increment(1); + } + } + return false; + } + catch (Exception ex) + { + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + Log.Error("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + if (ex.InnerException != null) + { + Console.WriteLine("\nInner Exception:"); + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + Log.Error("Inner Exception: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + } + } + return false; + } + public async Task DownloadPostDRMVideo(string policy, string signature, string kvp, string url, string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, ProgressTask task, string filenameFormat, SinglePost postInfo, SinglePost.Medium postMedia, SinglePost.Author author, Dictionary users) + { + try + { + string customFileName = string.Empty; + string path; + Uri uri = new(url); + string filename = System.IO.Path.GetFileName(uri.LocalPath).Split(".")[0]; + if (downloadConfig.FolderPerPost && postInfo != null && postInfo?.id is not null && postInfo?.postedAt is not null) + { + path = $"/Posts/Free/{postInfo.id} {postInfo.postedAt:yyyy-MM-dd HH-mm-ss}/Videos"; + } + else + { + path = "/Posts/Free/Videos"; + } + if (!Directory.Exists(folder + path)) + { + Directory.CreateDirectory(folder + path); + } + + if (!string.IsNullOrEmpty(filenameFormat) && postInfo != null && postMedia != null) + { + List properties = new(); + string pattern = @"\{(.*?)\}"; + MatchCollection matches = Regex.Matches(filenameFormat, pattern); + foreach (Match match in matches) + { + properties.Add(match.Groups[1].Value); + } + Dictionary values = await _FileNameHelper.GetFilename(postInfo, postMedia, author, properties, folder.Split("/")[^1], users); + customFileName = await _FileNameHelper.BuildFilename(filenameFormat, values); + } + + if (!await m_DBHelper.CheckDownloaded(folder, media_id, api_type)) + { + if (!string.IsNullOrEmpty(customFileName) ? !File.Exists(folder + path + "/" + customFileName + ".mp4") : !File.Exists(folder + path + "/" + filename + "_source.mp4")) + { + return await DownloadDrmMedia(auth.USER_AGENT, policy, signature, kvp, auth.COOKIE, url, decryptionKey, folder, lastModified, media_id, api_type, task, customFileName, filename, path); + } + else + { + long fileSizeInBytes = new FileInfo(!string.IsNullOrEmpty(customFileName) ? folder + path + "/" + customFileName + ".mp4" : folder + path + "/" + filename + "_source.mp4").Length; + if (downloadConfig.ShowScrapeSize) + { + task.Increment(fileSizeInBytes); + } + else + { + task.Increment(1); + } + await m_DBHelper.UpdateMedia(folder, media_id, api_type, folder + path, !string.IsNullOrEmpty(customFileName) ? customFileName + "mp4" : filename + "_source.mp4", fileSizeInBytes, true, lastModified); + } + } + else + { + if (!string.IsNullOrEmpty(customFileName)) + { + if (downloadConfig.RenameExistingFilesWhenCustomFormatIsSelected && (filename + "_source" != customFileName)) + { + string fullPathWithTheServerFileName = $"{folder}{path}/{filename}_source.mp4"; + string fullPathWithTheNewFileName = $"{folder}{path}/{customFileName}.mp4"; + if (!File.Exists(fullPathWithTheServerFileName)) + { + return false; + } + try + { + File.Move(fullPathWithTheServerFileName, fullPathWithTheNewFileName); + } + catch (Exception ex) + { + Console.WriteLine($"An error occurred: {ex.Message}"); + return false; + } + long size = await m_DBHelper.GetStoredFileSize(folder, media_id, api_type); + await m_DBHelper.UpdateMedia(folder, media_id, api_type, folder + path, customFileName + ".mp4", size, true, lastModified); + } + } + + if (downloadConfig.ShowScrapeSize) + { + long size = await m_DBHelper.GetStoredFileSize(folder, media_id, api_type); + task.Increment(size); + } + else + { + task.Increment(1); + } + } + return false; + } + catch (Exception ex) + { + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + Log.Error("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + if (ex.InnerException != null) + { + Console.WriteLine("\nInner Exception:"); + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + Log.Error("Inner Exception: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + } + } + return false; + } + public async Task DownloadStreamsDRMVideo(string policy, string signature, string kvp, string url, string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, ProgressTask task, string? filenameFormat, Streams.List? streamInfo, Streams.Medium? streamMedia, Streams.Author? author, Dictionary users) + { + try + { + string customFileName = string.Empty; + string path; + Uri uri = new(url); + string filename = System.IO.Path.GetFileName(uri.LocalPath).Split(".")[0]; + if (downloadConfig.FolderPerPost && streamInfo != null && streamInfo?.id is not null && streamInfo?.postedAt is not null) + { + path = $"/Posts/Free/{streamInfo.id} {streamInfo.postedAt:yyyy-MM-dd HH-mm-ss}/Videos"; + } + else + { + path = "/Posts/Free/Videos"; + } + if (!Directory.Exists(folder + path)) + { + Directory.CreateDirectory(folder + path); + } + + if (!string.IsNullOrEmpty(filenameFormat) && streamInfo != null && streamMedia != null) + { + List properties = new(); + string pattern = @"\{(.*?)\}"; + MatchCollection matches = Regex.Matches(filenameFormat, pattern); + foreach (Match match in matches) + { + properties.Add(match.Groups[1].Value); + } + Dictionary values = await _FileNameHelper.GetFilename(streamInfo, streamMedia, author, properties, folder.Split("/")[^1], users); + customFileName = await _FileNameHelper.BuildFilename(filenameFormat, values); + } + + if (!await m_DBHelper.CheckDownloaded(folder, media_id, api_type)) + { + if (!string.IsNullOrEmpty(customFileName) ? !File.Exists(folder + path + "/" + customFileName + ".mp4") : !File.Exists(folder + path + "/" + filename + "_source.mp4")) + { + return await DownloadDrmMedia(auth.USER_AGENT, policy, signature, kvp, auth.COOKIE, url, decryptionKey, folder, lastModified, media_id, api_type, task, customFileName, filename, path); + } + else + { + long fileSizeInBytes = new FileInfo(!string.IsNullOrEmpty(customFileName) ? folder + path + "/" + customFileName + ".mp4" : folder + path + "/" + filename + "_source.mp4").Length; + if (downloadConfig.ShowScrapeSize) + { + task.Increment(fileSizeInBytes); + } + else + { + task.Increment(1); + } + await m_DBHelper.UpdateMedia(folder, media_id, api_type, folder + path, !string.IsNullOrEmpty(customFileName) ? customFileName + "mp4" : filename + "_source.mp4", fileSizeInBytes, true, lastModified); + } + } + else + { + if (!string.IsNullOrEmpty(customFileName)) + { + if (downloadConfig.RenameExistingFilesWhenCustomFormatIsSelected && (filename + "_source" != customFileName)) + { + string fullPathWithTheServerFileName = $"{folder}{path}/{filename}_source.mp4"; + string fullPathWithTheNewFileName = $"{folder}{path}/{customFileName}.mp4"; + if (!File.Exists(fullPathWithTheServerFileName)) + { + return false; + } + try + { + File.Move(fullPathWithTheServerFileName, fullPathWithTheNewFileName); + } + catch (Exception ex) + { + Console.WriteLine($"An error occurred: {ex.Message}"); + return false; + } + long size = await m_DBHelper.GetStoredFileSize(folder, media_id, api_type); + await m_DBHelper.UpdateMedia(folder, media_id, api_type, folder + path, customFileName + ".mp4", size, true, lastModified); + } + } + + if (downloadConfig.ShowScrapeSize) + { + long size = await m_DBHelper.GetStoredFileSize(folder, media_id, api_type); + task.Increment(size); + } + else + { + task.Increment(1); + } + } + return false; + } + catch (Exception ex) + { + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + Log.Error("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + if (ex.InnerException != null) + { + Console.WriteLine("\nInner Exception:"); + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + Log.Error("Inner Exception: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + } + } + return false; + } + + public async Task DownloadPurchasedPostDRMVideo(string policy, string signature, string kvp, string url, string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, ProgressTask task, string? filenameFormat, Purchased.List? postInfo, Medium? postMedia, Purchased.FromUser? fromUser, Dictionary users) + { + try + { + string customFileName = string.Empty; + string path; + Uri uri = new(url); + string filename = System.IO.Path.GetFileName(uri.LocalPath).Split(".")[0]; + if (downloadConfig.FolderPerPaidPost && postInfo != null && postInfo?.id is not null && postInfo?.postedAt is not null) + { + path = $"/Posts/Paid/{postInfo.id} {postInfo.postedAt.Value:yyyy-MM-dd HH-mm-ss}/Videos"; + } + else + { + path = "/Posts/Paid/Videos"; + } + if (!Directory.Exists(folder + path)) + { + Directory.CreateDirectory(folder + path); + } + + + if (!string.IsNullOrEmpty(filenameFormat) && postInfo != null && postMedia != null) + { + List properties = new(); + string pattern = @"\{(.*?)\}"; + MatchCollection matches = Regex.Matches(filenameFormat, pattern); + foreach (Match match in matches) + { + properties.Add(match.Groups[1].Value); + } + Dictionary values = await _FileNameHelper.GetFilename(postInfo, postMedia, fromUser, properties, folder.Split("/")[^1], users); + customFileName = await _FileNameHelper.BuildFilename(filenameFormat, values); + } + + if (!await m_DBHelper.CheckDownloaded(folder, media_id, api_type)) + { + if (!string.IsNullOrEmpty(customFileName) ? !File.Exists(folder + path + "/" + customFileName + ".mp4") : !File.Exists(folder + path + "/" + filename + "_source.mp4")) + { + return await DownloadDrmMedia(auth.USER_AGENT, policy, signature, kvp, auth.COOKIE, url, decryptionKey, folder, lastModified, media_id, api_type, task, customFileName, filename, path); + } + else + { + long fileSizeInBytes = new FileInfo(!string.IsNullOrEmpty(customFileName) ? folder + path + "/" + customFileName + ".mp4" : folder + path + "/" + filename + "_source.mp4").Length; + if (downloadConfig.ShowScrapeSize) + { + task.Increment(fileSizeInBytes); + } + else + { + task.Increment(1); + } + await m_DBHelper.UpdateMedia(folder, media_id, api_type, folder + path, !string.IsNullOrEmpty(customFileName) ? customFileName + "mp4" : filename + "_source.mp4", fileSizeInBytes, true, lastModified); + } + } + else + { + if (!string.IsNullOrEmpty(customFileName)) + { + if (downloadConfig.RenameExistingFilesWhenCustomFormatIsSelected && (filename + "_source" != customFileName)) + { + string fullPathWithTheServerFileName = $"{folder}{path}/{filename}_source.mp4"; + string fullPathWithTheNewFileName = $"{folder}{path}/{customFileName}.mp4"; + if (!File.Exists(fullPathWithTheServerFileName)) + { + return false; + } + try + { + File.Move(fullPathWithTheServerFileName, fullPathWithTheNewFileName); + } + catch (Exception ex) + { + Console.WriteLine($"An error occurred: {ex.Message}"); + return false; + } + long size = await m_DBHelper.GetStoredFileSize(folder, media_id, api_type); + await m_DBHelper.UpdateMedia(folder, media_id, api_type, folder + path, customFileName + ".mp4", size, true, lastModified); + } + } + + if (downloadConfig.ShowScrapeSize) + { + long size = await m_DBHelper.GetStoredFileSize(folder, media_id, api_type); + task.Increment(size); + } + else + { + task.Increment(1); + } + } + return false; + } + catch (Exception ex) + { + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + Log.Error("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + if (ex.InnerException != null) + { + Console.WriteLine("\nInner Exception:"); + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + Log.Error("Inner Exception: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + } + } + return false; + } + + + public async Task DownloadArchivedPostDRMVideo(string policy, string signature, string kvp, string url, string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, ProgressTask task, string? filenameFormat, Archived.List? postInfo, Archived.Medium? postMedia, Archived.Author? author, Dictionary users) + { + try + { + string customFileName = string.Empty; + Uri uri = new(url); + string filename = System.IO.Path.GetFileName(uri.LocalPath).Split(".")[0]; + string path = "/Archived/Posts/Free/Videos"; + if (!Directory.Exists(folder + path)) + { + Directory.CreateDirectory(folder + path); + } + + if (!string.IsNullOrEmpty(filenameFormat) && postInfo != null && postMedia != null) + { + List properties = new(); + string pattern = @"\{(.*?)\}"; + MatchCollection matches = Regex.Matches(filenameFormat, pattern); + foreach (Match match in matches) + { + properties.Add(match.Groups[1].Value); + } + Dictionary values = await _FileNameHelper.GetFilename(postInfo, postMedia, author, properties, folder.Split("/")[^1], users); + customFileName = await _FileNameHelper.BuildFilename(filenameFormat, values); + } + + if (!await m_DBHelper.CheckDownloaded(folder, media_id, api_type)) + { + if (!string.IsNullOrEmpty(customFileName) ? !File.Exists(folder + path + "/" + customFileName + ".mp4") : !File.Exists(folder + path + "/" + filename + "_source.mp4")) + { + return await DownloadDrmMedia(auth.USER_AGENT, policy, signature, kvp, auth.COOKIE, url, decryptionKey, folder, lastModified, media_id, api_type, task, customFileName, filename, path); + } + else + { + long fileSizeInBytes = new FileInfo(!string.IsNullOrEmpty(customFileName) ? folder + path + "/" + customFileName + ".mp4" : folder + path + "/" + filename + "_source.mp4").Length; + if (downloadConfig.ShowScrapeSize) + { + task.Increment(fileSizeInBytes); + } + else + { + task.Increment(1); + } + await m_DBHelper.UpdateMedia(folder, media_id, api_type, folder + path, !string.IsNullOrEmpty(customFileName) ? customFileName + "mp4" : filename + "_source.mp4", fileSizeInBytes, true, lastModified); + } + } + else + { + if (!string.IsNullOrEmpty(customFileName)) + { + if (downloadConfig.RenameExistingFilesWhenCustomFormatIsSelected && (filename + "_source" != customFileName)) + { + string fullPathWithTheServerFileName = $"{folder}{path}/{filename}_source.mp4"; + string fullPathWithTheNewFileName = $"{folder}{path}/{customFileName}.mp4"; + if (!File.Exists(fullPathWithTheServerFileName)) + { + return false; + } + try + { + File.Move(fullPathWithTheServerFileName, fullPathWithTheNewFileName); + } + catch (Exception ex) + { + Console.WriteLine($"An error occurred: {ex.Message}"); + return false; + } + long size = await m_DBHelper.GetStoredFileSize(folder, media_id, api_type); + await m_DBHelper.UpdateMedia(folder, media_id, api_type, folder + path, customFileName + ".mp4", size, true, lastModified); + } + } + + if (downloadConfig.ShowScrapeSize) + { + long size = await m_DBHelper.GetStoredFileSize(folder, media_id, api_type); + task.Increment(size); + } + else + { + task.Increment(1); + } + } + return false; + } + catch (Exception ex) + { + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + Log.Error("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + if (ex.InnerException != null) + { + Console.WriteLine("\nInner Exception:"); + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + Log.Error("Inner Exception: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + } + } + return false; + } + #endregion +} diff --git a/OF DL/Helpers/FileNameHelper.cs b/OF DL/Helpers/FileNameHelper.cs new file mode 100644 index 0000000..2d5a3a9 --- /dev/null +++ b/OF DL/Helpers/FileNameHelper.cs @@ -0,0 +1,188 @@ +using HtmlAgilityPack; +using OF_DL.Entities; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace OF_DL.Helpers +{ + public class FileNameHelper : IFileNameHelper + { + private readonly Auth auth; + + public FileNameHelper(Auth auth) + { + this.auth = auth; + } + + public async Task> GetFilename(object obj1, object obj2, object obj3, List selectedProperties, string username, Dictionary users = null) + { + Dictionary values = new(); + Type type1 = obj1.GetType(); + Type type2 = obj2.GetType(); + PropertyInfo[] properties1 = type1.GetProperties(); + PropertyInfo[] properties2 = type2.GetProperties(); + + foreach (string propertyName in selectedProperties) + { + if (propertyName.Contains("media")) + { + object drmProperty = null; + object fileProperty = GetNestedPropertyValue(obj2, "files"); + if(fileProperty != null) + { + drmProperty = GetNestedPropertyValue(obj2, "files.drm"); + } + + if(fileProperty != null && drmProperty != null && propertyName == "mediaCreatedAt") + { + object mpdurl = GetNestedPropertyValue(obj2, "files.drm.manifest.dash"); + object policy = GetNestedPropertyValue(obj2, "files.drm.signature.dash.CloudFrontPolicy"); + object signature = GetNestedPropertyValue(obj2, "files.drm.signature.dash.CloudFrontSignature"); + object kvp = GetNestedPropertyValue(obj2, "files.drm.signature.dash.CloudFrontKeyPairId"); + DateTime lastModified = await DownloadHelper.GetDRMVideoLastModified(string.Join(",", mpdurl, policy, signature, kvp), auth); + values.Add(propertyName, lastModified.ToString("yyyy-MM-dd")); + continue; + } + else if((fileProperty == null || drmProperty == null) && propertyName == "mediaCreatedAt") + { + object source = GetNestedPropertyValue(obj2, "files.full.url"); + if(source != null) + { + DateTime lastModified = await DownloadHelper.GetMediaLastModified(source.ToString()); + values.Add(propertyName, lastModified.ToString("yyyy-MM-dd")); + continue; + } + else + { + object preview = GetNestedPropertyValue(obj2, "preview"); + if(preview != null) + { + DateTime lastModified = await DownloadHelper.GetMediaLastModified(preview.ToString()); + values.Add(propertyName, lastModified.ToString("yyyy-MM-dd")); + continue; + } + } + + } + PropertyInfo? property = Array.Find(properties2, p => p.Name.Equals(propertyName.Replace("media", ""), StringComparison.OrdinalIgnoreCase)); + if (property != null) + { + object? propertyValue = property.GetValue(obj2); + if (propertyValue != null) + { + if (propertyValue is DateTime dateTimeValue) + { + values.Add(propertyName, dateTimeValue.ToString("yyyy-MM-dd")); + } + else + { + values.Add(propertyName, propertyValue.ToString()); + } + } + } + } + else if (propertyName.Contains("filename")) + { + string sourcePropertyPath = "files.full.url"; + object sourcePropertyValue = GetNestedPropertyValue(obj2, sourcePropertyPath); + if (sourcePropertyValue != null) + { + Uri uri = new(sourcePropertyValue.ToString()); + string filename = System.IO.Path.GetFileName(uri.LocalPath); + values.Add(propertyName, filename.Split(".")[0]); + } + else + { + string propertyPath = "files.drm.manifest.dash"; + object nestedPropertyValue = GetNestedPropertyValue(obj2, propertyPath); + if (nestedPropertyValue != null) + { + Uri uri = new(nestedPropertyValue.ToString()); + string filename = System.IO.Path.GetFileName(uri.LocalPath); + values.Add(propertyName, filename.Split(".")[0] + "_source"); + } + } + } + else if (propertyName.Contains("username")) + { + if(!string.IsNullOrEmpty(username)) + { + values.Add(propertyName, username); + } + else + { + string propertyPath = "id"; + object nestedPropertyValue = GetNestedPropertyValue(obj3, propertyPath); + if (nestedPropertyValue != null) + { + values.Add(propertyName, users.FirstOrDefault(u => u.Value == Convert.ToInt32(nestedPropertyValue.ToString())).Key); + } + } + } + else if (propertyName.Contains("text", StringComparison.OrdinalIgnoreCase)) + { + PropertyInfo property = Array.Find(properties1, p => p.Name.Equals(propertyName, StringComparison.OrdinalIgnoreCase)); + if (property != null) + { + object propertyValue = property.GetValue(obj1); + if (propertyValue != null) + { + var pageDoc = new HtmlDocument(); + pageDoc.LoadHtml(propertyValue.ToString()); + var str = pageDoc.DocumentNode.InnerText; + if (str.Length > 100) // todo: add length limit to config + str = str.Substring(0, 100); + values.Add(propertyName, str); + } + } + } + else + { + PropertyInfo property = Array.Find(properties1, p => p.Name.Equals(propertyName, StringComparison.OrdinalIgnoreCase)); + if (property != null) + { + object propertyValue = property.GetValue(obj1); + if (propertyValue != null) + { + if (propertyValue is DateTime dateTimeValue) + { + values.Add(propertyName, dateTimeValue.ToString("yyyy-MM-dd")); + } + else + { + values.Add(propertyName, propertyValue.ToString()); + } + } + } + } + } + return values; + } + + static object GetNestedPropertyValue(object source, string propertyPath) + { + object value = source; + foreach (var propertyName in propertyPath.Split('.')) + { + PropertyInfo property = value.GetType().GetProperty(propertyName) ?? throw new ArgumentException($"Property '{propertyName}' not found."); + value = property.GetValue(value); + } + return value; + } + + public async Task BuildFilename(string fileFormat, Dictionary values) + { + foreach (var kvp in values) + { + string placeholder = "{" + kvp.Key + "}"; + fileFormat = fileFormat.Replace(placeholder, kvp.Value); + } + + return WidevineClient.Utils.RemoveInvalidFileNameChars($"{fileFormat}"); + } + } +} diff --git a/OF DL/Helpers/Interfaces/IAPIHelper.cs b/OF DL/Helpers/Interfaces/IAPIHelper.cs new file mode 100644 index 0000000..02c32a8 --- /dev/null +++ b/OF DL/Helpers/Interfaces/IAPIHelper.cs @@ -0,0 +1,38 @@ +using Newtonsoft.Json.Linq; +using OF_DL.Entities; +using OF_DL.Entities.Archived; +using OF_DL.Entities.Messages; +using OF_DL.Entities.Post; +using OF_DL.Entities.Purchased; +using OF_DL.Entities.Streams; +using OF_DL.Enumurations; +using Spectre.Console; + +namespace OF_DL.Helpers +{ + public interface IAPIHelper + { + Task GetDecryptionKeyCDRMProject(Dictionary drmHeaders, string licenceURL, string pssh); + Task GetDecryptionKeyCDM(Dictionary drmHeaders, string licenceURL, string pssh); + Task GetDRMMPDLastModified(string mpdUrl, string policy, string signature, string kvp); + Task GetDRMMPDPSSH(string mpdUrl, string policy, string signature, string kvp); + Task> GetLists(string endpoint, IDownloadConfig config); + Task> GetListUsers(string endpoint, IDownloadConfig config); + Task> GetMedia(MediaType mediatype, string endpoint, string? username, string folder, IDownloadConfig config, List paid_post_ids); + Task GetPaidPosts(string endpoint, string folder, string username, IDownloadConfig config, List paid_post_ids, StatusContext ctx); + Task GetPosts(string endpoint, string folder, IDownloadConfig config, List paid_post_ids, StatusContext ctx); + Task GetPost(string endpoint, string folder, IDownloadConfig config); + Task GetStreams(string endpoint, string folder, IDownloadConfig config, List paid_post_ids, StatusContext ctx); + Task GetArchived(string endpoint, string folder, IDownloadConfig config, StatusContext ctx); + Task GetMessages(string endpoint, string folder, IDownloadConfig config, StatusContext ctx); + Task GetPaidMessages(string endpoint, string folder, string username, IDownloadConfig config, StatusContext ctx); + Task> GetPurchasedTabUsers(string endpoint, IDownloadConfig config, Dictionary users); + Task> GetPurchasedTab(string endpoint, string folder, IDownloadConfig config, Dictionary users); + Task GetUserInfo(string endpoint); + Task GetUserInfoById(string endpoint); + Dictionary GetDynamicHeaders(string path, string queryParam); + Task> GetActiveSubscriptions(string endpoint, bool includeRestrictedSubscriptions, IDownloadConfig config); + Task> GetExpiredSubscriptions(string endpoint, bool includeRestrictedSubscriptions, IDownloadConfig config); + Task GetDecryptionKeyOFDL(Dictionary drmHeaders, string licenceURL, string pssh); + } +} diff --git a/OF DL/Helpers/Interfaces/IDBHelper.cs b/OF DL/Helpers/Interfaces/IDBHelper.cs new file mode 100644 index 0000000..770b91d --- /dev/null +++ b/OF DL/Helpers/Interfaces/IDBHelper.cs @@ -0,0 +1,17 @@ +namespace OF_DL.Helpers +{ + public interface IDBHelper + { + Task AddMessage(string folder, long post_id, string message_text, string price, bool is_paid, bool is_archived, DateTime created_at, int user_id); + Task AddPost(string folder, long post_id, string message_text, string price, bool is_paid, bool is_archived, DateTime created_at); + Task AddStory(string folder, long post_id, string message_text, string price, bool is_paid, bool is_archived, DateTime created_at); + Task CreateDB(string folder); + Task CreateUsersDB(Dictionary users); + Task CheckUsername(KeyValuePair user, string path); + Task AddMedia(string folder, long media_id, long post_id, string link, string? directory, string? filename, long? size, string api_type, string media_type, bool preview, bool downloaded, DateTime? created_at); + Task UpdateMedia(string folder, long media_id, string api_type, string directory, string filename, long size, bool downloaded, DateTime created_at); + Task GetStoredFileSize(string folder, long media_id, string api_type); + Task CheckDownloaded(string folder, long media_id, string api_type); + Task GetMostRecentPostDate(string folder); + } +} diff --git a/OF DL/Helpers/Interfaces/IDownloadHelper.cs b/OF DL/Helpers/Interfaces/IDownloadHelper.cs new file mode 100644 index 0000000..cdc8147 --- /dev/null +++ b/OF DL/Helpers/Interfaces/IDownloadHelper.cs @@ -0,0 +1,36 @@ +using OF_DL.Entities; +using OF_DL.Entities.Archived; +using OF_DL.Entities.Messages; +using OF_DL.Entities.Post; +using OF_DL.Entities.Purchased; +using OF_DL.Entities.Streams; +using Spectre.Console; +using static OF_DL.Entities.Messages.Messages; + +namespace OF_DL.Helpers +{ + public interface IDownloadHelper + { + Task CalculateTotalFileSize(List urls); + Task DownloadArchivedMedia(string url, string folder, long media_id, string api_type, ProgressTask task, string filenameFormat, Archived.List messageInfo, Archived.Medium messageMedia, Archived.Author author, Dictionary users); + Task DownloadArchivedPostDRMVideo(string policy, string signature, string kvp, string url, string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, ProgressTask task, string filenameFormat, Archived.List postInfo, Archived.Medium postMedia, Archived.Author author, Dictionary users); + Task DownloadPostDRMVideo(string policy, string signature, string kvp, string url, string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, ProgressTask task, string filenameFormat, SinglePost postInfo, SinglePost.Medium postMedia, SinglePost.Author author, Dictionary users); + Task DownloadAvatarHeader(string? avatarUrl, string? headerUrl, string folder, string username); + Task DownloadMessageDRMVideo(string policy, string signature, string kvp, string url, string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, ProgressTask task, string filenameFormat, Messages.List messageInfo, Messages.Medium messageMedia, Messages.FromUser fromUser, Dictionary users); + Task DownloadMessageMedia(string url, string folder, long media_id, string api_type, ProgressTask task, string filenameFormat, Messages.List messageInfo, Messages.Medium messageMedia, Messages.FromUser fromUser, Dictionary users); + Task DownloadPostDRMVideo(string policy, string signature, string kvp, string url, string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, ProgressTask task, string filenameFormat, Post.List postInfo, Post.Medium postMedia, Post.Author author, Dictionary users); + Task DownloadPostMedia(string url, string folder, long media_id, string api_type, ProgressTask task, string? filenameFormat, Post.List? postInfo, Post.Medium? postMedia, Post.Author? author, Dictionary users); + Task DownloadPostMedia(string url, string folder, long media_id, string api_type, ProgressTask task, string? filenameFormat, SinglePost? postInfo, SinglePost.Medium? postMedia, SinglePost.Author? author, Dictionary users); + Task DownloadPurchasedMedia(string url, string folder, long media_id, string api_type, ProgressTask task, string filenameFormat, Purchased.List messageInfo, Medium messageMedia, Purchased.FromUser fromUser, Dictionary users); + + Task DownloadSinglePurchasedMedia(string url, string folder, long media_id, string api_type, ProgressTask task, string? filenameFormat, SingleMessage? messageInfo, Medium? messageMedia, Entities.Messages.FromUser? fromUser, Dictionary users); + Task DownloadPurchasedMessageDRMVideo(string policy, string signature, string kvp, string url, string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, ProgressTask task, string filenameFormat, Purchased.List messageInfo, Medium messageMedia, Purchased.FromUser fromUser, Dictionary users); + + Task DownloadSinglePurchasedMessageDRMVideo(string policy, string signature, string kvp, string url, string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, ProgressTask task, string? filenameFormat, SingleMessage? messageInfo, Medium? messageMedia, Entities.Messages.FromUser? fromUser, Dictionary users); + Task DownloadPurchasedPostDRMVideo(string policy, string signature, string kvp, string url, string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, ProgressTask task, string filenameFormat, Purchased.List postInfo, Medium postMedia, Purchased.FromUser fromUser, Dictionary users); + Task DownloadPurchasedPostMedia(string url, string folder, long media_id, string api_type, ProgressTask task, string filenameFormat, Purchased.List messageInfo, Medium messageMedia, Purchased.FromUser fromUser, Dictionary users); + Task DownloadStoryMedia(string url, string folder, long media_id, string api_type, ProgressTask task); + Task DownloadStreamMedia(string url, string folder, long media_id, string api_type, ProgressTask task, string? filenameFormat, Streams.List? streamInfo, Streams.Medium? streamMedia, Streams.Author? author, Dictionary users); + Task DownloadStreamsDRMVideo(string policy, string signature, string kvp, string url, string decryptionKey, string folder, DateTime lastModified, long media_id, string api_type, ProgressTask task, string filenameFormat, Streams.List streamInfo, Streams.Medium streamMedia, Streams.Author author, Dictionary users); + } +} diff --git a/OF DL/Helpers/Interfaces/IFileNameHelper.cs b/OF DL/Helpers/Interfaces/IFileNameHelper.cs new file mode 100644 index 0000000..aae3ba8 --- /dev/null +++ b/OF DL/Helpers/Interfaces/IFileNameHelper.cs @@ -0,0 +1,8 @@ +namespace OF_DL.Helpers +{ + public interface IFileNameHelper + { + Task BuildFilename(string fileFormat, Dictionary values); + Task> GetFilename(object obj1, object obj2, object obj3, List selectedProperties, string username, Dictionary users = null); + } +} diff --git a/OF DL/HttpUtil.cs b/OF DL/HttpUtil.cs new file mode 100644 index 0000000..89d1214 --- /dev/null +++ b/OF DL/HttpUtil.cs @@ -0,0 +1,99 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text; + +namespace WidevineClient +{ + class HttpUtil + { + public static HttpClient Client { get; set; } = new HttpClient(new HttpClientHandler + { + AllowAutoRedirect = true, + //Proxy = null + }); + + public static byte[] PostData(string URL, Dictionary headers, string postData) + { + var mediaType = postData.StartsWith("{") ? "application/json" : "application/x-www-form-urlencoded"; + StringContent content = new StringContent(postData, Encoding.UTF8, mediaType); + //ByteArrayContent content = new ByteArrayContent(postData); + + HttpResponseMessage response = Post(URL, headers, content); + byte[] bytes = response.Content.ReadAsByteArrayAsync().Result; + return bytes; + } + + public static byte[] PostData(string URL, Dictionary headers, byte[] postData) + { + ByteArrayContent content = new ByteArrayContent(postData); + + HttpResponseMessage response = Post(URL, headers, content); + byte[] bytes = response.Content.ReadAsByteArrayAsync().Result; + return bytes; + } + + public static byte[] PostData(string URL, Dictionary headers, Dictionary postData) + { + FormUrlEncodedContent content = new FormUrlEncodedContent(postData); + + HttpResponseMessage response = Post(URL, headers, content); + byte[] bytes = response.Content.ReadAsByteArrayAsync().Result; + return bytes; + } + + public static string GetWebSource(string URL, Dictionary headers = null) + { + HttpResponseMessage response = Get(URL, headers); + byte[] bytes = response.Content.ReadAsByteArrayAsync().Result; + return Encoding.UTF8.GetString(bytes); + } + + public static byte[] GetBinary(string URL, Dictionary headers = null) + { + HttpResponseMessage response = Get(URL, headers); + byte[] bytes = response.Content.ReadAsByteArrayAsync().Result; + return bytes; + } + public static string GetString(byte[] bytes) + { + return Encoding.UTF8.GetString(bytes); + } + + static HttpResponseMessage Get(string URL, Dictionary headers = null) + { + HttpRequestMessage request = new HttpRequestMessage() + { + RequestUri = new Uri(URL), + Method = HttpMethod.Get + }; + + if (headers != null) + foreach (KeyValuePair header in headers) + request.Headers.TryAddWithoutValidation(header.Key, header.Value); + + return Send(request); + } + + static HttpResponseMessage Post(string URL, Dictionary headers, HttpContent content) + { + HttpRequestMessage request = new HttpRequestMessage() + { + RequestUri = new Uri(URL), + Method = HttpMethod.Post, + Content = content + }; + + if (headers != null) + foreach (KeyValuePair header in headers) + request.Headers.TryAddWithoutValidation(header.Key, header.Value); + + return Send(request); + } + + static HttpResponseMessage Send(HttpRequestMessage request) + { + return Client.SendAsync(request).Result; + } + } +} diff --git a/OF DL/Icon/download.ico b/OF DL/Icon/download.ico new file mode 100644 index 0000000000000000000000000000000000000000..222e2cc49645fe656394f5e7f375d659925499a8 GIT binary patch literal 1150 zcmeH@F%H5o3`Kt=b~-U3m9a-)V`1+VI?Ytduaq`jwphkFd)75CWFSGB#eq zipMfGwmkEWdQ5Ur%`-2Jl5b|Mn>^y{ET4<%Zw;&SYIB^_xoYY&!%MEt^`NJpVf77t uj@LSSc+)32C-ukY#{WIP#>~Ho=c{*meybb+(eVttFThX&&;2O5r}PCC4 + + + Exe + net8.0 + OF_DL + enable + enable + Icon\download.ico + + + + + + + + + + + + + + + + + + + + + + + + + References\Spectre.Console.dll + + + + + + Always + + + Always + + + Always + + + + diff --git a/OF DL/Program.cs b/OF DL/Program.cs new file mode 100644 index 0000000..d617b91 --- /dev/null +++ b/OF DL/Program.cs @@ -0,0 +1,3233 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using OF_DL.Entities; +using OF_DL.Entities.Archived; +using OF_DL.Entities.Messages; +using OF_DL.Entities.Post; +using OF_DL.Entities.Purchased; +using OF_DL.Entities.Streams; +using OF_DL.Enumerations; +using OF_DL.Enumurations; +using OF_DL.Helpers; +using Octokit; +using Serilog; +using Serilog.Core; +using Serilog.Events; +using Spectre.Console; +using System.IO; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Text.RegularExpressions; +using static OF_DL.Entities.Messages.Messages; +using Akka.Configuration; +using System.Text; +using static Akka.Actor.ProviderSelection; + +namespace OF_DL; + +public class Program +{ + public int MAX_AGE = 0; + public static List paid_post_ids = new(); + + private static bool clientIdBlobMissing = false; + private static bool devicePrivateKeyMissing = false; + private static Entities.Config? config = null; + private static Auth? auth = null; + private static LoggingLevelSwitch levelSwitch = new LoggingLevelSwitch(); + + private static async Task LoadAuthFromBrowser() + { + bool runningInDocker = Environment.GetEnvironmentVariable("OFDL_DOCKER") != null; + + try + { + AuthHelper authHelper = new(); + Task setupBrowserTask = authHelper.SetupBrowser(runningInDocker); + + Task.Delay(1000).Wait(); + if (!setupBrowserTask.IsCompleted) + { + AnsiConsole.MarkupLine($"[yellow]Downloading dependencies. Please wait ...[/]"); + } + setupBrowserTask.Wait(); + + Task getAuthTask = authHelper.GetAuthFromBrowser(); + Task.Delay(5000).Wait(); + if (!getAuthTask.IsCompleted) + { + if (runningInDocker) + { + AnsiConsole.MarkupLine( + "[yellow]In your web browser, navigate to the port forwarded from your docker container.[/]"); + AnsiConsole.MarkupLine( + "[yellow]For instance, if your docker run command included \"-p 8080:8080\", open your web browser to \"http://localhost:8080\".[/]"); + AnsiConsole.MarkupLine("[yellow]Once on that webpage, please use it to log in to your OF account. Do not navigate away from the page.[/]"); + } + else + { + AnsiConsole.MarkupLine($"[yellow]In the new window that has opened, please log in to your OF account. Do not close the window or tab. Do not navigate away from the page.[/]\n"); + AnsiConsole.MarkupLine($"[yellow]Note: Some users have reported that \"Sign in with Google\" has not been working with the new authentication method.[/]"); + AnsiConsole.MarkupLine($"[yellow]If you use this method or encounter other issues while logging in, use one of the legacy authentication methods documented here:[/]"); + AnsiConsole.MarkupLine($"[link]https://sim0n00ps.github.io/OF-DL/docs/config/auth#legacy-methods[/]"); + } + } + auth = await getAuthTask; + } + catch (Exception e) + { + AnsiConsole.MarkupLine($"\n[red]Authentication failed. Be sure to log into to OF using the new window that opened automatically.[/]"); + AnsiConsole.MarkupLine($"[red]The window will close automatically when the authentication process is finished.[/]"); + AnsiConsole.MarkupLine($"[red]If the problem persists, you may want to try using a legacy authentication method documented here:[/]\n"); + AnsiConsole.MarkupLine($"[link]https://sim0n00ps.github.io/OF-DL/docs/config/auth#legacy-methods[/]\n"); + AnsiConsole.MarkupLine($"[red]Press any key to exit.[/]"); + Log.Error(e, "auth invalid after attempt to get auth from browser"); + + Environment.Exit(2); + } + + if (auth == null) + { + AnsiConsole.MarkupLine($"\n[red]Authentication failed. Be sure to log into to OF using the new window that opened automatically.[/]"); + AnsiConsole.MarkupLine($"[red]The window will close automatically when the authentication process is finished.[/]"); + AnsiConsole.MarkupLine($"[red]If the problem persists, you may want to try using a legacy authentication method documented here:[/]\n"); + AnsiConsole.MarkupLine($"[link]https://sim0n00ps.github.io/OF-DL/docs/config/auth#legacy-methods[/]\n"); + AnsiConsole.MarkupLine($"[red]Press any key to exit.[/]"); + Log.Error("auth invalid after attempt to get auth from browser"); + + Environment.Exit(2); + } + else + { + await File.WriteAllTextAsync("auth.json", JsonConvert.SerializeObject(auth, Formatting.Indented)); + } + } + + public static async Task Main(string[] args) + { + bool cliNonInteractive = false; + + try + { + levelSwitch.MinimumLevel = LogEventLevel.Error; //set initial level (until we've read from config) + + Log.Logger = new LoggerConfiguration() + .MinimumLevel.ControlledBy(levelSwitch) + .WriteTo.File("logs/OFDL.txt", rollingInterval: RollingInterval.Day) + .CreateLogger(); + + AnsiConsole.Write(new FigletText("Welcome to OF-DL").Color(Color.Red)); + + //Remove config.json and convert to config.conf + if (File.Exists("config.json")) + { + AnsiConsole.Markup("[green]config.json located successfully!\n[/]"); + try + { + string jsonText = File.ReadAllText("config.json"); + var jsonConfig = JsonConvert.DeserializeObject(jsonText); + + if (jsonConfig != null) + { + var hoconConfig = new StringBuilder(); + hoconConfig.AppendLine("# External Tools"); + hoconConfig.AppendLine("External {"); + hoconConfig.AppendLine($" FFmpegPath = \"{jsonConfig.FFmpegPath}\""); + hoconConfig.AppendLine("}"); + + hoconConfig.AppendLine("# Download Settings"); + hoconConfig.AppendLine("Download {"); + hoconConfig.AppendLine(" Media {"); + hoconConfig.AppendLine($" DownloadAvatarHeaderPhoto = {jsonConfig.DownloadAvatarHeaderPhoto.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadPaidPosts = {jsonConfig.DownloadPaidPosts.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadPosts = {jsonConfig.DownloadPosts.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadArchived = {jsonConfig.DownloadArchived.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadStreams = {jsonConfig.DownloadStreams.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadStories = {jsonConfig.DownloadStories.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadHighlights = {jsonConfig.DownloadHighlights.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadMessages = {jsonConfig.DownloadMessages.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadPaidMessages = {jsonConfig.DownloadPaidMessages.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadImages = {jsonConfig.DownloadImages.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadVideos = {jsonConfig.DownloadVideos.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadAudios = {jsonConfig.DownloadAudios.ToString().ToLower()}"); + hoconConfig.AppendLine(" }"); + hoconConfig.AppendLine($" IgnoreOwnMessages = {jsonConfig.IgnoreOwnMessages.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadPostsIncrementally = {jsonConfig.DownloadPostsIncrementally.ToString().ToLower()}"); + hoconConfig.AppendLine($" BypassContentForCreatorsWhoNoLongerExist = {jsonConfig.BypassContentForCreatorsWhoNoLongerExist.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadDuplicatedMedia = {jsonConfig.DownloadDuplicatedMedia.ToString().ToLower()}"); + hoconConfig.AppendLine($" SkipAds = {jsonConfig.SkipAds.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadPath = \"{jsonConfig.DownloadPath}\""); + hoconConfig.AppendLine($" DownloadOnlySpecificDates = {jsonConfig.DownloadOnlySpecificDates.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadDateSelection = \"{jsonConfig.DownloadDateSelection.ToString().ToLower()}\""); + hoconConfig.AppendLine($" CustomDate = \"{jsonConfig.CustomDate?.ToString("yyyy-MM-dd")}\""); + hoconConfig.AppendLine($" ShowScrapeSize = {jsonConfig.ShowScrapeSize.ToString().ToLower()}"); + hoconConfig.AppendLine("}"); + + hoconConfig.AppendLine("# File Settings"); + hoconConfig.AppendLine("File {"); + hoconConfig.AppendLine($" PaidPostFileNameFormat = \"{jsonConfig.PaidPostFileNameFormat}\""); + hoconConfig.AppendLine($" PostFileNameFormat = \"{jsonConfig.PostFileNameFormat}\""); + hoconConfig.AppendLine($" PaidMessageFileNameFormat = \"{jsonConfig.PaidMessageFileNameFormat}\""); + hoconConfig.AppendLine($" MessageFileNameFormat = \"{jsonConfig.MessageFileNameFormat}\""); + hoconConfig.AppendLine($" RenameExistingFilesWhenCustomFormatIsSelected = {jsonConfig.RenameExistingFilesWhenCustomFormatIsSelected.ToString().ToLower()}"); + hoconConfig.AppendLine("}"); + + hoconConfig.AppendLine("# Creator-Specific Configurations"); + hoconConfig.AppendLine("CreatorConfigs {"); + foreach (var creatorConfig in jsonConfig.CreatorConfigs) + { + hoconConfig.AppendLine($" \"{creatorConfig.Key}\" {{"); + hoconConfig.AppendLine($" PaidPostFileNameFormat = \"{creatorConfig.Value.PaidPostFileNameFormat}\""); + hoconConfig.AppendLine($" PostFileNameFormat = \"{creatorConfig.Value.PostFileNameFormat}\""); + hoconConfig.AppendLine($" PaidMessageFileNameFormat = \"{creatorConfig.Value.PaidMessageFileNameFormat}\""); + hoconConfig.AppendLine($" MessageFileNameFormat = \"{creatorConfig.Value.MessageFileNameFormat}\""); + hoconConfig.AppendLine(" }"); + } + hoconConfig.AppendLine("}"); + + hoconConfig.AppendLine("# Folder Settings"); + hoconConfig.AppendLine("Folder {"); + hoconConfig.AppendLine($" FolderPerPaidPost = {jsonConfig.FolderPerPaidPost.ToString().ToLower()}"); + hoconConfig.AppendLine($" FolderPerPost = {jsonConfig.FolderPerPost.ToString().ToLower()}"); + hoconConfig.AppendLine($" FolderPerPaidMessage = {jsonConfig.FolderPerPaidMessage.ToString().ToLower()}"); + hoconConfig.AppendLine($" FolderPerMessage = {jsonConfig.FolderPerMessage.ToString().ToLower()}"); + hoconConfig.AppendLine("}"); + + hoconConfig.AppendLine("# Subscription Settings"); + hoconConfig.AppendLine("Subscriptions {"); + hoconConfig.AppendLine($" IncludeExpiredSubscriptions = {jsonConfig.IncludeExpiredSubscriptions.ToString().ToLower()}"); + hoconConfig.AppendLine($" IncludeRestrictedSubscriptions = {jsonConfig.IncludeRestrictedSubscriptions.ToString().ToLower()}"); + hoconConfig.AppendLine($" IgnoredUsersListName = \"{jsonConfig.IgnoredUsersListName}\""); + hoconConfig.AppendLine("}"); + + hoconConfig.AppendLine("# Interaction Settings"); + hoconConfig.AppendLine("Interaction {"); + hoconConfig.AppendLine($" NonInteractiveMode = {jsonConfig.NonInteractiveMode.ToString().ToLower()}"); + hoconConfig.AppendLine($" NonInteractiveModeListName = \"{jsonConfig.NonInteractiveModeListName}\""); + hoconConfig.AppendLine($" NonInteractiveModePurchasedTab = {jsonConfig.NonInteractiveModePurchasedTab.ToString().ToLower()}"); + hoconConfig.AppendLine("}"); + + hoconConfig.AppendLine("# Performance Settings"); + hoconConfig.AppendLine("Performance {"); + hoconConfig.AppendLine($" Timeout = {(jsonConfig.Timeout.HasValue ? jsonConfig.Timeout.Value : -1)}"); + hoconConfig.AppendLine($" LimitDownloadRate = {jsonConfig.LimitDownloadRate.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadLimitInMbPerSec = {jsonConfig.DownloadLimitInMbPerSec}"); + hoconConfig.AppendLine("}"); + + hoconConfig.AppendLine("# Logging/Debug Settings"); + hoconConfig.AppendLine("Logging {"); + hoconConfig.AppendLine($" LoggingLevel = \"{jsonConfig.LoggingLevel.ToString().ToLower()}\""); + hoconConfig.AppendLine("}"); + + File.WriteAllText("config.conf", hoconConfig.ToString()); + File.Delete("config.json"); + AnsiConsole.Markup("[green]config.conf created successfully from config.json!\n[/]"); + } + } + catch (Exception e) + { + Console.WriteLine(e); + AnsiConsole.MarkupLine($"\n[red]config.conf is not valid, check your syntax![/]\n"); + AnsiConsole.MarkupLine($"[red]Press any key to exit.[/]"); + Log.Error("config.conf processing failed.", e.Message); + + if (!cliNonInteractive) + { + Console.ReadKey(); + } + Environment.Exit(3); + } + } + + //I dont like it... but I needed to move config here, otherwise the logging level gets changed too late after we missed a whole bunch of important info + if (File.Exists("config.conf")) + { + AnsiConsole.Markup("[green]config.conf located successfully!\n[/]"); + try + { + string hoconText = File.ReadAllText("config.conf"); + + var hoconConfig = ConfigurationFactory.ParseString(hoconText); + + config = new Entities.Config + { + // FFmpeg Settings + FFmpegPath = hoconConfig.GetString("External.FFmpegPath"), + + // Download Settings + DownloadAvatarHeaderPhoto = hoconConfig.GetBoolean("Download.Media.DownloadAvatarHeaderPhoto"), + DownloadPaidPosts = hoconConfig.GetBoolean("Download.Media.DownloadPaidPosts"), + DownloadPosts = hoconConfig.GetBoolean("Download.Media.DownloadPosts"), + DownloadArchived = hoconConfig.GetBoolean("Download.Media.DownloadArchived"), + DownloadStreams = hoconConfig.GetBoolean("Download.Media.DownloadStreams"), + DownloadStories = hoconConfig.GetBoolean("Download.Media.DownloadStories"), + DownloadHighlights = hoconConfig.GetBoolean("Download.Media.DownloadHighlights"), + DownloadMessages = hoconConfig.GetBoolean("Download.Media.DownloadMessages"), + DownloadPaidMessages = hoconConfig.GetBoolean("Download.Media.DownloadPaidMessages"), + DownloadImages = hoconConfig.GetBoolean("Download.Media.DownloadImages"), + DownloadVideos = hoconConfig.GetBoolean("Download.Media.DownloadVideos"), + DownloadAudios = hoconConfig.GetBoolean("Download.Media.DownloadAudios"), + IgnoreOwnMessages = hoconConfig.GetBoolean("Download.IgnoreOwnMessages"), + DownloadPostsIncrementally = hoconConfig.GetBoolean("Download.DownloadPostsIncrementally"), + BypassContentForCreatorsWhoNoLongerExist = hoconConfig.GetBoolean("Download.BypassContentForCreatorsWhoNoLongerExist"), + DownloadDuplicatedMedia = hoconConfig.GetBoolean("Download.DownloadDuplicatedMedia"), + SkipAds = hoconConfig.GetBoolean("Download.SkipAds"), + DownloadPath = hoconConfig.GetString("Download.DownloadPath"), + DownloadOnlySpecificDates = hoconConfig.GetBoolean("Download.DownloadOnlySpecificDates"), + DownloadDateSelection = Enum.Parse(hoconConfig.GetString("Download.DownloadDateSelection"), true), + CustomDate = !string.IsNullOrWhiteSpace(hoconConfig.GetString("Download.CustomDate")) ? DateTime.Parse(hoconConfig.GetString("Download.CustomDate")) : null, + ShowScrapeSize = hoconConfig.GetBoolean("Download.ShowScrapeSize"), + + // File Settings + PaidPostFileNameFormat = hoconConfig.GetString("File.PaidPostFileNameFormat"), + PostFileNameFormat = hoconConfig.GetString("File.PostFileNameFormat"), + PaidMessageFileNameFormat = hoconConfig.GetString("File.PaidMessageFileNameFormat"), + MessageFileNameFormat = hoconConfig.GetString("File.MessageFileNameFormat"), + RenameExistingFilesWhenCustomFormatIsSelected = hoconConfig.GetBoolean("File.RenameExistingFilesWhenCustomFormatIsSelected"), + + // Folder Settings + FolderPerPaidPost = hoconConfig.GetBoolean("Folder.FolderPerPaidPost"), + FolderPerPost = hoconConfig.GetBoolean("Folder.FolderPerPost"), + FolderPerPaidMessage = hoconConfig.GetBoolean("Folder.FolderPerPaidMessage"), + FolderPerMessage = hoconConfig.GetBoolean("Folder.FolderPerMessage"), + + // Subscription Settings + IncludeExpiredSubscriptions = hoconConfig.GetBoolean("Subscriptions.IncludeExpiredSubscriptions"), + IncludeRestrictedSubscriptions = hoconConfig.GetBoolean("Subscriptions.IncludeRestrictedSubscriptions"), + IgnoredUsersListName = hoconConfig.GetString("Subscriptions.IgnoredUsersListName"), + + // Interaction Settings + NonInteractiveMode = hoconConfig.GetBoolean("Interaction.NonInteractiveMode"), + NonInteractiveModeListName = hoconConfig.GetString("Interaction.NonInteractiveModeListName"), + NonInteractiveModePurchasedTab = hoconConfig.GetBoolean("Interaction.NonInteractiveModePurchasedTab"), + + // Performance Settings + Timeout = string.IsNullOrWhiteSpace(hoconConfig.GetString("Performance.Timeout")) ? -1 : hoconConfig.GetInt("Performance.Timeout"), + LimitDownloadRate = hoconConfig.GetBoolean("Performance.LimitDownloadRate"), + DownloadLimitInMbPerSec = hoconConfig.GetInt("Performance.DownloadLimitInMbPerSec"), + + // Logging/Debug Settings + LoggingLevel = Enum.Parse(hoconConfig.GetString("Logging.LoggingLevel"), true) + }; + + ValidateFileNameFormat(config.PaidPostFileNameFormat, "PaidPostFileNameFormat"); + ValidateFileNameFormat(config.PostFileNameFormat, "PostFileNameFormat"); + ValidateFileNameFormat(config.PaidMessageFileNameFormat, "PaidMessageFileNameFormat"); + ValidateFileNameFormat(config.MessageFileNameFormat, "MessageFileNameFormat"); + + var creatorConfigsSection = hoconConfig.GetConfig("CreatorConfigs"); + if (creatorConfigsSection != null) + { + foreach (var key in creatorConfigsSection.AsEnumerable()) + { + var creatorKey = key.Key; + var creatorHocon = creatorConfigsSection.GetConfig(creatorKey); + if (!config.CreatorConfigs.ContainsKey(creatorKey) && creatorHocon != null) + { + config.CreatorConfigs.Add(key.Key, new CreatorConfig + { + PaidPostFileNameFormat = creatorHocon.GetString("PaidPostFileNameFormat"), + PostFileNameFormat = creatorHocon.GetString("PostFileNameFormat"), + PaidMessageFileNameFormat = creatorHocon.GetString("PaidMessageFileNameFormat"), + MessageFileNameFormat = creatorHocon.GetString("MessageFileNameFormat") + }); + + ValidateFileNameFormat(config.CreatorConfigs[key.Key].PaidPostFileNameFormat, $"{key.Key}.PaidPostFileNameFormat"); + ValidateFileNameFormat(config.CreatorConfigs[key.Key].PostFileNameFormat, $"{key.Key}.PostFileNameFormat"); + ValidateFileNameFormat(config.CreatorConfigs[key.Key].PaidMessageFileNameFormat, $"{key.Key}.PaidMessageFileNameFormat"); + ValidateFileNameFormat(config.CreatorConfigs[key.Key].MessageFileNameFormat, $"{key.Key}.MessageFileNameFormat"); + } + } + } + + levelSwitch.MinimumLevel = (LogEventLevel)config.LoggingLevel; //set the logging level based on config + Log.Debug("Configuration:"); + string configString = JsonConvert.SerializeObject(config, Formatting.Indented); + Log.Debug(configString); + } + catch (Exception e) + { + Console.WriteLine(e); + AnsiConsole.MarkupLine($"\n[red]config.conf is not valid, check your syntax![/]\n"); + AnsiConsole.MarkupLine($"[red]Press any key to exit.[/]"); + Log.Error("config.conf processing failed.", e.Message); + + if (!cliNonInteractive) + { + Console.ReadKey(); + } + Environment.Exit(3); + } + } + else + { + Entities.Config jsonConfig = new Entities.Config(); + var hoconConfig = new StringBuilder(); + hoconConfig.AppendLine("# External Tools"); + hoconConfig.AppendLine("External {"); + hoconConfig.AppendLine($" FFmpegPath = \"{jsonConfig.FFmpegPath}\""); + hoconConfig.AppendLine("}"); + + hoconConfig.AppendLine("# Download Settings"); + hoconConfig.AppendLine("Download {"); + hoconConfig.AppendLine(" Media {"); + hoconConfig.AppendLine($" DownloadAvatarHeaderPhoto = {jsonConfig.DownloadAvatarHeaderPhoto.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadPaidPosts = {jsonConfig.DownloadPaidPosts.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadPosts = {jsonConfig.DownloadPosts.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadArchived = {jsonConfig.DownloadArchived.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadStreams = {jsonConfig.DownloadStreams.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadStories = {jsonConfig.DownloadStories.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadHighlights = {jsonConfig.DownloadHighlights.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadMessages = {jsonConfig.DownloadMessages.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadPaidMessages = {jsonConfig.DownloadPaidMessages.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadImages = {jsonConfig.DownloadImages.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadVideos = {jsonConfig.DownloadVideos.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadAudios = {jsonConfig.DownloadAudios.ToString().ToLower()}"); + hoconConfig.AppendLine(" }"); + hoconConfig.AppendLine($" IgnoreOwnMessages = {jsonConfig.IgnoreOwnMessages.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadPostsIncrementally = {jsonConfig.DownloadPostsIncrementally.ToString().ToLower()}"); + hoconConfig.AppendLine($" BypassContentForCreatorsWhoNoLongerExist = {jsonConfig.BypassContentForCreatorsWhoNoLongerExist.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadDuplicatedMedia = {jsonConfig.DownloadDuplicatedMedia.ToString().ToLower()}"); + hoconConfig.AppendLine($" SkipAds = {jsonConfig.SkipAds.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadPath = \"{jsonConfig.DownloadPath}\""); + hoconConfig.AppendLine($" DownloadOnlySpecificDates = {jsonConfig.DownloadOnlySpecificDates.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadDateSelection = \"{jsonConfig.DownloadDateSelection.ToString().ToLower()}\""); + hoconConfig.AppendLine($" CustomDate = \"{jsonConfig.CustomDate?.ToString("yyyy-MM-dd")}\""); + hoconConfig.AppendLine($" ShowScrapeSize = {jsonConfig.ShowScrapeSize.ToString().ToLower()}"); + hoconConfig.AppendLine("}"); + + hoconConfig.AppendLine("# File Settings"); + hoconConfig.AppendLine("File {"); + hoconConfig.AppendLine($" PaidPostFileNameFormat = \"{jsonConfig.PaidPostFileNameFormat}\""); + hoconConfig.AppendLine($" PostFileNameFormat = \"{jsonConfig.PostFileNameFormat}\""); + hoconConfig.AppendLine($" PaidMessageFileNameFormat = \"{jsonConfig.PaidMessageFileNameFormat}\""); + hoconConfig.AppendLine($" MessageFileNameFormat = \"{jsonConfig.MessageFileNameFormat}\""); + hoconConfig.AppendLine($" RenameExistingFilesWhenCustomFormatIsSelected = {jsonConfig.RenameExistingFilesWhenCustomFormatIsSelected.ToString().ToLower()}"); + hoconConfig.AppendLine("}"); + + hoconConfig.AppendLine("# Creator-Specific Configurations"); + hoconConfig.AppendLine("CreatorConfigs {"); + foreach (var creatorConfig in jsonConfig.CreatorConfigs) + { + hoconConfig.AppendLine($" \"{creatorConfig.Key}\" {{"); + hoconConfig.AppendLine($" PaidPostFileNameFormat = \"{creatorConfig.Value.PaidPostFileNameFormat}\""); + hoconConfig.AppendLine($" PostFileNameFormat = \"{creatorConfig.Value.PostFileNameFormat}\""); + hoconConfig.AppendLine($" PaidMessageFileNameFormat = \"{creatorConfig.Value.PaidMessageFileNameFormat}\""); + hoconConfig.AppendLine($" MessageFileNameFormat = \"{creatorConfig.Value.MessageFileNameFormat}\""); + hoconConfig.AppendLine(" }"); + } + hoconConfig.AppendLine("}"); + + hoconConfig.AppendLine("# Folder Settings"); + hoconConfig.AppendLine("Folder {"); + hoconConfig.AppendLine($" FolderPerPaidPost = {jsonConfig.FolderPerPaidPost.ToString().ToLower()}"); + hoconConfig.AppendLine($" FolderPerPost = {jsonConfig.FolderPerPost.ToString().ToLower()}"); + hoconConfig.AppendLine($" FolderPerPaidMessage = {jsonConfig.FolderPerPaidMessage.ToString().ToLower()}"); + hoconConfig.AppendLine($" FolderPerMessage = {jsonConfig.FolderPerMessage.ToString().ToLower()}"); + hoconConfig.AppendLine("}"); + + hoconConfig.AppendLine("# Subscription Settings"); + hoconConfig.AppendLine("Subscriptions {"); + hoconConfig.AppendLine($" IncludeExpiredSubscriptions = {jsonConfig.IncludeExpiredSubscriptions.ToString().ToLower()}"); + hoconConfig.AppendLine($" IncludeRestrictedSubscriptions = {jsonConfig.IncludeRestrictedSubscriptions.ToString().ToLower()}"); + hoconConfig.AppendLine($" IgnoredUsersListName = \"{jsonConfig.IgnoredUsersListName}\""); + hoconConfig.AppendLine("}"); + + hoconConfig.AppendLine("# Interaction Settings"); + hoconConfig.AppendLine("Interaction {"); + hoconConfig.AppendLine($" NonInteractiveMode = {jsonConfig.NonInteractiveMode.ToString().ToLower()}"); + hoconConfig.AppendLine($" NonInteractiveModeListName = \"{jsonConfig.NonInteractiveModeListName}\""); + hoconConfig.AppendLine($" NonInteractiveModePurchasedTab = {jsonConfig.NonInteractiveModePurchasedTab.ToString().ToLower()}"); + hoconConfig.AppendLine("}"); + + hoconConfig.AppendLine("# Performance Settings"); + hoconConfig.AppendLine("Performance {"); + hoconConfig.AppendLine($" Timeout = {(jsonConfig.Timeout.HasValue ? jsonConfig.Timeout.Value : -1)}"); + hoconConfig.AppendLine($" LimitDownloadRate = {jsonConfig.LimitDownloadRate.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadLimitInMbPerSec = {jsonConfig.DownloadLimitInMbPerSec}"); + hoconConfig.AppendLine("}"); + + hoconConfig.AppendLine("# Logging/Debug Settings"); + hoconConfig.AppendLine("Logging {"); + hoconConfig.AppendLine($" LoggingLevel = \"{jsonConfig.LoggingLevel.ToString().ToLower()}\""); + hoconConfig.AppendLine("}"); + + File.WriteAllText("config.conf", hoconConfig.ToString()); + AnsiConsole.Markup("[red]config.conf does not exist, a default file has been created in the folder you are running the program from[/]"); + Log.Error("config.conf does not exist"); + + if (!cliNonInteractive) + { + Console.ReadKey(); + } + Environment.Exit(3); + } + + + if (args is not null && args.Length > 0) + { + const string NON_INTERACTIVE_ARG = "--non-interactive"; + + if (args.Any(a => NON_INTERACTIVE_ARG.Equals(NON_INTERACTIVE_ARG, StringComparison.OrdinalIgnoreCase))) + { + cliNonInteractive = true; + Log.Debug("NonInteractiveMode set via command line"); + } + + Log.Debug("Additional arguments:"); + foreach (string argument in args) + { + Log.Debug(argument); + } + } + + var os = Environment.OSVersion; + + Log.Debug($"Operating system information: {os.VersionString}"); + + if (os.Platform == PlatformID.Win32NT) + { + // check if this is windows 10+ + if (os.Version.Major < 10) + { + Console.Write("This appears to be running on an older version of Windows which is not supported.\n\n"); + Console.Write("OF-DL requires Windows 10 or higher when being run on Windows. Your reported version is: {0}\n\n", os.VersionString); + Console.Write("Press any key to continue.\n"); + Log.Error("Windows version prior to 10.x: {0}", os.VersionString); + + if (!cliNonInteractive) + { + Console.ReadKey(); + } + Environment.Exit(1); + } + else + { + AnsiConsole.Markup("[green]Valid version of Windows found.\n[/]"); + } + } + + try + { + // Only run the version check if not in DEBUG mode + #if !DEBUG + Version localVersion = Assembly.GetEntryAssembly()?.GetName().Version; //Only tested with numeric values. + + // Get all releases from GitHub + GitHubClient client = new GitHubClient(new ProductHeaderValue("SomeName")); + IReadOnlyList releases = await client.Repository.Release.GetAll("sim0n00ps", "OF-DL"); + + // Setup the versions + Version latestGitHubVersion = new Version(releases[0].TagName.Replace("OFDLV", "")); + + // Compare the Versions + int versionComparison = localVersion.CompareTo(latestGitHubVersion); + if (versionComparison < 0) + { + // The version on GitHub is more up to date than this local release. + AnsiConsole.Markup("[red]You are running OF-DL version " + $"{localVersion.Major}.{localVersion.Minor}.{localVersion.Build}\n[/]"); + AnsiConsole.Markup("[red]Please update to the current release on GitHub, " + $"{latestGitHubVersion.Major}.{latestGitHubVersion.Minor}.{latestGitHubVersion.Build}: {releases[0].HtmlUrl}\n[/]"); + Log.Debug("Detected outdated client running version " + $"{localVersion.Major}.{localVersion.Minor}.{localVersion.Build}"); + Log.Debug("Latest GitHub release version " + $"{latestGitHubVersion.Major}.{latestGitHubVersion.Minor}.{latestGitHubVersion.Build}"); + } + else + { + // This local version is greater than the release version on GitHub. + AnsiConsole.Markup("[green]You are running OF-DL version " + $"{localVersion.Major}.{localVersion.Minor}.{localVersion.Build}\n[/]"); + AnsiConsole.Markup("[green]Latest GitHub Release version: " + $"{latestGitHubVersion.Major}.{latestGitHubVersion.Minor}.{latestGitHubVersion.Build}\n[/]"); + Log.Debug("Detected client running version " + $"{localVersion.Major}.{localVersion.Minor}.{localVersion.Build}"); + Log.Debug("Latest GitHub release version " + $"{latestGitHubVersion.Major}.{latestGitHubVersion.Minor}.{latestGitHubVersion.Build}"); + } + #else + AnsiConsole.Markup("[yellow]Running in Debug/Local mode. Version check skipped.\n[/]"); + Log.Debug("Running in Debug/Local mode. Version check skipped."); + #endif + } + catch (Exception e) + { + AnsiConsole.Markup("[red]Error checking latest release on GitHub:\n[/]"); + Console.WriteLine(e); + Log.Error("Error checking latest release on GitHub.", e.Message); + } + + if (File.Exists("auth.json")) + { + AnsiConsole.Markup("[green]auth.json located successfully!\n[/]"); + Log.Debug("Auth file found"); + try + { + auth = JsonConvert.DeserializeObject(await File.ReadAllTextAsync("auth.json")); + Log.Debug("Auth file found and deserialized"); + } + catch (Exception _) + { + Log.Information("Auth file found but could not be deserialized"); + Log.Debug("Deleting auth.json"); + File.Delete("auth.json"); + + if (cliNonInteractive) + { + AnsiConsole.MarkupLine($"\n[red]auth.json has invalid JSON syntax. The file can be generated automatically when OF-DL is run in the standard, interactive mode.[/]\n"); + AnsiConsole.MarkupLine($"[red]You may also want to try using the browser extension which is documented here:[/]\n"); + AnsiConsole.MarkupLine($"[link]https://sim0n00ps.github.io/OF-DL/docs/config/auth#browser-extension[/]\n"); + AnsiConsole.MarkupLine($"[red]Press any key to exit.[/]"); + + Console.ReadKey(); + Environment.Exit(2); + } + + await LoadAuthFromBrowser(); + } + } + else + { + if (cliNonInteractive) + { + AnsiConsole.MarkupLine($"\n[red]auth.json is missing. The file can be generated automatically when OF-DL is run in the standard, interactive mode.[/]\n"); + AnsiConsole.MarkupLine($"[red]You may also want to try using the browser extension which is documented here:[/]\n"); + AnsiConsole.MarkupLine($"[link]https://sim0n00ps.github.io/OF-DL/docs/config/auth#browser-extension[/]\n"); + AnsiConsole.MarkupLine($"[red]Press any key to exit.[/]"); + + Console.ReadKey(); + Environment.Exit(2); + } + + await LoadAuthFromBrowser(); + } + + //Added to stop cookie being filled with un-needed headers + ValidateCookieString(); + + if (File.Exists("rules.json")) + { + AnsiConsole.Markup("[green]rules.json located successfully!\n[/]"); + try + { + JsonConvert.DeserializeObject(File.ReadAllText("rules.json")); + Log.Debug($"Rules.json: "); + Log.Debug(JsonConvert.SerializeObject(File.ReadAllText("rules.json"), Formatting.Indented)); + } + catch (Exception e) + { + Console.WriteLine(e); + AnsiConsole.MarkupLine($"\n[red]rules.json is not valid, check your JSON syntax![/]\n"); + AnsiConsole.MarkupLine($"[red]Please ensure you are using the latest version of the software.[/]\n"); + AnsiConsole.MarkupLine($"[red]Press any key to exit.[/]"); + Log.Error("rules.json processing failed.", e.Message); + + if (!cliNonInteractive) + { + Console.ReadKey(); + } + Environment.Exit(2); + } + } + + if(cliNonInteractive) + { + // CLI argument overrides configuration + config!.NonInteractiveMode = true; + Log.Debug("NonInteractiveMode = true"); + } + + if(config!.NonInteractiveMode) + { + cliNonInteractive = true; // If it was set in the config, reset the cli value so exception handling works + Log.Debug("NonInteractiveMode = true (set via config)"); + } + + var ffmpegFound = false; + var pathAutoDetected = false; + if (!string.IsNullOrEmpty(config!.FFmpegPath) && ValidateFilePath(config.FFmpegPath)) + { + // FFmpeg path is set in config.json and is valid + ffmpegFound = true; + Log.Debug($"FFMPEG found: {config.FFmpegPath}"); + Log.Debug("FFMPEG path set in config.conf"); + } + else if (!string.IsNullOrEmpty(auth!.FFMPEG_PATH) && ValidateFilePath(auth.FFMPEG_PATH)) + { + // FFmpeg path is set in auth.json and is valid (config.conf takes precedence and auth.json is only available for backward compatibility) + ffmpegFound = true; + config.FFmpegPath = auth.FFMPEG_PATH; + Log.Debug($"FFMPEG found: {config.FFmpegPath}"); + Log.Debug("FFMPEG path set in auth.json"); + } + else if (string.IsNullOrEmpty(config.FFmpegPath)) + { + // FFmpeg path is not set in config.conf, so we will try to locate it in the PATH or current directory + var ffmpegPath = GetFullPath("ffmpeg"); + if (ffmpegPath != null) + { + // FFmpeg is found in the PATH or current directory + ffmpegFound = true; + pathAutoDetected = true; + config.FFmpegPath = ffmpegPath; + Log.Debug($"FFMPEG found: {ffmpegPath}"); + Log.Debug("FFMPEG path found via PATH or current directory"); + } + else + { + // FFmpeg is not found in the PATH or current directory, so we will try to locate the windows executable + ffmpegPath = GetFullPath("ffmpeg.exe"); + if (ffmpegPath != null) + { + // FFmpeg windows executable is found in the PATH or current directory + ffmpegFound = true; + pathAutoDetected = true; + config.FFmpegPath = ffmpegPath; + Log.Debug($"FFMPEG found: {ffmpegPath}"); + Log.Debug("FFMPEG path found in windows excutable directory"); + } + } + } + + if (ffmpegFound) + { + if (pathAutoDetected) + { + AnsiConsole.Markup($"[green]FFmpeg located successfully. Path auto-detected: {config.FFmpegPath}\n[/]"); + } + else + { + AnsiConsole.Markup($"[green]FFmpeg located successfully\n[/]"); + } + + // Escape backslashes in the path for Windows + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && config.FFmpegPath!.Contains(@":\") && !config.FFmpegPath.Contains(@":\\")) + { + config.FFmpegPath = config.FFmpegPath.Replace(@"\", @"\\"); + } + } + else + { + AnsiConsole.Markup("[red]Cannot locate FFmpeg; please modify config.conf with the correct path. Press any key to exit.[/]"); + Log.Error($"Cannot locate FFmpeg with path: {config.FFmpegPath}"); + if (!config.NonInteractiveMode) + { + Console.ReadKey(); + } + Environment.Exit(4); + } + + if (!File.Exists(Path.Join(WidevineClient.Widevine.Constants.DEVICES_FOLDER, WidevineClient.Widevine.Constants.DEVICE_NAME, "device_client_id_blob"))) + { + clientIdBlobMissing = true; + Log.Debug("clientIdBlobMissing missing"); + } + else + { + AnsiConsole.Markup($"[green]device_client_id_blob located successfully![/]\n"); + Log.Debug("clientIdBlobMissing found: " + File.Exists(Path.Join(WidevineClient.Widevine.Constants.DEVICES_FOLDER, WidevineClient.Widevine.Constants.DEVICE_NAME, "device_client_id_blob"))); + } + + if (!File.Exists(Path.Join(WidevineClient.Widevine.Constants.DEVICES_FOLDER, WidevineClient.Widevine.Constants.DEVICE_NAME, "device_private_key"))) + { + devicePrivateKeyMissing = true; + Log.Debug("devicePrivateKeyMissing missing"); + } + else + { + AnsiConsole.Markup($"[green]device_private_key located successfully![/]\n"); + Log.Debug("devicePrivateKeyMissing found: " + File.Exists(Path.Join(WidevineClient.Widevine.Constants.DEVICES_FOLDER, WidevineClient.Widevine.Constants.DEVICE_NAME, "device_private_key"))); + } + + if (clientIdBlobMissing || devicePrivateKeyMissing) + { + AnsiConsole.Markup("[yellow]device_client_id_blob and/or device_private_key missing, https://ofdl.tools/ or https://cdrm-project.com/ will be used instead for DRM protected videos\n[/]"); + } + + //Check if auth is valid + var apiHelper = new APIHelper(auth, config); + + Entities.User? validate = await apiHelper.GetUserInfo($"/users/me"); + if (validate == null || (validate?.name == null && validate?.username == null)) + { + Log.Error("Auth failed"); + + auth = null; + if (File.Exists("auth.json")) + { + File.Delete("auth.json"); + } + + if (!cliNonInteractive) + { + await LoadAuthFromBrowser(); + } + + if (auth == null) + { + AnsiConsole.MarkupLine($"\n[red]Auth failed. Please try again or use other authentication methods detailed here:[/]\n"); + AnsiConsole.MarkupLine($"[link]https://sim0n00ps.github.io/OF-DL/docs/config/auth[/]\n"); + Console.ReadKey(); + Environment.Exit(2); + } + } + + AnsiConsole.Markup($"[green]Logged In successfully as {validate.name} {validate.username}\n[/]"); + await DownloadAllData(apiHelper, auth, config); + } + catch (Exception ex) + { + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + Log.Error("Exception caught: {0}\n\nStackTrace: {1}", ex.Message, ex.StackTrace); + if (ex.InnerException != null) + { + Console.WriteLine("\nInner Exception:"); + Console.WriteLine("Exception caught: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + Log.Error("Inner Exception: {0}\n\nStackTrace: {1}", ex.InnerException.Message, ex.InnerException.StackTrace); + } + Console.WriteLine("\nPress any key to exit."); + if (!cliNonInteractive) + { + Console.ReadKey(); + } + Environment.Exit(5); + } + } + + + private static async Task DownloadAllData(APIHelper m_ApiHelper, Auth Auth, Entities.Config Config) + { + DBHelper dBHelper = new DBHelper(Config); + + Log.Debug("Calling DownloadAllData"); + + do + { + DateTime startTime = DateTime.Now; + Dictionary users = new(); + Dictionary activeSubs = await m_ApiHelper.GetActiveSubscriptions("/subscriptions/subscribes", Config.IncludeRestrictedSubscriptions, Config); + + Log.Debug("Subscriptions: "); + + foreach (KeyValuePair activeSub in activeSubs) + { + if (!users.ContainsKey(activeSub.Key)) + { + users.Add(activeSub.Key, activeSub.Value); + Log.Debug($"Name: {activeSub.Key} ID: {activeSub.Value}"); + } + } + if (Config!.IncludeExpiredSubscriptions) + { + Log.Debug("Inactive Subscriptions: "); + + Dictionary expiredSubs = await m_ApiHelper.GetExpiredSubscriptions("/subscriptions/subscribes", Config.IncludeRestrictedSubscriptions, Config); + foreach (KeyValuePair expiredSub in expiredSubs) + { + if (!users.ContainsKey(expiredSub.Key)) + { + users.Add(expiredSub.Key, expiredSub.Value); + Log.Debug($"Name: {expiredSub.Key} ID: {expiredSub.Value}"); + } + } + } + + Dictionary lists = await m_ApiHelper.GetLists("/lists", Config); + + // Remove users from the list if they are in the ignored list + if (!string.IsNullOrEmpty(Config.IgnoredUsersListName)) + { + if (!lists.TryGetValue(Config.IgnoredUsersListName, out var ignoredUsersListId)) + { + AnsiConsole.Markup($"[red]Ignored users list '{Config.IgnoredUsersListName}' not found\n[/]"); + Log.Error($"Ignored users list '{Config.IgnoredUsersListName}' not found"); + } + else + { + var ignoredUsernames = await m_ApiHelper.GetListUsers($"/lists/{ignoredUsersListId}/users", Config) ?? []; + users = users.Where(x => !ignoredUsernames.Contains(x.Key)).ToDictionary(x => x.Key, x => x.Value); + } + } + + await dBHelper.CreateUsersDB(users); + KeyValuePair> hasSelectedUsersKVP; + if(Config.NonInteractiveMode && Config.NonInteractiveModePurchasedTab) + { + hasSelectedUsersKVP = new KeyValuePair>(true, new Dictionary { { "PurchasedTab", 0 } }); + } + else if (Config.NonInteractiveMode && string.IsNullOrEmpty(Config.NonInteractiveModeListName)) + { + hasSelectedUsersKVP = new KeyValuePair>(true, users); + } + else if (Config.NonInteractiveMode && !string.IsNullOrEmpty(Config.NonInteractiveModeListName)) + { + var listId = lists[Config.NonInteractiveModeListName]; + var listUsernames = await m_ApiHelper.GetListUsers($"/lists/{listId}/users", Config) ?? []; + var selectedUsers = users.Where(x => listUsernames.Contains(x.Key)).Distinct().ToDictionary(x => x.Key, x => x.Value); + hasSelectedUsersKVP = new KeyValuePair>(true, selectedUsers); + } + else + { + var userSelectionResult = await HandleUserSelection(m_ApiHelper, Config, users, lists); + + Config = userSelectionResult.updatedConfig; + hasSelectedUsersKVP = new KeyValuePair>(userSelectionResult.IsExit, userSelectionResult.selectedUsers); + } + + if (hasSelectedUsersKVP.Key && hasSelectedUsersKVP.Value != null && hasSelectedUsersKVP.Value.ContainsKey("SinglePost")) + { + AnsiConsole.Markup("[red]To find an individual post URL, click on the ... at the top right corner of the post and select 'Copy link to post'.\n\nTo return to the main menu, enter 'back' or 'exit' when prompted for the URL.\n\n[/]"); + string postUrl = AnsiConsole.Prompt( + new TextPrompt("[red]Please enter a post URL: [/]") + .ValidationErrorMessage("[red]Please enter a valid post URL[/]") + .Validate(url => + { + Log.Debug($"Single Post URL: {url}"); + Regex regex = new Regex("https://onlyfans\\.com/[0-9]+/[A-Za-z0-9]+", RegexOptions.IgnoreCase); + if (regex.IsMatch(url)) + { + return ValidationResult.Success(); + } + if (url == "" || url == "exit" || url == "back") { + return ValidationResult.Success(); + } + Log.Error("Post URL invalid"); + return ValidationResult.Error("[red]Please enter a valid post URL[/]"); + })); + + if (postUrl != "" && postUrl != "exit" && postUrl != "back") { + long post_id = Convert.ToInt64(postUrl.Split("/")[3]); + string username = postUrl.Split("/")[4]; + + Log.Debug($"Single Post ID: {post_id.ToString()}"); + Log.Debug($"Single Post Creator: {username}"); + + if (users.ContainsKey(username)) + { + string path = ""; + if (!string.IsNullOrEmpty(Config.DownloadPath)) + { + path = System.IO.Path.Combine(Config.DownloadPath, username); + } + else + { + path = $"__user_data__/sites/OnlyFans/{username}"; + } + + Log.Debug($"Download path: {path}"); + + if (!Directory.Exists(path)) + { + Directory.CreateDirectory(path); + AnsiConsole.Markup($"[red]Created folder for {username}\n[/]"); + Log.Debug($"Created folder for {username}"); + } + else + { + AnsiConsole.Markup($"[red]Folder for {username} already created\n[/]"); + } + + await dBHelper.CreateDB(path); + + var downloadContext = new DownloadContext(Auth, Config, GetCreatorFileNameFormatConfig(Config, username), m_ApiHelper, dBHelper); + + await DownloadSinglePost(downloadContext, post_id, path, users); + } + } + } + else if (hasSelectedUsersKVP.Key && hasSelectedUsersKVP.Value != null && hasSelectedUsersKVP.Value.ContainsKey("PurchasedTab")) + { + Dictionary purchasedTabUsers = await m_ApiHelper.GetPurchasedTabUsers("/posts/paid", Config, users); + AnsiConsole.Markup($"[red]Checking folders for Users in Purchased Tab\n[/]"); + foreach (KeyValuePair user in purchasedTabUsers) + { + string path = ""; + if (!string.IsNullOrEmpty(Config.DownloadPath)) + { + path = System.IO.Path.Combine(Config.DownloadPath, user.Key); + } + else + { + path = $"__user_data__/sites/OnlyFans/{user.Key}"; + } + + Log.Debug($"Download path: {path}"); + + await dBHelper.CheckUsername(user, path); + + if (!Directory.Exists(path)) + { + Directory.CreateDirectory(path); + AnsiConsole.Markup($"[red]Created folder for {user.Key}\n[/]"); + Log.Debug($"Created folder for {user.Key}"); + } + else + { + AnsiConsole.Markup($"[red]Folder for {user.Key} already created\n[/]"); + Log.Debug($"Folder for {user.Key} already created"); + } + + Entities.User user_info = await m_ApiHelper.GetUserInfo($"/users/{user.Key}"); + + await dBHelper.CreateDB(path); + } + + string p = ""; + if (!string.IsNullOrEmpty(Config.DownloadPath)) + { + p = Config.DownloadPath; + } + else + { + p = $"__user_data__/sites/OnlyFans/"; + } + + Log.Debug($"Download path: {p}"); + + List purchasedTabCollections = await m_ApiHelper.GetPurchasedTab("/posts/paid", p, Config, users); + foreach(PurchasedTabCollection purchasedTabCollection in purchasedTabCollections) + { + AnsiConsole.Markup($"[red]\nScraping Data for {purchasedTabCollection.Username}\n[/]"); + string path = ""; + if (!string.IsNullOrEmpty(Config.DownloadPath)) + { + path = System.IO.Path.Combine(Config.DownloadPath, purchasedTabCollection.Username); + } + else + { + path = $"__user_data__/sites/OnlyFans/{purchasedTabCollection.Username}"; + } + + + Log.Debug($"Download path: {path}"); + + var downloadContext = new DownloadContext(Auth, Config, GetCreatorFileNameFormatConfig(Config, purchasedTabCollection.Username), m_ApiHelper, dBHelper); + + int paidPostCount = 0; + int paidMessagesCount = 0; + paidPostCount = await DownloadPaidPostsPurchasedTab(downloadContext, purchasedTabCollection.PaidPosts, users.FirstOrDefault(u => u.Value == purchasedTabCollection.UserId), paidPostCount, path, users); + paidMessagesCount = await DownloadPaidMessagesPurchasedTab(downloadContext, purchasedTabCollection.PaidMessages, users.FirstOrDefault(u => u.Value == purchasedTabCollection.UserId), paidMessagesCount, path, users); + + AnsiConsole.Markup("\n"); + AnsiConsole.Write(new BreakdownChart() + .FullSize() + .AddItem("Paid Posts", paidPostCount, Color.Red) + .AddItem("Paid Messages", paidMessagesCount, Color.Aqua)); + AnsiConsole.Markup("\n"); + } + DateTime endTime = DateTime.Now; + TimeSpan totalTime = endTime - startTime; + AnsiConsole.Markup($"[green]Scrape Completed in {totalTime.TotalMinutes:0.00} minutes\n[/]"); + Log.Debug($"Scrape Completed in {totalTime.TotalMinutes:0.00} minutes"); + } + else if (hasSelectedUsersKVP.Key && hasSelectedUsersKVP.Value != null && hasSelectedUsersKVP.Value.ContainsKey("SingleMessage")) + { + AnsiConsole.Markup("[red]To find an individual message URL, note that you can only do so for PPV messages that you have unlocked. Go the main OnlyFans timeline, click on the Purchased tab, find the relevant message, click on the ... at the top right corner of the message, and select 'Copy link to message'. For all other messages, you cannot scrape them individually, you must scrape all messages from that creator.\n\nTo return to the main menu, enter 'back' or 'exit' when prompted for the URL.\n\n[/]"); + string messageUrl = AnsiConsole.Prompt( + new TextPrompt("[red]Please enter a message URL: [/]") + .ValidationErrorMessage("[red]Please enter a valid message URL[/]") + .Validate(url => + { + Log.Debug($"Single Paid Message URL: {url}"); + Regex regex = new Regex("https://onlyfans\\.com/my/chats/chat/[0-9]+/\\?firstId=[0-9]+$", RegexOptions.IgnoreCase); + if (regex.IsMatch(url)) + { + return ValidationResult.Success(); + } + if (url == "" || url == "back" || url == "exit") + { + return ValidationResult.Success(); + } + Log.Error("Message URL invalid"); + return ValidationResult.Error("[red]Please enter a valid message URL[/]"); + })); + + if (messageUrl != "" && messageUrl != "exit" && messageUrl != "back") + { + long message_id = Convert.ToInt64(messageUrl.Split("?firstId=")[1]); + long user_id = Convert.ToInt64(messageUrl.Split("/")[6]); + JObject user = await m_ApiHelper.GetUserInfoById($"/users/list?x[]={user_id.ToString()}"); + string username = string.Empty; + + Log.Debug($"Message ID: {message_id}"); + Log.Debug($"User ID: {user_id}"); + + if (user is null) + { + username = $"Deleted User - {user_id.ToString()}"; + Log.Debug("Content creator not longer exists - ", user_id.ToString()); + } + else if (!string.IsNullOrEmpty(user[user_id.ToString()]["username"].ToString())) + { + username = user[user_id.ToString()]["username"].ToString(); + Log.Debug("Content creator: ", username); + } + + string path = ""; + if (!string.IsNullOrEmpty(Config.DownloadPath)) + { + path = System.IO.Path.Combine(Config.DownloadPath, username); + } + else + { + path = $"__user_data__/sites/OnlyFans/{username}"; + } + + Log.Debug("Download path: ", path); + + if (!Directory.Exists(path)) + { + Directory.CreateDirectory(path); + AnsiConsole.Markup($"[red]Created folder for {username}\n[/]"); + Log.Debug($"Created folder for {username}"); + } + else + { + AnsiConsole.Markup($"[red]Folder for {username} already created\n[/]"); + Log.Debug($"Folder for {username} already created"); + } + + await dBHelper.CreateDB(path); + + var downloadContext = new DownloadContext(Auth, Config, GetCreatorFileNameFormatConfig(Config, username), m_ApiHelper, dBHelper); + + await DownloadPaidMessage(downloadContext, hasSelectedUsersKVP, username, 1, path, message_id); + } + } + else if (hasSelectedUsersKVP.Key && !hasSelectedUsersKVP.Value.ContainsKey("ConfigChanged")) + { + //Iterate over each user in the list of users + foreach (KeyValuePair user in hasSelectedUsersKVP.Value) + { + int paidPostCount = 0; + int postCount = 0; + int archivedCount = 0; + int streamsCount = 0; + int storiesCount = 0; + int highlightsCount = 0; + int messagesCount = 0; + int paidMessagesCount = 0; + AnsiConsole.Markup($"[red]\nScraping Data for {user.Key}\n[/]"); + + Log.Debug($"Scraping Data for {user.Key}"); + + string path = ""; + if (!string.IsNullOrEmpty(Config.DownloadPath)) + { + path = System.IO.Path.Combine(Config.DownloadPath, user.Key); + } + else + { + path = $"__user_data__/sites/OnlyFans/{user.Key}"; + } + + Log.Debug("Download path: ", path); + + await dBHelper.CheckUsername(user, path); + + if (!Directory.Exists(path)) + { + Directory.CreateDirectory(path); + AnsiConsole.Markup($"[red]Created folder for {user.Key}\n[/]"); + Log.Debug($"Created folder for {user.Key}"); + } + else + { + AnsiConsole.Markup($"[red]Folder for {user.Key} already created\n[/]"); + Log.Debug($"Folder for {user.Key} already created"); + } + + await dBHelper.CreateDB(path); + + var downloadContext = new DownloadContext(Auth, Config, GetCreatorFileNameFormatConfig(Config, user.Key), m_ApiHelper, dBHelper); + + if (Config.DownloadAvatarHeaderPhoto) + { + Entities.User? user_info = await m_ApiHelper.GetUserInfo($"/users/{user.Key}"); + if (user_info != null) + { + await downloadContext.DownloadHelper.DownloadAvatarHeader(user_info.avatar, user_info.header, path, user.Key); + } + } + + if (Config.DownloadPaidPosts) + { + paidPostCount = await DownloadPaidPosts(downloadContext, hasSelectedUsersKVP, user, paidPostCount, path); + } + + if (Config.DownloadPosts) + { + postCount = await DownloadFreePosts(downloadContext, hasSelectedUsersKVP, user, postCount, path); + } + + if (Config.DownloadArchived) + { + archivedCount = await DownloadArchived(downloadContext, hasSelectedUsersKVP, user, archivedCount, path); + } + + if (Config.DownloadStreams) + { + streamsCount = await DownloadStreams(downloadContext, hasSelectedUsersKVP, user, streamsCount, path); + } + + if (Config.DownloadStories) + { + storiesCount = await DownloadStories(downloadContext, user, storiesCount, path); + } + + if (Config.DownloadHighlights) + { + highlightsCount = await DownloadHighlights(downloadContext, user, highlightsCount, path); + } + + if (Config.DownloadMessages) + { + messagesCount = await DownloadMessages(downloadContext, hasSelectedUsersKVP, user, messagesCount, path); + } + + if (Config.DownloadPaidMessages) + { + paidMessagesCount = await DownloadPaidMessages(downloadContext, hasSelectedUsersKVP, user, paidMessagesCount, path); + } + + AnsiConsole.Markup("\n"); + AnsiConsole.Write(new BreakdownChart() + .FullSize() + .AddItem("Paid Posts", paidPostCount, Color.Red) + .AddItem("Posts", postCount, Color.Blue) + .AddItem("Archived", archivedCount, Color.Green) + .AddItem("Streams", streamsCount, Color.Purple) + .AddItem("Stories", storiesCount, Color.Yellow) + .AddItem("Highlights", highlightsCount, Color.Orange1) + .AddItem("Messages", messagesCount, Color.LightGreen) + .AddItem("Paid Messages", paidMessagesCount, Color.Aqua)); + AnsiConsole.Markup("\n"); + } + DateTime endTime = DateTime.Now; + TimeSpan totalTime = endTime - startTime; + AnsiConsole.Markup($"[green]Scrape Completed in {totalTime.TotalMinutes:0.00} minutes\n[/]"); + } + else if (hasSelectedUsersKVP.Key && hasSelectedUsersKVP.Value != null && hasSelectedUsersKVP.Value.ContainsKey("ConfigChanged")) + { + continue; + } + else + { + break; + } + } while (!Config.NonInteractiveMode); + } + + private static IFileNameFormatConfig GetCreatorFileNameFormatConfig(Entities.Config config, string userName) + { + FileNameFormatConfig combinedConfig = new FileNameFormatConfig(); + + Func func = (val1, val2) => + { + if (string.IsNullOrEmpty(val1)) + return val2; + else + return val1; + }; + + if(config.CreatorConfigs.ContainsKey(userName)) + { + CreatorConfig creatorConfig = config.CreatorConfigs[userName]; + if(creatorConfig != null) + { + combinedConfig.PaidMessageFileNameFormat = creatorConfig.PaidMessageFileNameFormat; + combinedConfig.PostFileNameFormat = creatorConfig.PostFileNameFormat; + combinedConfig.MessageFileNameFormat = creatorConfig.MessageFileNameFormat; + combinedConfig.PaidPostFileNameFormat = creatorConfig.PaidPostFileNameFormat; + } + } + + combinedConfig.PaidMessageFileNameFormat = func(combinedConfig.PaidMessageFileNameFormat, config.PaidMessageFileNameFormat); + combinedConfig.PostFileNameFormat = func(combinedConfig.PostFileNameFormat, config.PostFileNameFormat); + combinedConfig.MessageFileNameFormat = func(combinedConfig.MessageFileNameFormat, config.MessageFileNameFormat); + combinedConfig.PaidPostFileNameFormat = func(combinedConfig.PaidPostFileNameFormat, config.PaidPostFileNameFormat); + + Log.Debug($"PaidMessageFilenameFormat: {combinedConfig.PaidMessageFileNameFormat}"); + Log.Debug($"PostFileNameFormat: {combinedConfig.PostFileNameFormat}"); + Log.Debug($"MessageFileNameFormat: {combinedConfig.MessageFileNameFormat}"); + Log.Debug($"PaidPostFileNameFormatt: {combinedConfig.PaidPostFileNameFormat}"); + + return combinedConfig; + } + + private static async Task DownloadPaidMessages(IDownloadContext downloadContext, KeyValuePair> hasSelectedUsersKVP, KeyValuePair user, int paidMessagesCount, string path) + { + Log.Debug($"Calling DownloadPaidMessages - {user.Key}"); + + PaidMessageCollection paidMessageCollection = new PaidMessageCollection(); + + await AnsiConsole.Status() + .StartAsync("[red]Getting Paid Messages[/]", async ctx => + { + paidMessageCollection = await downloadContext.ApiHelper.GetPaidMessages("/posts/paid", path, user.Key, downloadContext.DownloadConfig!, ctx); + }); + int oldPaidMessagesCount = 0; + int newPaidMessagesCount = 0; + if (paidMessageCollection != null && paidMessageCollection.PaidMessages.Count > 0) + { + AnsiConsole.Markup($"[red]Found {paidMessageCollection.PaidMessages.Count} Media from {paidMessageCollection.PaidMessageObjects.Count} Paid Messages\n[/]"); + Log.Debug($"Found {paidMessageCollection.PaidMessages.Count} Media from {paidMessageCollection.PaidMessageObjects.Count} Paid Messages"); + paidMessagesCount = paidMessageCollection.PaidMessages.Count; + long totalSize = 0; + if (downloadContext.DownloadConfig.ShowScrapeSize) + { + totalSize = await downloadContext.DownloadHelper.CalculateTotalFileSize(paidMessageCollection.PaidMessages.Values.ToList()); + } + else + { + totalSize = paidMessagesCount; + } + await AnsiConsole.Progress() + .Columns(GetProgressColumns(downloadContext.DownloadConfig.ShowScrapeSize)) + .StartAsync(async ctx => + { + // Define tasks + var task = ctx.AddTask($"[red]Downloading {paidMessageCollection.PaidMessages.Count} Paid Messages[/]", autoStart: false); + Log.Debug($"Downloading {paidMessageCollection.PaidMessages.Count} Paid Messages"); + task.MaxValue = totalSize; + task.StartTask(); + foreach (KeyValuePair paidMessageKVP in paidMessageCollection.PaidMessages) + { + bool isNew; + if (paidMessageKVP.Value.Contains("cdn3.onlyfans.com/dash/files")) + { + string[] messageUrlParsed = paidMessageKVP.Value.Split(','); + string mpdURL = messageUrlParsed[0]; + string policy = messageUrlParsed[1]; + string signature = messageUrlParsed[2]; + string kvp = messageUrlParsed[3]; + string mediaId = messageUrlParsed[4]; + string messageId = messageUrlParsed[5]; + string? licenseURL = null; + string? pssh = await downloadContext.ApiHelper.GetDRMMPDPSSH(mpdURL, policy, signature, kvp); + if (pssh != null) + { + DateTime lastModified = await downloadContext.ApiHelper.GetDRMMPDLastModified(mpdURL, policy, signature, kvp); + Dictionary drmHeaders = downloadContext.ApiHelper.GetDynamicHeaders($"/api2/v2/users/media/{mediaId}/drm/message/{messageId}", "?type=widevine"); + string decryptionKey; + if (clientIdBlobMissing || devicePrivateKeyMissing) + { + decryptionKey = await downloadContext.ApiHelper.GetDecryptionKeyOFDL(drmHeaders, $"https://onlyfans.com/api2/v2/users/media/{mediaId}/drm/message/{messageId}?type=widevine", pssh); + } + else + { + decryptionKey = await downloadContext.ApiHelper.GetDecryptionKeyCDM(drmHeaders, $"https://onlyfans.com/api2/v2/users/media/{mediaId}/drm/message/{messageId}?type=widevine", pssh); + } + + + Medium? mediaInfo = paidMessageCollection.PaidMessageMedia.FirstOrDefault(m => m.id == paidMessageKVP.Key); + Purchased.List? messageInfo = paidMessageCollection.PaidMessageObjects.FirstOrDefault(p => p?.media?.Contains(mediaInfo) == true); + + isNew = await downloadContext.DownloadHelper.DownloadPurchasedMessageDRMVideo( + policy: policy, + signature: signature, + kvp: kvp, + url: mpdURL, + decryptionKey: decryptionKey, + folder: path, + lastModified: lastModified, + media_id: paidMessageKVP.Key, + api_type: "Messages", + task: task, + filenameFormat: downloadContext.FileNameFormatConfig.PaidMessageFileNameFormat ?? string.Empty, + messageInfo: messageInfo, + messageMedia: mediaInfo, + fromUser: messageInfo?.fromUser, + users: hasSelectedUsersKVP.Value); + + if (isNew) + { + newPaidMessagesCount++; + } + else + { + oldPaidMessagesCount++; + } + } + } + else + { + Medium? mediaInfo = paidMessageCollection.PaidMessageMedia.FirstOrDefault(m => m.id == paidMessageKVP.Key); + Purchased.List messageInfo = paidMessageCollection.PaidMessageObjects.FirstOrDefault(p => p?.media?.Contains(mediaInfo) == true); + + isNew = await downloadContext.DownloadHelper.DownloadPurchasedMedia( + url: paidMessageKVP.Value, + folder: path, + media_id: paidMessageKVP.Key, + api_type: "Messages", + task: task, + filenameFormat: downloadContext.FileNameFormatConfig.PaidMessageFileNameFormat ?? string.Empty, + messageInfo: messageInfo, + messageMedia: mediaInfo, + fromUser: messageInfo?.fromUser, + users: hasSelectedUsersKVP.Value); + if (isNew) + { + newPaidMessagesCount++; + } + else + { + oldPaidMessagesCount++; + } + } + } + task.StopTask(); + }); + AnsiConsole.Markup($"[red]Paid Messages Already Downloaded: {oldPaidMessagesCount} New Paid Messages Downloaded: {newPaidMessagesCount}[/]\n"); + } + else + { + AnsiConsole.Markup($"[red]Found 0 Paid Messages\n[/]"); + } + + return paidMessagesCount; + } + + private static async Task DownloadMessages(IDownloadContext downloadContext, KeyValuePair> hasSelectedUsersKVP, KeyValuePair user, int messagesCount, string path) + { + Log.Debug($"Calling DownloadMessages - {user.Key}"); + + MessageCollection messages = new MessageCollection(); + + await AnsiConsole.Status() + .StartAsync("[red]Getting Messages[/]", async ctx => + { + messages = await downloadContext.ApiHelper.GetMessages($"/chats/{user.Value}/messages", path, downloadContext.DownloadConfig!, ctx); + }); + int oldMessagesCount = 0; + int newMessagesCount = 0; + if (messages != null && messages.Messages.Count > 0) + { + AnsiConsole.Markup($"[red]Found {messages.Messages.Count} Media from {messages.MessageObjects.Count} Messages\n[/]"); + Log.Debug($"[red]Found {messages.Messages.Count} Media from {messages.MessageObjects.Count} Messages"); + messagesCount = messages.Messages.Count; + long totalSize = 0; + if (downloadContext.DownloadConfig.ShowScrapeSize) + { + totalSize = await downloadContext.DownloadHelper.CalculateTotalFileSize(messages.Messages.Values.ToList()); + } + else + { + totalSize = messagesCount; + } + await AnsiConsole.Progress() + .Columns(GetProgressColumns(downloadContext.DownloadConfig.ShowScrapeSize)) + .StartAsync(async ctx => + { + // Define tasks + var task = ctx.AddTask($"[red]Downloading {messages.Messages.Count} Messages[/]", autoStart: false); + Log.Debug($"Downloading {messages.Messages.Count} Messages"); + task.MaxValue = totalSize; + task.StartTask(); + foreach (KeyValuePair messageKVP in messages.Messages) + { + bool isNew; + if (messageKVP.Value.Contains("cdn3.onlyfans.com/dash/files")) + { + string[] messageUrlParsed = messageKVP.Value.Split(','); + string mpdURL = messageUrlParsed[0]; + string policy = messageUrlParsed[1]; + string signature = messageUrlParsed[2]; + string kvp = messageUrlParsed[3]; + string mediaId = messageUrlParsed[4]; + string messageId = messageUrlParsed[5]; + string? licenseURL = null; + string? pssh = await downloadContext.ApiHelper.GetDRMMPDPSSH(mpdURL, policy, signature, kvp); + if (pssh != null) + { + DateTime lastModified = await downloadContext.ApiHelper.GetDRMMPDLastModified(mpdURL, policy, signature, kvp); + Dictionary drmHeaders = downloadContext.ApiHelper.GetDynamicHeaders($"/api2/v2/users/media/{mediaId}/drm/message/{messageId}", "?type=widevine"); + string decryptionKey; + if (clientIdBlobMissing || devicePrivateKeyMissing) + { + decryptionKey = await downloadContext.ApiHelper.GetDecryptionKeyOFDL(drmHeaders, $"https://onlyfans.com/api2/v2/users/media/{mediaId}/drm/message/{messageId}?type=widevine", pssh); + } + else + { + decryptionKey = await downloadContext.ApiHelper.GetDecryptionKeyCDM(drmHeaders, $"https://onlyfans.com/api2/v2/users/media/{mediaId}/drm/message/{messageId}?type=widevine", pssh); + } + Messages.Medium? mediaInfo = messages.MessageMedia.FirstOrDefault(m => m.id == messageKVP.Key); + Messages.List? messageInfo = messages.MessageObjects.FirstOrDefault(p => p?.media?.Contains(mediaInfo) == true); + + isNew = await downloadContext.DownloadHelper.DownloadMessageDRMVideo( + policy: policy, + signature: signature, + kvp: kvp, + url: mpdURL, + decryptionKey: decryptionKey, + folder: path, + lastModified: lastModified, + media_id: messageKVP.Key, + api_type: "Messages", + task: task, + filenameFormat: downloadContext.FileNameFormatConfig.MessageFileNameFormat ?? string.Empty, + messageInfo: messageInfo, + messageMedia: mediaInfo, + fromUser: messageInfo?.fromUser, + users: hasSelectedUsersKVP.Value); + + + if (isNew) + { + newMessagesCount++; + } + else + { + oldMessagesCount++; + } + } + } + else + { + Messages.Medium? mediaInfo = messages.MessageMedia.FirstOrDefault(m => m.id == messageKVP.Key); + Messages.List? messageInfo = messages.MessageObjects.FirstOrDefault(p => p?.media?.Contains(mediaInfo) == true); + + isNew = await downloadContext.DownloadHelper.DownloadMessageMedia( + url: messageKVP.Value, + folder: path, + media_id: messageKVP.Key, + api_type: "Messages", + task: task, + filenameFormat: downloadContext.FileNameFormatConfig!.MessageFileNameFormat ?? string.Empty, + messageInfo: messageInfo, + messageMedia: mediaInfo, + fromUser: messageInfo?.fromUser, + users: hasSelectedUsersKVP.Value); + + if (isNew) + { + newMessagesCount++; + } + else + { + oldMessagesCount++; + } + } + } + task.StopTask(); + }); + AnsiConsole.Markup($"[red]Messages Already Downloaded: {oldMessagesCount} New Messages Downloaded: {newMessagesCount}[/]\n"); + } + else + { + AnsiConsole.Markup($"[red]Found 0 Messages\n[/]"); + } + + return messagesCount; + } + + private static async Task DownloadHighlights(IDownloadContext downloadContext, KeyValuePair user, int highlightsCount, string path) + { + Log.Debug($"Calling DownloadHighlights - {user.Key}"); + + AnsiConsole.Markup($"[red]Getting Highlights\n[/]"); + Dictionary highlights = await downloadContext.ApiHelper.GetMedia(MediaType.Highlights, $"/users/{user.Value}/stories/highlights", null, path, downloadContext.DownloadConfig!, paid_post_ids); + int oldHighlightsCount = 0; + int newHighlightsCount = 0; + if (highlights != null && highlights.Count > 0) + { + AnsiConsole.Markup($"[red]Found {highlights.Count} Highlights\n[/]"); + Log.Debug($"Found {highlights.Count} Highlights"); + highlightsCount = highlights.Count; + long totalSize = 0; + if (downloadContext.DownloadConfig.ShowScrapeSize) + { + totalSize = await downloadContext.DownloadHelper.CalculateTotalFileSize(highlights.Values.ToList()); + } + else + { + totalSize = highlightsCount; + } + await AnsiConsole.Progress() + .Columns(GetProgressColumns(downloadContext.DownloadConfig.ShowScrapeSize)) + .StartAsync(async ctx => + { + // Define tasks + var task = ctx.AddTask($"[red]Downloading {highlights.Count} Highlights[/]", autoStart: false); + Log.Debug($"Downloading {highlights.Count} Highlights"); + task.MaxValue = totalSize; + task.StartTask(); + foreach (KeyValuePair highlightKVP in highlights) + { + bool isNew = await downloadContext.DownloadHelper.DownloadStoryMedia(highlightKVP.Value, path, highlightKVP.Key, "Stories", task); + if (isNew) + { + newHighlightsCount++; + } + else + { + oldHighlightsCount++; + } + } + task.StopTask(); + }); + AnsiConsole.Markup($"[red]Highlights Already Downloaded: {oldHighlightsCount} New Highlights Downloaded: {newHighlightsCount}[/]\n"); + Log.Debug($"Highlights Already Downloaded: {oldHighlightsCount} New Highlights Downloaded: {newHighlightsCount}"); + } + else + { + AnsiConsole.Markup($"[red]Found 0 Highlights\n[/]"); + Log.Debug($"Found 0 Highlights"); + } + + return highlightsCount; + } + + private static async Task DownloadStories(IDownloadContext downloadContext, KeyValuePair user, int storiesCount, string path) + { + Log.Debug($"Calling DownloadStories - {user.Key}"); + + AnsiConsole.Markup($"[red]Getting Stories\n[/]"); + Dictionary stories = await downloadContext.ApiHelper.GetMedia(MediaType.Stories, $"/users/{user.Value}/stories", null, path, downloadContext.DownloadConfig!, paid_post_ids); + int oldStoriesCount = 0; + int newStoriesCount = 0; + if (stories != null && stories.Count > 0) + { + AnsiConsole.Markup($"[red]Found {stories.Count} Stories\n[/]"); + Log.Debug($"Found {stories.Count} Stories"); + storiesCount = stories.Count; + long totalSize = 0; + if (downloadContext.DownloadConfig.ShowScrapeSize) + { + totalSize = await downloadContext.DownloadHelper.CalculateTotalFileSize(stories.Values.ToList()); + } + else + { + totalSize = storiesCount; + } + await AnsiConsole.Progress() + .Columns(GetProgressColumns(downloadContext.DownloadConfig.ShowScrapeSize)) + .StartAsync(async ctx => + { + // Define tasks + var task = ctx.AddTask($"[red]Downloading {stories.Count} Stories[/]", autoStart: false); + Log.Debug($"Downloading {stories.Count} Stories"); + task.MaxValue = totalSize; + task.StartTask(); + foreach (KeyValuePair storyKVP in stories) + { + bool isNew = await downloadContext.DownloadHelper.DownloadStoryMedia(storyKVP.Value, path, storyKVP.Key, "Stories", task); + if (isNew) + { + newStoriesCount++; + } + else + { + oldStoriesCount++; + } + } + task.StopTask(); + }); + AnsiConsole.Markup($"[red]Stories Already Downloaded: {oldStoriesCount} New Stories Downloaded: {newStoriesCount}[/]\n"); + Log.Debug($"Stories Already Downloaded: {oldStoriesCount} New Stories Downloaded: {newStoriesCount}"); + } + else + { + AnsiConsole.Markup($"[red]Found 0 Stories\n[/]"); + Log.Debug($"Found 0 Stories"); + } + + return storiesCount; + } + + private static async Task DownloadArchived(IDownloadContext downloadContext, KeyValuePair> hasSelectedUsersKVP, KeyValuePair user, int archivedCount, string path) + { + Log.Debug($"Calling DownloadArchived - {user.Key}"); + + ArchivedCollection archived = new ArchivedCollection(); + + await AnsiConsole.Status() + .StartAsync("[red]Getting Archived Posts[/]", async ctx => + { + archived = await downloadContext.ApiHelper.GetArchived($"/users/{user.Value}/posts", path, downloadContext.DownloadConfig!, ctx); + }); + + int oldArchivedCount = 0; + int newArchivedCount = 0; + if (archived != null && archived.ArchivedPosts.Count > 0) + { + AnsiConsole.Markup($"[red]Found {archived.ArchivedPosts.Count} Media from {archived.ArchivedPostObjects.Count} Archived Posts\n[/]"); + Log.Debug($"Found {archived.ArchivedPosts.Count} Media from {archived.ArchivedPostObjects.Count} Archived Posts"); + archivedCount = archived.ArchivedPosts.Count; + long totalSize = 0; + if (downloadContext.DownloadConfig.ShowScrapeSize) + { + totalSize = await downloadContext.DownloadHelper.CalculateTotalFileSize(archived.ArchivedPosts.Values.ToList()); + } + else + { + totalSize = archivedCount; + } + await AnsiConsole.Progress() + .Columns(GetProgressColumns(downloadContext.DownloadConfig.ShowScrapeSize)) + .StartAsync(async ctx => + { + // Define tasks + var task = ctx.AddTask($"[red]Downloading {archived.ArchivedPosts.Count} Archived Posts[/]", autoStart: false); + Log.Debug($"Downloading {archived.ArchivedPosts.Count} Archived Posts"); + task.MaxValue = totalSize; + task.StartTask(); + foreach (KeyValuePair archivedKVP in archived.ArchivedPosts) + { + bool isNew; + if (archivedKVP.Value.Contains("cdn3.onlyfans.com/dash/files")) + { + string[] messageUrlParsed = archivedKVP.Value.Split(','); + string mpdURL = messageUrlParsed[0]; + string policy = messageUrlParsed[1]; + string signature = messageUrlParsed[2]; + string kvp = messageUrlParsed[3]; + string mediaId = messageUrlParsed[4]; + string postId = messageUrlParsed[5]; + string? licenseURL = null; + string? pssh = await downloadContext.ApiHelper.GetDRMMPDPSSH(mpdURL, policy, signature, kvp); + if (pssh != null) + { + DateTime lastModified = await downloadContext.ApiHelper.GetDRMMPDLastModified(mpdURL, policy, signature, kvp); + Dictionary drmHeaders = downloadContext.ApiHelper.GetDynamicHeaders($"/api2/v2/users/media/{mediaId}/drm/post/{postId}", "?type=widevine"); + string decryptionKey; + if (clientIdBlobMissing || devicePrivateKeyMissing) + { + decryptionKey = await downloadContext.ApiHelper.GetDecryptionKeyOFDL(drmHeaders, $"https://onlyfans.com/api2/v2/users/media/{mediaId}/drm/post/{postId}?type=widevine", pssh); + } + else + { + decryptionKey = await downloadContext.ApiHelper.GetDecryptionKeyCDM(drmHeaders, $"https://onlyfans.com/api2/v2/users/media/{mediaId}/drm/post/{postId}?type=widevine", pssh); + } + Archived.Medium? mediaInfo = archived.ArchivedPostMedia.FirstOrDefault(m => m.id == archivedKVP.Key); + Archived.List? postInfo = archived.ArchivedPostObjects.FirstOrDefault(p => p?.media?.Contains(mediaInfo) == true); + + isNew = await downloadContext.DownloadHelper.DownloadArchivedPostDRMVideo( + policy: policy, + signature: signature, + kvp: kvp, + url: mpdURL, + decryptionKey: decryptionKey, + folder: path, + lastModified: lastModified, + media_id: archivedKVP.Key, + api_type: "Posts", + task: task, + filenameFormat: downloadContext.FileNameFormatConfig.PostFileNameFormat ?? string.Empty, + postInfo: postInfo, + postMedia: mediaInfo, + author: postInfo?.author, + users: hasSelectedUsersKVP.Value); + + if (isNew) + { + newArchivedCount++; + } + else + { + oldArchivedCount++; + } + } + } + else + { + Archived.Medium? mediaInfo = archived.ArchivedPostMedia.FirstOrDefault(m => m.id == archivedKVP.Key); + Archived.List? postInfo = archived.ArchivedPostObjects.FirstOrDefault(p => p?.media?.Contains(mediaInfo) == true); + + isNew = await downloadContext.DownloadHelper.DownloadArchivedMedia( + url: archivedKVP.Value, + folder: path, + media_id: archivedKVP.Key, + api_type: "Posts", + task: task, + filenameFormat: downloadContext.FileNameFormatConfig.PostFileNameFormat ?? string.Empty, + messageInfo: postInfo, + messageMedia: mediaInfo, + author: postInfo?.author, + users: hasSelectedUsersKVP.Value); + + if (isNew) + { + newArchivedCount++; + } + else + { + oldArchivedCount++; + } + } + } + task.StopTask(); + }); + AnsiConsole.Markup($"[red]Archived Posts Already Downloaded: {oldArchivedCount} New Archived Posts Downloaded: {newArchivedCount}[/]\n"); + } + else + { + AnsiConsole.Markup($"[red]Found 0 Archived Posts\n[/]"); + } + + return archivedCount; + } + + private static async Task DownloadFreePosts(IDownloadContext downloadContext, KeyValuePair> hasSelectedUsersKVP, KeyValuePair user, int postCount, string path) + { + Log.Debug($"Calling DownloadFreePosts - {user.Key}"); + + PostCollection posts = new PostCollection(); + + await AnsiConsole.Status() + .StartAsync("[red]Getting Posts (this may take a long time, depending on the number of Posts the creator has)[/]", async ctx => + { + posts = await downloadContext.ApiHelper.GetPosts($"/users/{user.Value}/posts", path, downloadContext.DownloadConfig!, paid_post_ids, ctx); + }); + + int oldPostCount = 0; + int newPostCount = 0; + if (posts == null || posts.Posts.Count <= 0) + { + AnsiConsole.Markup($"[red]Found 0 Posts\n[/]"); + Log.Debug($"Found 0 Posts"); + return 0; + } + + AnsiConsole.Markup($"[red]Found {posts.Posts.Count} Media from {posts.PostObjects.Count} Posts\n[/]"); + Log.Debug($"Found {posts.Posts.Count} Media from {posts.PostObjects.Count} Posts"); + postCount = posts.Posts.Count; + long totalSize = 0; + if (downloadContext.DownloadConfig.ShowScrapeSize) + { + totalSize = await downloadContext.DownloadHelper.CalculateTotalFileSize(posts.Posts.Values.ToList()); + } + else + { + totalSize = postCount; + } + await AnsiConsole.Progress() + .Columns(GetProgressColumns(downloadContext.DownloadConfig.ShowScrapeSize)) + .StartAsync(async ctx => + { + var task = ctx.AddTask($"[red]Downloading {posts.Posts.Count} Posts[/]", autoStart: false); + Log.Debug($"Downloading {posts.Posts.Count} Posts"); + task.MaxValue = totalSize; + task.StartTask(); + foreach (KeyValuePair postKVP in posts.Posts) + { + bool isNew; + if (postKVP.Value.Contains("cdn3.onlyfans.com/dash/files")) + { + string[] messageUrlParsed = postKVP.Value.Split(','); + string mpdURL = messageUrlParsed[0]; + string policy = messageUrlParsed[1]; + string signature = messageUrlParsed[2]; + string kvp = messageUrlParsed[3]; + string mediaId = messageUrlParsed[4]; + string postId = messageUrlParsed[5]; + string? licenseURL = null; + string? pssh = await downloadContext.ApiHelper.GetDRMMPDPSSH(mpdURL, policy, signature, kvp); + if (pssh == null) + { + continue; + } + + DateTime lastModified = await downloadContext.ApiHelper.GetDRMMPDLastModified(mpdURL, policy, signature, kvp); + Dictionary drmHeaders = downloadContext.ApiHelper.GetDynamicHeaders($"/api2/v2/users/media/{mediaId}/drm/post/{postId}", "?type=widevine"); + string decryptionKey; + if (clientIdBlobMissing || devicePrivateKeyMissing) + { + decryptionKey = await downloadContext.ApiHelper.GetDecryptionKeyOFDL(drmHeaders, $"https://onlyfans.com/api2/v2/users/media/{mediaId}/drm/post/{postId}?type=widevine", pssh); + } + else + { + decryptionKey = await downloadContext.ApiHelper.GetDecryptionKeyCDM(drmHeaders, $"https://onlyfans.com/api2/v2/users/media/{mediaId}/drm/post/{postId}?type=widevine", pssh); + } + Post.Medium mediaInfo = posts.PostMedia.FirstOrDefault(m => m.id == postKVP.Key); + Post.List postInfo = posts.PostObjects.FirstOrDefault(p => p?.media?.Contains(mediaInfo) == true); + + isNew = await downloadContext.DownloadHelper.DownloadPostDRMVideo( + policy: policy, + signature: signature, + kvp: kvp, + url: mpdURL, + decryptionKey: decryptionKey, + folder: path, + lastModified: lastModified, + media_id: postKVP.Key, + api_type: "Posts", + task: task, + filenameFormat: downloadContext.FileNameFormatConfig.PostFileNameFormat ?? string.Empty, + postInfo: postInfo, + postMedia: mediaInfo, + author: postInfo?.author, + users: hasSelectedUsersKVP.Value); + if (isNew) + { + newPostCount++; + } + else + { + oldPostCount++; + } + } + else + { + try + { + Post.Medium? mediaInfo = posts.PostMedia.FirstOrDefault(m => (m?.id == postKVP.Key) == true); + Post.List? postInfo = posts.PostObjects.FirstOrDefault(p => p?.media?.Contains(mediaInfo) == true); + + isNew = await downloadContext.DownloadHelper.DownloadPostMedia( + url: postKVP.Value, + folder: path, + media_id: postKVP.Key, + api_type: "Posts", + task: task, + filenameFormat: downloadContext.FileNameFormatConfig.PostFileNameFormat ?? string.Empty, + postInfo: postInfo, + postMedia: mediaInfo, + author: postInfo?.author, + users: hasSelectedUsersKVP.Value); + if (isNew) + { + newPostCount++; + } + else + { + oldPostCount++; + } + } + catch + { + Console.WriteLine("Media was null"); + } + } + } + task.StopTask(); + }); + AnsiConsole.Markup($"[red]Posts Already Downloaded: {oldPostCount} New Posts Downloaded: {newPostCount}[/]\n"); + Log.Debug("Posts Already Downloaded: {oldPostCount} New Posts Downloaded: {newPostCount}"); + + return postCount; + } + + private static async Task DownloadPaidPosts(IDownloadContext downloadContext, KeyValuePair> hasSelectedUsersKVP, KeyValuePair user, int paidPostCount, string path) + { + Log.Debug($"Calling DownloadPaidPosts - {user.Key}"); + + PaidPostCollection purchasedPosts = new PaidPostCollection(); + + await AnsiConsole.Status() + .StartAsync("[red]Getting Paid Posts[/]", async ctx => + { + purchasedPosts = await downloadContext.ApiHelper.GetPaidPosts("/posts/paid", path, user.Key, downloadContext.DownloadConfig!, paid_post_ids, ctx); + }); + + int oldPaidPostCount = 0; + int newPaidPostCount = 0; + if (purchasedPosts == null || purchasedPosts.PaidPosts.Count <= 0) + { + AnsiConsole.Markup($"[red]Found 0 Paid Posts\n[/]"); + Log.Debug("Found 0 Paid Posts"); + return 0; + } + + AnsiConsole.Markup($"[red]Found {purchasedPosts.PaidPosts.Count} Media from {purchasedPosts.PaidPostObjects.Count} Paid Posts\n[/]"); + Log.Debug($"Found {purchasedPosts.PaidPosts.Count} Media from {purchasedPosts.PaidPostObjects.Count} Paid Posts"); + paidPostCount = purchasedPosts.PaidPosts.Count; + long totalSize = 0; + if (downloadContext.DownloadConfig.ShowScrapeSize) + { + totalSize = await downloadContext.DownloadHelper.CalculateTotalFileSize(purchasedPosts.PaidPosts.Values.ToList()); + } + else + { + totalSize = paidPostCount; + } + await AnsiConsole.Progress() + .Columns(GetProgressColumns(downloadContext.DownloadConfig.ShowScrapeSize)) + .StartAsync(async ctx => + { + // Define tasks + var task = ctx.AddTask($"[red]Downloading {purchasedPosts.PaidPosts.Count} Paid Posts[/]", autoStart: false); + Log.Debug($"Downloading {purchasedPosts.PaidPosts.Count} Paid Posts"); + task.MaxValue = totalSize; + task.StartTask(); + foreach (KeyValuePair purchasedPostKVP in purchasedPosts.PaidPosts) + { + bool isNew; + if (purchasedPostKVP.Value.Contains("cdn3.onlyfans.com/dash/files")) + { + string[] messageUrlParsed = purchasedPostKVP.Value.Split(','); + string mpdURL = messageUrlParsed[0]; + string policy = messageUrlParsed[1]; + string signature = messageUrlParsed[2]; + string kvp = messageUrlParsed[3]; + string mediaId = messageUrlParsed[4]; + string postId = messageUrlParsed[5]; + string? licenseURL = null; + string? pssh = await downloadContext.ApiHelper.GetDRMMPDPSSH(mpdURL, policy, signature, kvp); + if (pssh == null) + { + continue; + } + + DateTime lastModified = await downloadContext.ApiHelper.GetDRMMPDLastModified(mpdURL, policy, signature, kvp); + Dictionary drmHeaders = downloadContext.ApiHelper.GetDynamicHeaders($"/api2/v2/users/media/{mediaId}/drm/post/{postId}", "?type=widevine"); + string decryptionKey; + if (clientIdBlobMissing || devicePrivateKeyMissing) + { + decryptionKey = await downloadContext.ApiHelper.GetDecryptionKeyOFDL(drmHeaders, $"https://onlyfans.com/api2/v2/users/media/{mediaId}/drm/post/{postId}?type=widevine", pssh); + } + else + { + decryptionKey = await downloadContext.ApiHelper.GetDecryptionKeyCDM(drmHeaders, $"https://onlyfans.com/api2/v2/users/media/{mediaId}/drm/post/{postId}?type=widevine", pssh); + } + Medium? mediaInfo = purchasedPosts.PaidPostMedia.FirstOrDefault(m => m.id == purchasedPostKVP.Key); + Purchased.List? postInfo = purchasedPosts.PaidPostObjects.FirstOrDefault(p => p?.media?.Contains(mediaInfo) == true); + + isNew = await downloadContext.DownloadHelper.DownloadPurchasedPostDRMVideo( + policy: policy, + signature: signature, + kvp: kvp, + url: mpdURL, + decryptionKey: decryptionKey, + folder: path, + lastModified: lastModified, + media_id: purchasedPostKVP.Key, + api_type: "Posts", + task: task, + filenameFormat: downloadContext.FileNameFormatConfig.PaidPostFileNameFormat ?? string.Empty, + postInfo: postInfo, + postMedia: mediaInfo, + fromUser: postInfo?.fromUser, + users: hasSelectedUsersKVP.Value); + if (isNew) + { + newPaidPostCount++; + } + else + { + oldPaidPostCount++; + } + } + else + { + Medium mediaInfo = purchasedPosts.PaidPostMedia.FirstOrDefault(m => m.id == purchasedPostKVP.Key); + Purchased.List postInfo = purchasedPosts.PaidPostObjects.FirstOrDefault(p => p?.media?.Contains(mediaInfo) == true); + + isNew = await downloadContext.DownloadHelper.DownloadPurchasedPostMedia( + url: purchasedPostKVP.Value, + folder: path, + media_id: purchasedPostKVP.Key, + api_type: "Posts", + task: task, + filenameFormat: downloadContext.FileNameFormatConfig.PaidPostFileNameFormat ?? string.Empty, + messageInfo: postInfo, + messageMedia: mediaInfo, + fromUser: postInfo?.fromUser, + users: hasSelectedUsersKVP.Value); + if (isNew) + { + newPaidPostCount++; + } + else + { + oldPaidPostCount++; + } + } + } + task.StopTask(); + }); + AnsiConsole.Markup($"[red]Paid Posts Already Downloaded: {oldPaidPostCount} New Paid Posts Downloaded: {newPaidPostCount}[/]\n"); + Log.Debug($"Paid Posts Already Downloaded: {oldPaidPostCount} New Paid Posts Downloaded: {newPaidPostCount}"); + return paidPostCount; + } + + private static async Task DownloadPaidPostsPurchasedTab(IDownloadContext downloadContext, PaidPostCollection purchasedPosts, KeyValuePair user, int paidPostCount, string path, Dictionary users) + { + int oldPaidPostCount = 0; + int newPaidPostCount = 0; + if (purchasedPosts == null || purchasedPosts.PaidPosts.Count <= 0) + { + AnsiConsole.Markup($"[red]Found 0 Paid Posts\n[/]"); + Log.Debug("Found 0 Paid Posts"); + return 0; + } + + AnsiConsole.Markup($"[red]Found {purchasedPosts.PaidPosts.Count} Media from {purchasedPosts.PaidPostObjects.Count} Paid Posts\n[/]"); + Log.Debug($"Found {purchasedPosts.PaidPosts.Count} Media from {purchasedPosts.PaidPostObjects.Count} Paid Posts"); + + paidPostCount = purchasedPosts.PaidPosts.Count; + long totalSize = 0; + if (downloadContext.DownloadConfig.ShowScrapeSize) + { + totalSize = await downloadContext.DownloadHelper.CalculateTotalFileSize(purchasedPosts.PaidPosts.Values.ToList()); + } + else + { + totalSize = paidPostCount; + } + await AnsiConsole.Progress() + .Columns(GetProgressColumns(downloadContext.DownloadConfig.ShowScrapeSize)) + .StartAsync(async ctx => + { + // Define tasks + var task = ctx.AddTask($"[red]Downloading {purchasedPosts.PaidPosts.Count} Paid Posts[/]", autoStart: false); + Log.Debug($"Downloading {purchasedPosts.PaidPosts.Count} Paid Posts"); + task.MaxValue = totalSize; + task.StartTask(); + foreach (KeyValuePair purchasedPostKVP in purchasedPosts.PaidPosts) + { + bool isNew; + if (purchasedPostKVP.Value.Contains("cdn3.onlyfans.com/dash/files")) + { + string[] messageUrlParsed = purchasedPostKVP.Value.Split(','); + string mpdURL = messageUrlParsed[0]; + string policy = messageUrlParsed[1]; + string signature = messageUrlParsed[2]; + string kvp = messageUrlParsed[3]; + string mediaId = messageUrlParsed[4]; + string postId = messageUrlParsed[5]; + string? licenseURL = null; + string? pssh = await downloadContext.ApiHelper.GetDRMMPDPSSH(mpdURL, policy, signature, kvp); + if (pssh == null) + { + continue; + } + + DateTime lastModified = await downloadContext.ApiHelper.GetDRMMPDLastModified(mpdURL, policy, signature, kvp); + Dictionary drmHeaders = downloadContext.ApiHelper.GetDynamicHeaders($"/api2/v2/users/media/{mediaId}/drm/post/{postId}", "?type=widevine"); + string decryptionKey; + if (clientIdBlobMissing || devicePrivateKeyMissing) + { + decryptionKey = await downloadContext.ApiHelper.GetDecryptionKeyOFDL(drmHeaders, $"https://onlyfans.com/api2/v2/users/media/{mediaId}/drm/post/{postId}?type=widevine", pssh); + } + else + { + decryptionKey = await downloadContext.ApiHelper.GetDecryptionKeyCDM(drmHeaders, $"https://onlyfans.com/api2/v2/users/media/{mediaId}/drm/post/{postId}?type=widevine", pssh); + } + Medium? mediaInfo = purchasedPosts?.PaidPostMedia?.FirstOrDefault(m => m.id == purchasedPostKVP.Key); + Purchased.List? postInfo = mediaInfo != null ? purchasedPosts?.PaidPostObjects?.FirstOrDefault(p => p?.media?.Contains(mediaInfo) == true) : null; + + isNew = await downloadContext.DownloadHelper.DownloadPurchasedPostDRMVideo( + policy: policy, + signature: signature, + kvp: kvp, + url: mpdURL, + decryptionKey: decryptionKey, + folder: path, + lastModified: lastModified, + media_id: purchasedPostKVP.Key, + api_type: "Posts", + task: task, + filenameFormat: downloadContext.FileNameFormatConfig.PaidPostFileNameFormat ?? string.Empty, + postInfo: postInfo, + postMedia: mediaInfo, + fromUser: postInfo?.fromUser, + users: users); + if (isNew) + { + newPaidPostCount++; + } + else + { + oldPaidPostCount++; + } + } + else + { + Medium? mediaInfo = purchasedPosts?.PaidPostMedia?.FirstOrDefault(m => m.id == purchasedPostKVP.Key); + Purchased.List? postInfo = mediaInfo != null ? purchasedPosts?.PaidPostObjects?.FirstOrDefault(p => p?.media?.Contains(mediaInfo) == true) : null; + + isNew = await downloadContext.DownloadHelper.DownloadPurchasedPostMedia( + url: purchasedPostKVP.Value, + folder: path, + media_id: purchasedPostKVP.Key, + api_type: "Posts", + task: task, + filenameFormat: downloadContext.FileNameFormatConfig.PaidPostFileNameFormat ?? string.Empty, + messageInfo: postInfo, + messageMedia: mediaInfo, + fromUser: postInfo?.fromUser, + users: users); + if (isNew) + { + newPaidPostCount++; + } + else + { + oldPaidPostCount++; + } + } + } + task.StopTask(); + }); + AnsiConsole.Markup($"[red]Paid Posts Already Downloaded: {oldPaidPostCount} New Paid Posts Downloaded: {newPaidPostCount}[/]\n"); + Log.Debug($"Paid Posts Already Downloaded: {oldPaidPostCount} New Paid Posts Downloaded: {newPaidPostCount}"); + return paidPostCount; + } + + private static async Task DownloadPaidMessagesPurchasedTab(IDownloadContext downloadContext, PaidMessageCollection paidMessageCollection, KeyValuePair user, int paidMessagesCount, string path, Dictionary users) + { + int oldPaidMessagesCount = 0; + int newPaidMessagesCount = 0; + if (paidMessageCollection != null && paidMessageCollection.PaidMessages.Count > 0) + { + AnsiConsole.Markup($"[red]Found {paidMessageCollection.PaidMessages.Count} Media from {paidMessageCollection.PaidMessageObjects.Count} Paid Messages\n[/]"); + Log.Debug($"Found {paidMessageCollection.PaidMessages.Count} Media from {paidMessageCollection.PaidMessageObjects.Count} Paid Messages"); + paidMessagesCount = paidMessageCollection.PaidMessages.Count; + long totalSize = 0; + if (downloadContext.DownloadConfig.ShowScrapeSize) + { + totalSize = await downloadContext.DownloadHelper.CalculateTotalFileSize(paidMessageCollection.PaidMessages.Values.ToList()); + } + else + { + totalSize = paidMessagesCount; + } + await AnsiConsole.Progress() + .Columns(GetProgressColumns(downloadContext.DownloadConfig.ShowScrapeSize)) + .StartAsync(async ctx => + { + // Define tasks + var task = ctx.AddTask($"[red]Downloading {paidMessageCollection.PaidMessages.Count} Paid Messages[/]", autoStart: false); + Log.Debug($"Downloading {paidMessageCollection.PaidMessages.Count} Paid Messages"); + task.MaxValue = totalSize; + task.StartTask(); + foreach (KeyValuePair paidMessageKVP in paidMessageCollection.PaidMessages) + { + bool isNew; + if (paidMessageKVP.Value.Contains("cdn3.onlyfans.com/dash/files")) + { + string[] messageUrlParsed = paidMessageKVP.Value.Split(','); + string mpdURL = messageUrlParsed[0]; + string policy = messageUrlParsed[1]; + string signature = messageUrlParsed[2]; + string kvp = messageUrlParsed[3]; + string mediaId = messageUrlParsed[4]; + string messageId = messageUrlParsed[5]; + string? licenseURL = null; + string? pssh = await downloadContext.ApiHelper.GetDRMMPDPSSH(mpdURL, policy, signature, kvp); + if (pssh != null) + { + DateTime lastModified = await downloadContext.ApiHelper.GetDRMMPDLastModified(mpdURL, policy, signature, kvp); + Dictionary drmHeaders = downloadContext.ApiHelper.GetDynamicHeaders($"/api2/v2/users/media/{mediaId}/drm/message/{messageId}", "?type=widevine"); + string decryptionKey; + if (clientIdBlobMissing || devicePrivateKeyMissing) + { + decryptionKey = await downloadContext.ApiHelper.GetDecryptionKeyOFDL(drmHeaders, $"https://onlyfans.com/api2/v2/users/media/{mediaId}/drm/message/{messageId}?type=widevine", pssh); + } + else + { + decryptionKey = await downloadContext.ApiHelper.GetDecryptionKeyCDM(drmHeaders, $"https://onlyfans.com/api2/v2/users/media/{mediaId}/drm/message/{messageId}?type=widevine", pssh); + } + + Medium? mediaInfo = paidMessageCollection.PaidMessageMedia.FirstOrDefault(m => m.id == paidMessageKVP.Key); + Purchased.List? messageInfo = paidMessageCollection.PaidMessageObjects.FirstOrDefault(p => p?.media?.Contains(mediaInfo) == true); + + isNew = await downloadContext.DownloadHelper.DownloadPurchasedMessageDRMVideo( + policy: policy, + signature: signature, + kvp: kvp, + url: mpdURL, + decryptionKey: decryptionKey, + folder: path, + lastModified: lastModified, + media_id: paidMessageKVP.Key, + api_type: "Messages", + task: task, + filenameFormat: downloadContext.FileNameFormatConfig.PaidMessageFileNameFormat ?? string.Empty, + messageInfo: messageInfo, + messageMedia: mediaInfo, + fromUser: messageInfo?.fromUser, + users: users); + + if (isNew) + { + newPaidMessagesCount++; + } + else + { + oldPaidMessagesCount++; + } + } + } + else + { + Medium? mediaInfo = paidMessageCollection.PaidMessageMedia.FirstOrDefault(m => m.id == paidMessageKVP.Key); + Purchased.List messageInfo = paidMessageCollection.PaidMessageObjects.FirstOrDefault(p => p?.media?.Contains(mediaInfo) == true); + + isNew = await downloadContext.DownloadHelper.DownloadPurchasedMedia( + url: paidMessageKVP.Value, + folder: path, + media_id: paidMessageKVP.Key, + api_type: "Messages", + task: task, + filenameFormat: downloadContext.FileNameFormatConfig.PaidMessageFileNameFormat ?? string.Empty, + messageInfo: messageInfo, + messageMedia: mediaInfo, + fromUser: messageInfo?.fromUser, + users: users); + if (isNew) + { + newPaidMessagesCount++; + } + else + { + oldPaidMessagesCount++; + } + } + } + task.StopTask(); + }); + AnsiConsole.Markup($"[red]Paid Messages Already Downloaded: {oldPaidMessagesCount} New Paid Messages Downloaded: {newPaidMessagesCount}[/]\n"); + Log.Debug($"[red]Paid Messages Already Downloaded: {oldPaidMessagesCount} New Paid Messages Downloaded: {newPaidMessagesCount}"); + } + else + { + AnsiConsole.Markup($"[red]Found 0 Paid Messages\n[/]"); + Log.Debug($"Found 0 Paid Messages"); + } + + return paidMessagesCount; + } + + private static async Task DownloadStreams(IDownloadContext downloadContext, KeyValuePair> hasSelectedUsersKVP, KeyValuePair user, int streamsCount, string path) + { + Log.Debug($"Calling DownloadStreams - {user.Key}"); + + StreamsCollection streams = new StreamsCollection(); + + await AnsiConsole.Status() + .StartAsync("[red]Getting Streams[/]", async ctx => + { + streams = await downloadContext.ApiHelper.GetStreams($"/users/{user.Value}/posts/streams", path, downloadContext.DownloadConfig!, paid_post_ids, ctx); + }); + + int oldStreamsCount = 0; + int newStreamsCount = 0; + if (streams == null || streams.Streams.Count <= 0) + { + AnsiConsole.Markup($"[red]Found 0 Streams\n[/]"); + Log.Debug($"Found 0 Streams"); + return 0; + } + + AnsiConsole.Markup($"[red]Found {streams.Streams.Count} Media from {streams.StreamObjects.Count} Streams\n[/]"); + Log.Debug($"Found {streams.Streams.Count} Media from {streams.StreamObjects.Count} Streams"); + streamsCount = streams.Streams.Count; + long totalSize = 0; + if (downloadContext.DownloadConfig.ShowScrapeSize) + { + totalSize = await downloadContext.DownloadHelper.CalculateTotalFileSize(streams.Streams.Values.ToList()); + } + else + { + totalSize = streamsCount; + } + await AnsiConsole.Progress() + .Columns(GetProgressColumns(downloadContext.DownloadConfig.ShowScrapeSize)) + .StartAsync(async ctx => + { + var task = ctx.AddTask($"[red]Downloading {streams.Streams.Count} Streams[/]", autoStart: false); + Log.Debug($"Downloading {streams.Streams.Count} Streams"); + task.MaxValue = totalSize; + task.StartTask(); + foreach (KeyValuePair streamKVP in streams.Streams) + { + bool isNew; + if (streamKVP.Value.Contains("cdn3.onlyfans.com/dash/files")) + { + string[] messageUrlParsed = streamKVP.Value.Split(','); + string mpdURL = messageUrlParsed[0]; + string policy = messageUrlParsed[1]; + string signature = messageUrlParsed[2]; + string kvp = messageUrlParsed[3]; + string mediaId = messageUrlParsed[4]; + string postId = messageUrlParsed[5]; + string? licenseURL = null; + string? pssh = await downloadContext.ApiHelper.GetDRMMPDPSSH(mpdURL, policy, signature, kvp); + if (pssh == null) + { + continue; + } + + DateTime lastModified = await downloadContext.ApiHelper.GetDRMMPDLastModified(mpdURL, policy, signature, kvp); + Dictionary drmHeaders = downloadContext.ApiHelper.GetDynamicHeaders($"/api2/v2/users/media/{mediaId}/drm/post/{postId}", "?type=widevine"); + string decryptionKey; + if (clientIdBlobMissing || devicePrivateKeyMissing) + { + decryptionKey = await downloadContext.ApiHelper.GetDecryptionKeyOFDL(drmHeaders, $"https://onlyfans.com/api2/v2/users/media/{mediaId}/drm/post/{postId}?type=widevine", pssh); + } + else + { + decryptionKey = await downloadContext.ApiHelper.GetDecryptionKeyCDM(drmHeaders, $"https://onlyfans.com/api2/v2/users/media/{mediaId}/drm/post/{postId}?type=widevine", pssh); + } + Streams.Medium mediaInfo = streams.StreamMedia.FirstOrDefault(m => m.id == streamKVP.Key); + Streams.List streamInfo = streams.StreamObjects.FirstOrDefault(p => p?.media?.Contains(mediaInfo) == true); + + isNew = await downloadContext.DownloadHelper.DownloadStreamsDRMVideo( + policy: policy, + signature: signature, + kvp: kvp, + url: mpdURL, + decryptionKey: decryptionKey, + folder: path, + lastModified: lastModified, + media_id: streamKVP.Key, + api_type: "Posts", + task: task, + filenameFormat: downloadContext.FileNameFormatConfig.PostFileNameFormat ?? string.Empty, + streamInfo: streamInfo, + streamMedia: mediaInfo, + author: streamInfo?.author, + users: hasSelectedUsersKVP.Value); + if (isNew) + { + newStreamsCount++; + } + else + { + oldStreamsCount++; + } + } + else + { + try + { + Streams.Medium? mediaInfo = streams.StreamMedia.FirstOrDefault(m => (m?.id == streamKVP.Key) == true); + Streams.List? streamInfo = streams.StreamObjects.FirstOrDefault(p => p?.media?.Contains(mediaInfo) == true); + + isNew = await downloadContext.DownloadHelper.DownloadStreamMedia( + url: streamKVP.Value, + folder: path, + media_id: streamKVP.Key, + api_type: "Posts", + task: task, + filenameFormat: downloadContext.FileNameFormatConfig.PostFileNameFormat ?? string.Empty, + streamInfo: streamInfo, + streamMedia: mediaInfo, + author: streamInfo?.author, + users: hasSelectedUsersKVP.Value); + if (isNew) + { + newStreamsCount++; + } + else + { + oldStreamsCount++; + } + } + catch + { + Console.WriteLine("Media was null"); + } + } + } + task.StopTask(); + }); + AnsiConsole.Markup($"[red]Streams Already Downloaded: {oldStreamsCount} New Streams Downloaded: {newStreamsCount}[/]\n"); + Log.Debug($"Streams Already Downloaded: {oldStreamsCount} New Streams Downloaded: {newStreamsCount}"); + return streamsCount; + } + + private static async Task DownloadPaidMessage(IDownloadContext downloadContext, KeyValuePair> hasSelectedUsersKVP, string username, int paidMessagesCount, string path, long message_id) + { + Log.Debug($"Calling DownloadPaidMessage - {username}"); + + AnsiConsole.Markup($"[red]Getting Paid Message\n[/]"); + + SinglePaidMessageCollection singlePaidMessageCollection = await downloadContext.ApiHelper.GetPaidMessage($"/messages/{message_id.ToString()}", path, downloadContext.DownloadConfig!); + int oldPaidMessagesCount = 0; + int newPaidMessagesCount = 0; + if (singlePaidMessageCollection != null && singlePaidMessageCollection.SingleMessages.Count > 0) + { + AnsiConsole.Markup($"[red]Found {singlePaidMessageCollection.SingleMessages.Count} Media from {singlePaidMessageCollection.SingleMessageObjects.Count} Paid Messages\n[/]"); + Log.Debug($"Found {singlePaidMessageCollection.SingleMessages.Count} Media from {singlePaidMessageCollection.SingleMessageObjects.Count} Paid Messages"); + paidMessagesCount = singlePaidMessageCollection.SingleMessages.Count; + long totalSize = 0; + if (downloadContext.DownloadConfig.ShowScrapeSize) + { + totalSize = await downloadContext.DownloadHelper.CalculateTotalFileSize(singlePaidMessageCollection.SingleMessages.Values.ToList()); + } + else + { + totalSize = paidMessagesCount; + } + await AnsiConsole.Progress() + .Columns(GetProgressColumns(downloadContext.DownloadConfig.ShowScrapeSize)) + .StartAsync(async ctx => + { + // Define tasks + var task = ctx.AddTask($"[red]Downloading {singlePaidMessageCollection.SingleMessages.Count} Paid Messages[/]", autoStart: false); + Log.Debug($"Downloading {singlePaidMessageCollection.SingleMessages.Count} Paid Messages"); + task.MaxValue = totalSize; + task.StartTask(); + foreach (KeyValuePair paidMessageKVP in singlePaidMessageCollection.SingleMessages) + { + bool isNew; + if (paidMessageKVP.Value.Contains("cdn3.onlyfans.com/dash/files")) + { + string[] messageUrlParsed = paidMessageKVP.Value.Split(','); + string mpdURL = messageUrlParsed[0]; + string policy = messageUrlParsed[1]; + string signature = messageUrlParsed[2]; + string kvp = messageUrlParsed[3]; + string mediaId = messageUrlParsed[4]; + string messageId = messageUrlParsed[5]; + string? licenseURL = null; + string? pssh = await downloadContext.ApiHelper.GetDRMMPDPSSH(mpdURL, policy, signature, kvp); + if (pssh != null) + { + DateTime lastModified = await downloadContext.ApiHelper.GetDRMMPDLastModified(mpdURL, policy, signature, kvp); + Dictionary drmHeaders = downloadContext.ApiHelper.GetDynamicHeaders($"/api2/v2/users/media/{mediaId}/drm/message/{messageId}", "?type=widevine"); + string decryptionKey; + if (clientIdBlobMissing || devicePrivateKeyMissing) + { + decryptionKey = await downloadContext.ApiHelper.GetDecryptionKeyOFDL(drmHeaders, $"https://onlyfans.com/api2/v2/users/media/{mediaId}/drm/message/{messageId}?type=widevine", pssh); + } + else + { + decryptionKey = await downloadContext.ApiHelper.GetDecryptionKeyCDM(drmHeaders, $"https://onlyfans.com/api2/v2/users/media/{mediaId}/drm/message/{messageId}?type=widevine", pssh); + } + + Medium? mediaInfo = singlePaidMessageCollection.SingleMessageMedia.FirstOrDefault(m => m.id == paidMessageKVP.Key); + SingleMessage? messageInfo = singlePaidMessageCollection.SingleMessageObjects.FirstOrDefault(p => p?.media?.Contains(mediaInfo) == true); + + isNew = await downloadContext.DownloadHelper.DownloadSinglePurchasedMessageDRMVideo( + policy: policy, + signature: signature, + kvp: kvp, + url: mpdURL, + decryptionKey: decryptionKey, + folder: path, + lastModified: lastModified, + media_id: paidMessageKVP.Key, + api_type: "Messages", + task: task, + filenameFormat: downloadContext.FileNameFormatConfig.PaidMessageFileNameFormat ?? string.Empty, + messageInfo: messageInfo, + messageMedia: mediaInfo, + fromUser: messageInfo?.fromUser, + users: hasSelectedUsersKVP.Value); + + if (isNew) + { + newPaidMessagesCount++; + } + else + { + oldPaidMessagesCount++; + } + } + } + else + { + Medium? mediaInfo = singlePaidMessageCollection.SingleMessageMedia.FirstOrDefault(m => m.id == paidMessageKVP.Key); + SingleMessage? messageInfo = singlePaidMessageCollection.SingleMessageObjects.FirstOrDefault(p => p?.media?.Contains(mediaInfo) == true); + + isNew = await downloadContext.DownloadHelper.DownloadSinglePurchasedMedia( + url: paidMessageKVP.Value, + folder: path, + media_id: paidMessageKVP.Key, + api_type: "Messages", + task: task, + filenameFormat: downloadContext.FileNameFormatConfig.PaidMessageFileNameFormat ?? string.Empty, + messageInfo: messageInfo, + messageMedia: mediaInfo, + fromUser: messageInfo?.fromUser, + users: hasSelectedUsersKVP.Value); + if (isNew) + { + newPaidMessagesCount++; + } + else + { + oldPaidMessagesCount++; + } + } + } + task.StopTask(); + }); + AnsiConsole.Markup($"[red]Paid Messages Already Downloaded: {oldPaidMessagesCount} New Paid Messages Downloaded: {newPaidMessagesCount}[/]\n"); + Log.Debug($"Paid Messages Already Downloaded: {oldPaidMessagesCount} New Paid Messages Downloaded: {newPaidMessagesCount}"); + } + else + { + AnsiConsole.Markup($"[red]Found 0 Paid Messages\n[/]"); + Log.Debug($"Found 0 Paid Messages"); + } + + return paidMessagesCount; + } + + private static async Task DownloadSinglePost(IDownloadContext downloadContext, long post_id, string path, Dictionary users) + { + Log.Debug($"Calling DownloadSinglePost - {post_id.ToString()}"); + + AnsiConsole.Markup($"[red]Getting Post\n[/]"); + SinglePostCollection post = await downloadContext.ApiHelper.GetPost($"/posts/{post_id.ToString()}", path, downloadContext.DownloadConfig!); + if (post == null) + { + AnsiConsole.Markup($"[red]Couldn't find post\n[/]"); + Log.Debug($"Couldn't find post"); + return; + } + + long totalSize = 0; + if (downloadContext.DownloadConfig.ShowScrapeSize) + { + totalSize = await downloadContext.DownloadHelper.CalculateTotalFileSize(post.SinglePosts.Values.ToList()); + } + else + { + totalSize = post.SinglePosts.Count; + } + bool isNew = false; + await AnsiConsole.Progress() + .Columns(GetProgressColumns(downloadContext.DownloadConfig.ShowScrapeSize)) + .StartAsync(async ctx => + { + var task = ctx.AddTask($"[red]Downloading Post[/]", autoStart: false); + task.MaxValue = totalSize; + task.StartTask(); + foreach (KeyValuePair postKVP in post.SinglePosts) + { + if (postKVP.Value.Contains("cdn3.onlyfans.com/dash/files")) + { + string[] messageUrlParsed = postKVP.Value.Split(','); + string mpdURL = messageUrlParsed[0]; + string policy = messageUrlParsed[1]; + string signature = messageUrlParsed[2]; + string kvp = messageUrlParsed[3]; + string mediaId = messageUrlParsed[4]; + string postId = messageUrlParsed[5]; + string? licenseURL = null; + string? pssh = await downloadContext.ApiHelper.GetDRMMPDPSSH(mpdURL, policy, signature, kvp); + if (pssh == null) + { + continue; + } + + DateTime lastModified = await downloadContext.ApiHelper.GetDRMMPDLastModified(mpdURL, policy, signature, kvp); + Dictionary drmHeaders = downloadContext.ApiHelper.GetDynamicHeaders($"/api2/v2/users/media/{mediaId}/drm/post/{postId}", "?type=widevine"); + string decryptionKey; + if (clientIdBlobMissing || devicePrivateKeyMissing) + { + decryptionKey = await downloadContext.ApiHelper.GetDecryptionKeyOFDL(drmHeaders, $"https://onlyfans.com/api2/v2/users/media/{mediaId}/drm/post/{postId}?type=widevine", pssh); + } + else + { + decryptionKey = await downloadContext.ApiHelper.GetDecryptionKeyCDM(drmHeaders, $"https://onlyfans.com/api2/v2/users/media/{mediaId}/drm/post/{postId}?type=widevine", pssh); + } + SinglePost.Medium mediaInfo = post.SinglePostMedia.FirstOrDefault(m => m.id == postKVP.Key); + SinglePost postInfo = post.SinglePostObjects.FirstOrDefault(p => p?.media?.Contains(mediaInfo) == true); + + isNew = await downloadContext.DownloadHelper.DownloadPostDRMVideo( + policy: policy, + signature: signature, + kvp: kvp, + url: mpdURL, + decryptionKey: decryptionKey, + folder: path, + lastModified: lastModified, + media_id: postKVP.Key, + api_type: "Posts", + task: task, + filenameFormat: downloadContext.FileNameFormatConfig.PostFileNameFormat ?? string.Empty, + postInfo: postInfo, + postMedia: mediaInfo, + author: postInfo?.author, + users: users); + } + else + { + try + { + SinglePost.Medium? mediaInfo = post.SinglePostMedia.FirstOrDefault(m => (m?.id == postKVP.Key) == true); + SinglePost? postInfo = post.SinglePostObjects.FirstOrDefault(p => p?.media?.Contains(mediaInfo) == true); + + isNew = await downloadContext.DownloadHelper.DownloadPostMedia( + url: postKVP.Value, + folder: path, + media_id: postKVP.Key, + api_type: "Posts", + task: task, + filenameFormat: downloadContext.FileNameFormatConfig.PostFileNameFormat ?? string.Empty, + postInfo: postInfo, + postMedia: mediaInfo, + author: postInfo?.author, + users: users); + } + catch + { + Console.WriteLine("Media was null"); + } + } + } + task.StopTask(); + }); + if (isNew) + { + AnsiConsole.Markup($"[red]Post {post_id} downloaded\n[/]"); + Log.Debug($"Post {post_id} downloaded"); + } + else + { + AnsiConsole.Markup($"[red]Post {post_id} already downloaded\n[/]"); + Log.Debug($"Post {post_id} already downloaded"); + } + } + + public static async Task<(bool IsExit, Dictionary? selectedUsers, Entities.Config? updatedConfig)> HandleUserSelection(APIHelper apiHelper, Entities.Config currentConfig, Dictionary users, Dictionary lists) + { + bool hasSelectedUsers = false; + Dictionary selectedUsers = new Dictionary(); + + while (!hasSelectedUsers) + { + var mainMenuOptions = GetMainMenuOptions(users, lists); + + var mainMenuSelection = AnsiConsole.Prompt( + new SelectionPrompt() + .Title("[red]Select Accounts to Scrape | Select All = All Accounts | List = Download content from users on List | Custom = Specific Account(s)[/]") + .AddChoices(mainMenuOptions) + ); + + switch (mainMenuSelection) + { + case "[red]Select All[/]": + selectedUsers = users; + hasSelectedUsers = true; + break; + case "[red]List[/]": + while (true) + { + var listSelectionPrompt = new MultiSelectionPrompt(); + listSelectionPrompt.Title = "[red]Select List[/]"; + listSelectionPrompt.PageSize = 10; + listSelectionPrompt.AddChoice("[red]Go Back[/]"); + foreach (string key in lists.Keys.Select(k => $"[red]{k}[/]").ToList()) + { + listSelectionPrompt.AddChoice(key); + } + var listSelection = AnsiConsole.Prompt(listSelectionPrompt); + + if (listSelection.Contains("[red]Go Back[/]")) + { + break; // Go back to the main menu + } + else + { + hasSelectedUsers = true; + List listUsernames = new(); + foreach (var item in listSelection) + { + int listId = lists[item.Replace("[red]", "").Replace("[/]", "")]; + List usernames = await apiHelper.GetListUsers($"/lists/{listId}/users", config); + foreach (string user in usernames) + { + listUsernames.Add(user); + } + } + selectedUsers = users.Where(x => listUsernames.Contains($"{x.Key}")).Distinct().ToDictionary(x => x.Key, x => x.Value); + AnsiConsole.Markup(string.Format("[red]Downloading from List(s): {0}[/]", string.Join(", ", listSelection))); + break; + } + } + break; + case "[red]Custom[/]": + while (true) + { + var selectedNamesPrompt = new MultiSelectionPrompt(); + selectedNamesPrompt.MoreChoicesText("[grey](Move up and down to reveal more choices)[/]"); + selectedNamesPrompt.InstructionsText("[grey](Press to select, to accept)[/]\n[grey](Press A-Z to easily navigate the list)[/]"); + selectedNamesPrompt.Title("[red]Select users[/]"); + selectedNamesPrompt.PageSize(10); + selectedNamesPrompt.AddChoice("[red]Go Back[/]"); + foreach (string key in users.Keys.OrderBy(k => k).Select(k => $"[red]{k}[/]").ToList()) + { + selectedNamesPrompt.AddChoice(key); + } + var userSelection = AnsiConsole.Prompt(selectedNamesPrompt); + if (userSelection.Contains("[red]Go Back[/]")) + { + break; // Go back to the main menu + } + else + { + hasSelectedUsers = true; + selectedUsers = users.Where(x => userSelection.Contains($"[red]{x.Key}[/]")).ToDictionary(x => x.Key, x => x.Value); + break; + } + } + break; + case "[red]Download Single Post[/]": + return (true, new Dictionary { { "SinglePost", 0 } }, currentConfig); + case "[red]Download Single Paid Message[/]": + return (true, new Dictionary { { "SingleMessage", 0 } }, currentConfig); + case "[red]Download Purchased Tab[/]": + return (true, new Dictionary { { "PurchasedTab", 0 } }, currentConfig); + case "[red]Edit config.conf[/]": + while (true) + { + if (currentConfig == null) + currentConfig = new Entities.Config(); + + var choices = new List<(string choice, bool isSelected)> + { + ("[red]Go Back[/]", false) + }; + + foreach(var propInfo in typeof(Entities.Config).GetProperties()) + { + var attr = propInfo.GetCustomAttribute(); + if(attr != null) + { + string itemLabel = $"[red]{propInfo.Name}[/]"; + choices.Add(new(itemLabel, (bool)propInfo.GetValue(currentConfig)!)); + } + } + + MultiSelectionPrompt multiSelectionPrompt = new MultiSelectionPrompt() + .Title("[red]Edit config.conf[/]") + .PageSize(25); + + foreach (var choice in choices) + { + multiSelectionPrompt.AddChoices(choice.choice, (selectionItem) => { if (choice.isSelected) selectionItem.Select(); }); + } + + var configOptions = AnsiConsole.Prompt(multiSelectionPrompt); + + if (configOptions.Contains("[red]Go Back[/]")) + { + break; + } + + bool configChanged = false; + + Entities.Config newConfig = new Entities.Config(); + foreach (var propInfo in typeof(Entities.Config).GetProperties()) + { + var attr = propInfo.GetCustomAttribute(); + if (attr != null) + { + // + // Get the new choice from the selection + // + string itemLabel = $"[red]{propInfo.Name}[/]"; + var newValue = configOptions.Contains(itemLabel); + var oldValue = choices.Where(c => c.choice == itemLabel).Select(c => c.isSelected).First(); + propInfo.SetValue(newConfig, newValue); + + if (newValue != oldValue) + configChanged = true; + } + else + { + // + // Reassign any non toggleable values + // + propInfo.SetValue(newConfig, propInfo.GetValue(currentConfig)); + } + } + + var hoconConfig = new StringBuilder(); + hoconConfig.AppendLine("# External Tools"); + hoconConfig.AppendLine("External {"); + hoconConfig.AppendLine($" FFmpegPath = \"{newConfig.FFmpegPath}\""); + hoconConfig.AppendLine("}"); + + hoconConfig.AppendLine("# Download Settings"); + hoconConfig.AppendLine("Download {"); + hoconConfig.AppendLine(" Media {"); + hoconConfig.AppendLine($" DownloadAvatarHeaderPhoto = {newConfig.DownloadAvatarHeaderPhoto.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadPaidPosts = {newConfig.DownloadPaidPosts.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadPosts = {newConfig.DownloadPosts.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadArchived = {newConfig.DownloadArchived.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadStreams = {newConfig.DownloadStreams.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadStories = {newConfig.DownloadStories.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadHighlights = {newConfig.DownloadHighlights.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadMessages = {newConfig.DownloadMessages.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadPaidMessages = {newConfig.DownloadPaidMessages.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadImages = {newConfig.DownloadImages.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadVideos = {newConfig.DownloadVideos.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadAudios = {newConfig.DownloadAudios.ToString().ToLower()}"); + hoconConfig.AppendLine(" }"); + hoconConfig.AppendLine($" IgnoreOwnMessages = {newConfig.IgnoreOwnMessages.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadPostsIncrementally = {newConfig.DownloadPostsIncrementally.ToString().ToLower()}"); + hoconConfig.AppendLine($" BypassContentForCreatorsWhoNoLongerExist = {newConfig.BypassContentForCreatorsWhoNoLongerExist.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadDuplicatedMedia = {newConfig.DownloadDuplicatedMedia.ToString().ToLower()}"); + hoconConfig.AppendLine($" SkipAds = {newConfig.SkipAds.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadPath = \"{newConfig.DownloadPath}\""); + hoconConfig.AppendLine($" DownloadOnlySpecificDates = {newConfig.DownloadOnlySpecificDates.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadDateSelection = \"{newConfig.DownloadDateSelection.ToString().ToLower()}\""); + hoconConfig.AppendLine($" CustomDate = \"{newConfig.CustomDate?.ToString("yyyy-MM-dd")}\""); + hoconConfig.AppendLine($" ShowScrapeSize = {newConfig.ShowScrapeSize.ToString().ToLower()}"); + hoconConfig.AppendLine("}"); + + hoconConfig.AppendLine("# File Settings"); + hoconConfig.AppendLine("File {"); + hoconConfig.AppendLine($" PaidPostFileNameFormat = \"{newConfig.PaidPostFileNameFormat}\""); + hoconConfig.AppendLine($" PostFileNameFormat = \"{newConfig.PostFileNameFormat}\""); + hoconConfig.AppendLine($" PaidMessageFileNameFormat = \"{newConfig.PaidMessageFileNameFormat}\""); + hoconConfig.AppendLine($" MessageFileNameFormat = \"{newConfig.MessageFileNameFormat}\""); + hoconConfig.AppendLine($" RenameExistingFilesWhenCustomFormatIsSelected = {newConfig.RenameExistingFilesWhenCustomFormatIsSelected.ToString().ToLower()}"); + hoconConfig.AppendLine("}"); + + hoconConfig.AppendLine("# Creator-Specific Configurations"); + hoconConfig.AppendLine("CreatorConfigs {"); + foreach (var creatorConfig in newConfig.CreatorConfigs) + { + hoconConfig.AppendLine($" \"{creatorConfig.Key}\" {{"); + hoconConfig.AppendLine($" PaidPostFileNameFormat = \"{creatorConfig.Value.PaidPostFileNameFormat}\""); + hoconConfig.AppendLine($" PostFileNameFormat = \"{creatorConfig.Value.PostFileNameFormat}\""); + hoconConfig.AppendLine($" PaidMessageFileNameFormat = \"{creatorConfig.Value.PaidMessageFileNameFormat}\""); + hoconConfig.AppendLine($" MessageFileNameFormat = \"{creatorConfig.Value.MessageFileNameFormat}\""); + hoconConfig.AppendLine(" }"); + } + hoconConfig.AppendLine("}"); + + hoconConfig.AppendLine("# Folder Settings"); + hoconConfig.AppendLine("Folder {"); + hoconConfig.AppendLine($" FolderPerPaidPost = {newConfig.FolderPerPaidPost.ToString().ToLower()}"); + hoconConfig.AppendLine($" FolderPerPost = {newConfig.FolderPerPost.ToString().ToLower()}"); + hoconConfig.AppendLine($" FolderPerPaidMessage = {newConfig.FolderPerPaidMessage.ToString().ToLower()}"); + hoconConfig.AppendLine($" FolderPerMessage = {newConfig.FolderPerMessage.ToString().ToLower()}"); + hoconConfig.AppendLine("}"); + + hoconConfig.AppendLine("# Subscription Settings"); + hoconConfig.AppendLine("Subscriptions {"); + hoconConfig.AppendLine($" IncludeExpiredSubscriptions = {newConfig.IncludeExpiredSubscriptions.ToString().ToLower()}"); + hoconConfig.AppendLine($" IncludeRestrictedSubscriptions = {newConfig.IncludeRestrictedSubscriptions.ToString().ToLower()}"); + hoconConfig.AppendLine($" IgnoredUsersListName = \"{newConfig.IgnoredUsersListName}\""); + hoconConfig.AppendLine("}"); + + hoconConfig.AppendLine("# Interaction Settings"); + hoconConfig.AppendLine("Interaction {"); + hoconConfig.AppendLine($" NonInteractiveMode = {newConfig.NonInteractiveMode.ToString().ToLower()}"); + hoconConfig.AppendLine($" NonInteractiveModeListName = \"{newConfig.NonInteractiveModeListName}\""); + hoconConfig.AppendLine($" NonInteractiveModePurchasedTab = {newConfig.NonInteractiveModePurchasedTab.ToString().ToLower()}"); + hoconConfig.AppendLine("}"); + + hoconConfig.AppendLine("# Performance Settings"); + hoconConfig.AppendLine("Performance {"); + hoconConfig.AppendLine($" Timeout = {(newConfig.Timeout.HasValue ? newConfig.Timeout.Value : -1)}"); + hoconConfig.AppendLine($" LimitDownloadRate = {newConfig.LimitDownloadRate.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadLimitInMbPerSec = {newConfig.DownloadLimitInMbPerSec}"); + hoconConfig.AppendLine("}"); + + hoconConfig.AppendLine("# Logging/Debug Settings"); + hoconConfig.AppendLine("Logging {"); + hoconConfig.AppendLine($" LoggingLevel = \"{newConfig.LoggingLevel.ToString().ToLower()}\""); + hoconConfig.AppendLine("}"); + + File.WriteAllText("config.conf", hoconConfig.ToString()); + + string newConfigString = JsonConvert.SerializeObject(newConfig, Formatting.Indented); + + Log.Debug($"Config changed:"); + Log.Debug(newConfigString); + + currentConfig = newConfig; + if (configChanged) + { + return (true, new Dictionary { { "ConfigChanged", 0 } }, currentConfig); + } + break; + } + break; + case "[red]Change logging level[/]": + while (true) + { + var choices = new List<(string choice, bool isSelected)> + { + ("[red]Go Back[/]", false) + }; + + foreach (string name in typeof(LoggingLevel).GetEnumNames()) + { + string itemLabel = $"[red]{name}[/]"; + choices.Add(new(itemLabel, name == levelSwitch.MinimumLevel.ToString())); + } + + SelectionPrompt selectionPrompt = new SelectionPrompt() + .Title("[red]Select logging level[/]") + .PageSize(25); + + foreach (var choice in choices) + { + selectionPrompt.AddChoice(choice.choice); + } + + string levelOption = AnsiConsole.Prompt(selectionPrompt); + + if (levelOption.Contains("[red]Go Back[/]")) + { + break; + } + + levelOption = levelOption.Replace("[red]", "").Replace("[/]", ""); + LoggingLevel newLogLevel = (LoggingLevel)Enum.Parse(typeof(LoggingLevel), levelOption, true); + levelSwitch.MinimumLevel = (LogEventLevel)newLogLevel; + + Log.Debug($"Logging level changed to: {levelOption}"); + + bool configChanged = false; + + Entities.Config newConfig = new Entities.Config(); + + newConfig = currentConfig; + + newConfig.LoggingLevel = newLogLevel; + + currentConfig = newConfig; + + // Dump new config in the log file + Log.Debug("Configuration:"); + string configString = JsonConvert.SerializeObject(currentConfig, Formatting.Indented); + Log.Debug(configString); + + var hoconConfig = new StringBuilder(); + hoconConfig.AppendLine("# External Tools"); + hoconConfig.AppendLine("External {"); + hoconConfig.AppendLine($" FFmpegPath = \"{newConfig.FFmpegPath}\""); + hoconConfig.AppendLine("}"); + + hoconConfig.AppendLine("# Download Settings"); + hoconConfig.AppendLine("Download {"); + hoconConfig.AppendLine(" Media {"); + hoconConfig.AppendLine($" DownloadAvatarHeaderPhoto = {newConfig.DownloadAvatarHeaderPhoto.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadPaidPosts = {newConfig.DownloadPaidPosts.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadPosts = {newConfig.DownloadPosts.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadArchived = {newConfig.DownloadArchived.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadStreams = {newConfig.DownloadStreams.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadStories = {newConfig.DownloadStories.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadHighlights = {newConfig.DownloadHighlights.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadMessages = {newConfig.DownloadMessages.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadPaidMessages = {newConfig.DownloadPaidMessages.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadImages = {newConfig.DownloadImages.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadVideos = {newConfig.DownloadVideos.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadAudios = {newConfig.DownloadAudios.ToString().ToLower()}"); + hoconConfig.AppendLine(" }"); + hoconConfig.AppendLine($" IgnoreOwnMessages = {newConfig.IgnoreOwnMessages.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadPostsIncrementally = {newConfig.DownloadPostsIncrementally.ToString().ToLower()}"); + hoconConfig.AppendLine($" BypassContentForCreatorsWhoNoLongerExist = {newConfig.BypassContentForCreatorsWhoNoLongerExist.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadDuplicatedMedia = {newConfig.DownloadDuplicatedMedia.ToString().ToLower()}"); + hoconConfig.AppendLine($" SkipAds = {newConfig.SkipAds.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadPath = \"{newConfig.DownloadPath}\""); + hoconConfig.AppendLine($" DownloadOnlySpecificDates = {newConfig.DownloadOnlySpecificDates.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadDateSelection = \"{newConfig.DownloadDateSelection.ToString().ToLower()}\""); + hoconConfig.AppendLine($" CustomDate = \"{newConfig.CustomDate?.ToString("yyyy-MM-dd")}\""); + hoconConfig.AppendLine($" ShowScrapeSize = {newConfig.ShowScrapeSize.ToString().ToLower()}"); + hoconConfig.AppendLine("}"); + + hoconConfig.AppendLine("# File Settings"); + hoconConfig.AppendLine("File {"); + hoconConfig.AppendLine($" PaidPostFileNameFormat = \"{newConfig.PaidPostFileNameFormat}\""); + hoconConfig.AppendLine($" PostFileNameFormat = \"{newConfig.PostFileNameFormat}\""); + hoconConfig.AppendLine($" PaidMessageFileNameFormat = \"{newConfig.PaidMessageFileNameFormat}\""); + hoconConfig.AppendLine($" MessageFileNameFormat = \"{newConfig.MessageFileNameFormat}\""); + hoconConfig.AppendLine($" RenameExistingFilesWhenCustomFormatIsSelected = {newConfig.RenameExistingFilesWhenCustomFormatIsSelected.ToString().ToLower()}"); + hoconConfig.AppendLine("}"); + + hoconConfig.AppendLine("# Creator-Specific Configurations"); + hoconConfig.AppendLine("CreatorConfigs {"); + foreach (var creatorConfig in newConfig.CreatorConfigs) + { + hoconConfig.AppendLine($" \"{creatorConfig.Key}\" {{"); + hoconConfig.AppendLine($" PaidPostFileNameFormat = \"{creatorConfig.Value.PaidPostFileNameFormat}\""); + hoconConfig.AppendLine($" PostFileNameFormat = \"{creatorConfig.Value.PostFileNameFormat}\""); + hoconConfig.AppendLine($" PaidMessageFileNameFormat = \"{creatorConfig.Value.PaidMessageFileNameFormat}\""); + hoconConfig.AppendLine($" MessageFileNameFormat = \"{creatorConfig.Value.MessageFileNameFormat}\""); + hoconConfig.AppendLine(" }"); + } + hoconConfig.AppendLine("}"); + + hoconConfig.AppendLine("# Folder Settings"); + hoconConfig.AppendLine("Folder {"); + hoconConfig.AppendLine($" FolderPerPaidPost = {newConfig.FolderPerPaidPost.ToString().ToLower()}"); + hoconConfig.AppendLine($" FolderPerPost = {newConfig.FolderPerPost.ToString().ToLower()}"); + hoconConfig.AppendLine($" FolderPerPaidMessage = {newConfig.FolderPerPaidMessage.ToString().ToLower()}"); + hoconConfig.AppendLine($" FolderPerMessage = {newConfig.FolderPerMessage.ToString().ToLower()}"); + hoconConfig.AppendLine("}"); + + hoconConfig.AppendLine("# Subscription Settings"); + hoconConfig.AppendLine("Subscriptions {"); + hoconConfig.AppendLine($" IncludeExpiredSubscriptions = {newConfig.IncludeExpiredSubscriptions.ToString().ToLower()}"); + hoconConfig.AppendLine($" IncludeRestrictedSubscriptions = {newConfig.IncludeRestrictedSubscriptions.ToString().ToLower()}"); + hoconConfig.AppendLine($" IgnoredUsersListName = \"{newConfig.IgnoredUsersListName}\""); + hoconConfig.AppendLine("}"); + + hoconConfig.AppendLine("# Interaction Settings"); + hoconConfig.AppendLine("Interaction {"); + hoconConfig.AppendLine($" NonInteractiveMode = {newConfig.NonInteractiveMode.ToString().ToLower()}"); + hoconConfig.AppendLine($" NonInteractiveModeListName = \"{newConfig.NonInteractiveModeListName}\""); + hoconConfig.AppendLine($" NonInteractiveModePurchasedTab = {newConfig.NonInteractiveModePurchasedTab.ToString().ToLower()}"); + hoconConfig.AppendLine("}"); + + hoconConfig.AppendLine("# Performance Settings"); + hoconConfig.AppendLine("Performance {"); + hoconConfig.AppendLine($" Timeout = {(newConfig.Timeout.HasValue ? newConfig.Timeout.Value : -1)}"); + hoconConfig.AppendLine($" LimitDownloadRate = {newConfig.LimitDownloadRate.ToString().ToLower()}"); + hoconConfig.AppendLine($" DownloadLimitInMbPerSec = {newConfig.DownloadLimitInMbPerSec}"); + hoconConfig.AppendLine("}"); + + hoconConfig.AppendLine("# Logging/Debug Settings"); + hoconConfig.AppendLine("Logging {"); + hoconConfig.AppendLine($" LoggingLevel = \"{newConfig.LoggingLevel.ToString().ToLower()}\""); + hoconConfig.AppendLine("}"); + + File.WriteAllText("config.conf", hoconConfig.ToString()); + + if (configChanged) + { + return (true, new Dictionary { { "ConfigChanged", 0 } }, currentConfig); + } + + break; + } + break; + case "[red]Logout and Exit[/]": + if (Directory.Exists("chrome-data")) + { + Log.Information("Deleting chrome-data folder"); + Directory.Delete("chrome-data", true); + } + if (File.Exists("auth.json")) + { + Log.Information("Deleting auth.json"); + File.Delete("auth.json"); + } + return (false, null, currentConfig); // Return false to indicate exit + case "[red]Exit[/]": + return (false, null, currentConfig); // Return false to indicate exit + } + } + + return (true, selectedUsers, currentConfig); // Return true to indicate selected users + } + + public static List GetMainMenuOptions(Dictionary users, Dictionary lists) + { + if (lists.Count > 0) + { + return new List + { + "[red]Select All[/]", + "[red]List[/]", + "[red]Custom[/]", + "[red]Download Single Post[/]", + "[red]Download Single Paid Message[/]", + "[red]Download Purchased Tab[/]", + "[red]Edit config.conf[/]", + "[red]Change logging level[/]", + "[red]Logout and Exit[/]", + "[red]Exit[/]" + }; + } + else + { + return new List + { + "[red]Select All[/]", + "[red]Custom[/]", + "[red]Download Single Post[/]", + "[red]Download Single Paid Message[/]", + "[red]Download Purchased Tab[/]", + "[red]Edit config.conf[/]", + "[red]Change logging level[/]", + "[red]Logout and Exit[/]", + "[red]Exit[/]" + }; + } + } + + static bool ValidateFilePath(string path) + { + char[] invalidChars = System.IO.Path.GetInvalidPathChars(); + char[] foundInvalidChars = path.Where(c => invalidChars.Contains(c)).ToArray(); + + if (foundInvalidChars.Any()) + { + AnsiConsole.Markup($"[red]Invalid characters found in path {path}:[/] {string.Join(", ", foundInvalidChars)}\n"); + return false; + } + + if (!System.IO.File.Exists(path)) + { + if (System.IO.Directory.Exists(path)) + { + AnsiConsole.Markup($"[red]The provided path {path} improperly points to a directory and not a file.[/]\n"); + } + else + { + AnsiConsole.Markup($"[red]The provided path {path} does not exist or is not accessible.[/]\n"); + } + return false; + } + + return true; + } + static ProgressColumn[] GetProgressColumns(bool showScrapeSize) + { + List progressColumns; + if (showScrapeSize) + { + progressColumns = new List() + { + new TaskDescriptionColumn(), new ProgressBarColumn(), new PercentageColumn(), new DownloadedColumn(), new RemainingTimeColumn() + }; + } + else + { + progressColumns = new List() + { + new TaskDescriptionColumn(), new ProgressBarColumn(), new PercentageColumn() + }; + } + return progressColumns.ToArray(); + } + + public static string? GetFullPath(string filename) + { + if (File.Exists(filename)) + { + return Path.GetFullPath(filename); + } + + var pathEnv = Environment.GetEnvironmentVariable("PATH") ?? string.Empty; + foreach (var path in pathEnv.Split(Path.PathSeparator)) + { + var fullPath = Path.Combine(path, filename); + if (File.Exists(fullPath)) + { + return fullPath; + } + } + return null; + } + + public static void ValidateCookieString() + { + string pattern = @"(auth_id=\d+)|(sess=[^;]+)"; + var matches = Regex.Matches(auth.COOKIE, pattern); + + string output = string.Join("; ", matches); + + if (!output.EndsWith(";")) + { + output += ";"; + } + + if(auth.COOKIE.Trim() != output.Trim()) + { + auth.COOKIE = output; + string newAuthString = JsonConvert.SerializeObject(auth, Formatting.Indented); + File.WriteAllText("auth.json", newAuthString); + } + } + + public static void ValidateFileNameFormat(string? format, string settingName) + { + if(!string.IsNullOrEmpty(format) && !format.Contains("{mediaId}", StringComparison.OrdinalIgnoreCase) && !format.Contains("{filename}", StringComparison.OrdinalIgnoreCase)) + { + AnsiConsole.Markup($"[red]{settingName} is not unique enough, please make sure you include either '{{mediaId}}' or '{{filename}}' to ensure that files are not overwritten with the same filename.[/]\n"); + AnsiConsole.Markup("[red]Press any key to continue.[/]\n"); + Console.ReadKey(); + Environment.Exit(2); + } + } +} diff --git a/OF DL/References/Spectre.Console.deps.json b/OF DL/References/Spectre.Console.deps.json new file mode 100644 index 0000000..5470288 --- /dev/null +++ b/OF DL/References/Spectre.Console.deps.json @@ -0,0 +1,112 @@ +{ + "runtimeTarget": { + "name": ".NETCoreApp,Version=v7.0", + "signature": "" + }, + "compilationOptions": {}, + "targets": { + ".NETCoreApp,Version=v7.0": { + "Spectre.Console/0.0.0-preview.0": { + "dependencies": { + "Microsoft.SourceLink.GitHub": "1.1.1", + "MinVer": "4.2.0", + "Roslynator.Analyzers": "4.1.2", + "StyleCop.Analyzers": "1.2.0-beta.435", + "System.Memory": "4.5.5", + "Wcwidth.Sources": "1.0.0" + }, + "runtime": { + "Spectre.Console.dll": {} + } + }, + "Microsoft.Build.Tasks.Git/1.1.1": {}, + "Microsoft.SourceLink.Common/1.1.1": {}, + "Microsoft.SourceLink.GitHub/1.1.1": { + "dependencies": { + "Microsoft.Build.Tasks.Git": "1.1.1", + "Microsoft.SourceLink.Common": "1.1.1" + } + }, + "MinVer/4.2.0": {}, + "Roslynator.Analyzers/4.1.2": {}, + "StyleCop.Analyzers/1.2.0-beta.435": { + "dependencies": { + "StyleCop.Analyzers.Unstable": "1.2.0.435" + } + }, + "StyleCop.Analyzers.Unstable/1.2.0.435": {}, + "System.Memory/4.5.5": {}, + "Wcwidth.Sources/1.0.0": {} + } + }, + "libraries": { + "Spectre.Console/0.0.0-preview.0": { + "type": "project", + "serviceable": false, + "sha512": "" + }, + "Microsoft.Build.Tasks.Git/1.1.1": { + "type": "package", + "serviceable": true, + "sha512": "sha512-AT3HlgTjsqHnWpBHSNeR0KxbLZD7bztlZVj7I8vgeYG9SYqbeFGh0TM/KVtC6fg53nrWHl3VfZFvb5BiQFcY6Q==", + "path": "microsoft.build.tasks.git/1.1.1", + "hashPath": "microsoft.build.tasks.git.1.1.1.nupkg.sha512" + }, + "Microsoft.SourceLink.Common/1.1.1": { + "type": "package", + "serviceable": true, + "sha512": "sha512-WMcGpWKrmJmzrNeuaEb23bEMnbtR/vLmvZtkAP5qWu7vQsY59GqfRJd65sFpBszbd2k/bQ8cs8eWawQKAabkVg==", + "path": "microsoft.sourcelink.common/1.1.1", + "hashPath": "microsoft.sourcelink.common.1.1.1.nupkg.sha512" + }, + "Microsoft.SourceLink.GitHub/1.1.1": { + "type": "package", + "serviceable": true, + "sha512": "sha512-IaJGnOv/M7UQjRJks7B6p7pbPnOwisYGOIzqCz5ilGFTApZ3ktOR+6zJ12ZRPInulBmdAf1SrGdDG2MU8g6XTw==", + "path": "microsoft.sourcelink.github/1.1.1", + "hashPath": "microsoft.sourcelink.github.1.1.1.nupkg.sha512" + }, + "MinVer/4.2.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-Po4tv+sri1jsaebQ8F6+yD5ru9Gas5mR111F6HR2ULqwflvjjZXMstpeOc1GHMJeQa3g4E3b8MX8K2cShkuUAg==", + "path": "minver/4.2.0", + "hashPath": "minver.4.2.0.nupkg.sha512" + }, + "Roslynator.Analyzers/4.1.2": { + "type": "package", + "serviceable": true, + "sha512": "sha512-bNl3GRSBFjJymYnwq/IRDD9MOSZz9VKdGk9RsN0MWIXoSRnVKQv84f6s9nLE13y20lZgMZKlDqGw2uInBH4JgA==", + "path": "roslynator.analyzers/4.1.2", + "hashPath": "roslynator.analyzers.4.1.2.nupkg.sha512" + }, + "StyleCop.Analyzers/1.2.0-beta.435": { + "type": "package", + "serviceable": true, + "sha512": "sha512-TADk7vdGXtfTnYCV7GyleaaRTQjfoSfZXprQrVMm7cSJtJbFc1QIbWPyLvrgrfGdfHbGmUPvaN4ODKNxg2jgPQ==", + "path": "stylecop.analyzers/1.2.0-beta.435", + "hashPath": "stylecop.analyzers.1.2.0-beta.435.nupkg.sha512" + }, + "StyleCop.Analyzers.Unstable/1.2.0.435": { + "type": "package", + "serviceable": true, + "sha512": "sha512-ouwPWZxbOV3SmCZxIRqHvljkSzkCyi1tDoMzQtDb/bRP8ctASV/iRJr+A2Gdj0QLaLmWnqTWDrH82/iP+X80Lg==", + "path": "stylecop.analyzers.unstable/1.2.0.435", + "hashPath": "stylecop.analyzers.unstable.1.2.0.435.nupkg.sha512" + }, + "System.Memory/4.5.5": { + "type": "package", + "serviceable": true, + "sha512": "sha512-XIWiDvKPXaTveaB7HVganDlOCRoj03l+jrwNvcge/t8vhGYKvqV+dMv6G4SAX2NoNmN0wZfVPTAlFwZcZvVOUw==", + "path": "system.memory/4.5.5", + "hashPath": "system.memory.4.5.5.nupkg.sha512" + }, + "Wcwidth.Sources/1.0.0": { + "type": "package", + "serviceable": true, + "sha512": "sha512-86tmwfGXRz7GJQXBnoTFoMvqSqd6irfkEkRzQFR54W/nweaR8cUvzY8x++z+B/+eUPSuqD2Ah1iPJHgthy4pzg==", + "path": "wcwidth.sources/1.0.0", + "hashPath": "wcwidth.sources.1.0.0.nupkg.sha512" + } + } +} \ No newline at end of file diff --git a/OF DL/References/Spectre.Console.dll b/OF DL/References/Spectre.Console.dll new file mode 100644 index 0000000000000000000000000000000000000000..d2ca26d534333da91900e4f28a5d517f972a7c8c GIT binary patch literal 694272 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%0DF6@fTo*t$tt!S9EPVI79>6;{ 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¥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 content = new List(); + + foreach (string line in html.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None)) + { + if (line.Contains("<" + element) && line.Contains(attribute)) + { + string contentPart = line.Substring(0, line.LastIndexOf("<")); + if (contentPart.EndsWith(">")) + contentPart = contentPart[..^1]; + + contentPart = contentPart[(contentPart.LastIndexOf(">") + 1)..]; + + if (contentPart.Contains("<")) + contentPart = contentPart[..contentPart.IndexOf("<")]; + + content.Add(contentPart); + } + } + return content.ToArray(); + } + + public static string BytesToHex(byte[] data) + { + return BitConverter.ToString(data).Replace("-", ""); + } + public static byte[] HexToBytes(string hex) + { + hex = hex.Trim(); + byte[] bytes = new byte[hex.Length / 2]; + + for (int i = 0; i < hex.Length; i += 2) + bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16); + + return bytes; + } + + public static bool IsBase64Encoded(string str) + { + try + { + byte[] data = Convert.FromBase64String(str); + return true; + } + catch + { + return false; + } + } + + public static string Base64Pad(string base64) + { + if (base64.Length % 4 != 0) + { + base64 = base64.PadRight(base64.Length + (4 - (base64.Length % 4)), '='); + } + return base64; + } + public static string Base64ToString(string base64) + { + return Encoding.UTF8.GetString(Convert.FromBase64String(base64)); + } + public static string StringToBase64(string str) + { + return Convert.ToBase64String(Encoding.UTF8.GetBytes(str)); + } + + public static void TitleProgress(long read, long length) + { + long readMB = read / 1024 / 1024; + long lengthMB = length / 1024 / 1024; + Console.Title = $"{readMB}/{lengthMB}MB"; + } + + public static void TitleProgressNoConversion(long read, long length) + { + Console.Title = $"{read}/{length}MB"; + } + + public static string Version() + { + return System.Reflection.Assembly.GetCallingAssembly().GetName().Version.ToString(); + } + + public static string? RemoveInvalidFileNameChars(string? fileName) + { + return string.IsNullOrEmpty(fileName) ? fileName : string.Concat(fileName.Split(Path.GetInvalidFileNameChars())); + } + + public static List CalculateFolderMD5(string folder) + { + List md5Hashes = new List(); + if (Directory.Exists(folder)) + { + string[] files = Directory.GetFiles(folder); + + foreach (string file in files) + { + md5Hashes.Add(CalculateMD5(file)); + } + } + + return md5Hashes; + } + + public static string CalculateMD5(string filePath) + { + using (var md5 = MD5.Create()) + { + using (var stream = File.OpenRead(filePath)) + { + byte[] hash = md5.ComputeHash(stream); + return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant(); + } + } + } + } +} diff --git a/OF DL/Utils/ThrottledStream.cs b/OF DL/Utils/ThrottledStream.cs new file mode 100644 index 0000000..07b8857 --- /dev/null +++ b/OF DL/Utils/ThrottledStream.cs @@ -0,0 +1,159 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Reactive.Concurrency; +using System.Text; +using System.Threading.Tasks; + +namespace OF_DL.Utils; + + +public class ThrottledStream : Stream + +{ + private readonly Stream parent; + private readonly int maxBytesPerSecond; + private readonly IScheduler scheduler; + private readonly IStopwatch stopwatch; + private readonly bool shouldThrottle; + + private long processed; + + public ThrottledStream(Stream parent, int maxBytesPerSecond, IScheduler scheduler, bool shouldThrottle) + { + this.shouldThrottle = shouldThrottle; + this.maxBytesPerSecond = maxBytesPerSecond; + this.parent = parent; + this.scheduler = scheduler; + stopwatch = scheduler.StartStopwatch(); + processed = 0; + } + + public ThrottledStream(Stream parent, int maxBytesPerSecond, bool shouldThrottle) + : this(parent, maxBytesPerSecond, Scheduler.Immediate, shouldThrottle) + { + } + + + protected void Throttle(int bytes) + { + if (!shouldThrottle) return; + processed += bytes; + var targetTime = TimeSpan.FromSeconds((double)processed / maxBytesPerSecond); + var actualTime = stopwatch.Elapsed; + var sleep = targetTime - actualTime; + if (sleep > TimeSpan.Zero) + { + using var waitHandle = new AutoResetEvent(initialState: false); + scheduler.Sleep(sleep).GetAwaiter().OnCompleted(() => waitHandle.Set()); + waitHandle.WaitOne(); + } + } + + protected async Task ThrottleAsync(int bytes) + { + if (!shouldThrottle) return; + processed += bytes; + var targetTime = TimeSpan.FromSeconds((double)processed / maxBytesPerSecond); + var actualTime = stopwatch.Elapsed; + var sleep = targetTime - actualTime; + + if (sleep > TimeSpan.Zero) + { + await Task.Delay(sleep, CancellationToken.None).ConfigureAwait(false); + } + } + + public override async Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) + { + var read = await parent.ReadAsync(buffer.AsMemory(offset, count), cancellationToken).ConfigureAwait(false); + await ThrottleAsync(read).ConfigureAwait(false); + return read; + } + + public override async ValueTask ReadAsync(Memory buffer, CancellationToken cancellationToken = default) + { + int bytesRead = await parent.ReadAsync(buffer, cancellationToken).ConfigureAwait(false); + await ThrottleAsync(bytesRead).ConfigureAwait(false); + return bytesRead; + } + + public override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) + { + await ThrottleAsync(count).ConfigureAwait(false); + await parent.WriteAsync(buffer.AsMemory(offset, count), cancellationToken).ConfigureAwait(false); + } + + public override async ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken = default) + { + await ThrottleAsync(buffer.Length).ConfigureAwait(false); + await parent.WriteAsync(buffer, cancellationToken).ConfigureAwait(false); + } + + + public override bool CanRead + { + get { return parent.CanRead; } + } + + + public override bool CanSeek + { + get { return parent.CanSeek; } + } + + + public override bool CanWrite + { + get { return parent.CanWrite; } + } + + + public override void Flush() + { + parent.Flush(); + } + + + public override long Length + { + get { return parent.Length; } + } + + + public override long Position + { + get + { + return parent.Position; + } + set + { + parent.Position = value; + } + } + + public override int Read(byte[] buffer, int offset, int count) + { + var read = parent.Read(buffer, offset, count); + Throttle(read); + return read; + } + + public override long Seek(long offset, SeekOrigin origin) + { + return parent.Seek(offset, origin); + } + + public override void SetLength(long value) + { + parent.SetLength(value); + } + + public override void Write(byte[] buffer, int offset, int count) + { + Throttle(count); + parent.Write(buffer, offset, count); + } +} diff --git a/OF DL/Utils/XmlUtils.cs b/OF DL/Utils/XmlUtils.cs new file mode 100644 index 0000000..d55be10 --- /dev/null +++ b/OF DL/Utils/XmlUtils.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml.Linq; + +namespace OF_DL.Utils +{ + internal static class XmlUtils + { + public static string EvaluateInnerText(string xmlValue) + { + try + { + var parsedText = XElement.Parse($"{xmlValue}"); + return parsedText.Value; + } + catch + { } + + return string.Empty; + } + } +} diff --git a/OF DL/Widevine/CDM.cs b/OF DL/Widevine/CDM.cs new file mode 100644 index 0000000..bfb2841 --- /dev/null +++ b/OF DL/Widevine/CDM.cs @@ -0,0 +1,581 @@ +using ProtoBuf; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Security.Cryptography; +using System.Text; +using WidevineClient.Crypto; + +namespace WidevineClient.Widevine +{ + public class CDM + { + static Dictionary Devices { get; } = new Dictionary() + { + [Constants.DEVICE_NAME] = new CDMDevice(Constants.DEVICE_NAME, null, null, null) + }; + static Dictionary Sessions { get; set; } = new Dictionary(); + + static byte[] CheckPSSH(string psshB64) + { + byte[] systemID = new byte[] { 237, 239, 139, 169, 121, 214, 74, 206, 163, 200, 39, 220, 213, 29, 33, 237 }; + + if (psshB64.Length % 4 != 0) + { + psshB64 = psshB64.PadRight(psshB64.Length + (4 - (psshB64.Length % 4)), '='); + } + + byte[] pssh = Convert.FromBase64String(psshB64); + + if (pssh.Length < 30) + return pssh; + + if (!pssh[12..28].SequenceEqual(systemID)) + { + List newPssh = new List() { 0, 0, 0 }; + newPssh.Add((byte)(32 + pssh.Length)); + newPssh.AddRange(Encoding.UTF8.GetBytes("pssh")); + newPssh.AddRange(new byte[] { 0, 0, 0, 0 }); + newPssh.AddRange(systemID); + newPssh.AddRange(new byte[] { 0, 0, 0, 0 }); + newPssh[31] = (byte)(pssh.Length); + newPssh.AddRange(pssh); + + return newPssh.ToArray(); + } + else + { + return pssh; + } + } + + public static string OpenSession(string initDataB64, string deviceName, bool offline = false, bool raw = false) + { + byte[] initData = CheckPSSH(initDataB64); + + var device = Devices[deviceName]; + + byte[] sessionId = new byte[16]; + + if (device.IsAndroid) + { + string randHex = ""; + + Random rand = new Random(); + string choice = "ABCDEF0123456789"; + for (int i = 0; i < 16; i++) + randHex += choice[rand.Next(16)]; + + string counter = "01"; + string rest = "00000000000000"; + sessionId = Encoding.ASCII.GetBytes(randHex + counter + rest); + } + else + { + Random rand = new Random(); + rand.NextBytes(sessionId); + } + + Session session; + dynamic parsedInitData = ParseInitData(initData); + + if (parsedInitData != null) + { + session = new Session(sessionId, parsedInitData, device, offline); + } + else if (raw) + { + session = new Session(sessionId, initData, device, offline); + } + else + { + return null; + } + + Sessions.Add(Utils.BytesToHex(sessionId), session); + + return Utils.BytesToHex(sessionId); + } + + static WidevineCencHeader ParseInitData(byte[] initData) + { + WidevineCencHeader cencHeader; + + try + { + cencHeader = Serializer.Deserialize(new MemoryStream(initData[32..])); + } + catch + { + try + { + //needed for HBO Max + + PSSHBox psshBox = PSSHBox.FromByteArray(initData); + cencHeader = Serializer.Deserialize(new MemoryStream(psshBox.Data)); + } + catch + { + //Logger.Verbose("Unable to parse, unsupported init data format"); + return null; + } + } + + return cencHeader; + } + + public static bool CloseSession(string sessionId) + { + //Logger.Debug($"CloseSession(session_id={Utils.BytesToHex(sessionId)})"); + //Logger.Verbose("Closing CDM session"); + + if (Sessions.ContainsKey(sessionId)) + { + Sessions.Remove(sessionId); + //Logger.Verbose("CDM session closed"); + return true; + } + else + { + //Logger.Info($"Session {sessionId} not found"); + return false; + } + } + + public static bool SetServiceCertificate(string sessionId, byte[] certData) + { + //Logger.Debug($"SetServiceCertificate(sessionId={Utils.BytesToHex(sessionId)}, cert={certB64})"); + //Logger.Verbose($"Setting service certificate"); + + if (!Sessions.ContainsKey(sessionId)) + { + //Logger.Error("Session ID doesn't exist"); + return false; + } + + SignedMessage signedMessage = new SignedMessage(); + + try + { + signedMessage = Serializer.Deserialize(new MemoryStream(certData)); + } + catch + { + //Logger.Warn("Failed to parse cert as SignedMessage"); + } + + SignedDeviceCertificate serviceCertificate; + try + { + try + { + //Logger.Debug("Service cert provided as signedmessage"); + serviceCertificate = Serializer.Deserialize(new MemoryStream(signedMessage.Msg)); + } + catch + { + //Logger.Debug("Service cert provided as signeddevicecertificate"); + serviceCertificate = Serializer.Deserialize(new MemoryStream(certData)); + } + } + catch + { + //Logger.Error("Failed to parse service certificate"); + return false; + } + + Sessions[sessionId].ServiceCertificate = serviceCertificate; + Sessions[sessionId].PrivacyMode = true; + + return true; + } + + public static byte[] GetLicenseRequest(string sessionId) + { + //Logger.Debug($"GetLicenseRequest(sessionId={Utils.BytesToHex(sessionId)})"); + //Logger.Verbose($"Getting license request"); + + if (!Sessions.ContainsKey(sessionId)) + { + //Logger.Error("Session ID doesn't exist"); + return null; + } + + var session = Sessions[sessionId]; + + //Logger.Debug("Building license request"); + + dynamic licenseRequest; + + if (session.InitData is WidevineCencHeader) + { + licenseRequest = new SignedLicenseRequest + { + Type = SignedLicenseRequest.MessageType.LicenseRequest, + Msg = new LicenseRequest + { + Type = LicenseRequest.RequestType.New, + KeyControlNonce = 1093602366, + ProtocolVersion = ProtocolVersion.Current, + ContentId = new LicenseRequest.ContentIdentification + { + CencId = new LicenseRequest.ContentIdentification.Cenc + { + LicenseType = session.Offline ? LicenseType.Offline : LicenseType.Default, + RequestId = session.SessionId, + Pssh = session.InitData + } + } + } + }; + } + else + { + licenseRequest = new SignedLicenseRequestRaw + { + Type = SignedLicenseRequestRaw.MessageType.LicenseRequest, + Msg = new LicenseRequestRaw + { + Type = LicenseRequestRaw.RequestType.New, + KeyControlNonce = 1093602366, + ProtocolVersion = ProtocolVersion.Current, + ContentId = new LicenseRequestRaw.ContentIdentification + { + CencId = new LicenseRequestRaw.ContentIdentification.Cenc + { + LicenseType = session.Offline ? LicenseType.Offline : LicenseType.Default, + RequestId = session.SessionId, + Pssh = session.InitData + } + } + } + }; + } + + if (session.PrivacyMode) + { + //Logger.Debug("Privacy mode & serivce certificate loaded, encrypting client id"); + + EncryptedClientIdentification encryptedClientIdProto = new EncryptedClientIdentification(); + + //Logger.Debug("Unencrypted client id " + Utils.SerializeToString(clientId)); + + using var memoryStream = new MemoryStream(); + Serializer.Serialize(memoryStream, session.Device.ClientID); + byte[] data = Padding.AddPKCS7Padding(memoryStream.ToArray(), 16); + + using AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider + { + BlockSize = 128, + Padding = PaddingMode.PKCS7, + Mode = CipherMode.CBC + }; + aesProvider.GenerateKey(); + aesProvider.GenerateIV(); + + using MemoryStream mstream = new MemoryStream(); + using CryptoStream cryptoStream = new CryptoStream(mstream, aesProvider.CreateEncryptor(aesProvider.Key, aesProvider.IV), CryptoStreamMode.Write); + cryptoStream.Write(data, 0, data.Length); + encryptedClientIdProto.EncryptedClientId = mstream.ToArray(); + + using RSACryptoServiceProvider RSA = new RSACryptoServiceProvider(); + RSA.ImportRSAPublicKey(session.ServiceCertificate.DeviceCertificate.PublicKey, out int bytesRead); + encryptedClientIdProto.EncryptedPrivacyKey = RSA.Encrypt(aesProvider.Key, RSAEncryptionPadding.OaepSHA1); + encryptedClientIdProto.EncryptedClientIdIv = aesProvider.IV; + encryptedClientIdProto.ServiceId = Encoding.UTF8.GetString(session.ServiceCertificate.DeviceCertificate.ServiceId); + encryptedClientIdProto.ServiceCertificateSerialNumber = session.ServiceCertificate.DeviceCertificate.SerialNumber; + + licenseRequest.Msg.EncryptedClientId = encryptedClientIdProto; + } + else + { + licenseRequest.Msg.ClientId = session.Device.ClientID; + } + + //Logger.Debug("Signing license request"); + + using (var memoryStream = new MemoryStream()) + { + Serializer.Serialize(memoryStream, licenseRequest.Msg); + byte[] data = memoryStream.ToArray(); + session.LicenseRequest = data; + + licenseRequest.Signature = session.Device.Sign(data); + } + + //Logger.Verbose("License request created"); + + byte[] requestBytes; + using (var memoryStream = new MemoryStream()) + { + Serializer.Serialize(memoryStream, licenseRequest); + requestBytes = memoryStream.ToArray(); + } + + Sessions[sessionId] = session; + + //Logger.Debug($"license request b64: {Convert.ToBase64String(requestBytes)}"); + return requestBytes; + } + + public static void ProvideLicense(string sessionId, byte[] license) + { + //Logger.Debug($"ProvideLicense(sessionId={Utils.BytesToHex(sessionId)}, licenseB64={licenseB64})"); + //Logger.Verbose("Decrypting provided license"); + + if (!Sessions.ContainsKey(sessionId)) + { + throw new Exception("Session ID doesn't exist"); + } + + var session = Sessions[sessionId]; + + if (session.LicenseRequest == null) + { + throw new Exception("Generate a license request first"); + } + + SignedLicense signedLicense; + try + { + signedLicense = Serializer.Deserialize(new MemoryStream(license)); + } + catch + { + throw new Exception("Unable to parse license"); + } + + //Logger.Debug("License: " + Utils.SerializeToString(signedLicense)); + + session.License = signedLicense; + + //Logger.Debug($"Deriving keys from session key"); + + try + { + var sessionKey = session.Device.Decrypt(session.License.SessionKey); + + if (sessionKey.Length != 16) + { + throw new Exception("Unable to decrypt session key"); + } + + session.SessionKey = sessionKey; + } + catch + { + throw new Exception("Unable to decrypt session key"); + } + + //Logger.Debug("Session key: " + Utils.BytesToHex(session.SessionKey)); + + session.DerivedKeys = DeriveKeys(session.LicenseRequest, session.SessionKey); + + //Logger.Debug("Verifying license signature"); + + byte[] licenseBytes; + using (var memoryStream = new MemoryStream()) + { + Serializer.Serialize(memoryStream, signedLicense.Msg); + licenseBytes = memoryStream.ToArray(); + } + byte[] hmacHash = CryptoUtils.GetHMACSHA256Digest(licenseBytes, session.DerivedKeys.Auth1); + + if (!hmacHash.SequenceEqual(signedLicense.Signature)) + { + throw new Exception("License signature mismatch"); + } + + foreach (License.KeyContainer key in signedLicense.Msg.Keys) + { + string type = key.Type.ToString(); + + if (type == "Signing") + continue; + + byte[] keyId; + byte[] encryptedKey = key.Key; + byte[] iv = key.Iv; + keyId = key.Id; + if (keyId == null) + { + keyId = Encoding.ASCII.GetBytes(key.Type.ToString()); + } + + byte[] decryptedKey; + + using MemoryStream mstream = new MemoryStream(); + using AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider + { + Mode = CipherMode.CBC, + Padding = PaddingMode.PKCS7 + }; + using CryptoStream cryptoStream = new CryptoStream(mstream, aesProvider.CreateDecryptor(session.DerivedKeys.Enc, iv), CryptoStreamMode.Write); + cryptoStream.Write(encryptedKey, 0, encryptedKey.Length); + decryptedKey = mstream.ToArray(); + + List permissions = new List(); + if (type == "OperatorSession") + { + foreach (PropertyInfo perm in key._OperatorSessionKeyPermissions.GetType().GetProperties()) + { + if ((uint)perm.GetValue(key._OperatorSessionKeyPermissions) == 1) + { + permissions.Add(perm.Name); + } + } + } + session.ContentKeys.Add(new ContentKey + { + KeyID = keyId, + Type = type, + Bytes = decryptedKey, + Permissions = permissions + }); + } + + //Logger.Debug($"Key count: {session.Keys.Count}"); + + Sessions[sessionId] = session; + + //Logger.Verbose("Decrypted all keys"); + } + + public static DerivedKeys DeriveKeys(byte[] message, byte[] key) + { + byte[] encKeyBase = Encoding.UTF8.GetBytes("ENCRYPTION").Concat(new byte[] { 0x0, }).Concat(message).Concat(new byte[] { 0x0, 0x0, 0x0, 0x80 }).ToArray(); + byte[] authKeyBase = Encoding.UTF8.GetBytes("AUTHENTICATION").Concat(new byte[] { 0x0, }).Concat(message).Concat(new byte[] { 0x0, 0x0, 0x2, 0x0 }).ToArray(); + + byte[] encKey = new byte[] { 0x01 }.Concat(encKeyBase).ToArray(); + byte[] authKey1 = new byte[] { 0x01 }.Concat(authKeyBase).ToArray(); + byte[] authKey2 = new byte[] { 0x02 }.Concat(authKeyBase).ToArray(); + byte[] authKey3 = new byte[] { 0x03 }.Concat(authKeyBase).ToArray(); + byte[] authKey4 = new byte[] { 0x04 }.Concat(authKeyBase).ToArray(); + + byte[] encCmacKey = CryptoUtils.GetCMACDigest(encKey, key); + byte[] authCmacKey1 = CryptoUtils.GetCMACDigest(authKey1, key); + byte[] authCmacKey2 = CryptoUtils.GetCMACDigest(authKey2, key); + byte[] authCmacKey3 = CryptoUtils.GetCMACDigest(authKey3, key); + byte[] authCmacKey4 = CryptoUtils.GetCMACDigest(authKey4, key); + + byte[] authCmacCombined1 = authCmacKey1.Concat(authCmacKey2).ToArray(); + byte[] authCmacCombined2 = authCmacKey3.Concat(authCmacKey4).ToArray(); + + return new DerivedKeys + { + Auth1 = authCmacCombined1, + Auth2 = authCmacCombined2, + Enc = encCmacKey + }; + } + + public static List GetKeys(string sessionId) + { + if (Sessions.ContainsKey(sessionId)) + return Sessions[sessionId].ContentKeys; + else + { + throw new Exception("Session not found"); + } + } + } +} + + + +/* + public static List ProvideLicense(string requestB64, string licenseB64) + { + byte[] licenseRequest; + + var request = Serializer.Deserialize(new MemoryStream(Convert.FromBase64String(requestB64))); + + using (var ms = new MemoryStream()) + { + Serializer.Serialize(ms, request.Msg); + licenseRequest = ms.ToArray(); + } + + SignedLicense signedLicense; + try + { + signedLicense = Serializer.Deserialize(new MemoryStream(Convert.FromBase64String(licenseB64))); + } + catch + { + return null; + } + + byte[] sessionKey; + try + { + + sessionKey = Controllers.Adapter.OaepDecrypt(Convert.ToBase64String(signedLicense.SessionKey)); + + if (sessionKey.Length != 16) + { + return null; + } + } + catch + { + return null; + } + + byte[] encKeyBase = Encoding.UTF8.GetBytes("ENCRYPTION").Concat(new byte[] { 0x0, }).Concat(licenseRequest).Concat(new byte[] { 0x0, 0x0, 0x0, 0x80 }).ToArray(); + + byte[] encKey = new byte[] { 0x01 }.Concat(encKeyBase).ToArray(); + + byte[] encCmacKey = GetCmacDigest(encKey, sessionKey); + + byte[] encryptionKey = encCmacKey; + + List keys = new List(); + + foreach (License.KeyContainer key in signedLicense.Msg.Keys) + { + string type = key.Type.ToString(); + if (type == "Signing") + { + continue; + } + + byte[] keyId; + byte[] encryptedKey = key.Key; + byte[] iv = key.Iv; + keyId = key.Id; + if (keyId == null) + { + keyId = Encoding.ASCII.GetBytes(key.Type.ToString()); + } + + byte[] decryptedKey; + + using MemoryStream mstream = new MemoryStream(); + using AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider + { + Mode = CipherMode.CBC, + Padding = PaddingMode.PKCS7 + }; + using CryptoStream cryptoStream = new CryptoStream(mstream, aesProvider.CreateDecryptor(encryptionKey, iv), CryptoStreamMode.Write); + cryptoStream.Write(encryptedKey, 0, encryptedKey.Length); + decryptedKey = mstream.ToArray(); + + List permissions = new List(); + if (type == "OPERATOR_SESSION") + { + foreach (FieldInfo perm in key._OperatorSessionKeyPermissions.GetType().GetFields()) + { + if ((uint)perm.GetValue(key._OperatorSessionKeyPermissions) == 1) + { + permissions.Add(perm.Name); + } + } + } + keys.Add(BitConverter.ToString(keyId).Replace("-","").ToLower() + ":" + BitConverter.ToString(decryptedKey).Replace("-", "").ToLower()); + } + + return keys; + }*/ diff --git a/OF DL/Widevine/CDMDevice.cs b/OF DL/Widevine/CDMDevice.cs new file mode 100644 index 0000000..4259511 --- /dev/null +++ b/OF DL/Widevine/CDMDevice.cs @@ -0,0 +1,93 @@ +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Encodings; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Signers; +using Org.BouncyCastle.OpenSsl; +using ProtoBuf; +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace WidevineClient.Widevine +{ + public class CDMDevice + { + public string DeviceName { get; set; } + public ClientIdentification ClientID { get; set; } + AsymmetricCipherKeyPair DeviceKeys { get; set; } + + public virtual bool IsAndroid { get; set; } = true; + + public CDMDevice(string deviceName, byte[] clientIdBlobBytes = null, byte[] privateKeyBytes = null, byte[] vmpBytes = null) + { + DeviceName = deviceName; + + string privateKeyPath = Path.Join(Constants.DEVICES_FOLDER, deviceName, "device_private_key"); + string vmpPath = Path.Join(Constants.DEVICES_FOLDER, deviceName, "device_vmp_blob"); + + if (clientIdBlobBytes == null) + { + string clientIDPath = Path.Join(Constants.DEVICES_FOLDER, deviceName, "device_client_id_blob"); + + if (!File.Exists(clientIDPath)) + throw new Exception("No client id blob found"); + + clientIdBlobBytes = File.ReadAllBytes(clientIDPath); + } + + ClientID = Serializer.Deserialize(new MemoryStream(clientIdBlobBytes)); + + if (privateKeyBytes != null) + { + using var reader = new StringReader(Encoding.UTF8.GetString(privateKeyBytes)); + DeviceKeys = (AsymmetricCipherKeyPair)new PemReader(reader).ReadObject(); + } + else if (File.Exists(privateKeyPath)) + { + using var reader = File.OpenText(privateKeyPath); + DeviceKeys = (AsymmetricCipherKeyPair)new PemReader(reader).ReadObject(); + } + + if (vmpBytes != null) + { + var vmp = Serializer.Deserialize(new MemoryStream(vmpBytes)); + ClientID.FileHashes = vmp; + } + else if (File.Exists(vmpPath)) + { + var vmp = Serializer.Deserialize(new MemoryStream(File.ReadAllBytes(vmpPath))); + ClientID.FileHashes = vmp; + } + } + + public virtual byte[] Decrypt(byte[] data) + { + OaepEncoding eng = new OaepEncoding(new RsaEngine()); + eng.Init(false, DeviceKeys.Private); + + int length = data.Length; + int blockSize = eng.GetInputBlockSize(); + + List plainText = new List(); + + for (int chunkPosition = 0; chunkPosition < length; chunkPosition += blockSize) + { + int chunkSize = Math.Min(blockSize, length - chunkPosition); + plainText.AddRange(eng.ProcessBlock(data, chunkPosition, chunkSize)); + } + + return plainText.ToArray(); + } + + public virtual byte[] Sign(byte[] data) + { + PssSigner eng = new PssSigner(new RsaEngine(), new Sha1Digest()); + + eng.Init(true, DeviceKeys.Private); + eng.BlockUpdate(data, 0, data.Length); + return eng.GenerateSignature(); + } + } +} diff --git a/OF DL/Widevine/Constants.cs b/OF DL/Widevine/Constants.cs new file mode 100644 index 0000000..a206c2f --- /dev/null +++ b/OF DL/Widevine/Constants.cs @@ -0,0 +1,9 @@ +namespace WidevineClient.Widevine +{ + public class Constants + { + public static string WORKING_FOLDER { get; set; } = System.IO.Path.GetFullPath(System.IO.Path.Join(System.IO.Directory.GetCurrentDirectory(), "cdm")); + public static string DEVICES_FOLDER { get; set; } = System.IO.Path.GetFullPath(System.IO.Path.Join(WORKING_FOLDER, "devices")); + public static string DEVICE_NAME { get; set; } = "chrome_1610"; + } +} diff --git a/OF DL/Widevine/ContentKey.cs b/OF DL/Widevine/ContentKey.cs new file mode 100644 index 0000000..f10b9be --- /dev/null +++ b/OF DL/Widevine/ContentKey.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; +using System.Text.Json.Serialization; + +namespace WidevineClient.Widevine +{ + [Serializable] + public class ContentKey + { + [JsonPropertyName("key_id")] + public byte[] KeyID { get; set; } + + [JsonPropertyName("type")] + public string Type { get; set; } + + [JsonPropertyName("bytes")] + public byte[] Bytes { get; set; } + + [NotMapped] + [JsonPropertyName("permissions")] + public List Permissions { + get + { + return PermissionsString.Split(",").ToList(); + } + set + { + PermissionsString = string.Join(",", value); + } + } + + [JsonIgnore] + public string PermissionsString { get; set; } + + public override string ToString() + { + return $"{BitConverter.ToString(KeyID).Replace("-", "").ToLower()}:{BitConverter.ToString(Bytes).Replace("-", "").ToLower()}"; + } + } +} diff --git a/OF DL/Widevine/DerivedKeys.cs b/OF DL/Widevine/DerivedKeys.cs new file mode 100644 index 0000000..27b95be --- /dev/null +++ b/OF DL/Widevine/DerivedKeys.cs @@ -0,0 +1,9 @@ +namespace WidevineClient.Widevine +{ + public class DerivedKeys + { + public byte[] Auth1 { get; set; } + public byte[] Auth2 { get; set; } + public byte[] Enc { get; set; } + } +} diff --git a/OF DL/Widevine/PSSHBox.cs b/OF DL/Widevine/PSSHBox.cs new file mode 100644 index 0000000..c735366 --- /dev/null +++ b/OF DL/Widevine/PSSHBox.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace WidevineClient.Widevine +{ + class PSSHBox + { + static readonly byte[] PSSH_HEADER = new byte[] { 0x70, 0x73, 0x73, 0x68 }; + + public List KIDs { get; set; } = new List(); + public byte[] Data { get; set; } + + PSSHBox(List kids, byte[] data) + { + KIDs = kids; + Data = data; + } + + public static PSSHBox FromByteArray(byte[] psshbox) + { + using var stream = new System.IO.MemoryStream(psshbox); + + stream.Seek(4, System.IO.SeekOrigin.Current); + byte[] header = new byte[4]; + stream.Read(header, 0, 4); + + if (!header.SequenceEqual(PSSH_HEADER)) + throw new Exception("Not a pssh box"); + + stream.Seek(20, System.IO.SeekOrigin.Current); + byte[] kidCountBytes = new byte[4]; + stream.Read(kidCountBytes, 0, 4); + + if (BitConverter.IsLittleEndian) + Array.Reverse(kidCountBytes); + uint kidCount = BitConverter.ToUInt32(kidCountBytes); + + List kids = new List(); + for (int i = 0; i < kidCount; i++) + { + byte[] kid = new byte[16]; + stream.Read(kid); + kids.Add(kid); + } + + byte[] dataLengthBytes = new byte[4]; + stream.Read(dataLengthBytes); + + if (BitConverter.IsLittleEndian) + Array.Reverse(dataLengthBytes); + uint dataLength = BitConverter.ToUInt32(dataLengthBytes); + + if (dataLength == 0) + return new PSSHBox(kids, null); + + byte[] data = new byte[dataLength]; + stream.Read(data); + + return new PSSHBox(kids, data); + } + } +} diff --git a/OF DL/Widevine/Session.cs b/OF DL/Widevine/Session.cs new file mode 100644 index 0000000..51cd618 --- /dev/null +++ b/OF DL/Widevine/Session.cs @@ -0,0 +1,27 @@ +using System.Collections.Generic; + +namespace WidevineClient.Widevine +{ + class Session + { + public byte[] SessionId { get; set; } + public dynamic InitData { get; set; } + public bool Offline { get; set; } + public CDMDevice Device { get; set; } + public byte[] SessionKey { get; set; } + public DerivedKeys DerivedKeys { get; set; } + public byte[] LicenseRequest { get; set; } + public SignedLicense License { get; set; } + public SignedDeviceCertificate ServiceCertificate { get; set; } + public bool PrivacyMode { get; set; } + public List ContentKeys { get; set; } = new List(); + + public Session(byte[] sessionId, dynamic initData, CDMDevice device, bool offline) + { + SessionId = sessionId; + InitData = initData; + Offline = offline; + Device = device; + } + } +} \ No newline at end of file diff --git a/OF DL/Widevine/WvProto2.cs b/OF DL/Widevine/WvProto2.cs new file mode 100644 index 0000000..2a5c0b4 --- /dev/null +++ b/OF DL/Widevine/WvProto2.cs @@ -0,0 +1,2257 @@ +// +// This file was generated by a tool; you should avoid making direct changes. +// Consider using 'partial classes' to extend these types +// Input: my.proto +// + +#region Designer generated code +#pragma warning disable CS0612, CS0618, CS1591, CS3021, IDE0079, IDE1006, RCS1036, RCS1057, RCS1085, RCS1192 +[global::ProtoBuf.ProtoContract()] +public partial class ClientIdentification : global::ProtoBuf.IExtensible +{ + private global::ProtoBuf.IExtension __pbn__extensionData; + global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) + => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing); + + [global::ProtoBuf.ProtoMember(1, IsRequired = true)] + public TokenType Type { get; set; } + + [global::ProtoBuf.ProtoMember(2)] + public SignedDeviceCertificate Token { get; set; } + + [global::ProtoBuf.ProtoMember(3, Name = @"ClientInfo")] + public global::System.Collections.Generic.List ClientInfoes { get; } = new global::System.Collections.Generic.List(); + + [global::ProtoBuf.ProtoMember(4)] + public byte[] ProviderClientToken + { + get => __pbn__ProviderClientToken; + set => __pbn__ProviderClientToken = value; + } + public bool ShouldSerializeProviderClientToken() => __pbn__ProviderClientToken != null; + public void ResetProviderClientToken() => __pbn__ProviderClientToken = null; + private byte[] __pbn__ProviderClientToken; + + [global::ProtoBuf.ProtoMember(5)] + public uint LicenseCounter + { + get => __pbn__LicenseCounter.GetValueOrDefault(); + set => __pbn__LicenseCounter = value; + } + public bool ShouldSerializeLicenseCounter() => __pbn__LicenseCounter != null; + public void ResetLicenseCounter() => __pbn__LicenseCounter = null; + private uint? __pbn__LicenseCounter; + + [global::ProtoBuf.ProtoMember(6)] + public ClientCapabilities _ClientCapabilities { get; set; } + + [global::ProtoBuf.ProtoMember(7, Name = @"_FileHashes")] + public FileHashes FileHashes { get; set; } + + [global::ProtoBuf.ProtoContract()] + public partial class NameValue : global::ProtoBuf.IExtensible + { + private global::ProtoBuf.IExtension __pbn__extensionData; + global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) + => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing); + + [global::ProtoBuf.ProtoMember(1, IsRequired = true)] + public string Name { get; set; } + + [global::ProtoBuf.ProtoMember(2, IsRequired = true)] + public string Value { get; set; } + + } + + [global::ProtoBuf.ProtoContract()] + public partial class ClientCapabilities : global::ProtoBuf.IExtensible + { + private global::ProtoBuf.IExtension __pbn__extensionData; + global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) + => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing); + + [global::ProtoBuf.ProtoMember(1)] + public uint ClientToken + { + get => __pbn__ClientToken.GetValueOrDefault(); + set => __pbn__ClientToken = value; + } + public bool ShouldSerializeClientToken() => __pbn__ClientToken != null; + public void ResetClientToken() => __pbn__ClientToken = null; + private uint? __pbn__ClientToken; + + [global::ProtoBuf.ProtoMember(2)] + public uint SessionToken + { + get => __pbn__SessionToken.GetValueOrDefault(); + set => __pbn__SessionToken = value; + } + public bool ShouldSerializeSessionToken() => __pbn__SessionToken != null; + public void ResetSessionToken() => __pbn__SessionToken = null; + private uint? __pbn__SessionToken; + + [global::ProtoBuf.ProtoMember(3)] + public uint VideoResolutionConstraints + { + get => __pbn__VideoResolutionConstraints.GetValueOrDefault(); + set => __pbn__VideoResolutionConstraints = value; + } + public bool ShouldSerializeVideoResolutionConstraints() => __pbn__VideoResolutionConstraints != null; + public void ResetVideoResolutionConstraints() => __pbn__VideoResolutionConstraints = null; + private uint? __pbn__VideoResolutionConstraints; + + [global::ProtoBuf.ProtoMember(4)] + [global::System.ComponentModel.DefaultValue(HdcpVersion.HdcpNone)] + public HdcpVersion MaxHdcpVersion + { + get => __pbn__MaxHdcpVersion ?? HdcpVersion.HdcpNone; + set => __pbn__MaxHdcpVersion = value; + } + public bool ShouldSerializeMaxHdcpVersion() => __pbn__MaxHdcpVersion != null; + public void ResetMaxHdcpVersion() => __pbn__MaxHdcpVersion = null; + private HdcpVersion? __pbn__MaxHdcpVersion; + + [global::ProtoBuf.ProtoMember(5)] + public uint OemCryptoApiVersion + { + get => __pbn__OemCryptoApiVersion.GetValueOrDefault(); + set => __pbn__OemCryptoApiVersion = value; + } + public bool ShouldSerializeOemCryptoApiVersion() => __pbn__OemCryptoApiVersion != null; + public void ResetOemCryptoApiVersion() => __pbn__OemCryptoApiVersion = null; + private uint? __pbn__OemCryptoApiVersion; + + [global::ProtoBuf.ProtoContract()] + public enum HdcpVersion + { + [global::ProtoBuf.ProtoEnum(Name = @"HDCP_NONE")] + HdcpNone = 0, + [global::ProtoBuf.ProtoEnum(Name = @"HDCP_V1")] + HdcpV1 = 1, + [global::ProtoBuf.ProtoEnum(Name = @"HDCP_V2")] + HdcpV2 = 2, + [global::ProtoBuf.ProtoEnum(Name = @"HDCP_V2_1")] + HdcpV21 = 3, + [global::ProtoBuf.ProtoEnum(Name = @"HDCP_V2_2")] + HdcpV22 = 4, + [global::ProtoBuf.ProtoEnum(Name = @"HDCP_V2_3")] + HdcpV23 = 5, + } + + } + + [global::ProtoBuf.ProtoContract()] + public enum TokenType + { + [global::ProtoBuf.ProtoEnum(Name = @"KEYBOX")] + Keybox = 0, + [global::ProtoBuf.ProtoEnum(Name = @"DEVICE_CERTIFICATE")] + DeviceCertificate = 1, + [global::ProtoBuf.ProtoEnum(Name = @"REMOTE_ATTESTATION_CERTIFICATE")] + RemoteAttestationCertificate = 2, + } + +} + +[global::ProtoBuf.ProtoContract()] +public partial class DeviceCertificate : global::ProtoBuf.IExtensible +{ + private global::ProtoBuf.IExtension __pbn__extensionData; + global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) + => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing); + + [global::ProtoBuf.ProtoMember(1, IsRequired = true)] + public CertificateType Type { get; set; } + + [global::ProtoBuf.ProtoMember(2)] + public byte[] SerialNumber + { + get => __pbn__SerialNumber; + set => __pbn__SerialNumber = value; + } + public bool ShouldSerializeSerialNumber() => __pbn__SerialNumber != null; + public void ResetSerialNumber() => __pbn__SerialNumber = null; + private byte[] __pbn__SerialNumber; + + [global::ProtoBuf.ProtoMember(3)] + public uint CreationTimeSeconds + { + get => __pbn__CreationTimeSeconds.GetValueOrDefault(); + set => __pbn__CreationTimeSeconds = value; + } + public bool ShouldSerializeCreationTimeSeconds() => __pbn__CreationTimeSeconds != null; + public void ResetCreationTimeSeconds() => __pbn__CreationTimeSeconds = null; + private uint? __pbn__CreationTimeSeconds; + + [global::ProtoBuf.ProtoMember(4)] + public byte[] PublicKey + { + get => __pbn__PublicKey; + set => __pbn__PublicKey = value; + } + public bool ShouldSerializePublicKey() => __pbn__PublicKey != null; + public void ResetPublicKey() => __pbn__PublicKey = null; + private byte[] __pbn__PublicKey; + + [global::ProtoBuf.ProtoMember(5)] + public uint SystemId + { + get => __pbn__SystemId.GetValueOrDefault(); + set => __pbn__SystemId = value; + } + public bool ShouldSerializeSystemId() => __pbn__SystemId != null; + public void ResetSystemId() => __pbn__SystemId = null; + private uint? __pbn__SystemId; + + [global::ProtoBuf.ProtoMember(6)] + public uint TestDeviceDeprecated + { + get => __pbn__TestDeviceDeprecated.GetValueOrDefault(); + set => __pbn__TestDeviceDeprecated = value; + } + public bool ShouldSerializeTestDeviceDeprecated() => __pbn__TestDeviceDeprecated != null; + public void ResetTestDeviceDeprecated() => __pbn__TestDeviceDeprecated = null; + private uint? __pbn__TestDeviceDeprecated; + + [global::ProtoBuf.ProtoMember(7)] + public byte[] ServiceId + { + get => __pbn__ServiceId; + set => __pbn__ServiceId = value; + } + public bool ShouldSerializeServiceId() => __pbn__ServiceId != null; + public void ResetServiceId() => __pbn__ServiceId = null; + private byte[] __pbn__ServiceId; + + [global::ProtoBuf.ProtoContract()] + public enum CertificateType + { + [global::ProtoBuf.ProtoEnum(Name = @"ROOT")] + Root = 0, + [global::ProtoBuf.ProtoEnum(Name = @"INTERMEDIATE")] + Intermediate = 1, + [global::ProtoBuf.ProtoEnum(Name = @"USER_DEVICE")] + UserDevice = 2, + [global::ProtoBuf.ProtoEnum(Name = @"SERVICE")] + Service = 3, + } + +} + +[global::ProtoBuf.ProtoContract()] +public partial class DeviceCertificateStatus : global::ProtoBuf.IExtensible +{ + private global::ProtoBuf.IExtension __pbn__extensionData; + global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) + => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing); + + [global::ProtoBuf.ProtoMember(1)] + public byte[] SerialNumber + { + get => __pbn__SerialNumber; + set => __pbn__SerialNumber = value; + } + public bool ShouldSerializeSerialNumber() => __pbn__SerialNumber != null; + public void ResetSerialNumber() => __pbn__SerialNumber = null; + private byte[] __pbn__SerialNumber; + + [global::ProtoBuf.ProtoMember(2)] + [global::System.ComponentModel.DefaultValue(CertificateStatus.Valid)] + public CertificateStatus Status + { + get => __pbn__Status ?? CertificateStatus.Valid; + set => __pbn__Status = value; + } + public bool ShouldSerializeStatus() => __pbn__Status != null; + public void ResetStatus() => __pbn__Status = null; + private CertificateStatus? __pbn__Status; + + [global::ProtoBuf.ProtoMember(4)] + public ProvisionedDeviceInfo DeviceInfo { get; set; } + + [global::ProtoBuf.ProtoContract()] + public enum CertificateStatus + { + [global::ProtoBuf.ProtoEnum(Name = @"VALID")] + Valid = 0, + [global::ProtoBuf.ProtoEnum(Name = @"REVOKED")] + Revoked = 1, + } + +} + +[global::ProtoBuf.ProtoContract()] +public partial class DeviceCertificateStatusList : global::ProtoBuf.IExtensible +{ + private global::ProtoBuf.IExtension __pbn__extensionData; + global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) + => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing); + + [global::ProtoBuf.ProtoMember(1)] + public uint CreationTimeSeconds + { + get => __pbn__CreationTimeSeconds.GetValueOrDefault(); + set => __pbn__CreationTimeSeconds = value; + } + public bool ShouldSerializeCreationTimeSeconds() => __pbn__CreationTimeSeconds != null; + public void ResetCreationTimeSeconds() => __pbn__CreationTimeSeconds = null; + private uint? __pbn__CreationTimeSeconds; + + [global::ProtoBuf.ProtoMember(2)] + public global::System.Collections.Generic.List CertificateStatus { get; } = new global::System.Collections.Generic.List(); + +} + +[global::ProtoBuf.ProtoContract()] +public partial class SignedDeviceCertificateStatusList : global::ProtoBuf.IExtensible +{ + private global::ProtoBuf.IExtension __pbn__extensionData; + global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) + => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing); + + [global::ProtoBuf.ProtoMember(1)] + public DeviceCertificateStatusList CertificateList { get; set; } + + [global::ProtoBuf.ProtoMember(2)] + public byte[] Signature + { + get => __pbn__Signature; + set => __pbn__Signature = value; + } + public bool ShouldSerializeSignature() => __pbn__Signature != null; + public void ResetSignature() => __pbn__Signature = null; + private byte[] __pbn__Signature; + +} + +[global::ProtoBuf.ProtoContract()] +public partial class EncryptedClientIdentification : global::ProtoBuf.IExtensible +{ + private global::ProtoBuf.IExtension __pbn__extensionData; + global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) + => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing); + + [global::ProtoBuf.ProtoMember(1, IsRequired = true)] + public string ServiceId { get; set; } + + [global::ProtoBuf.ProtoMember(2)] + public byte[] ServiceCertificateSerialNumber + { + get => __pbn__ServiceCertificateSerialNumber; + set => __pbn__ServiceCertificateSerialNumber = value; + } + public bool ShouldSerializeServiceCertificateSerialNumber() => __pbn__ServiceCertificateSerialNumber != null; + public void ResetServiceCertificateSerialNumber() => __pbn__ServiceCertificateSerialNumber = null; + private byte[] __pbn__ServiceCertificateSerialNumber; + + [global::ProtoBuf.ProtoMember(3, IsRequired = true)] + public byte[] EncryptedClientId { get; set; } + + [global::ProtoBuf.ProtoMember(4, IsRequired = true)] + public byte[] EncryptedClientIdIv { get; set; } + + [global::ProtoBuf.ProtoMember(5, IsRequired = true)] + public byte[] EncryptedPrivacyKey { get; set; } + +} + +[global::ProtoBuf.ProtoContract()] +public partial class LicenseIdentification : global::ProtoBuf.IExtensible +{ + private global::ProtoBuf.IExtension __pbn__extensionData; + global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) + => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing); + + [global::ProtoBuf.ProtoMember(1)] + public byte[] RequestId + { + get => __pbn__RequestId; + set => __pbn__RequestId = value; + } + public bool ShouldSerializeRequestId() => __pbn__RequestId != null; + public void ResetRequestId() => __pbn__RequestId = null; + private byte[] __pbn__RequestId; + + [global::ProtoBuf.ProtoMember(2)] + public byte[] SessionId + { + get => __pbn__SessionId; + set => __pbn__SessionId = value; + } + public bool ShouldSerializeSessionId() => __pbn__SessionId != null; + public void ResetSessionId() => __pbn__SessionId = null; + private byte[] __pbn__SessionId; + + [global::ProtoBuf.ProtoMember(3)] + public byte[] PurchaseId + { + get => __pbn__PurchaseId; + set => __pbn__PurchaseId = value; + } + public bool ShouldSerializePurchaseId() => __pbn__PurchaseId != null; + public void ResetPurchaseId() => __pbn__PurchaseId = null; + private byte[] __pbn__PurchaseId; + + [global::ProtoBuf.ProtoMember(4)] + [global::System.ComponentModel.DefaultValue(LicenseType.Zero)] + public LicenseType Type + { + get => __pbn__Type ?? LicenseType.Zero; + set => __pbn__Type = value; + } + public bool ShouldSerializeType() => __pbn__Type != null; + public void ResetType() => __pbn__Type = null; + private LicenseType? __pbn__Type; + + [global::ProtoBuf.ProtoMember(5)] + public uint Version + { + get => __pbn__Version.GetValueOrDefault(); + set => __pbn__Version = value; + } + public bool ShouldSerializeVersion() => __pbn__Version != null; + public void ResetVersion() => __pbn__Version = null; + private uint? __pbn__Version; + + [global::ProtoBuf.ProtoMember(6)] + public byte[] ProviderSessionToken + { + get => __pbn__ProviderSessionToken; + set => __pbn__ProviderSessionToken = value; + } + public bool ShouldSerializeProviderSessionToken() => __pbn__ProviderSessionToken != null; + public void ResetProviderSessionToken() => __pbn__ProviderSessionToken = null; + private byte[] __pbn__ProviderSessionToken; + +} + +[global::ProtoBuf.ProtoContract()] +public partial class License : global::ProtoBuf.IExtensible +{ + private global::ProtoBuf.IExtension __pbn__extensionData; + global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) + => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing); + + [global::ProtoBuf.ProtoMember(1)] + public LicenseIdentification Id { get; set; } + + [global::ProtoBuf.ProtoMember(2)] + public Policy _Policy { get; set; } + + [global::ProtoBuf.ProtoMember(3, Name = @"Key")] + public global::System.Collections.Generic.List Keys { get; } = new global::System.Collections.Generic.List(); + + [global::ProtoBuf.ProtoMember(4)] + public uint LicenseStartTime + { + get => __pbn__LicenseStartTime.GetValueOrDefault(); + set => __pbn__LicenseStartTime = value; + } + public bool ShouldSerializeLicenseStartTime() => __pbn__LicenseStartTime != null; + public void ResetLicenseStartTime() => __pbn__LicenseStartTime = null; + private uint? __pbn__LicenseStartTime; + + [global::ProtoBuf.ProtoMember(5)] + public uint RemoteAttestationVerified + { + get => __pbn__RemoteAttestationVerified.GetValueOrDefault(); + set => __pbn__RemoteAttestationVerified = value; + } + public bool ShouldSerializeRemoteAttestationVerified() => __pbn__RemoteAttestationVerified != null; + public void ResetRemoteAttestationVerified() => __pbn__RemoteAttestationVerified = null; + private uint? __pbn__RemoteAttestationVerified; + + [global::ProtoBuf.ProtoMember(6)] + public byte[] ProviderClientToken + { + get => __pbn__ProviderClientToken; + set => __pbn__ProviderClientToken = value; + } + public bool ShouldSerializeProviderClientToken() => __pbn__ProviderClientToken != null; + public void ResetProviderClientToken() => __pbn__ProviderClientToken = null; + private byte[] __pbn__ProviderClientToken; + + [global::ProtoBuf.ProtoMember(7)] + public uint ProtectionScheme + { + get => __pbn__ProtectionScheme.GetValueOrDefault(); + set => __pbn__ProtectionScheme = value; + } + public bool ShouldSerializeProtectionScheme() => __pbn__ProtectionScheme != null; + public void ResetProtectionScheme() => __pbn__ProtectionScheme = null; + private uint? __pbn__ProtectionScheme; + + [global::ProtoBuf.ProtoContract()] + public partial class Policy : global::ProtoBuf.IExtensible + { + private global::ProtoBuf.IExtension __pbn__extensionData; + global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) + => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing); + + [global::ProtoBuf.ProtoMember(1)] + public bool CanPlay + { + get => __pbn__CanPlay.GetValueOrDefault(); + set => __pbn__CanPlay = value; + } + public bool ShouldSerializeCanPlay() => __pbn__CanPlay != null; + public void ResetCanPlay() => __pbn__CanPlay = null; + private bool? __pbn__CanPlay; + + [global::ProtoBuf.ProtoMember(2)] + public bool CanPersist + { + get => __pbn__CanPersist.GetValueOrDefault(); + set => __pbn__CanPersist = value; + } + public bool ShouldSerializeCanPersist() => __pbn__CanPersist != null; + public void ResetCanPersist() => __pbn__CanPersist = null; + private bool? __pbn__CanPersist; + + [global::ProtoBuf.ProtoMember(3)] + public bool CanRenew + { + get => __pbn__CanRenew.GetValueOrDefault(); + set => __pbn__CanRenew = value; + } + public bool ShouldSerializeCanRenew() => __pbn__CanRenew != null; + public void ResetCanRenew() => __pbn__CanRenew = null; + private bool? __pbn__CanRenew; + + [global::ProtoBuf.ProtoMember(4)] + public uint RentalDurationSeconds + { + get => __pbn__RentalDurationSeconds.GetValueOrDefault(); + set => __pbn__RentalDurationSeconds = value; + } + public bool ShouldSerializeRentalDurationSeconds() => __pbn__RentalDurationSeconds != null; + public void ResetRentalDurationSeconds() => __pbn__RentalDurationSeconds = null; + private uint? __pbn__RentalDurationSeconds; + + [global::ProtoBuf.ProtoMember(5)] + public uint PlaybackDurationSeconds + { + get => __pbn__PlaybackDurationSeconds.GetValueOrDefault(); + set => __pbn__PlaybackDurationSeconds = value; + } + public bool ShouldSerializePlaybackDurationSeconds() => __pbn__PlaybackDurationSeconds != null; + public void ResetPlaybackDurationSeconds() => __pbn__PlaybackDurationSeconds = null; + private uint? __pbn__PlaybackDurationSeconds; + + [global::ProtoBuf.ProtoMember(6)] + public uint LicenseDurationSeconds + { + get => __pbn__LicenseDurationSeconds.GetValueOrDefault(); + set => __pbn__LicenseDurationSeconds = value; + } + public bool ShouldSerializeLicenseDurationSeconds() => __pbn__LicenseDurationSeconds != null; + public void ResetLicenseDurationSeconds() => __pbn__LicenseDurationSeconds = null; + private uint? __pbn__LicenseDurationSeconds; + + [global::ProtoBuf.ProtoMember(7)] + public uint RenewalRecoveryDurationSeconds + { + get => __pbn__RenewalRecoveryDurationSeconds.GetValueOrDefault(); + set => __pbn__RenewalRecoveryDurationSeconds = value; + } + public bool ShouldSerializeRenewalRecoveryDurationSeconds() => __pbn__RenewalRecoveryDurationSeconds != null; + public void ResetRenewalRecoveryDurationSeconds() => __pbn__RenewalRecoveryDurationSeconds = null; + private uint? __pbn__RenewalRecoveryDurationSeconds; + + [global::ProtoBuf.ProtoMember(8)] + [global::System.ComponentModel.DefaultValue("")] + public string RenewalServerUrl + { + get => __pbn__RenewalServerUrl ?? ""; + set => __pbn__RenewalServerUrl = value; + } + public bool ShouldSerializeRenewalServerUrl() => __pbn__RenewalServerUrl != null; + public void ResetRenewalServerUrl() => __pbn__RenewalServerUrl = null; + private string __pbn__RenewalServerUrl; + + [global::ProtoBuf.ProtoMember(9)] + public uint RenewalDelaySeconds + { + get => __pbn__RenewalDelaySeconds.GetValueOrDefault(); + set => __pbn__RenewalDelaySeconds = value; + } + public bool ShouldSerializeRenewalDelaySeconds() => __pbn__RenewalDelaySeconds != null; + public void ResetRenewalDelaySeconds() => __pbn__RenewalDelaySeconds = null; + private uint? __pbn__RenewalDelaySeconds; + + [global::ProtoBuf.ProtoMember(10)] + public uint RenewalRetryIntervalSeconds + { + get => __pbn__RenewalRetryIntervalSeconds.GetValueOrDefault(); + set => __pbn__RenewalRetryIntervalSeconds = value; + } + public bool ShouldSerializeRenewalRetryIntervalSeconds() => __pbn__RenewalRetryIntervalSeconds != null; + public void ResetRenewalRetryIntervalSeconds() => __pbn__RenewalRetryIntervalSeconds = null; + private uint? __pbn__RenewalRetryIntervalSeconds; + + [global::ProtoBuf.ProtoMember(11)] + public bool RenewWithUsage + { + get => __pbn__RenewWithUsage.GetValueOrDefault(); + set => __pbn__RenewWithUsage = value; + } + public bool ShouldSerializeRenewWithUsage() => __pbn__RenewWithUsage != null; + public void ResetRenewWithUsage() => __pbn__RenewWithUsage = null; + private bool? __pbn__RenewWithUsage; + + } + + [global::ProtoBuf.ProtoContract()] + public partial class KeyContainer : global::ProtoBuf.IExtensible + { + private global::ProtoBuf.IExtension __pbn__extensionData; + global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) + => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing); + + [global::ProtoBuf.ProtoMember(1)] + public byte[] Id + { + get => __pbn__Id; + set => __pbn__Id = value; + } + public bool ShouldSerializeId() => __pbn__Id != null; + public void ResetId() => __pbn__Id = null; + private byte[] __pbn__Id; + + [global::ProtoBuf.ProtoMember(2)] + public byte[] Iv + { + get => __pbn__Iv; + set => __pbn__Iv = value; + } + public bool ShouldSerializeIv() => __pbn__Iv != null; + public void ResetIv() => __pbn__Iv = null; + private byte[] __pbn__Iv; + + [global::ProtoBuf.ProtoMember(3)] + public byte[] Key + { + get => __pbn__Key; + set => __pbn__Key = value; + } + public bool ShouldSerializeKey() => __pbn__Key != null; + public void ResetKey() => __pbn__Key = null; + private byte[] __pbn__Key; + + [global::ProtoBuf.ProtoMember(4)] + [global::System.ComponentModel.DefaultValue(KeyType.Signing)] + public KeyType Type + { + get => __pbn__Type ?? KeyType.Signing; + set => __pbn__Type = value; + } + public bool ShouldSerializeType() => __pbn__Type != null; + public void ResetType() => __pbn__Type = null; + private KeyType? __pbn__Type; + + [global::ProtoBuf.ProtoMember(5)] + [global::System.ComponentModel.DefaultValue(SecurityLevel.SwSecureCrypto)] + public SecurityLevel Level + { + get => __pbn__Level ?? SecurityLevel.SwSecureCrypto; + set => __pbn__Level = value; + } + public bool ShouldSerializeLevel() => __pbn__Level != null; + public void ResetLevel() => __pbn__Level = null; + private SecurityLevel? __pbn__Level; + + [global::ProtoBuf.ProtoMember(6)] + public OutputProtection RequiredProtection { get; set; } + + [global::ProtoBuf.ProtoMember(7)] + public OutputProtection RequestedProtection { get; set; } + + [global::ProtoBuf.ProtoMember(8)] + public KeyControl _KeyControl { get; set; } + + [global::ProtoBuf.ProtoMember(9)] + public OperatorSessionKeyPermissions _OperatorSessionKeyPermissions { get; set; } + + [global::ProtoBuf.ProtoMember(10)] + public global::System.Collections.Generic.List VideoResolutionConstraints { get; } = new global::System.Collections.Generic.List(); + + [global::ProtoBuf.ProtoContract()] + public partial class OutputProtection : global::ProtoBuf.IExtensible + { + private global::ProtoBuf.IExtension __pbn__extensionData; + global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) + => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing); + + [global::ProtoBuf.ProtoMember(1)] + [global::System.ComponentModel.DefaultValue(ClientIdentification.ClientCapabilities.HdcpVersion.HdcpNone)] + public ClientIdentification.ClientCapabilities.HdcpVersion Hdcp + { + get => __pbn__Hdcp ?? ClientIdentification.ClientCapabilities.HdcpVersion.HdcpNone; + set => __pbn__Hdcp = value; + } + public bool ShouldSerializeHdcp() => __pbn__Hdcp != null; + public void ResetHdcp() => __pbn__Hdcp = null; + private ClientIdentification.ClientCapabilities.HdcpVersion? __pbn__Hdcp; + + [global::ProtoBuf.ProtoMember(2)] + [global::System.ComponentModel.DefaultValue(Cgms.CopyFree)] + public Cgms CgmsFlags + { + get => __pbn__CgmsFlags ?? Cgms.CopyFree; + set => __pbn__CgmsFlags = value; + } + public bool ShouldSerializeCgmsFlags() => __pbn__CgmsFlags != null; + public void ResetCgmsFlags() => __pbn__CgmsFlags = null; + private Cgms? __pbn__CgmsFlags; + + [global::ProtoBuf.ProtoContract(Name = @"CGMS")] + public enum Cgms + { + [global::ProtoBuf.ProtoEnum(Name = @"COPY_FREE")] + CopyFree = 0, + [global::ProtoBuf.ProtoEnum(Name = @"COPY_ONCE")] + CopyOnce = 2, + [global::ProtoBuf.ProtoEnum(Name = @"COPY_NEVER")] + CopyNever = 3, + [global::ProtoBuf.ProtoEnum(Name = @"CGMS_NONE")] + CgmsNone = 42, + } + + } + + [global::ProtoBuf.ProtoContract()] + public partial class KeyControl : global::ProtoBuf.IExtensible + { + private global::ProtoBuf.IExtension __pbn__extensionData; + global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) + => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing); + + [global::ProtoBuf.ProtoMember(1, IsRequired = true)] + public byte[] KeyControlBlock { get; set; } + + [global::ProtoBuf.ProtoMember(2, IsRequired = true)] + public byte[] Iv { get; set; } + + } + + [global::ProtoBuf.ProtoContract()] + public partial class OperatorSessionKeyPermissions : global::ProtoBuf.IExtensible + { + private global::ProtoBuf.IExtension __pbn__extensionData; + global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) + => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing); + + [global::ProtoBuf.ProtoMember(1)] + public uint AllowEncrypt + { + get => __pbn__AllowEncrypt.GetValueOrDefault(); + set => __pbn__AllowEncrypt = value; + } + public bool ShouldSerializeAllowEncrypt() => __pbn__AllowEncrypt != null; + public void ResetAllowEncrypt() => __pbn__AllowEncrypt = null; + private uint? __pbn__AllowEncrypt; + + [global::ProtoBuf.ProtoMember(2)] + public uint AllowDecrypt + { + get => __pbn__AllowDecrypt.GetValueOrDefault(); + set => __pbn__AllowDecrypt = value; + } + public bool ShouldSerializeAllowDecrypt() => __pbn__AllowDecrypt != null; + public void ResetAllowDecrypt() => __pbn__AllowDecrypt = null; + private uint? __pbn__AllowDecrypt; + + [global::ProtoBuf.ProtoMember(3)] + public uint AllowSign + { + get => __pbn__AllowSign.GetValueOrDefault(); + set => __pbn__AllowSign = value; + } + public bool ShouldSerializeAllowSign() => __pbn__AllowSign != null; + public void ResetAllowSign() => __pbn__AllowSign = null; + private uint? __pbn__AllowSign; + + [global::ProtoBuf.ProtoMember(4)] + public uint AllowSignatureVerify + { + get => __pbn__AllowSignatureVerify.GetValueOrDefault(); + set => __pbn__AllowSignatureVerify = value; + } + public bool ShouldSerializeAllowSignatureVerify() => __pbn__AllowSignatureVerify != null; + public void ResetAllowSignatureVerify() => __pbn__AllowSignatureVerify = null; + private uint? __pbn__AllowSignatureVerify; + + } + + [global::ProtoBuf.ProtoContract()] + public partial class VideoResolutionConstraint : global::ProtoBuf.IExtensible + { + private global::ProtoBuf.IExtension __pbn__extensionData; + global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) + => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing); + + [global::ProtoBuf.ProtoMember(1)] + public uint MinResolutionPixels + { + get => __pbn__MinResolutionPixels.GetValueOrDefault(); + set => __pbn__MinResolutionPixels = value; + } + public bool ShouldSerializeMinResolutionPixels() => __pbn__MinResolutionPixels != null; + public void ResetMinResolutionPixels() => __pbn__MinResolutionPixels = null; + private uint? __pbn__MinResolutionPixels; + + [global::ProtoBuf.ProtoMember(2)] + public uint MaxResolutionPixels + { + get => __pbn__MaxResolutionPixels.GetValueOrDefault(); + set => __pbn__MaxResolutionPixels = value; + } + public bool ShouldSerializeMaxResolutionPixels() => __pbn__MaxResolutionPixels != null; + public void ResetMaxResolutionPixels() => __pbn__MaxResolutionPixels = null; + private uint? __pbn__MaxResolutionPixels; + + [global::ProtoBuf.ProtoMember(3)] + public License.KeyContainer.OutputProtection RequiredProtection { get; set; } + + } + + [global::ProtoBuf.ProtoContract()] + public enum KeyType + { + [global::ProtoBuf.ProtoEnum(Name = @"SIGNING")] + Signing = 1, + [global::ProtoBuf.ProtoEnum(Name = @"CONTENT")] + Content = 2, + [global::ProtoBuf.ProtoEnum(Name = @"KEY_CONTROL")] + KeyControl = 3, + [global::ProtoBuf.ProtoEnum(Name = @"OPERATOR_SESSION")] + OperatorSession = 4, + } + + [global::ProtoBuf.ProtoContract()] + public enum SecurityLevel + { + [global::ProtoBuf.ProtoEnum(Name = @"SW_SECURE_CRYPTO")] + SwSecureCrypto = 1, + [global::ProtoBuf.ProtoEnum(Name = @"SW_SECURE_DECODE")] + SwSecureDecode = 2, + [global::ProtoBuf.ProtoEnum(Name = @"HW_SECURE_CRYPTO")] + HwSecureCrypto = 3, + [global::ProtoBuf.ProtoEnum(Name = @"HW_SECURE_DECODE")] + HwSecureDecode = 4, + [global::ProtoBuf.ProtoEnum(Name = @"HW_SECURE_ALL")] + HwSecureAll = 5, + } + + } + +} + +[global::ProtoBuf.ProtoContract()] +public partial class LicenseError : global::ProtoBuf.IExtensible +{ + private global::ProtoBuf.IExtension __pbn__extensionData; + global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) + => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing); + + [global::ProtoBuf.ProtoMember(1)] + [global::System.ComponentModel.DefaultValue(Error.InvalidDeviceCertificate)] + public Error ErrorCode + { + get => __pbn__ErrorCode ?? Error.InvalidDeviceCertificate; + set => __pbn__ErrorCode = value; + } + public bool ShouldSerializeErrorCode() => __pbn__ErrorCode != null; + public void ResetErrorCode() => __pbn__ErrorCode = null; + private Error? __pbn__ErrorCode; + + [global::ProtoBuf.ProtoContract()] + public enum Error + { + [global::ProtoBuf.ProtoEnum(Name = @"INVALID_DEVICE_CERTIFICATE")] + InvalidDeviceCertificate = 1, + [global::ProtoBuf.ProtoEnum(Name = @"REVOKED_DEVICE_CERTIFICATE")] + RevokedDeviceCertificate = 2, + [global::ProtoBuf.ProtoEnum(Name = @"SERVICE_UNAVAILABLE")] + ServiceUnavailable = 3, + } + +} + +[global::ProtoBuf.ProtoContract()] +public partial class LicenseRequest : global::ProtoBuf.IExtensible +{ + private global::ProtoBuf.IExtension __pbn__extensionData; + global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) + => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing); + + [global::ProtoBuf.ProtoMember(1)] + public ClientIdentification ClientId { get; set; } + + [global::ProtoBuf.ProtoMember(2)] + public ContentIdentification ContentId { get; set; } + + [global::ProtoBuf.ProtoMember(3)] + [global::System.ComponentModel.DefaultValue(RequestType.New)] + public RequestType Type + { + get => __pbn__Type ?? RequestType.New; + set => __pbn__Type = value; + } + public bool ShouldSerializeType() => __pbn__Type != null; + public void ResetType() => __pbn__Type = null; + private RequestType? __pbn__Type; + + [global::ProtoBuf.ProtoMember(4)] + public uint RequestTime + { + get => __pbn__RequestTime.GetValueOrDefault(); + set => __pbn__RequestTime = value; + } + public bool ShouldSerializeRequestTime() => __pbn__RequestTime != null; + public void ResetRequestTime() => __pbn__RequestTime = null; + private uint? __pbn__RequestTime; + + [global::ProtoBuf.ProtoMember(5)] + public byte[] KeyControlNonceDeprecated + { + get => __pbn__KeyControlNonceDeprecated; + set => __pbn__KeyControlNonceDeprecated = value; + } + public bool ShouldSerializeKeyControlNonceDeprecated() => __pbn__KeyControlNonceDeprecated != null; + public void ResetKeyControlNonceDeprecated() => __pbn__KeyControlNonceDeprecated = null; + private byte[] __pbn__KeyControlNonceDeprecated; + + [global::ProtoBuf.ProtoMember(6)] + [global::System.ComponentModel.DefaultValue(ProtocolVersion.Current)] + public ProtocolVersion ProtocolVersion + { + get => __pbn__ProtocolVersion ?? ProtocolVersion.Current; + set => __pbn__ProtocolVersion = value; + } + public bool ShouldSerializeProtocolVersion() => __pbn__ProtocolVersion != null; + public void ResetProtocolVersion() => __pbn__ProtocolVersion = null; + private ProtocolVersion? __pbn__ProtocolVersion; + + [global::ProtoBuf.ProtoMember(7)] + public uint KeyControlNonce + { + get => __pbn__KeyControlNonce.GetValueOrDefault(); + set => __pbn__KeyControlNonce = value; + } + public bool ShouldSerializeKeyControlNonce() => __pbn__KeyControlNonce != null; + public void ResetKeyControlNonce() => __pbn__KeyControlNonce = null; + private uint? __pbn__KeyControlNonce; + + [global::ProtoBuf.ProtoMember(8)] + public EncryptedClientIdentification EncryptedClientId { get; set; } + + [global::ProtoBuf.ProtoContract()] + public partial class ContentIdentification : global::ProtoBuf.IExtensible + { + private global::ProtoBuf.IExtension __pbn__extensionData; + global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) + => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing); + + [global::ProtoBuf.ProtoMember(1)] + public Cenc CencId { get; set; } + + [global::ProtoBuf.ProtoMember(2)] + public WebM WebmId { get; set; } + + [global::ProtoBuf.ProtoMember(3)] + public ExistingLicense License { get; set; } + + [global::ProtoBuf.ProtoContract(Name = @"CENC")] + public partial class Cenc : global::ProtoBuf.IExtensible + { + private global::ProtoBuf.IExtension __pbn__extensionData; + global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) + => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing); + + [global::ProtoBuf.ProtoMember(1)] + public WidevineCencHeader Pssh { get; set; } + + [global::ProtoBuf.ProtoMember(2)] + [global::System.ComponentModel.DefaultValue(LicenseType.Zero)] + public LicenseType LicenseType + { + get => __pbn__LicenseType ?? LicenseType.Zero; + set => __pbn__LicenseType = value; + } + public bool ShouldSerializeLicenseType() => __pbn__LicenseType != null; + public void ResetLicenseType() => __pbn__LicenseType = null; + private LicenseType? __pbn__LicenseType; + + [global::ProtoBuf.ProtoMember(3)] + public byte[] RequestId + { + get => __pbn__RequestId; + set => __pbn__RequestId = value; + } + public bool ShouldSerializeRequestId() => __pbn__RequestId != null; + public void ResetRequestId() => __pbn__RequestId = null; + private byte[] __pbn__RequestId; + + } + + [global::ProtoBuf.ProtoContract()] + public partial class WebM : global::ProtoBuf.IExtensible + { + private global::ProtoBuf.IExtension __pbn__extensionData; + global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) + => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing); + + [global::ProtoBuf.ProtoMember(1)] + public byte[] Header + { + get => __pbn__Header; + set => __pbn__Header = value; + } + public bool ShouldSerializeHeader() => __pbn__Header != null; + public void ResetHeader() => __pbn__Header = null; + private byte[] __pbn__Header; + + [global::ProtoBuf.ProtoMember(2)] + [global::System.ComponentModel.DefaultValue(LicenseType.Zero)] + public LicenseType LicenseType + { + get => __pbn__LicenseType ?? LicenseType.Zero; + set => __pbn__LicenseType = value; + } + public bool ShouldSerializeLicenseType() => __pbn__LicenseType != null; + public void ResetLicenseType() => __pbn__LicenseType = null; + private LicenseType? __pbn__LicenseType; + + [global::ProtoBuf.ProtoMember(3)] + public byte[] RequestId + { + get => __pbn__RequestId; + set => __pbn__RequestId = value; + } + public bool ShouldSerializeRequestId() => __pbn__RequestId != null; + public void ResetRequestId() => __pbn__RequestId = null; + private byte[] __pbn__RequestId; + + } + + [global::ProtoBuf.ProtoContract()] + public partial class ExistingLicense : global::ProtoBuf.IExtensible + { + private global::ProtoBuf.IExtension __pbn__extensionData; + global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) + => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing); + + [global::ProtoBuf.ProtoMember(1)] + public LicenseIdentification LicenseId { get; set; } + + [global::ProtoBuf.ProtoMember(2)] + public uint SecondsSinceStarted + { + get => __pbn__SecondsSinceStarted.GetValueOrDefault(); + set => __pbn__SecondsSinceStarted = value; + } + public bool ShouldSerializeSecondsSinceStarted() => __pbn__SecondsSinceStarted != null; + public void ResetSecondsSinceStarted() => __pbn__SecondsSinceStarted = null; + private uint? __pbn__SecondsSinceStarted; + + [global::ProtoBuf.ProtoMember(3)] + public uint SecondsSinceLastPlayed + { + get => __pbn__SecondsSinceLastPlayed.GetValueOrDefault(); + set => __pbn__SecondsSinceLastPlayed = value; + } + public bool ShouldSerializeSecondsSinceLastPlayed() => __pbn__SecondsSinceLastPlayed != null; + public void ResetSecondsSinceLastPlayed() => __pbn__SecondsSinceLastPlayed = null; + private uint? __pbn__SecondsSinceLastPlayed; + + [global::ProtoBuf.ProtoMember(4)] + public byte[] SessionUsageTableEntry + { + get => __pbn__SessionUsageTableEntry; + set => __pbn__SessionUsageTableEntry = value; + } + public bool ShouldSerializeSessionUsageTableEntry() => __pbn__SessionUsageTableEntry != null; + public void ResetSessionUsageTableEntry() => __pbn__SessionUsageTableEntry = null; + private byte[] __pbn__SessionUsageTableEntry; + + } + + } + + [global::ProtoBuf.ProtoContract()] + public enum RequestType + { + [global::ProtoBuf.ProtoEnum(Name = @"NEW")] + New = 1, + [global::ProtoBuf.ProtoEnum(Name = @"RENEWAL")] + Renewal = 2, + [global::ProtoBuf.ProtoEnum(Name = @"RELEASE")] + Release = 3, + } + +} + +[global::ProtoBuf.ProtoContract()] +public partial class LicenseRequestRaw : global::ProtoBuf.IExtensible +{ + private global::ProtoBuf.IExtension __pbn__extensionData; + global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) + => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing); + + [global::ProtoBuf.ProtoMember(1)] + public ClientIdentification ClientId { get; set; } + + [global::ProtoBuf.ProtoMember(2)] + public ContentIdentification ContentId { get; set; } + + [global::ProtoBuf.ProtoMember(3)] + [global::System.ComponentModel.DefaultValue(RequestType.New)] + public RequestType Type + { + get => __pbn__Type ?? RequestType.New; + set => __pbn__Type = value; + } + public bool ShouldSerializeType() => __pbn__Type != null; + public void ResetType() => __pbn__Type = null; + private RequestType? __pbn__Type; + + [global::ProtoBuf.ProtoMember(4)] + public uint RequestTime + { + get => __pbn__RequestTime.GetValueOrDefault(); + set => __pbn__RequestTime = value; + } + public bool ShouldSerializeRequestTime() => __pbn__RequestTime != null; + public void ResetRequestTime() => __pbn__RequestTime = null; + private uint? __pbn__RequestTime; + + [global::ProtoBuf.ProtoMember(5)] + public byte[] KeyControlNonceDeprecated + { + get => __pbn__KeyControlNonceDeprecated; + set => __pbn__KeyControlNonceDeprecated = value; + } + public bool ShouldSerializeKeyControlNonceDeprecated() => __pbn__KeyControlNonceDeprecated != null; + public void ResetKeyControlNonceDeprecated() => __pbn__KeyControlNonceDeprecated = null; + private byte[] __pbn__KeyControlNonceDeprecated; + + [global::ProtoBuf.ProtoMember(6)] + [global::System.ComponentModel.DefaultValue(ProtocolVersion.Current)] + public ProtocolVersion ProtocolVersion + { + get => __pbn__ProtocolVersion ?? ProtocolVersion.Current; + set => __pbn__ProtocolVersion = value; + } + public bool ShouldSerializeProtocolVersion() => __pbn__ProtocolVersion != null; + public void ResetProtocolVersion() => __pbn__ProtocolVersion = null; + private ProtocolVersion? __pbn__ProtocolVersion; + + [global::ProtoBuf.ProtoMember(7)] + public uint KeyControlNonce + { + get => __pbn__KeyControlNonce.GetValueOrDefault(); + set => __pbn__KeyControlNonce = value; + } + public bool ShouldSerializeKeyControlNonce() => __pbn__KeyControlNonce != null; + public void ResetKeyControlNonce() => __pbn__KeyControlNonce = null; + private uint? __pbn__KeyControlNonce; + + [global::ProtoBuf.ProtoMember(8)] + public EncryptedClientIdentification EncryptedClientId { get; set; } + + [global::ProtoBuf.ProtoContract()] + public partial class ContentIdentification : global::ProtoBuf.IExtensible + { + private global::ProtoBuf.IExtension __pbn__extensionData; + global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) + => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing); + + [global::ProtoBuf.ProtoMember(1)] + public Cenc CencId { get; set; } + + [global::ProtoBuf.ProtoMember(2)] + public WebM WebmId { get; set; } + + [global::ProtoBuf.ProtoMember(3)] + public ExistingLicense License { get; set; } + + [global::ProtoBuf.ProtoContract(Name = @"CENC")] + public partial class Cenc : global::ProtoBuf.IExtensible + { + private global::ProtoBuf.IExtension __pbn__extensionData; + global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) + => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing); + + [global::ProtoBuf.ProtoMember(1)] + public byte[] Pssh + { + get => __pbn__Pssh; + set => __pbn__Pssh = value; + } + public bool ShouldSerializePssh() => __pbn__Pssh != null; + public void ResetPssh() => __pbn__Pssh = null; + private byte[] __pbn__Pssh; + + [global::ProtoBuf.ProtoMember(2)] + [global::System.ComponentModel.DefaultValue(LicenseType.Zero)] + public LicenseType LicenseType + { + get => __pbn__LicenseType ?? LicenseType.Zero; + set => __pbn__LicenseType = value; + } + public bool ShouldSerializeLicenseType() => __pbn__LicenseType != null; + public void ResetLicenseType() => __pbn__LicenseType = null; + private LicenseType? __pbn__LicenseType; + + [global::ProtoBuf.ProtoMember(3)] + public byte[] RequestId + { + get => __pbn__RequestId; + set => __pbn__RequestId = value; + } + public bool ShouldSerializeRequestId() => __pbn__RequestId != null; + public void ResetRequestId() => __pbn__RequestId = null; + private byte[] __pbn__RequestId; + + } + + [global::ProtoBuf.ProtoContract()] + public partial class WebM : global::ProtoBuf.IExtensible + { + private global::ProtoBuf.IExtension __pbn__extensionData; + global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) + => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing); + + [global::ProtoBuf.ProtoMember(1)] + public byte[] Header + { + get => __pbn__Header; + set => __pbn__Header = value; + } + public bool ShouldSerializeHeader() => __pbn__Header != null; + public void ResetHeader() => __pbn__Header = null; + private byte[] __pbn__Header; + + [global::ProtoBuf.ProtoMember(2)] + [global::System.ComponentModel.DefaultValue(LicenseType.Zero)] + public LicenseType LicenseType + { + get => __pbn__LicenseType ?? LicenseType.Zero; + set => __pbn__LicenseType = value; + } + public bool ShouldSerializeLicenseType() => __pbn__LicenseType != null; + public void ResetLicenseType() => __pbn__LicenseType = null; + private LicenseType? __pbn__LicenseType; + + [global::ProtoBuf.ProtoMember(3)] + public byte[] RequestId + { + get => __pbn__RequestId; + set => __pbn__RequestId = value; + } + public bool ShouldSerializeRequestId() => __pbn__RequestId != null; + public void ResetRequestId() => __pbn__RequestId = null; + private byte[] __pbn__RequestId; + + } + + [global::ProtoBuf.ProtoContract()] + public partial class ExistingLicense : global::ProtoBuf.IExtensible + { + private global::ProtoBuf.IExtension __pbn__extensionData; + global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) + => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing); + + [global::ProtoBuf.ProtoMember(1)] + public LicenseIdentification LicenseId { get; set; } + + [global::ProtoBuf.ProtoMember(2)] + public uint SecondsSinceStarted + { + get => __pbn__SecondsSinceStarted.GetValueOrDefault(); + set => __pbn__SecondsSinceStarted = value; + } + public bool ShouldSerializeSecondsSinceStarted() => __pbn__SecondsSinceStarted != null; + public void ResetSecondsSinceStarted() => __pbn__SecondsSinceStarted = null; + private uint? __pbn__SecondsSinceStarted; + + [global::ProtoBuf.ProtoMember(3)] + public uint SecondsSinceLastPlayed + { + get => __pbn__SecondsSinceLastPlayed.GetValueOrDefault(); + set => __pbn__SecondsSinceLastPlayed = value; + } + public bool ShouldSerializeSecondsSinceLastPlayed() => __pbn__SecondsSinceLastPlayed != null; + public void ResetSecondsSinceLastPlayed() => __pbn__SecondsSinceLastPlayed = null; + private uint? __pbn__SecondsSinceLastPlayed; + + [global::ProtoBuf.ProtoMember(4)] + public byte[] SessionUsageTableEntry + { + get => __pbn__SessionUsageTableEntry; + set => __pbn__SessionUsageTableEntry = value; + } + public bool ShouldSerializeSessionUsageTableEntry() => __pbn__SessionUsageTableEntry != null; + public void ResetSessionUsageTableEntry() => __pbn__SessionUsageTableEntry = null; + private byte[] __pbn__SessionUsageTableEntry; + + } + + } + + [global::ProtoBuf.ProtoContract()] + public enum RequestType + { + [global::ProtoBuf.ProtoEnum(Name = @"NEW")] + New = 1, + [global::ProtoBuf.ProtoEnum(Name = @"RENEWAL")] + Renewal = 2, + [global::ProtoBuf.ProtoEnum(Name = @"RELEASE")] + Release = 3, + } + +} + +[global::ProtoBuf.ProtoContract()] +public partial class ProvisionedDeviceInfo : global::ProtoBuf.IExtensible +{ + private global::ProtoBuf.IExtension __pbn__extensionData; + global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) + => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing); + + [global::ProtoBuf.ProtoMember(1)] + public uint SystemId + { + get => __pbn__SystemId.GetValueOrDefault(); + set => __pbn__SystemId = value; + } + public bool ShouldSerializeSystemId() => __pbn__SystemId != null; + public void ResetSystemId() => __pbn__SystemId = null; + private uint? __pbn__SystemId; + + [global::ProtoBuf.ProtoMember(2)] + [global::System.ComponentModel.DefaultValue("")] + public string Soc + { + get => __pbn__Soc ?? ""; + set => __pbn__Soc = value; + } + public bool ShouldSerializeSoc() => __pbn__Soc != null; + public void ResetSoc() => __pbn__Soc = null; + private string __pbn__Soc; + + [global::ProtoBuf.ProtoMember(3)] + [global::System.ComponentModel.DefaultValue("")] + public string Manufacturer + { + get => __pbn__Manufacturer ?? ""; + set => __pbn__Manufacturer = value; + } + public bool ShouldSerializeManufacturer() => __pbn__Manufacturer != null; + public void ResetManufacturer() => __pbn__Manufacturer = null; + private string __pbn__Manufacturer; + + [global::ProtoBuf.ProtoMember(4)] + [global::System.ComponentModel.DefaultValue("")] + public string Model + { + get => __pbn__Model ?? ""; + set => __pbn__Model = value; + } + public bool ShouldSerializeModel() => __pbn__Model != null; + public void ResetModel() => __pbn__Model = null; + private string __pbn__Model; + + [global::ProtoBuf.ProtoMember(5)] + [global::System.ComponentModel.DefaultValue("")] + public string DeviceType + { + get => __pbn__DeviceType ?? ""; + set => __pbn__DeviceType = value; + } + public bool ShouldSerializeDeviceType() => __pbn__DeviceType != null; + public void ResetDeviceType() => __pbn__DeviceType = null; + private string __pbn__DeviceType; + + [global::ProtoBuf.ProtoMember(6)] + public uint ModelYear + { + get => __pbn__ModelYear.GetValueOrDefault(); + set => __pbn__ModelYear = value; + } + public bool ShouldSerializeModelYear() => __pbn__ModelYear != null; + public void ResetModelYear() => __pbn__ModelYear = null; + private uint? __pbn__ModelYear; + + [global::ProtoBuf.ProtoMember(7)] + [global::System.ComponentModel.DefaultValue(WvSecurityLevel.LevelUnspecified)] + public WvSecurityLevel SecurityLevel + { + get => __pbn__SecurityLevel ?? WvSecurityLevel.LevelUnspecified; + set => __pbn__SecurityLevel = value; + } + public bool ShouldSerializeSecurityLevel() => __pbn__SecurityLevel != null; + public void ResetSecurityLevel() => __pbn__SecurityLevel = null; + private WvSecurityLevel? __pbn__SecurityLevel; + + [global::ProtoBuf.ProtoMember(8)] + public uint TestDevice + { + get => __pbn__TestDevice.GetValueOrDefault(); + set => __pbn__TestDevice = value; + } + public bool ShouldSerializeTestDevice() => __pbn__TestDevice != null; + public void ResetTestDevice() => __pbn__TestDevice = null; + private uint? __pbn__TestDevice; + + [global::ProtoBuf.ProtoContract()] + public enum WvSecurityLevel + { + [global::ProtoBuf.ProtoEnum(Name = @"LEVEL_UNSPECIFIED")] + LevelUnspecified = 0, + [global::ProtoBuf.ProtoEnum(Name = @"LEVEL_1")] + Level1 = 1, + [global::ProtoBuf.ProtoEnum(Name = @"LEVEL_2")] + Level2 = 2, + [global::ProtoBuf.ProtoEnum(Name = @"LEVEL_3")] + Level3 = 3, + } + +} + +[global::ProtoBuf.ProtoContract()] +public partial class RemoteAttestation : global::ProtoBuf.IExtensible +{ + private global::ProtoBuf.IExtension __pbn__extensionData; + global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) + => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing); + + [global::ProtoBuf.ProtoMember(1)] + public EncryptedClientIdentification Certificate { get; set; } + + [global::ProtoBuf.ProtoMember(2)] + [global::System.ComponentModel.DefaultValue("")] + public string Salt + { + get => __pbn__Salt ?? ""; + set => __pbn__Salt = value; + } + public bool ShouldSerializeSalt() => __pbn__Salt != null; + public void ResetSalt() => __pbn__Salt = null; + private string __pbn__Salt; + + [global::ProtoBuf.ProtoMember(3)] + [global::System.ComponentModel.DefaultValue("")] + public string Signature + { + get => __pbn__Signature ?? ""; + set => __pbn__Signature = value; + } + public bool ShouldSerializeSignature() => __pbn__Signature != null; + public void ResetSignature() => __pbn__Signature = null; + private string __pbn__Signature; + +} + +[global::ProtoBuf.ProtoContract()] +public partial class ProvisioningOptions : global::ProtoBuf.IExtensible +{ + private global::ProtoBuf.IExtension __pbn__extensionData; + global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) + => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing); + + [global::ProtoBuf.ProtoMember(1)] + [global::System.ComponentModel.DefaultValue(CertificateType.WidevineDrm)] + public CertificateType certificate_type + { + get => __pbn__certificate_type ?? CertificateType.WidevineDrm; + set => __pbn__certificate_type = value; + } + public bool ShouldSerializecertificate_type() => __pbn__certificate_type != null; + public void Resetcertificate_type() => __pbn__certificate_type = null; + private CertificateType? __pbn__certificate_type; + + [global::ProtoBuf.ProtoMember(2, Name = @"certificate_authority")] + [global::System.ComponentModel.DefaultValue("")] + public string CertificateAuthority + { + get => __pbn__CertificateAuthority ?? ""; + set => __pbn__CertificateAuthority = value; + } + public bool ShouldSerializeCertificateAuthority() => __pbn__CertificateAuthority != null; + public void ResetCertificateAuthority() => __pbn__CertificateAuthority = null; + private string __pbn__CertificateAuthority; + + [global::ProtoBuf.ProtoContract()] + public enum CertificateType + { + [global::ProtoBuf.ProtoEnum(Name = @"WIDEVINE_DRM")] + WidevineDrm = 0, + X509 = 1, + } + +} + +[global::ProtoBuf.ProtoContract()] +public partial class ProvisioningRequest : global::ProtoBuf.IExtensible +{ + private global::ProtoBuf.IExtension __pbn__extensionData; + global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) + => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing); + + [global::ProtoBuf.ProtoMember(1, Name = @"client_id")] + public ClientIdentification ClientId { get; set; } + + [global::ProtoBuf.ProtoMember(5, Name = @"encrypted_client_id")] + public EncryptedClientIdentification EncryptedClientId { get; set; } + + [global::ProtoBuf.ProtoMember(2, Name = @"nonce")] + public byte[] Nonce + { + get => __pbn__Nonce; + set => __pbn__Nonce = value; + } + public bool ShouldSerializeNonce() => __pbn__Nonce != null; + public void ResetNonce() => __pbn__Nonce = null; + private byte[] __pbn__Nonce; + + [global::ProtoBuf.ProtoMember(3, Name = @"options")] + public ProvisioningOptions Options { get; set; } + + [global::ProtoBuf.ProtoMember(4, Name = @"stable_id")] + public byte[] StableId + { + get => __pbn__StableId; + set => __pbn__StableId = value; + } + public bool ShouldSerializeStableId() => __pbn__StableId != null; + public void ResetStableId() => __pbn__StableId = null; + private byte[] __pbn__StableId; + + [global::ProtoBuf.ProtoMember(6, Name = @"provider_id")] + public byte[] ProviderId + { + get => __pbn__ProviderId; + set => __pbn__ProviderId = value; + } + public bool ShouldSerializeProviderId() => __pbn__ProviderId != null; + public void ResetProviderId() => __pbn__ProviderId = null; + private byte[] __pbn__ProviderId; + + [global::ProtoBuf.ProtoMember(7, Name = @"spoid")] + public byte[] Spoid + { + get => __pbn__Spoid; + set => __pbn__Spoid = value; + } + public bool ShouldSerializeSpoid() => __pbn__Spoid != null; + public void ResetSpoid() => __pbn__Spoid = null; + private byte[] __pbn__Spoid; + +} + +[global::ProtoBuf.ProtoContract()] +public partial class ProvisioningResponse : global::ProtoBuf.IExtensible +{ + private global::ProtoBuf.IExtension __pbn__extensionData; + global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) + => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing); + + [global::ProtoBuf.ProtoMember(1, Name = @"device_rsa_key")] + public byte[] DeviceRsaKey + { + get => __pbn__DeviceRsaKey; + set => __pbn__DeviceRsaKey = value; + } + public bool ShouldSerializeDeviceRsaKey() => __pbn__DeviceRsaKey != null; + public void ResetDeviceRsaKey() => __pbn__DeviceRsaKey = null; + private byte[] __pbn__DeviceRsaKey; + + [global::ProtoBuf.ProtoMember(2, Name = @"device_rsa_key_iv")] + public byte[] DeviceRsaKeyIv + { + get => __pbn__DeviceRsaKeyIv; + set => __pbn__DeviceRsaKeyIv = value; + } + public bool ShouldSerializeDeviceRsaKeyIv() => __pbn__DeviceRsaKeyIv != null; + public void ResetDeviceRsaKeyIv() => __pbn__DeviceRsaKeyIv = null; + private byte[] __pbn__DeviceRsaKeyIv; + + [global::ProtoBuf.ProtoMember(3, Name = @"device_certificate")] + public SignedDeviceCertificate DeviceCertificate { get; set; } + + [global::ProtoBuf.ProtoMember(4, Name = @"nonce")] + public byte[] Nonce + { + get => __pbn__Nonce; + set => __pbn__Nonce = value; + } + public bool ShouldSerializeNonce() => __pbn__Nonce != null; + public void ResetNonce() => __pbn__Nonce = null; + private byte[] __pbn__Nonce; + + [global::ProtoBuf.ProtoMember(5, Name = @"wrapping_key")] + public byte[] WrappingKey + { + get => __pbn__WrappingKey; + set => __pbn__WrappingKey = value; + } + public bool ShouldSerializeWrappingKey() => __pbn__WrappingKey != null; + public void ResetWrappingKey() => __pbn__WrappingKey = null; + private byte[] __pbn__WrappingKey; + +} + +[global::ProtoBuf.ProtoContract()] +public partial class SignedProvisioningMessage : global::ProtoBuf.IExtensible +{ + private global::ProtoBuf.IExtension __pbn__extensionData; + global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) + => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing); + + [global::ProtoBuf.ProtoMember(1, Name = @"message")] + public ProvisioningResponse Message { get; set; } + + [global::ProtoBuf.ProtoMember(2, Name = @"signature")] + public byte[] Signature + { + get => __pbn__Signature; + set => __pbn__Signature = value; + } + public bool ShouldSerializeSignature() => __pbn__Signature != null; + public void ResetSignature() => __pbn__Signature = null; + private byte[] __pbn__Signature; + + [global::ProtoBuf.ProtoMember(3)] + [global::System.ComponentModel.DefaultValue(ProtocolVersion.Version2)] + public ProtocolVersion protocol_version + { + get => __pbn__protocol_version ?? ProtocolVersion.Version2; + set => __pbn__protocol_version = value; + } + public bool ShouldSerializeprotocol_version() => __pbn__protocol_version != null; + public void Resetprotocol_version() => __pbn__protocol_version = null; + private ProtocolVersion? __pbn__protocol_version; + + [global::ProtoBuf.ProtoContract()] + public enum ProtocolVersion + { + [global::ProtoBuf.ProtoEnum(Name = @"VERSION_2")] + Version2 = 2, + [global::ProtoBuf.ProtoEnum(Name = @"VERSION_3")] + Version3 = 3, + } + +} + +[global::ProtoBuf.ProtoContract()] +public partial class DeviceCertificateHack0 : global::ProtoBuf.IExtensible +{ + private global::ProtoBuf.IExtension __pbn__extensionData; + global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) + => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing); + + [global::ProtoBuf.ProtoMember(1, Name = @"message")] + public DeviceCertificateHack1 Message { get; set; } + + [global::ProtoBuf.ProtoMember(2, Name = @"signature")] + public byte[] Signature + { + get => __pbn__Signature; + set => __pbn__Signature = value; + } + public bool ShouldSerializeSignature() => __pbn__Signature != null; + public void ResetSignature() => __pbn__Signature = null; + private byte[] __pbn__Signature; + +} + +[global::ProtoBuf.ProtoContract()] +public partial class DeviceCertificateHack1 : global::ProtoBuf.IExtensible +{ + private global::ProtoBuf.IExtension __pbn__extensionData; + global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) + => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing); + + [global::ProtoBuf.ProtoMember(3, Name = @"message")] + public DeviceCertificateHack2 Message { get; set; } + +} + +[global::ProtoBuf.ProtoContract()] +public partial class DeviceCertificateHack2 : global::ProtoBuf.IExtensible +{ + private global::ProtoBuf.IExtension __pbn__extensionData; + global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) + => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing); + + [global::ProtoBuf.ProtoMember(1, Name = @"device_certificate")] + public SignedDeviceCertificate DeviceCertificate { get; set; } + + [global::ProtoBuf.ProtoMember(2)] + public byte[] extraData + { + get => __pbn__extraData; + set => __pbn__extraData = value; + } + public bool ShouldSerializeextraData() => __pbn__extraData != null; + public void ResetextraData() => __pbn__extraData = null; + private byte[] __pbn__extraData; + +} + +[global::ProtoBuf.ProtoContract()] +public partial class SignedDeviceCertificate : global::ProtoBuf.IExtensible +{ + private global::ProtoBuf.IExtension __pbn__extensionData; + global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) + => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing); + + [global::ProtoBuf.ProtoMember(1, Name = @"_DeviceCertificate")] + public DeviceCertificate DeviceCertificate { get; set; } + + [global::ProtoBuf.ProtoMember(2)] + public byte[] Signature + { + get => __pbn__Signature; + set => __pbn__Signature = value; + } + public bool ShouldSerializeSignature() => __pbn__Signature != null; + public void ResetSignature() => __pbn__Signature = null; + private byte[] __pbn__Signature; + + [global::ProtoBuf.ProtoMember(3)] + public SignedDeviceCertificate Signer { get; set; } + +} + +[global::ProtoBuf.ProtoContract()] +public partial class SignedMessage : global::ProtoBuf.IExtensible +{ + private global::ProtoBuf.IExtension __pbn__extensionData; + global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) + => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing); + + [global::ProtoBuf.ProtoMember(1)] + [global::System.ComponentModel.DefaultValue(MessageType.LicenseRequest)] + public MessageType Type + { + get => __pbn__Type ?? MessageType.LicenseRequest; + set => __pbn__Type = value; + } + public bool ShouldSerializeType() => __pbn__Type != null; + public void ResetType() => __pbn__Type = null; + private MessageType? __pbn__Type; + + [global::ProtoBuf.ProtoMember(2)] + public byte[] Msg + { + get => __pbn__Msg; + set => __pbn__Msg = value; + } + public bool ShouldSerializeMsg() => __pbn__Msg != null; + public void ResetMsg() => __pbn__Msg = null; + private byte[] __pbn__Msg; + + [global::ProtoBuf.ProtoMember(3)] + public byte[] Signature + { + get => __pbn__Signature; + set => __pbn__Signature = value; + } + public bool ShouldSerializeSignature() => __pbn__Signature != null; + public void ResetSignature() => __pbn__Signature = null; + private byte[] __pbn__Signature; + + [global::ProtoBuf.ProtoMember(4)] + public byte[] SessionKey + { + get => __pbn__SessionKey; + set => __pbn__SessionKey = value; + } + public bool ShouldSerializeSessionKey() => __pbn__SessionKey != null; + public void ResetSessionKey() => __pbn__SessionKey = null; + private byte[] __pbn__SessionKey; + + [global::ProtoBuf.ProtoMember(5)] + public RemoteAttestation RemoteAttestation { get; set; } + + [global::ProtoBuf.ProtoContract()] + public enum MessageType + { + [global::ProtoBuf.ProtoEnum(Name = @"LICENSE_REQUEST")] + LicenseRequest = 1, + [global::ProtoBuf.ProtoEnum(Name = @"LICENSE")] + License = 2, + [global::ProtoBuf.ProtoEnum(Name = @"ERROR_RESPONSE")] + ErrorResponse = 3, + [global::ProtoBuf.ProtoEnum(Name = @"SERVICE_CERTIFICATE_REQUEST")] + ServiceCertificateRequest = 4, + [global::ProtoBuf.ProtoEnum(Name = @"SERVICE_CERTIFICATE")] + ServiceCertificate = 5, + } + +} + +[global::ProtoBuf.ProtoContract()] +public partial class WidevineCencHeader : global::ProtoBuf.IExtensible +{ + private global::ProtoBuf.IExtension __pbn__extensionData; + global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) + => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing); + + [global::ProtoBuf.ProtoMember(1)] + [global::System.ComponentModel.DefaultValue(Algorithm.Unencrypted)] + public Algorithm algorithm + { + get => __pbn__algorithm ?? Algorithm.Unencrypted; + set => __pbn__algorithm = value; + } + public bool ShouldSerializealgorithm() => __pbn__algorithm != null; + public void Resetalgorithm() => __pbn__algorithm = null; + private Algorithm? __pbn__algorithm; + + [global::ProtoBuf.ProtoMember(2, Name = @"key_id")] + public global::System.Collections.Generic.List KeyIds { get; } = new global::System.Collections.Generic.List(); + + [global::ProtoBuf.ProtoMember(3, Name = @"provider")] + [global::System.ComponentModel.DefaultValue("")] + public string Provider + { + get => __pbn__Provider ?? ""; + set => __pbn__Provider = value; + } + public bool ShouldSerializeProvider() => __pbn__Provider != null; + public void ResetProvider() => __pbn__Provider = null; + private string __pbn__Provider; + + [global::ProtoBuf.ProtoMember(4, Name = @"content_id")] + public byte[] ContentId + { + get => __pbn__ContentId; + set => __pbn__ContentId = value; + } + public bool ShouldSerializeContentId() => __pbn__ContentId != null; + public void ResetContentId() => __pbn__ContentId = null; + private byte[] __pbn__ContentId; + + [global::ProtoBuf.ProtoMember(5, Name = @"track_type_deprecated")] + [global::System.ComponentModel.DefaultValue("")] + public string TrackTypeDeprecated + { + get => __pbn__TrackTypeDeprecated ?? ""; + set => __pbn__TrackTypeDeprecated = value; + } + public bool ShouldSerializeTrackTypeDeprecated() => __pbn__TrackTypeDeprecated != null; + public void ResetTrackTypeDeprecated() => __pbn__TrackTypeDeprecated = null; + private string __pbn__TrackTypeDeprecated; + + [global::ProtoBuf.ProtoMember(6, Name = @"policy")] + [global::System.ComponentModel.DefaultValue("")] + public string Policy + { + get => __pbn__Policy ?? ""; + set => __pbn__Policy = value; + } + public bool ShouldSerializePolicy() => __pbn__Policy != null; + public void ResetPolicy() => __pbn__Policy = null; + private string __pbn__Policy; + + [global::ProtoBuf.ProtoMember(7, Name = @"crypto_period_index")] + public uint CryptoPeriodIndex + { + get => __pbn__CryptoPeriodIndex.GetValueOrDefault(); + set => __pbn__CryptoPeriodIndex = value; + } + public bool ShouldSerializeCryptoPeriodIndex() => __pbn__CryptoPeriodIndex != null; + public void ResetCryptoPeriodIndex() => __pbn__CryptoPeriodIndex = null; + private uint? __pbn__CryptoPeriodIndex; + + [global::ProtoBuf.ProtoMember(8, Name = @"grouped_license")] + public byte[] GroupedLicense + { + get => __pbn__GroupedLicense; + set => __pbn__GroupedLicense = value; + } + public bool ShouldSerializeGroupedLicense() => __pbn__GroupedLicense != null; + public void ResetGroupedLicense() => __pbn__GroupedLicense = null; + private byte[] __pbn__GroupedLicense; + + [global::ProtoBuf.ProtoMember(9, Name = @"protection_scheme")] + public uint ProtectionScheme + { + get => __pbn__ProtectionScheme.GetValueOrDefault(); + set => __pbn__ProtectionScheme = value; + } + public bool ShouldSerializeProtectionScheme() => __pbn__ProtectionScheme != null; + public void ResetProtectionScheme() => __pbn__ProtectionScheme = null; + private uint? __pbn__ProtectionScheme; + + [global::ProtoBuf.ProtoMember(10, Name = @"crypto_period_seconds")] + public uint CryptoPeriodSeconds + { + get => __pbn__CryptoPeriodSeconds.GetValueOrDefault(); + set => __pbn__CryptoPeriodSeconds = value; + } + public bool ShouldSerializeCryptoPeriodSeconds() => __pbn__CryptoPeriodSeconds != null; + public void ResetCryptoPeriodSeconds() => __pbn__CryptoPeriodSeconds = null; + private uint? __pbn__CryptoPeriodSeconds; + + [global::ProtoBuf.ProtoContract()] + public enum Algorithm + { + [global::ProtoBuf.ProtoEnum(Name = @"UNENCRYPTED")] + Unencrypted = 0, + [global::ProtoBuf.ProtoEnum(Name = @"AESCTR")] + Aesctr = 1, + } + +} + +[global::ProtoBuf.ProtoContract()] +public partial class SignedLicenseRequest : global::ProtoBuf.IExtensible +{ + private global::ProtoBuf.IExtension __pbn__extensionData; + global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) + => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing); + + [global::ProtoBuf.ProtoMember(1)] + [global::System.ComponentModel.DefaultValue(MessageType.LicenseRequest)] + public MessageType Type + { + get => __pbn__Type ?? MessageType.LicenseRequest; + set => __pbn__Type = value; + } + public bool ShouldSerializeType() => __pbn__Type != null; + public void ResetType() => __pbn__Type = null; + private MessageType? __pbn__Type; + + [global::ProtoBuf.ProtoMember(2)] + public LicenseRequest Msg { get; set; } + + [global::ProtoBuf.ProtoMember(3)] + public byte[] Signature + { + get => __pbn__Signature; + set => __pbn__Signature = value; + } + public bool ShouldSerializeSignature() => __pbn__Signature != null; + public void ResetSignature() => __pbn__Signature = null; + private byte[] __pbn__Signature; + + [global::ProtoBuf.ProtoMember(4)] + public byte[] SessionKey + { + get => __pbn__SessionKey; + set => __pbn__SessionKey = value; + } + public bool ShouldSerializeSessionKey() => __pbn__SessionKey != null; + public void ResetSessionKey() => __pbn__SessionKey = null; + private byte[] __pbn__SessionKey; + + [global::ProtoBuf.ProtoMember(5)] + public RemoteAttestation RemoteAttestation { get; set; } + + [global::ProtoBuf.ProtoContract()] + public enum MessageType + { + [global::ProtoBuf.ProtoEnum(Name = @"LICENSE_REQUEST")] + LicenseRequest = 1, + [global::ProtoBuf.ProtoEnum(Name = @"LICENSE")] + License = 2, + [global::ProtoBuf.ProtoEnum(Name = @"ERROR_RESPONSE")] + ErrorResponse = 3, + [global::ProtoBuf.ProtoEnum(Name = @"SERVICE_CERTIFICATE_REQUEST")] + ServiceCertificateRequest = 4, + [global::ProtoBuf.ProtoEnum(Name = @"SERVICE_CERTIFICATE")] + ServiceCertificate = 5, + } + +} + +[global::ProtoBuf.ProtoContract()] +public partial class SignedLicenseRequestRaw : global::ProtoBuf.IExtensible +{ + private global::ProtoBuf.IExtension __pbn__extensionData; + global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) + => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing); + + [global::ProtoBuf.ProtoMember(1)] + [global::System.ComponentModel.DefaultValue(MessageType.LicenseRequest)] + public MessageType Type + { + get => __pbn__Type ?? MessageType.LicenseRequest; + set => __pbn__Type = value; + } + public bool ShouldSerializeType() => __pbn__Type != null; + public void ResetType() => __pbn__Type = null; + private MessageType? __pbn__Type; + + [global::ProtoBuf.ProtoMember(2)] + public LicenseRequestRaw Msg { get; set; } + + [global::ProtoBuf.ProtoMember(3)] + public byte[] Signature + { + get => __pbn__Signature; + set => __pbn__Signature = value; + } + public bool ShouldSerializeSignature() => __pbn__Signature != null; + public void ResetSignature() => __pbn__Signature = null; + private byte[] __pbn__Signature; + + [global::ProtoBuf.ProtoMember(4)] + public byte[] SessionKey + { + get => __pbn__SessionKey; + set => __pbn__SessionKey = value; + } + public bool ShouldSerializeSessionKey() => __pbn__SessionKey != null; + public void ResetSessionKey() => __pbn__SessionKey = null; + private byte[] __pbn__SessionKey; + + [global::ProtoBuf.ProtoMember(5)] + public RemoteAttestation RemoteAttestation { get; set; } + + [global::ProtoBuf.ProtoContract()] + public enum MessageType + { + [global::ProtoBuf.ProtoEnum(Name = @"LICENSE_REQUEST")] + LicenseRequest = 1, + [global::ProtoBuf.ProtoEnum(Name = @"LICENSE")] + License = 2, + [global::ProtoBuf.ProtoEnum(Name = @"ERROR_RESPONSE")] + ErrorResponse = 3, + [global::ProtoBuf.ProtoEnum(Name = @"SERVICE_CERTIFICATE_REQUEST")] + ServiceCertificateRequest = 4, + [global::ProtoBuf.ProtoEnum(Name = @"SERVICE_CERTIFICATE")] + ServiceCertificate = 5, + } + +} + +[global::ProtoBuf.ProtoContract()] +public partial class SignedLicense : global::ProtoBuf.IExtensible +{ + private global::ProtoBuf.IExtension __pbn__extensionData; + global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) + => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing); + + [global::ProtoBuf.ProtoMember(1)] + [global::System.ComponentModel.DefaultValue(MessageType.LicenseRequest)] + public MessageType Type + { + get => __pbn__Type ?? MessageType.LicenseRequest; + set => __pbn__Type = value; + } + public bool ShouldSerializeType() => __pbn__Type != null; + public void ResetType() => __pbn__Type = null; + private MessageType? __pbn__Type; + + [global::ProtoBuf.ProtoMember(2)] + public License Msg { get; set; } + + [global::ProtoBuf.ProtoMember(3)] + public byte[] Signature + { + get => __pbn__Signature; + set => __pbn__Signature = value; + } + public bool ShouldSerializeSignature() => __pbn__Signature != null; + public void ResetSignature() => __pbn__Signature = null; + private byte[] __pbn__Signature; + + [global::ProtoBuf.ProtoMember(4)] + public byte[] SessionKey + { + get => __pbn__SessionKey; + set => __pbn__SessionKey = value; + } + public bool ShouldSerializeSessionKey() => __pbn__SessionKey != null; + public void ResetSessionKey() => __pbn__SessionKey = null; + private byte[] __pbn__SessionKey; + + [global::ProtoBuf.ProtoMember(5)] + public RemoteAttestation RemoteAttestation { get; set; } + + [global::ProtoBuf.ProtoContract()] + public enum MessageType + { + [global::ProtoBuf.ProtoEnum(Name = @"LICENSE_REQUEST")] + LicenseRequest = 1, + [global::ProtoBuf.ProtoEnum(Name = @"LICENSE")] + License = 2, + [global::ProtoBuf.ProtoEnum(Name = @"ERROR_RESPONSE")] + ErrorResponse = 3, + [global::ProtoBuf.ProtoEnum(Name = @"SERVICE_CERTIFICATE_REQUEST")] + ServiceCertificateRequest = 4, + [global::ProtoBuf.ProtoEnum(Name = @"SERVICE_CERTIFICATE")] + ServiceCertificate = 5, + } + +} + +[global::ProtoBuf.ProtoContract()] +public partial class SignedServiceCertificate : global::ProtoBuf.IExtensible +{ + private global::ProtoBuf.IExtension __pbn__extensionData; + global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) + => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing); + + [global::ProtoBuf.ProtoMember(1)] + [global::System.ComponentModel.DefaultValue(MessageType.LicenseRequest)] + public MessageType Type + { + get => __pbn__Type ?? MessageType.LicenseRequest; + set => __pbn__Type = value; + } + public bool ShouldSerializeType() => __pbn__Type != null; + public void ResetType() => __pbn__Type = null; + private MessageType? __pbn__Type; + + [global::ProtoBuf.ProtoMember(2)] + public SignedDeviceCertificate Msg { get; set; } + + [global::ProtoBuf.ProtoMember(3)] + public byte[] Signature + { + get => __pbn__Signature; + set => __pbn__Signature = value; + } + public bool ShouldSerializeSignature() => __pbn__Signature != null; + public void ResetSignature() => __pbn__Signature = null; + private byte[] __pbn__Signature; + + [global::ProtoBuf.ProtoMember(4)] + public byte[] SessionKey + { + get => __pbn__SessionKey; + set => __pbn__SessionKey = value; + } + public bool ShouldSerializeSessionKey() => __pbn__SessionKey != null; + public void ResetSessionKey() => __pbn__SessionKey = null; + private byte[] __pbn__SessionKey; + + [global::ProtoBuf.ProtoMember(5)] + public RemoteAttestation RemoteAttestation { get; set; } + + [global::ProtoBuf.ProtoContract()] + public enum MessageType + { + [global::ProtoBuf.ProtoEnum(Name = @"LICENSE_REQUEST")] + LicenseRequest = 1, + [global::ProtoBuf.ProtoEnum(Name = @"LICENSE")] + License = 2, + [global::ProtoBuf.ProtoEnum(Name = @"ERROR_RESPONSE")] + ErrorResponse = 3, + [global::ProtoBuf.ProtoEnum(Name = @"SERVICE_CERTIFICATE_REQUEST")] + ServiceCertificateRequest = 4, + [global::ProtoBuf.ProtoEnum(Name = @"SERVICE_CERTIFICATE")] + ServiceCertificate = 5, + } + +} + +[global::ProtoBuf.ProtoContract()] +public partial class FileHashes : global::ProtoBuf.IExtensible +{ + private global::ProtoBuf.IExtension __pbn__extensionData; + global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) + => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing); + + [global::ProtoBuf.ProtoMember(1, Name = @"signer")] + public byte[] Signer + { + get => __pbn__Signer; + set => __pbn__Signer = value; + } + public bool ShouldSerializeSigner() => __pbn__Signer != null; + public void ResetSigner() => __pbn__Signer = null; + private byte[] __pbn__Signer; + + [global::ProtoBuf.ProtoMember(2, Name = @"signatures")] + public global::System.Collections.Generic.List Signatures { get; } = new global::System.Collections.Generic.List(); + + [global::ProtoBuf.ProtoContract()] + public partial class Signature : global::ProtoBuf.IExtensible + { + private global::ProtoBuf.IExtension __pbn__extensionData; + global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) + => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing); + + [global::ProtoBuf.ProtoMember(1, Name = @"filename")] + [global::System.ComponentModel.DefaultValue("")] + public string Filename + { + get => __pbn__Filename ?? ""; + set => __pbn__Filename = value; + } + public bool ShouldSerializeFilename() => __pbn__Filename != null; + public void ResetFilename() => __pbn__Filename = null; + private string __pbn__Filename; + + [global::ProtoBuf.ProtoMember(2, Name = @"test_signing")] + public bool TestSigning + { + get => __pbn__TestSigning.GetValueOrDefault(); + set => __pbn__TestSigning = value; + } + public bool ShouldSerializeTestSigning() => __pbn__TestSigning != null; + public void ResetTestSigning() => __pbn__TestSigning = null; + private bool? __pbn__TestSigning; + + [global::ProtoBuf.ProtoMember(3)] + public byte[] SHA512Hash + { + get => __pbn__SHA512Hash; + set => __pbn__SHA512Hash = value; + } + public bool ShouldSerializeSHA512Hash() => __pbn__SHA512Hash != null; + public void ResetSHA512Hash() => __pbn__SHA512Hash = null; + private byte[] __pbn__SHA512Hash; + + [global::ProtoBuf.ProtoMember(4, Name = @"main_exe")] + public bool MainExe + { + get => __pbn__MainExe.GetValueOrDefault(); + set => __pbn__MainExe = value; + } + public bool ShouldSerializeMainExe() => __pbn__MainExe != null; + public void ResetMainExe() => __pbn__MainExe = null; + private bool? __pbn__MainExe; + + [global::ProtoBuf.ProtoMember(5)] + public byte[] signature + { + get => __pbn__signature; + set => __pbn__signature = value; + } + public bool ShouldSerializesignature() => __pbn__signature != null; + public void Resetsignature() => __pbn__signature = null; + private byte[] __pbn__signature; + + } + +} + +[global::ProtoBuf.ProtoContract()] +public enum LicenseType +{ + [global::ProtoBuf.ProtoEnum(Name = @"ZERO")] + Zero = 0, + [global::ProtoBuf.ProtoEnum(Name = @"DEFAULT")] + Default = 1, + [global::ProtoBuf.ProtoEnum(Name = @"OFFLINE")] + Offline = 2, +} + +[global::ProtoBuf.ProtoContract()] +public enum ProtocolVersion +{ + [global::ProtoBuf.ProtoEnum(Name = @"CURRENT")] + Current = 21, +} + +#pragma warning restore CS0612, CS0618, CS1591, CS3021, IDE0079, IDE1006, RCS1036, RCS1057, RCS1085, RCS1192 +#endregion diff --git a/OF DL/rules.json b/OF DL/rules.json new file mode 100644 index 0000000..9cb9785 --- /dev/null +++ b/OF DL/rules.json @@ -0,0 +1,8 @@ +{ + "app-token": "33d57ade8c02dbc5a333db99ff9ae26a", + "static_param": "RyY8GpixStP90t68HWIJ8Qzo745n0hy0", + "prefix": "30586", + "suffix": "67000213", + "checksum_constant": 521, + "checksum_indexes": [ 0, 2, 3, 7, 7, 8, 8, 10, 11, 13, 14, 16, 17, 17, 17, 19, 19, 20, 21, 21, 23, 23, 24, 24, 27, 27, 29, 30, 31, 34, 35, 39 ] +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..fc337c2 --- /dev/null +++ b/README.md @@ -0,0 +1,39 @@ +# PLEASE READ BEFORE DOWNLOADING +THIS TOOL CANNOT BYPASS PAYWALLS, IT CAN ONLY DOWNLOAD CONTENT YOU HAVE ACCESS TO, PLEASE DO NOT DOWNLOAD THIS TOOL THINKING YOU CAN BYPASS PAYING FOR THINGS!!!!! + +# OF-DL +Scrape all the media from an OnlyFans account + +Join the discord [here](https://discord.com/invite/6bUW8EJ53j) + +# Documentation +Please refer to https://sim0n00ps.github.io/OF-DL/ for instructions on: +- Requirements +- Installing the Program +- Running the Program +- Config options + +# Video Tutorial + + + + + + +https://github.com/user-attachments/assets/1474e85a-30df-4cf0-abf1-2ed9433f61c3 + + + + + + + +# Issues +If you have any questions or issues please raise them on here, all I ask is that you please look back through previous issues to see if your issue or question has been fixed/answered already, it gets annoying when people create issues without checking previous issues which usually leads to me or others repeating themselves, thank you. + +# Disclaimers +This tool is not associated or involved with Onlyfans in any way. +I am not responsible for anything that happens to you or your account when using the tool. + +# Donations +If you would like to donate then here is a link to my ko-fi page https://ko-fi.com/sim0n00ps. Donations are not required but are very much appreciated :) diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh new file mode 100644 index 0000000..f9e9e37 --- /dev/null +++ b/docker/entrypoint.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +mkdir -p /config/cdm/devices/chrome_1610 +mkdir -p /config/logs/ + +if [ ! -f /config/config.conf ] && [ ! -f /config/config.json ]; then + cp /default-config/config.conf /config/config.conf +fi + +if [ ! -f /config/rules.json ]; then + cp /default-config/rules.json /config/rules.json +fi + +{ + supervisord -c /etc/supervisor/conf.d/supervisord.conf & +} &> /dev/null + +# Wait for the 3 supervisor programs to start: X11 (Xvfb), X11vnc, and noVNC +NUM_RUNNING_SERVICES=$(supervisorctl -c /etc/supervisor/conf.d/supervisord.conf status | grep RUNNING | wc -l) +while [ $NUM_RUNNING_SERVICES != "3" ]; do + sleep 1 + NUM_RUNNING_SERVICES=$(supervisorctl -c /etc/supervisor/conf.d/supervisord.conf status | grep RUNNING | wc -l) +done + +/app/OF\ DL diff --git a/docker/supervisord.conf b/docker/supervisord.conf new file mode 100644 index 0000000..f8f7cd6 --- /dev/null +++ b/docker/supervisord.conf @@ -0,0 +1,25 @@ +[unix_http_server] +file=/tmp/supervisor.sock + +[supervisord] +nodaemon=true +logfile=/config/logs/supervisord.log +pidfile=/var/run/supervisord.pid + +[rpcinterface:supervisor] +supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface + +[supervisorctl] +serverurl=unix:///tmp/supervisor.sock + +[program:X11] +command=Xvfb :0 -screen 0 "%(ENV_DISPLAY_WIDTH)s"x"%(ENV_DISPLAY_HEIGHT)s"x24 +autorestart=true + +[program:x11vnc] +command=/usr/bin/x11vnc +autorestart=true + +[program:websockify] +command=websockify --web /usr/share/novnc 8080 localhost:5900 +autorestart=true diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 0000000..b2d6de3 --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1,20 @@ +# Dependencies +/node_modules + +# Production +/build + +# Generated files +.docusaurus +.cache-loader + +# Misc +.DS_Store +.env.local +.env.development.local +.env.test.local +.env.production.local + +npm-debug.log* +yarn-debug.log* +yarn-error.log* diff --git a/docs/.nvmrc b/docs/.nvmrc new file mode 100644 index 0000000..8ce7030 --- /dev/null +++ b/docs/.nvmrc @@ -0,0 +1 @@ +20.16.0 diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..0c6c2c2 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,41 @@ +# Website + +This website is built using [Docusaurus](https://docusaurus.io/), a modern static website generator. + +### Installation + +``` +$ yarn +``` + +### Local Development + +``` +$ yarn start +``` + +This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server. + +### Build + +``` +$ yarn build +``` + +This command generates static content into the `build` directory and can be served using any static contents hosting service. + +### Deployment + +Using SSH: + +``` +$ USE_SSH=true yarn deploy +``` + +Not using SSH: + +``` +$ GIT_USER= yarn deploy +``` + +If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch. diff --git a/docs/babel.config.js b/docs/babel.config.js new file mode 100644 index 0000000..e00595d --- /dev/null +++ b/docs/babel.config.js @@ -0,0 +1,3 @@ +module.exports = { + presets: [require.resolve('@docusaurus/core/lib/babel/preset')], +}; diff --git a/docs/docs/config/_category_.json b/docs/docs/config/_category_.json new file mode 100644 index 0000000..d5acb54 --- /dev/null +++ b/docs/docs/config/_category_.json @@ -0,0 +1,8 @@ +{ + "label": "Configuration", + "position": 2, + "link": { + "type": "generated-index", + "description": "Configuration options and information for OF-DL" + } +} diff --git a/docs/docs/config/auth.md b/docs/docs/config/auth.md new file mode 100644 index 0000000..1d3ca01 --- /dev/null +++ b/docs/docs/config/auth.md @@ -0,0 +1,78 @@ +--- +sidebar_position: 1 +--- + +# Authentication + +## Current Method (versions >= 1.9.0) + +OF DL allows you to log in to your OnlyFans account directly. This simplifies the authentication process significantly. +When prompted by the application, log into your OnlyFans account. Do not close the opened window, tab, or navigate away to another webpage. +The new window will close automatically when the authentication process has finished. + +:::warning + +Some users have reported that "Sign in with Google" has not been working with this authentication method. +If you use the Google sign-in option to log into your OnlyFans account, use one of the [legacy authentication methods](#legacy-methods) described below. + +::: + +:::info + +If you are using docker, follow the special [authentication instructions documented](/docs/installation/docker) to authenticate OF-DL + +::: + +## Legacy Methods + +Legacy authentication methods involve creating/editing `auth.json` file yourself. + +### Browser Extension + +You can use a browser extension to help get the required info for the `auth.json` file. The extension supports Google Chrome and Firefox and can be found [here](https://github.com/whimsical-c4lic0/OF-DL-Auth-Helper/) (https://github.com/whimsical-c4lic0/OF-DL-Auth-Helper/). + +### Manual Method + +Open `auth.json` in a text editor of your choice. The default windows notepad is sufficient. When you open `auth.json` for the first time you should see something like this: + +```json +{ + "USER_ID": "", + "USER_AGENT": "", + "X_BC": "", + "COOKIE": "" +} +``` + +Next, log into OnlyFans, and press F12 to open the dev tools. In the filter box, type `api`, and open any page on OnlyFans (e.g. Messages). You should see some requests appear in the list within the network tab: + +![Image of dev tools panel showing network tab](/img/network_tab.png) + +Click on one of the requests you see in the list, and scroll down until you find the 'Request Headers' section. + +![Image of dev tools panel showing request headers](/img/request_headers.png) + +You should be able to find the 3 fields we need, `Cookie`, `User-Agent` and `x-bc`. + +Within Cookie you will find 2 bits of information that we need to copy, these being `sess` and `auth_id`. + +So heading back to your text editor: + +The value of `USER_ID` will be set to what `auth_id` is set to. + +The value of `USER_AGENT` will be set to what the `User-Agent` is set to in the Request Headers. + +The value of `X_BC` will be set to what the `X-Bc` is set to in the Request Headers. + +The value of `COOKIE` will be set to `auth_id=YOUR AUTH_ID HERE; sess=YOUR SESS HERE;`, please make sure you copy the values from within the Cookie field found in the Request Headers section. + +If you have done everything correct you should end up with something like this (this is all dummy info): + +```json +{ + "USER_ID": "123456", + "USER_AGENT": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0", + "X_BC": "2a9b28a68e7c03a9f0d3b98c28d70e8105e1f1df", + "COOKIE": "auth_id=123456; sess=k3s9tnzdc8vt2h47ljxpmwqy5r;" +} +``` diff --git a/docs/docs/config/cdm.md b/docs/docs/config/cdm.md new file mode 100644 index 0000000..e171807 --- /dev/null +++ b/docs/docs/config/cdm.md @@ -0,0 +1,32 @@ +--- +sidebar_position: 4 +--- + +# CDM (optional, but recommended) + +Without Widevine/CDM keys, OF DL uses the 3rd party website cdrm-project.org for decrypting DRM videos. With keys, OF DL directly communicates with OnlyFans. It is highly recommended to use keys, both in case the cdrm-project site is having issues (which occur frequently, in our experience) and it will result in faster download speeds, too. However, this is optional, as things will work as long as cdrm-project is functional. + +Two files need to be generated, called `device_client_id_blob` and `device_private_key`. In your main OF DL folder (where you have `config.json` and `auth.json`), create a folder called `cdm` (if it does not already exist). Inside it, create a folder called `devices` and inside that, create a folder called `chrome_1610`. Finally, inside this last folder (`chrome_1610`), place the two key files. (Note that this folder name is a legacy name and OFDL does not actually use Chrome itself.) + +## Manual Generation Method + +You can find a tutorial on how to do this [here](https://forum.videohelp.com/threads/408031-Dumping-Your-own-L3-CDM-with-Android-Studio). + +I have also made some [batch scripts](https://github.com/sim0n00ps/L3-Dumping) to run the commands included in the guide linked above that can save you some time and makes the process a little simpler. + +## Discord Method + +Generating these keys can be complicated, so the team (shout out to Masaki here) have set up a bot on the Discord server to help securely deliver these keys to users who need them. You can join the discord sever [here](https://discord.com/invite/6bUW8EJ53j) + +After joining, visit the bot [here](https://discord.com/channels/1198332760947966094/1333835216313122887) (the pinned post in the `#ofdl` support forum) + +## After install + +Restart OF DL, and you should no longer see the yellow warning message about cdrm-project and instead see two green messages like so: + +``` +device_client_id_blob located successfully! +device_private_key located successfully! +``` + +You are now independent of cdrm-project! diff --git a/docs/docs/config/configuration.md b/docs/docs/config/configuration.md new file mode 100644 index 0000000..d4e67f2 --- /dev/null +++ b/docs/docs/config/configuration.md @@ -0,0 +1,516 @@ +--- +sidebar_position: 2 +--- + +# Configuration + +The `config.conf` file contains all the options you can change, these options are listed below: + +# Configuration - External Tools + +## FFmpegPath + +Type: `string` + +Default: `""` + +Allowed values: Any valid path or `""` + +Description: This is the path to the FFmpeg executable (`ffmpeg.exe` on Windows and `ffmpeg` on Linux/macOS). +If the path is not set then the program will try to find it in both the same directory as the OF-DL executable as well +as the PATH environment variable. + +:::note + +If you are using a Windows path, you will need to escape the backslashes, e.g. `"C:\\ffmpeg\\bin\\ffmpeg.exe"` +For example, this is not valid: `"C:\some\path\ffmpeg.exe"`, but `"C:/some/path/ffmpeg.exe"` and `"C:\\some\\path\\ffmpeg.exe"` are both valid. + +::: + +# Configuration - Download Settings + +## DownloadAvatarHeaderPhoto + +Type: `boolean` + +Default: `true` + +Allowed values: `true`, `false` + +Description: Avatar and header images will be downloaded if set to `true` + +## DownloadPaidPosts + +Type: `boolean` + +Default: `true` + +Allowed values: `true`, `false` + +Description: Paid posts will be downloaded if set to `true` + +## DownloadPosts + +Type: `boolean` + +Default: `true` + +Allowed values: `true`, `false` + +Description: Free posts will be downloaded if set to `true` + +## DownloadArchived + +Type: `boolean` + +Default: `true` + +Allowed values: `true`, `false` + +Description: Posts in the "Archived" tab will be downloaded if set to `true` + +## DownloadStreams + +Type: `boolean` + +Default: `true` + +Allowed values: `true`, `false` + +Description: Posts in the "Streams" tab will be downloaded if set to `true` + +## DownloadStories + +Type: `boolean` + +Default: `true` + +Allowed values: `true`, `false` + +Description: Stories on a user's profile will be downloaded if set to `true` + +## DownloadHighlights + +Type: `boolean` + +Default: `true` + +Allowed values: `true`, `false` + +Description: Highlights on a user's will be downloaded if set to `true` + +## DownloadMessages + +Type: `boolean` + +Default: `true` + +Allowed values: `true`, `false` + +Description: Free media within messages (including paid message previews) will be downloaded if set to `true` + +## DownloadPaidMessages + +Type: `boolean` + +Default: `true` + +Allowed values: `true`, `false` + +Description: Paid media within messages (excluding paid message previews) will be downloaded if set to `true` + +## DownloadImages + +Type: `boolean` + +Default: `true` + +Allowed values: `true`, `false` + +Description: Images will be downloaded if set to `true` + +## DownloadVideos + +Type: `boolean` + +Default: `true` + +Allowed values: `true`, `false` + +Description: Videos will be downloaded if set to `true` + +## DownloadAudios + +Type: `boolean` + +Default: `true` + +Allowed values: `true`, `false` + +Description: Audios will be downloaded if set to `true` + +## IgnoreOwnMessages + +Type: `boolean` + +Default: `false` + +Allowed values: `true`, `false` + +Description: By default (or when set to `false`), messages that were sent by yourself will be added to the metadata DB and any media which has been sent by yourself will be downloaded. If set to `true`, the program will not add messages sent by yourself to the metadata DB and will not download any media which has been sent by yourself. + +## DownloadPostsIncrementally + +Type: `boolean` + +Default: `false` + +Allowed values: `true`, `false` + +Description: If set to `true`, only new posts will be downloaded from the date of the last post that was downloaded based off what's in the `user_data.db` file. +If set to `false`, the default behaviour will apply, and all posts will be gathered and compared against the database to see if they need to be downloaded or not. + +## BypassContentForCreatorsWhoNoLongerExist + +Type: `boolean` + +Default: `false` + +Allowed values: `true`, `false` + +Description: When a creator no longer exists (their account has been deleted), most of their content will be inaccessible. +Purchased content, however, will still be accessible by downloading media usisng the "Download Purchased Tab" menu option +or with the [NonInteractiveModePurchasedTab](#noninteractivemodepurchasedtab) config option when downloading media in non-interactive mode. + +## DownloadDuplicatedMedia + +Type: `boolean` + +Default: `false` + +Allowed values: `true`, `false` + +Description: By default (or when set to `false`), the program will not download duplicated media. If set to `true`, duplicated media will be downloaded. + +## SkipAds + +Type: `boolean` + +Default: `false` + +Allowed values: `true`, `false` + +Description: Posts and messages that contain #ad or free trial links will be ignored if set to `true` + +## DownloadPath + +Type: `string` + +Default: `""` + +Allowed values: Any valid path + +Description: If left blank then content will be downloaded to `__user_data__/sites/OnlyFans/{username}`. +If you set the download path to `"S:/"`, then content will be downloaded to `S:/{username}` + +:::note + +If you are using a Windows path, you will need to escape the backslashes, e.g. `"C:\\Users\\user\\Downloads\\OnlyFans\\"` +Please make sure your path ends with a `/` + +::: + +## DownloadOnlySpecificDates + +Type: `boolean` + +Default: `false` + +Allowed values: `true`, `false` + +Description: If set to `true`, posts will be downloaded based on the [DownloadDateSelection](#downloaddateselection) and [CustomDate](#customdate) config options. +If set to `false`, all posts will be downloaded. + +## DownloadDateSelection + +Type: `string` + +Default: `"before"` + +Allowed values: `"before"`, `"after"` + +Description: [DownloadOnlySpecificDates](#downloadonlyspecificdates) needs to be set to `true` for this to work. This will get all posts from before +the date if set to `"before"`, and all posts from the date you specify up until the current date if set to `"after"`. +The date you specify will be in the [CustomDate](#customdate) config option. + +## CustomDate + +Type: `string` + +Default: `null` + +Allowed values: Any date in `yyyy-mm-dd` format or `null` + +Description: [DownloadOnlySpecificDates](#downloadonlyspecificdates) needs to be set to `true` for this to work. +This date will be used when you are trying to download between/after a certain date. See [DownloadOnlySpecificDates](#downloadonlyspecificdates) and +[DownloadDateSelection](#downloaddateselection) for more information. + +# Configuration - File Settings + +## PaidPostFileNameFormat + +Type: `string` + +Default: `""` + +Allowed values: Any valid string + +Description: Please refer to [custom filename formats](/docs/config/custom-filename-formats#paidpostfilenameformat) page to see what fields you can use. + +## PostFileNameFormat + +Type: `string` + +Default: `""` + +Allowed values: Any valid string + +Description: Please refer to the [custom filename formats](/docs/config/custom-filename-formats#postfilenameformat) page to see what fields you can use. + +## PaidMessageFileNameFormat + +Type: `string` + +Default: `""` + +Allowed values: Any valid string + +Description: Please refer to [custom filename formats](/docs/config/custom-filename-formats#paidmessagefilenameformat) page to see what fields you can use. + +## MessageFileNameFormat + +Type: `string` + +Default: `""` + +Allowed values: Any valid string + +Description: Please refer to [custom filename formats](/docs/config/custom-filename-formats#messagefilenameformat) page to see what fields you can use. + +## RenameExistingFilesWhenCustomFormatIsSelected + +Type: `boolean` + +Default: `false` + +Allowed values: `true`, `false` + +Description: When `true`, any current files downloaded will have the current format applied to them. +When `false`, only new files will have the current format applied to them. + +# Configuration - Creator-Specific Configurations + +## CreatorConfigs + +Type: `object` + +Default: `{}` + +Allowed values: An array of Creator Config objects + +Description: This configuration options allows you to set file name formats for specific creators. +This is useful if you want to have different file name formats for different creators. The values set here will override the global values set in the config file +(see [PaidPostFileNameFormat](#paidpostfilenameformat), [PostFileNameFormat](#postfilenameformat), +[PaidMessageFileNAmeFormat](#paidmessagefilenameformat), and [MessageFileNameFormat](#messagefilenameformat)). +For more information on the file name formats, see the [custom filename formats](/docs/config/custom-filename-formats) page. + +Example: +``` +"CreatorConfigs": { + "creator_one": { + "PaidPostFileNameFormat": "{id}_{mediaid}_{filename}", + "PostFileNameFormat": "{username}_{id}_{mediaid}_{mediaCreatedAt}", + "PaidMessageFileNameFormat": "{id}_{mediaid}_{createdAt}", + "MessageFileNameFormat": "{id}_{mediaid}_{filename}" + }, + "creator_two": { + "PaidPostFileNameFormat": "{id}_{mediaid}", + "PostFileNameFormat": "{username}_{id}_{mediaid}", + "PaidMessageFileNameFormat": "{id}_{mediaid}", + "MessageFileNameFormat": "{id}_{mediaid}" + } +} +``` + +# Configuration - Folder Settings + +## FolderPerPaidPost + +Type: `boolean` + +Default: `false` + +Allowed values: `true`, `false` + +Description: A folder will be created for each paid post (containing all the media for that post) if set to `true`. +When set to `false`, paid post media will be downloaded into the `Posts/Paid` folder. + +## FolderPerPost + +Type: `boolean` + +Default: `false` + +Allowed values: `true`, `false` + +Description: A folder will be created for each post (containing all the media for that post) if set to `true`. +When set to `false`, post media will be downloaded into the `Posts/Free` folder. + +## FolderPerPaidMessage + +Type: `boolean` + +Default: `false` + +Allowed values: `true`, `false` + +Description: A folder will be created for each paid message (containing all the media for that message) if set to `true`. +When set to `false`, paid message media will be downloaded into the `Messages/Paid` folder. + +## FolderPerMessage + +Type: `boolean` + +Default: `false` + +Allowed values: `true`, `false` + +Description: A folder will be created for each message (containing all the media for that message) if set to `true`. +When set to `false`, message media will be downloaded into the `Messages/Free` folder. + +# Configuration - Subscription Settings + +## IncludeExpiredSubscriptions + +Type: `boolean` + +Default: `false` + +Allowed values: `true`, `false` + +Description: If set to `true`, expired subscriptions will appear in the user list under the "Custom" menu option. + +## IncludeRestrictedSubscriptions + +Type: `boolean` + +Default: `false` + +Allowed values: `true`, `false` + +Description: If set to `true`, media from restricted creators will be downloaded. If set to `false`, restricted creators will be ignored. + +## IgnoredUsersListName + +Type: `string` + +Default: `""` + +Allowed values: The name of a list of users you have created on OnlyFans or `""` + +Description: When set to the name of a list, users in the list will be ignored when scraping content. +If set to `""` (or an invalid list name), no users will be ignored when scraping content. + +# Configuration - Interaction Settings + +## NonInteractiveMode + +Type: `boolean` + +Default: `false` + +Allowed values: `true`, `false` + +Description: If set to `true`, the program will run without any input from the user. It will scrape all users automatically +(unless [NonInteractiveModeListName](#noninteractivemodelistname) or [NonInteractiveModePurchasedTab](#noninteractivemodepurchasedtab) are configured). +If set to `false`, the default behaviour will apply, and you will be able to choose an option from the menu. + +:::warning + +If NonInteractiveMode is enabled, you will be unable to authenticate OF-DL using the standard authentication method. +Before you can run OF-DL in NonInteractiveMode, you must either + +1. Generate an auth.json file by running OF-DL with NonInteractiveMode disabled and authenticating OF-DL using the standard method **OR** +2. Generate an auth.json file by using a [legacy authentication method](/docs/config/auth#legacy-methods) + +::: + +## NonInteractiveModeListName + +Type: `string` + +Default: `""` + +Allowed values: The name of a list of users you have created on OnlyFans or `""` + +Description: When set to the name of a list, non-interactive mode will download media from the list of users instead of all +users (when [NonInteractiveMode](#noninteractivemode) is set to `true`). If set to `""`, all users will be scraped +(unless [NonInteractiveModePurchasedTab](#noninteractivemodepurchasedtab) is configured). + +## NonInteractiveModePurchasedTab + +Type: `boolean` + +Default: `false` + +Allowed values: `true`, `false` + +Description: When set to `true`, non-interactive mode will only download content from the Purchased tab +(when [NonInteractiveMode](#noninteractivemode) is set to `true`). If set to `false`, all users will be scraped +(unless [NonInteractiveModeListName](#noninteractivemodelistname) is configured). + +# Configuration - Performance Settings + +## Timeout + +Type: `integer` + +Default: `-1` + +Allowed values: Any positive integer or `-1` + +Description: You won't need to set this, but if you see errors about the configured timeout of 100 seconds elapsing then +you could set this to be more than 100. It is recommended that you leave this as the default value. + +## LimitDownloadRate + +Type: `boolean` + +Default: `false` + +Allowed values: `true`, `false` + +Description: If set to `true`, the download rate will be limited to the value set in [DownloadLimitInMbPerSec](#downloadlimitinmbpersec). + +## DownloadLimitInMbPerSec + +Type: `integer` + +Default: `4` + +Allowed values: Any positive integer + +Description: The download rate in MB per second. This will only be used if [LimitDownloadRate](#limitdownloadrate) is set to `true`. + +# Configuration - Logging/Debug Settings + +## LoggingLevel + +Type: `string` + +Default: `"Error"` + +Allowed values: `"Verbose"`, `"Debug"`, `"Information"`, `"Warning"`, `"Error"`, `"Fatal"` + +Description: The level of logging that will be saved to the log files in the `logs` folder. +When requesting help with an issue, it is recommended to set this to `"Verbose"` and provide the log file. diff --git a/docs/docs/config/custom-filename-formats.md b/docs/docs/config/custom-filename-formats.md new file mode 100644 index 0000000..72631fd --- /dev/null +++ b/docs/docs/config/custom-filename-formats.md @@ -0,0 +1,94 @@ +--- +sidebar_position: 3 +--- + +# Custom Filename Formats + +In the config.conf file you can now specify some custom filename formats that will be used when downloading files. I have had to add 4 new fields to the auth.json file, these are: + +- PaidPostFileNameFormat +- PostFileNameFormat +- PaidMessageFileNameFormat +- MessageFileNameFormat + +I have had to do it this way as the names of fields from the API responses are different in some places +so it would become a mess using 1 file format for everything, besides having separate formats can be useful if you only +want posts to have a custom format and the rest just use the default filename. + +Below are the names of the fields you can use in each format: + +## PaidPostFileNameFormat + +`id` - Id of the post + +`postedAt` - The date when the post was made yyyy-mm-dd + +`mediaId` - Id of the media + +`mediaCreatedAt` - The date when the media was uploaded to OnlyFans yyyy-mm-dd + +`filename` - The original filename e.g 0gy8cmw5jjjs5pt487b9g_source.mp4 or 914x1706_6b211f68a4e315125ecf70137bb75d8e.jpg + +`username` - The username of the creator e.g onlyfans + +`text` - The text of the post + +## PostFileNameFormat + +`id` - Id of the post + +`postedAt` - The date when the post was made yyyy-mm-dd + +`mediaId` - Id of the media + +`mediaCreatedAt` - The date when the media was uploaded to OnlyFans yyyy-mm-dd + +`filename` - The original filename e.g 0gy8cmw5jjjs5pt487b9g_source.mp4 or 914x1706_6b211f68a4e315125ecf70137bb75d8e.jpg + +`username` - The username of the creator e.g onlyfans + +`text` - The text of the post + +`rawText` - The text of the post + +## PaidMessageFileNameFormat + +`id` - Id of the message + +`createdAt` - The date when the message was sent yyyy-mm-dd + +`mediaId` - Id of the media + +`mediaCreatedAt` - The date when the media was uploaded to OnlyFans yyyy-mm-dd + +`filename` - The original filename e.g 0gy8cmw5jjjs5pt487b9g_source.mp4 or 914x1706_6b211f68a4e315125ecf70137bb75d8e.jpg + +`username` - The username of the creator e.g onlyfans + +`text` - The text of the message + +## MessageFileNameFormat + +`id` - Id of the message + +`createdAt` - The date when the message was sent yyyy-mm-dd + +`mediaId` - Id of the media + +`mediaCreatedAt` - The date when the media was uploaded to OnlyFans yyyy-mm-dd + +`filename` - The original filename e.g 0gy8cmw5jjjs5pt487b9g_source.mp4 or 914x1706_6b211f68a4e315125ecf70137bb75d8e.jpg + +`username` - The username of the creator e.g onlyfans + +`text` - The text of the message + +## Examples + +`"PaidPostFileNameFormat": "{id}_{mediaid}_{filename}"` + +`"PostFileNameFormat": "{username}_{id}_{mediaid}_{mediaCreatedAt}"` + +`"PaidMessageFileNameFormat": "{id}_{mediaid}_{createdAt}"` + +`"MessageFileNameFormat": "{id}_{mediaid}_{filename}"` diff --git a/docs/docs/installation/_category_.json b/docs/docs/installation/_category_.json new file mode 100644 index 0000000..716a1d8 --- /dev/null +++ b/docs/docs/installation/_category_.json @@ -0,0 +1,8 @@ +{ + "label": "Installation", + "position": 1, + "link": { + "type": "generated-index", + "description": "Installation instructions for OF-DL" + } +} diff --git a/docs/docs/installation/docker.md b/docs/docs/installation/docker.md new file mode 100644 index 0000000..2549743 --- /dev/null +++ b/docs/docs/installation/docker.md @@ -0,0 +1,48 @@ +--- +sidebar_position: 2 +--- + +# Docker + +## Running OF-DL + +To run OF-DL in a docker container, follow these steps: + +1. Install Docker Desktop (Windows, macOS) or Docker Engine (Linux) and launch it +2. Open your terminal application of choice (macOS Terminal, GNOME Terminal, etc.) +3. Create two directories, one called `config` and one called `data`. + - An example might be: + ```bash + mkdir -p $HOME/ofdl/config $HOME/ofdl/data + ``` + Adjust `$HOME/ofdl` as desired (including in the commands below) if you want the files stored elsewhere. +4. Run the following command to start the docker container: + ```bash + docker run --rm -it -v $HOME/ofdl/data/:/data -v $HOME/ofdl/config/:/config -p 8080:8080 ghcr.io/sim0n00ps/of-dl:latest + ``` + If `config.json` and/or `rules.json` don't exist in the `config` directory, files with default values will be created when you run the docker container. + If you have your own Widevine keys, those files should be placed under `$HOME/ofdl/config/cdm/devices/chrome_1610/`. +5. OF-DL needs to be authenticated with your OnlyFans account. When prompted, open [http://localhost:8080](http://localhost:8080) in a web browser to log in to your OnlyFans account. + +## Updating OF-DL + +When a new version of OF-DL is released, you can download the latest docker image by executing: + +```bash +docker pull ghcr.io/sim0n00ps/of-dl:latest +``` + +You can then run the new version of OF-DL by executing the `docker run` command in the [Running OF-DL](#running-of-dl) section above. + +## Building the Docker Image (Optional) + +Since official docker images are provided for OF-DL through GitHub Container Registry (ghcr.io), you do not need to build the docker image yourself. +If you would like to build the docker image yourself, however, start by cloning the OF-DL repository and opening a terminal in the root directory of the repository. +Then, execute the following command while replacing `x.x.x` with the current version of OF-DL: + +```bash +VERSION="x.x.x" docker build --build-arg VERSION=$VERSION -t of-dl . +``` + +You can then run a container using the image you just built by executing the `docker run` command in the +[Running OF-DL](#running-of-dl) section above while replacing `ghcr.io/sim0n00ps/of-dl:latest` with `of-dl`. diff --git a/docs/docs/installation/linux.md b/docs/docs/installation/linux.md new file mode 100644 index 0000000..b7e571c --- /dev/null +++ b/docs/docs/installation/linux.md @@ -0,0 +1,48 @@ +--- +sidebar_position: 3 +--- + +# Linux + +A Linux release of OF-DL is not available at this time, however you can run OF-DL on Linux using Docker. +Please refer to the [Docker](/docs/installation/docker) page for instructions on how to run OF-DL in a Docker container. +If you do not have Docker installed, you can download it from [here](https://docs.docker.com/desktop/install/linux-install/). +If you would like to run OF-DL natively on Linux, you can build it from source by following the instructions below. + +## Building from source + +- Install the libicu library + +```bash +sudo apt-get install libicu-dev +``` + +- Install .NET version 8 + +```bash + wget https://dot.net/v1/dotnet-install.sh + sudo bash dotnet-install.sh --architecture x64 --install-dir /usr/share/dotnet/ --runtime dotnet --version 8.0.7 +``` + +- Clone the repo + +```bash +git clone https://github.com/sim0n00ps/OF-DL.git +cd 'OF-DL' +``` + +- Build the project. Replace `%VERSION%` with the current version number of OF-DL (e.g. `1.7.68`). + +```bash +dotnet publish -p:Version=%VERSION% -c Release +cd 'OF DL/bin/Release/net8.0' +``` + +- Download the windows release as described on [here](/docs/installation/windows#installation). +- Add the `config.json` and `rules.json` files as well as the `cdm` folder to the `OF DL/bin/Release/net8.0` folder. + +- Run the application + +```bash +DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1 ./'OF DL' +``` diff --git a/docs/docs/installation/macos.md b/docs/docs/installation/macos.md new file mode 100644 index 0000000..f03d038 --- /dev/null +++ b/docs/docs/installation/macos.md @@ -0,0 +1,9 @@ +--- +sidebar_position: 4 +--- + +# macOS + +macOS releases of OF-DL are not available at this time, however you can run OF-DL on macOS using Docker. +Please refer to the [Docker](/docs/installation/docker) page for instructions on how to run OF-DL in a Docker container. +If you do not have Docker installed, you can download it from [here](https://docs.docker.com/desktop/install/mac-install/). diff --git a/docs/docs/installation/windows.md b/docs/docs/installation/windows.md new file mode 100644 index 0000000..cff2fc6 --- /dev/null +++ b/docs/docs/installation/windows.md @@ -0,0 +1,26 @@ +--- +sidebar_position: 1 +--- + +# Windows + +## Requirements + +### FFmpeg + +You will need to download FFmpeg. You can download it from [here](https://www.gyan.dev/ffmpeg/builds/). +Make sure you download `ffmpeg-release-essentials.zip`. Unzip it anywhere on your computer. You only need `ffmpeg.exe`, and you can ignore the rest. +Move `ffmpeg.exe` to the same folder as `OF DL.exe` (downloaded in the installation steps below). If you choose to move `ffmpeg.exe` to a different folder, +you will need to specify the path to `ffmpeg.exe` in the config file (see the `FFmpegPath` [config option](/docs/config/configuration#ffmpegpath)). + +## Installation + +1. Navigate to the OF-DL [releases page](https://github.com/sim0n00ps/OF-DL/releases), and download the latest release zip file. The zip file will be named `OFDLVx.x.x.zip` where `x.x.x` is the version number. +2. Unzip the downloaded file. The destination folder can be anywhere on your computer, preferably somewhere where you want to download content to/already have content downloaded. +3. Your folder should contain a folder named `cdm` as well as the following files: + - OF DL.exe + - config.json + - rules.json + - e_sqlite3.dll + - ffmpeg.exe +4. Once you have done this, run OF DL.exe diff --git a/docs/docs/running-the-program.md b/docs/docs/running-the-program.md new file mode 100644 index 0000000..fb520a4 --- /dev/null +++ b/docs/docs/running-the-program.md @@ -0,0 +1,54 @@ +--- +sidebar_position: 3 +--- + +# Running the Program + +Once you are happy you have filled everything in [auth.json](/docs/config/auth) correctly, you can double click OF-DL.exe and you should see a command prompt window appear, it should look something like this: + +![CLI welcome banner](/img/welcome_banner.png) + +It should locate `config.json`, `rules.json` and FFmpeg successfully. If anything doesn't get located +successfully, then make sure the files exist or the path is correct. + +OF-DL will open a new window, if needed, to allow you to log into your OnlyFans account. The window will automatically close once +the authorization process has finished. If the auth info is correct then you should see a message in green text +`Logged In successfully as {Your Username} {Your User Id}`. However, if the authorization has failed, +then a message in red text will appear `Auth failed, please check the values in auth.json are correct, press any key to exit.` +This means you need to go back and fill in the `auth.json` file again, this will usually indicate that your `user-agent` has changed or you need to re-copy your `sess` value. + +If you're logged in successfully then you will be greeted with a selection prompt. To navigate the menu the can use the ↑ & ↓ arrows and press `enter` to choose that option. + +![CLI main menu](/img/cli_menu.png) + +The `Select All` option will go through every account you are currently subscribed to and grab all of the media from the users. + +The `List` option will show you all the lists you have created on OnlyFans and you can then select 1 or more lists to download the content of the users within those lists. + +The `Custom` option allows you to select 1 or more accounts you want to scrape media from so if you only want to get media from a select number of accounts then you can do that. +To navigate the menu the can use the ↑ & ↓ arrows. You can also press keys A-Z on the keyboard whilst in the menu to easily navigate the menu and for example +pressing the letter 'c' on the keyboard will highlight the first user in the list whose username starts with the letter 'c'. To select/deselect an account, +press the space key, and after you are happy with your selection(s), press the enter key to start downloading. + +The `Download Single Post` allows you to download a post from a URL, to get this URL go to any post and press the 3 dots, Copy link to post. + +The `Download Single Message` allows you to download a message from a URL, to get this URL go to any message in the **purchased tab** and press the 3 dots, Copy link to message. + +The `Download Purchased Tab` option will download all the media from the purchased tab in OnlyFans. + +The `Edit config.json` option allows you to change the config from within the program. + +The `Change logging level` option allows you to change the logging level that the program uses when writing logs to files in the `logs` folder. + +The `Logout and Exit` option allows you to remove your authentication from OF-DL. This is useful if you use multiple OnlyFans accounts. + +After you have made your selection the content should start downloading. Content is downloaded in this order: + +1. Paid Posts +2. Posts +3. Archived +4. Streams +5. Stories +6. Highlights +7. Messages +8. Paid Messages diff --git a/docs/docusaurus.config.js b/docs/docusaurus.config.js new file mode 100644 index 0000000..6ddbff9 --- /dev/null +++ b/docs/docusaurus.config.js @@ -0,0 +1,123 @@ +// @ts-check +// `@type` JSDoc annotations allow editor autocompletion and type checking +// (when paired with `@ts-check`). +// There are various equivalent ways to declare your Docusaurus config. +// See: https://docusaurus.io/docs/api/docusaurus-config + +import {themes as prismThemes} from 'prism-react-renderer'; + +/** @type {import('@docusaurus/types').Config} */ +const config = { + title: 'OF-DL', + tagline: 'A media scraper for OnlyFans with DRM video support', + favicon: 'img/logo.png', + + // Set the production url of your site here + url: 'https://sim0n00ps.github.io', + // Set the // pathname under which your site is served + // For GitHub pages deployment, it is often '//' + baseUrl: '/OF-DL/', + + // GitHub pages deployment config. + // If you aren't using GitHub pages, you don't need these. + organizationName: 'sim0n00ps', // Usually your GitHub org/user name. + projectName: 'OF-DL', // Usually your repo name. + + onBrokenLinks: 'throw', + onBrokenMarkdownLinks: 'warn', + + // Even if you don't use internationalization, you can use this field to set + // useful metadata like html lang. For example, if your site is Chinese, you + // may want to replace "en" with "zh-Hans". + i18n: { + defaultLocale: 'en', + locales: ['en'], + }, + + presets: [ + [ + '@docusaurus/preset-classic', + /** @type {import('@docusaurus/preset-classic').Options} */ + ({ + docs: { + sidebarPath: './sidebars.js', + }, + blog: false, + }), + ], + ], + + themeConfig: + /** @type {import('@docusaurus/preset-classic').ThemeConfig} */ + ({ + colorMode: { + respectPrefersColorScheme: true, + }, + navbar: { + title: 'OF-DL', + logo: { + alt: 'OF-DL Logo', + src: 'img/logo.png', + }, + items: [ + { + type: 'docSidebar', + sidebarId: 'generatedSidebar', + position: 'left', + label: 'Docs', + }, + { + href: 'https://github.com/sim0n00ps/OF-DL', + label: 'GitHub', + position: 'right', + }, + ], + }, + footer: { + style: 'dark', + links: [ + { + title: 'Docs', + items: [ + { + label: 'Installation', + to: '/docs/installation/windows', + }, + { + label: 'Configuration', + to: '/docs/config/auth', + }, + { + label: 'Running the Program', + to: '/docs/running-the-program', + }, + ], + }, + { + title: 'Community', + items: [ + { + label: 'Discord', + href: 'https://discord.com/invite/6bUW8EJ53j', + }, + ], + }, + { + title: 'More', + items: [ + { + label: 'GitHub', + href: 'https://github.com/sim0n00ps/OF-DL', + }, + ], + }, + ], + }, + prism: { + theme: prismThemes.github, + darkTheme: prismThemes.dracula, + }, + }), +}; + +export default config; diff --git a/docs/package-lock.json b/docs/package-lock.json new file mode 100644 index 0000000..9d4c166 --- /dev/null +++ b/docs/package-lock.json @@ -0,0 +1,15550 @@ +{ + "name": "of-dl", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "of-dl", + "version": "0.0.0", + "dependencies": { + "@docusaurus/core": "3.4.0", + "@docusaurus/preset-classic": "3.4.0", + "@mdx-js/react": "^3.0.0", + "clsx": "^2.0.0", + "prism-react-renderer": "^2.3.0", + "react": "^18.0.0", + "react-dom": "^18.0.0" + }, + "devDependencies": { + "@docusaurus/module-type-aliases": "3.4.0", + "@docusaurus/types": "3.4.0" + }, + "engines": { + "node": ">=18.0" + } + }, + "node_modules/@algolia/autocomplete-core": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.9.3.tgz", + "integrity": "sha512-009HdfugtGCdC4JdXUbVJClA0q0zh24yyePn+KUGk3rP7j8FEe/m5Yo/z65gn6nP/cM39PxpzqKrL7A6fP6PPw==", + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-plugin-algolia-insights": "1.9.3", + "@algolia/autocomplete-shared": "1.9.3" + } + }, + "node_modules/@algolia/autocomplete-plugin-algolia-insights": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.9.3.tgz", + "integrity": "sha512-a/yTUkcO/Vyy+JffmAnTWbr4/90cLzw+CC3bRbhnULr/EM0fGNvM13oQQ14f2moLMcVDyAx/leczLlAOovhSZg==", + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-shared": "1.9.3" + }, + "peerDependencies": { + "search-insights": ">= 1 < 3" + } + }, + "node_modules/@algolia/autocomplete-preset-algolia": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.9.3.tgz", + "integrity": "sha512-d4qlt6YmrLMYy95n5TB52wtNDr6EgAIPH81dvvvW8UmuWRgxEtY0NJiPwl/h95JtG2vmRM804M0DSwMCNZlzRA==", + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-shared": "1.9.3" + }, + "peerDependencies": { + "@algolia/client-search": ">= 4.9.1 < 6", + "algoliasearch": ">= 4.9.1 < 6" + } + }, + "node_modules/@algolia/autocomplete-shared": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.9.3.tgz", + "integrity": "sha512-Wnm9E4Ye6Rl6sTTqjoymD+l8DjSTHsHboVRYrKgEt8Q7UHm9nYbqhN/i0fhUYA3OAEH7WA8x3jfpnmJm3rKvaQ==", + "license": "MIT", + "peerDependencies": { + "@algolia/client-search": ">= 4.9.1 < 6", + "algoliasearch": ">= 4.9.1 < 6" + } + }, + "node_modules/@algolia/cache-browser-local-storage": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.24.0.tgz", + "integrity": "sha512-t63W9BnoXVrGy9iYHBgObNXqYXM3tYXCjDSHeNwnsc324r4o5UiVKUiAB4THQ5z9U5hTj6qUvwg/Ez43ZD85ww==", + "license": "MIT", + "dependencies": { + "@algolia/cache-common": "4.24.0" + } + }, + "node_modules/@algolia/cache-common": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.24.0.tgz", + "integrity": "sha512-emi+v+DmVLpMGhp0V9q9h5CdkURsNmFC+cOS6uK9ndeJm9J4TiqSvPYVu+THUP8P/S08rxf5x2P+p3CfID0Y4g==", + "license": "MIT" + }, + "node_modules/@algolia/cache-in-memory": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.24.0.tgz", + "integrity": "sha512-gDrt2so19jW26jY3/MkFg5mEypFIPbPoXsQGQWAi6TrCPsNOSEYepBMPlucqWigsmEy/prp5ug2jy/N3PVG/8w==", + "license": "MIT", + "dependencies": { + "@algolia/cache-common": "4.24.0" + } + }, + "node_modules/@algolia/client-account": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.24.0.tgz", + "integrity": "sha512-adcvyJ3KjPZFDybxlqnf+5KgxJtBjwTPTeyG2aOyoJvx0Y8dUQAEOEVOJ/GBxX0WWNbmaSrhDURMhc+QeevDsA==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "4.24.0", + "@algolia/client-search": "4.24.0", + "@algolia/transporter": "4.24.0" + } + }, + "node_modules/@algolia/client-analytics": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.24.0.tgz", + "integrity": "sha512-y8jOZt1OjwWU4N2qr8G4AxXAzaa8DBvyHTWlHzX/7Me1LX8OayfgHexqrsL4vSBcoMmVw2XnVW9MhL+Y2ZDJXg==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "4.24.0", + "@algolia/client-search": "4.24.0", + "@algolia/requester-common": "4.24.0", + "@algolia/transporter": "4.24.0" + } + }, + "node_modules/@algolia/client-common": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.24.0.tgz", + "integrity": "sha512-bc2ROsNL6w6rqpl5jj/UywlIYC21TwSSoFHKl01lYirGMW+9Eek6r02Tocg4gZ8HAw3iBvu6XQiM3BEbmEMoiA==", + "license": "MIT", + "dependencies": { + "@algolia/requester-common": "4.24.0", + "@algolia/transporter": "4.24.0" + } + }, + "node_modules/@algolia/client-personalization": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.24.0.tgz", + "integrity": "sha512-l5FRFm/yngztweU0HdUzz1rC4yoWCFo3IF+dVIVTfEPg906eZg5BOd1k0K6rZx5JzyyoP4LdmOikfkfGsKVE9w==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "4.24.0", + "@algolia/requester-common": "4.24.0", + "@algolia/transporter": "4.24.0" + } + }, + "node_modules/@algolia/client-search": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.24.0.tgz", + "integrity": "sha512-uRW6EpNapmLAD0mW47OXqTP8eiIx5F6qN9/x/7HHO6owL3N1IXqydGwW5nhDFBrV+ldouro2W1VX3XlcUXEFCA==", + "license": "MIT", + "dependencies": { + "@algolia/client-common": "4.24.0", + "@algolia/requester-common": "4.24.0", + "@algolia/transporter": "4.24.0" + } + }, + "node_modules/@algolia/events": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@algolia/events/-/events-4.0.1.tgz", + "integrity": "sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ==", + "license": "MIT" + }, + "node_modules/@algolia/logger-common": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.24.0.tgz", + "integrity": "sha512-LLUNjkahj9KtKYrQhFKCzMx0BY3RnNP4FEtO+sBybCjJ73E8jNdaKJ/Dd8A/VA4imVHP5tADZ8pn5B8Ga/wTMA==", + "license": "MIT" + }, + "node_modules/@algolia/logger-console": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.24.0.tgz", + "integrity": "sha512-X4C8IoHgHfiUROfoRCV+lzSy+LHMgkoEEU1BbKcsfnV0i0S20zyy0NLww9dwVHUWNfPPxdMU+/wKmLGYf96yTg==", + "license": "MIT", + "dependencies": { + "@algolia/logger-common": "4.24.0" + } + }, + "node_modules/@algolia/recommend": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-4.24.0.tgz", + "integrity": "sha512-P9kcgerfVBpfYHDfVZDvvdJv0lEoCvzNlOy2nykyt5bK8TyieYyiD0lguIJdRZZYGre03WIAFf14pgE+V+IBlw==", + "license": "MIT", + "dependencies": { + "@algolia/cache-browser-local-storage": "4.24.0", + "@algolia/cache-common": "4.24.0", + "@algolia/cache-in-memory": "4.24.0", + "@algolia/client-common": "4.24.0", + "@algolia/client-search": "4.24.0", + "@algolia/logger-common": "4.24.0", + "@algolia/logger-console": "4.24.0", + "@algolia/requester-browser-xhr": "4.24.0", + "@algolia/requester-common": "4.24.0", + "@algolia/requester-node-http": "4.24.0", + "@algolia/transporter": "4.24.0" + } + }, + "node_modules/@algolia/requester-browser-xhr": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.24.0.tgz", + "integrity": "sha512-Z2NxZMb6+nVXSjF13YpjYTdvV3032YTBSGm2vnYvYPA6mMxzM3v5rsCiSspndn9rzIW4Qp1lPHBvuoKJV6jnAA==", + "license": "MIT", + "dependencies": { + "@algolia/requester-common": "4.24.0" + } + }, + "node_modules/@algolia/requester-common": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.24.0.tgz", + "integrity": "sha512-k3CXJ2OVnvgE3HMwcojpvY6d9kgKMPRxs/kVohrwF5WMr2fnqojnycZkxPoEg+bXm8fi5BBfFmOqgYztRtHsQA==", + "license": "MIT" + }, + "node_modules/@algolia/requester-node-http": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.24.0.tgz", + "integrity": "sha512-JF18yTjNOVYvU/L3UosRcvbPMGT9B+/GQWNWnenIImglzNVGpyzChkXLnrSf6uxwVNO6ESGu6oN8MqcGQcjQJw==", + "license": "MIT", + "dependencies": { + "@algolia/requester-common": "4.24.0" + } + }, + "node_modules/@algolia/transporter": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.24.0.tgz", + "integrity": "sha512-86nI7w6NzWxd1Zp9q3413dRshDqAzSbsQjhcDhPIatEFiZrL1/TjnHL8S7jVKFePlIMzDsZWXAXwXzcok9c5oA==", + "license": "MIT", + "dependencies": { + "@algolia/cache-common": "4.24.0", + "@algolia/logger-common": "4.24.0", + "@algolia/requester-common": "4.24.0" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "license": "Apache-2.0", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "dependencies": { + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.24.9", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.9.tgz", + "integrity": "sha512-e701mcfApCJqMMueQI0Fb68Amflj83+dvAvHawoBpAz+GDjCIyGHzNwnefjsWJ3xiYAqqiQFoWbspGYBdb2/ng==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.24.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.9.tgz", + "integrity": "sha512-5e3FI4Q3M3Pbr21+5xJwCv6ZT6KmGkI0vw3Tozy5ODAQFTIWe37iT8Cr7Ice2Ntb+M3iSKCEWMB1MBgKrW3whg==", + "license": "MIT", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.24.9", + "@babel/helper-compilation-targets": "^7.24.8", + "@babel/helper-module-transforms": "^7.24.9", + "@babel/helpers": "^7.24.8", + "@babel/parser": "^7.24.8", + "@babel/template": "^7.24.7", + "@babel/traverse": "^7.24.8", + "@babel/types": "^7.24.9", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.24.10", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.10.tgz", + "integrity": "sha512-o9HBZL1G2129luEUlG1hB4N/nlYNWHnpwlND9eOMclRqqu1YDy2sSYVCFUZwl8I1Gxh+QSRrP2vD7EpUmFVXxg==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.24.9", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", + "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.7.tgz", + "integrity": "sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.8.tgz", + "integrity": "sha512-oU+UoqCHdp+nWVDkpldqIQL/i/bvAv53tRqLG/s+cOXxe66zOYLU7ar/Xs3LdmBihrUMEUhwu6dMZwbNOYDwvw==", + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.24.8", + "@babel/helper-validator-option": "^7.24.8", + "browserslist": "^4.23.1", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.8.tgz", + "integrity": "sha512-4f6Oqnmyp2PP3olgUMmOwC3akxSm5aBYraQ6YDdKy7NcAMkDECHWG0DEnV6M2UAkERgIBhYt8S27rURPg7SxWA==", + "license": "MIT", + "dependencies": { + "@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.8", + "@babel/helper-optimise-call-expression": "^7.24.7", + "@babel/helper-replace-supers": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.24.7.tgz", + "integrity": "sha512-03TCmXy2FtXJEZfbXDTSqq1fRJArk7lX9DOFC/47VthYcxyIOx+eXQmdo6DOQvrbpIix+KfXwvuXdFDZHxt+rA==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "regexpu-core": "^5.3.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", + "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz", + "integrity": "sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz", + "integrity": "sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==", + "license": "MIT", + "dependencies": { + "@babel/template": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz", + "integrity": "sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.8.tgz", + "integrity": "sha512-LABppdt+Lp/RlBxqrh4qgf1oEH/WxdzQNDJIu5gC/W1GyvPVrOBiItmmM8wan2fm4oYqFuFfkXmlGpLQhPY8CA==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.24.8", + "@babel/types": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", + "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.24.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.9.tgz", + "integrity": "sha512-oYbh+rtFKj/HwBQkFlUzvcybzklmVdVV3UU+mN7n2t/q3yGHbuVdNxyFvSBO1tfvjyArpHNcWMAzsSPdyI46hw==", + "license": "MIT", + "dependencies": { + "@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" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz", + "integrity": "sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", + "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.24.7.tgz", + "integrity": "sha512-9pKLcTlZ92hNZMQfGCHImUpDOlAgkkpqalWEeftW5FBya75k8Li2ilerxkM/uBEj01iBZXcCIB/bwvDYgWyibA==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-wrap-function": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.24.7.tgz", + "integrity": "sha512-qTAxxBM81VEyoAY0TtLrx1oAEJc09ZK67Q9ljQToqCnA+55eNwCORaxlKyu+rNfX86o8OXRUSNUnrtsAZXM9sg==", + "license": "MIT", + "dependencies": { + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-member-expression-to-functions": "^7.24.7", + "@babel/helper-optimise-call-expression": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", + "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz", + "integrity": "sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz", + "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", + "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.24.7.tgz", + "integrity": "sha512-N9JIYk3TD+1vq/wn77YnJOqMtfWhNewNE+DJV4puD2X7Ew9J4JvrzrFDfTfyv5EgEXVy9/Wt8QiOErzEmv5Ifw==", + "license": "MIT", + "dependencies": { + "@babel/helper-function-name": "^7.24.7", + "@babel/template": "^7.24.7", + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.10.tgz", + "integrity": "sha512-UPYc3SauzZ3JGgj87GgZ89JVdC5dj0AoetR5Bw6wj4niittNyFh6+eOGonYvJ1ao6B8lEa3Q3klS7ADZ53bc5g==", + "dependencies": { + "@babel/template": "^7.26.9", + "@babel/types": "^7.26.10" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.10.tgz", + "integrity": "sha512-6aQR2zGE/QFi8JpDLjUZEPYOs7+mhKXm86VaKFiLP35JQwQb6bwUE+XbvkH0EptsYhbNBSUGaUBLKqxH1xSgsA==", + "dependencies": { + "@babel/types": "^7.26.10" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.7.tgz", + "integrity": "sha512-TiT1ss81W80eQsN+722OaeQMY/G4yTb4G9JrqeiDADs3N8lbPMGldWi9x8tyqCW5NLx1Jh2AvkE6r6QvEltMMQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.24.7.tgz", + "integrity": "sha512-unaQgZ/iRu/By6tsjMZzpeBZjChYfLYry6HrEXPoz3KmfF0sVBQ1l8zKMQ4xRGLWVsjuvB8nQfjNP/DcfEOCsg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.7.tgz", + "integrity": "sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.24.7.tgz", + "integrity": "sha512-utA4HuR6F4Vvcr+o4DnjL8fCOlgRFGbeeBEGNg3ZTrLFw6VWG5XmUrvcQ0FjIYMU2ST4XcR2Wsp7t9qOAPnxMg==", + "license": "MIT", + "dependencies": { + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.7.tgz", + "integrity": "sha512-Ec3NRUMoi8gskrkBe3fNmEQfxDvY8bgfQpz6jlk/41kX9eUjvpyqWU7PBP/pLAvMaSQjbMNKJmvX57jP+M6bPg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.7.tgz", + "integrity": "sha512-hbX+lKKeUMGihnK8nvKqmXBInriT3GVjzXKFriV3YC6APGxMbP8RZNFwy91+hocLXq90Mta+HshoB31802bb8A==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz", + "integrity": "sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.7.tgz", + "integrity": "sha512-c/+fVeJBB0FeKsFvwytYiUD+LBvhHjGSI0g446PRGdSVGZLRNArBUno2PETbAly3tpiNAQR5XaZ+JslxkotsbA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.7.tgz", + "integrity": "sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.24.7.tgz", + "integrity": "sha512-o+iF77e3u7ZS4AoAuJvapz9Fm001PuD2V3Lp6OSE4FYQke+cSewYtnek+THqGRWyQloRCyvWL1OkyfNEl9vr/g==", + "license": "MIT", + "dependencies": { + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-remap-async-to-generator": "^7.24.7", + "@babel/plugin-syntax-async-generators": "^7.8.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.7.tgz", + "integrity": "sha512-SQY01PcJfmQ+4Ash7NE+rpbLFbmqA2GPIgqzxfFTL4t1FKRq4zTms/7htKpoCUI9OcFYgzqfmCdH53s6/jn5fA==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-remap-async-to-generator": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.7.tgz", + "integrity": "sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.7.tgz", + "integrity": "sha512-Nd5CvgMbWc+oWzBsuaMcbwjJWAcp5qzrbg69SZdHSP7AMY0AbWFqFO0WTFCA1jxhMCwodRwvRec8k0QUbZk7RQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.7.tgz", + "integrity": "sha512-vKbfawVYayKcSeSR5YYzzyXvsDFWU2mD8U5TFeXtbCPLFUqe7GyCgvO6XDHzje862ODrOwy6WCPmKeWHbCFJ4w==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.7.tgz", + "integrity": "sha512-HMXK3WbBPpZQufbMG4B46A90PkuuhN9vBCb5T8+VAHqvAqvcLi+2cKoukcpmUYkszLhScU3l1iudhrks3DggRQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.8.tgz", + "integrity": "sha512-VXy91c47uujj758ud9wx+OMgheXm4qJfyhj1P18YvlrQkNOSrwsteHk+EFS3OMGfhMhpZa0A+81eE7G4QC+3CA==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-compilation-targets": "^7.24.8", + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-function-name": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-replace-supers": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.7.tgz", + "integrity": "sha512-25cS7v+707Gu6Ds2oY6tCkUwsJ9YIDbggd9+cu9jzzDgiNq7hR/8dkzxWfKWnTic26vsI3EsCXNd4iEB6e8esQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/template": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.8.tgz", + "integrity": "sha512-36e87mfY8TnRxc7yc6M9g9gOB7rKgSahqkIKwLpz4Ppk2+zC2Cy1is0uwtuSG6AE4zlTOUa+7JGz9jCJGLqQFQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.7.tgz", + "integrity": "sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.7.tgz", + "integrity": "sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.7.tgz", + "integrity": "sha512-sc3X26PhZQDb3JhORmakcbvkeInvxz+A8oda99lj7J60QRuPZvNAk9wQlTBS1ZynelDrDmTU4pw1tyc5d5ZMUg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.7.tgz", + "integrity": "sha512-Rqe/vSc9OYgDajNIK35u7ot+KeCoetqQYFXM4Epf7M7ez3lWlOjrDjrwMei6caCVhfdw+mIKD4cgdGNy5JQotQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.7.tgz", + "integrity": "sha512-v0K9uNYsPL3oXZ/7F9NNIbAj2jv1whUEtyA6aujhekLs56R++JDQuzRcP2/z4WX5Vg/c5lE9uWZA0/iUoFhLTA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.7.tgz", + "integrity": "sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.24.7.tgz", + "integrity": "sha512-U9FcnA821YoILngSmYkW6FjyQe2TyZD5pHt4EVIhmcTkrJw/3KqcrRSxuOo5tFZJi7TE19iDyI1u+weTI7bn2w==", + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-function-name": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.7.tgz", + "integrity": "sha512-2yFnBGDvRuxAaE/f0vfBKvtnvvqU8tGpMHqMNpTN2oWMKIR3NqFkjaAgGwawhqK/pIN2T3XdjGPdaG0vDhOBGw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-json-strings": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.24.7.tgz", + "integrity": "sha512-vcwCbb4HDH+hWi8Pqenwnjy+UiklO4Kt1vfspcQYFhJdpthSnW8XvWGyDZWKNVrVbVViI/S7K9PDJZiUmP2fYQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.7.tgz", + "integrity": "sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.7.tgz", + "integrity": "sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.7.tgz", + "integrity": "sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.8.tgz", + "integrity": "sha512-WHsk9H8XxRs3JXKWFiqtQebdh9b/pTk4EgueygFzYlTKAg0Ud985mSevdNjdXdFBATSKVJGQXP1tv6aGbssLKA==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.24.8", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-simple-access": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.24.7.tgz", + "integrity": "sha512-GYQE0tW7YoaN13qFh3O1NCY4MPkUiAH3fiF7UcV/I3ajmDKEdG3l+UOcbAm4zUE3gnvUU+Eni7XrVKo9eO9auw==", + "license": "MIT", + "dependencies": { + "@babel/helper-hoist-variables": "^7.24.7", + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.7.tgz", + "integrity": "sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.7.tgz", + "integrity": "sha512-/jr7h/EWeJtk1U/uz2jlsCioHkZk1JJZVcc8oQsJ1dUlaJD83f4/6Zeh2aHt9BIFokHIsSeDfhUmju0+1GPd6g==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.7.tgz", + "integrity": "sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.7.tgz", + "integrity": "sha512-Ts7xQVk1OEocqzm8rHMXHlxvsfZ0cEF2yomUqpKENHWMF4zKk175Y4q8H5knJes6PgYad50uuRmt3UJuhBw8pQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.7.tgz", + "integrity": "sha512-e6q1TiVUzvH9KRvicuxdBTUj4AdKSRwzIyFFnfnezpCfP2/7Qmbb8qbU2j7GODbl4JMkblitCQjKYUaX/qkkwA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.7.tgz", + "integrity": "sha512-4QrHAr0aXQCEFni2q4DqKLD31n2DL+RxcwnNjDFkSG0eNQ/xCavnRkfCUjsyqGC2OviNJvZOF/mQqZBw7i2C5Q==", + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.7.tgz", + "integrity": "sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-replace-supers": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.7.tgz", + "integrity": "sha512-uLEndKqP5BfBbC/5jTwPxLh9kqPWWgzN/f8w6UwAIirAEqiIVJWWY312X72Eub09g5KF9+Zn7+hT7sDxmhRuKA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.8.tgz", + "integrity": "sha512-5cTOLSMs9eypEy8JUVvIKOu6NgvbJMnpG62VpIHrTmROdQ+L5mDAaI40g25k5vXti55JWNX5jCkq3HZxXBQANw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.7.tgz", + "integrity": "sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.7.tgz", + "integrity": "sha512-COTCOkG2hn4JKGEKBADkA8WNb35TGkkRbI5iT845dB+NyqgO8Hn+ajPbSnIQznneJTa3d30scb6iz/DhH8GsJQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.7.tgz", + "integrity": "sha512-9z76mxwnwFxMyxZWEgdgECQglF2Q7cFLm0kMf8pGwt+GSJsY0cONKj/UuO4bOH0w/uAel3ekS4ra5CEAyJRmDA==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.7.tgz", + "integrity": "sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-constant-elements": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.24.7.tgz", + "integrity": "sha512-7LidzZfUXyfZ8/buRW6qIIHBY8wAZ1OrY9c/wTr8YhZ6vMPo+Uc/CVFLYY1spZrEQlD4w5u8wjqk5NQ3OVqQKA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-display-name": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.24.7.tgz", + "integrity": "sha512-H/Snz9PFxKsS1JLI4dJLtnJgCJRoo0AUm3chP6NYr+9En1JMKloheEiLIhlp5MDVznWo+H3AAC1Mc8lmUEpsgg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.24.7.tgz", + "integrity": "sha512-+Dj06GDZEFRYvclU6k4bme55GKBEWUmByM/eoKuqg4zTNQHiApWRhQph5fxQB2wAEFvRzL1tOEj1RJ19wJrhoA==", + "license": "MIT", + "dependencies": { + "@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/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-development": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.24.7.tgz", + "integrity": "sha512-QG9EnzoGn+Qar7rxuW+ZOsbWOt56FvvI93xInqsZDC5fsekx1AlIO4KIJ5M+D0p0SqSH156EpmZyXq630B8OlQ==", + "license": "MIT", + "dependencies": { + "@babel/plugin-transform-react-jsx": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-pure-annotations": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.24.7.tgz", + "integrity": "sha512-PLgBVk3fzbmEjBJ/u8kFzOqS9tUeDjiaWud/rRym/yjCo/M9cASPlnrd2ZmmZpQT40fOOrvR8jh+n8jikrOhNA==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.7.tgz", + "integrity": "sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "regenerator-transform": "^0.15.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.7.tgz", + "integrity": "sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.24.7.tgz", + "integrity": "sha512-YqXjrk4C+a1kZjewqt+Mmu2UuV1s07y8kqcUf4qYLnoqemhR4gRQikhdAhSVJioMjVTu6Mo6pAbaypEA3jY6fw==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.1", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.7.tgz", + "integrity": "sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.7.tgz", + "integrity": "sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.7.tgz", + "integrity": "sha512-kHPSIJc9v24zEml5geKg9Mjx5ULpfncj0wRpYtxbvKyTtHCYDkVE3aHQ03FrpEo4gEe2vrJJS1Y9CJTaThA52g==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.7.tgz", + "integrity": "sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.8.tgz", + "integrity": "sha512-adNTUpDCVnmAE58VEqKlAA6ZBlNkMnWD0ZcW76lyNFN3MJniyGFZfNwERVk8Ap56MCnXztmDr19T4mPTztcuaw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.24.8.tgz", + "integrity": "sha512-CgFgtN61BbdOGCP4fLaAMOPkzWUh6yQZNMr5YSt8uz2cZSSiQONCQFWqsE4NeVfOIhqDOlS9CR3WD91FzMeB2Q==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-create-class-features-plugin": "^7.24.8", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/plugin-syntax-typescript": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.7.tgz", + "integrity": "sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.7.tgz", + "integrity": "sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.7.tgz", + "integrity": "sha512-hlQ96MBZSAXUq7ltkjtu3FJCCSMx/j629ns3hA3pXnBXjanNP0LHi+JpPeA81zaWgVK1VGH95Xuy7u0RyQ8kMg==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.7.tgz", + "integrity": "sha512-2G8aAvF4wy1w/AGZkemprdGMRg5o6zPNhbHVImRz3lss55TYCBd6xStN19rt8XJHq20sqV0JbyWjOWwQRwV/wg==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.24.8.tgz", + "integrity": "sha512-vObvMZB6hNWuDxhSaEPTKCwcqkAIuDtE+bQGn4XMXne1DSLzFVY8Vmj1bm+mUQXYNN8NmaQEO+r8MMbzPr1jBQ==", + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.24.8", + "@babel/helper-compilation-targets": "^7.24.8", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-validator-option": "^7.24.8", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.24.7", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.24.7", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.7", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.24.7", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.24.7", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.24.7", + "@babel/plugin-transform-async-generator-functions": "^7.24.7", + "@babel/plugin-transform-async-to-generator": "^7.24.7", + "@babel/plugin-transform-block-scoped-functions": "^7.24.7", + "@babel/plugin-transform-block-scoping": "^7.24.7", + "@babel/plugin-transform-class-properties": "^7.24.7", + "@babel/plugin-transform-class-static-block": "^7.24.7", + "@babel/plugin-transform-classes": "^7.24.8", + "@babel/plugin-transform-computed-properties": "^7.24.7", + "@babel/plugin-transform-destructuring": "^7.24.8", + "@babel/plugin-transform-dotall-regex": "^7.24.7", + "@babel/plugin-transform-duplicate-keys": "^7.24.7", + "@babel/plugin-transform-dynamic-import": "^7.24.7", + "@babel/plugin-transform-exponentiation-operator": "^7.24.7", + "@babel/plugin-transform-export-namespace-from": "^7.24.7", + "@babel/plugin-transform-for-of": "^7.24.7", + "@babel/plugin-transform-function-name": "^7.24.7", + "@babel/plugin-transform-json-strings": "^7.24.7", + "@babel/plugin-transform-literals": "^7.24.7", + "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", + "@babel/plugin-transform-member-expression-literals": "^7.24.7", + "@babel/plugin-transform-modules-amd": "^7.24.7", + "@babel/plugin-transform-modules-commonjs": "^7.24.8", + "@babel/plugin-transform-modules-systemjs": "^7.24.7", + "@babel/plugin-transform-modules-umd": "^7.24.7", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", + "@babel/plugin-transform-new-target": "^7.24.7", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", + "@babel/plugin-transform-numeric-separator": "^7.24.7", + "@babel/plugin-transform-object-rest-spread": "^7.24.7", + "@babel/plugin-transform-object-super": "^7.24.7", + "@babel/plugin-transform-optional-catch-binding": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.8", + "@babel/plugin-transform-parameters": "^7.24.7", + "@babel/plugin-transform-private-methods": "^7.24.7", + "@babel/plugin-transform-private-property-in-object": "^7.24.7", + "@babel/plugin-transform-property-literals": "^7.24.7", + "@babel/plugin-transform-regenerator": "^7.24.7", + "@babel/plugin-transform-reserved-words": "^7.24.7", + "@babel/plugin-transform-shorthand-properties": "^7.24.7", + "@babel/plugin-transform-spread": "^7.24.7", + "@babel/plugin-transform-sticky-regex": "^7.24.7", + "@babel/plugin-transform-template-literals": "^7.24.7", + "@babel/plugin-transform-typeof-symbol": "^7.24.8", + "@babel/plugin-transform-unicode-escapes": "^7.24.7", + "@babel/plugin-transform-unicode-property-regex": "^7.24.7", + "@babel/plugin-transform-unicode-regex": "^7.24.7", + "@babel/plugin-transform-unicode-sets-regex": "^7.24.7", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.4", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "core-js-compat": "^3.37.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/preset-react": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.24.7.tgz", + "integrity": "sha512-AAH4lEkpmzFWrGVlHaxJB7RLH21uPQ9+He+eFLWHmF9IuFQVugz8eAsamaW0DXRrTfco5zj1wWtpdcXJUOfsag==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-validator-option": "^7.24.7", + "@babel/plugin-transform-react-display-name": "^7.24.7", + "@babel/plugin-transform-react-jsx": "^7.24.7", + "@babel/plugin-transform-react-jsx-development": "^7.24.7", + "@babel/plugin-transform-react-pure-annotations": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-typescript": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.24.7.tgz", + "integrity": "sha512-SyXRe3OdWwIwalxDg5UtJnJQO+YPcTfwiIY2B0Xlddh9o7jpWLvv8X1RthIeDOxQ+O1ML5BLPCONToObyVQVuQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-validator-option": "^7.24.7", + "@babel/plugin-syntax-jsx": "^7.24.7", + "@babel/plugin-transform-modules-commonjs": "^7.24.7", + "@babel/plugin-transform-typescript": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", + "license": "MIT" + }, + "node_modules/@babel/runtime": { + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.10.tgz", + "integrity": "sha512-2WJMeRQPHKSPemqk/awGrAiuFfzBmOIPXKizAsVhWH9YJqLZ0H+HS4c8loHGgW6utJ3E/ejXQUsiGaQy2NZ9Fw==", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/runtime-corejs3": { + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.26.10.tgz", + "integrity": "sha512-uITFQYO68pMEYR46AHgQoyBg7KPPJDAbGn4jUTIRgCFJIp88MIBUianVOplhZDEec07bp9zIyr4Kp0FCyQzmWg==", + "dependencies": { + "core-js-pure": "^3.30.2", + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.26.9.tgz", + "integrity": "sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==", + "dependencies": { + "@babel/code-frame": "^7.26.2", + "@babel/parser": "^7.26.9", + "@babel/types": "^7.26.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.8.tgz", + "integrity": "sha512-t0P1xxAPzEDcEPmjprAQq19NWum4K0EQPjMwZQZbHt+GiZqvjCHjj755Weq1YRPVzBI+3zSfvScfpnuIecVFJQ==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.24.8", + "@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.8", + "@babel/types": "^7.24.8", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.10.tgz", + "integrity": "sha512-emqcG3vHrpxUKTrxcblR36dcrcoRDvKmnL/dCL6ZsHaShW80qxCAcNhzQZrpeM765VzEos+xOi4s+r4IXzTwdQ==", + "dependencies": { + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/@discoveryjs/json-ext": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", + "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@docsearch/css": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.6.1.tgz", + "integrity": "sha512-VtVb5DS+0hRIprU2CO6ZQjK2Zg4QU5HrDM1+ix6rT0umsYvFvatMAnf97NHZlVWDaaLlx7GRfR/7FikANiM2Fg==", + "license": "MIT" + }, + "node_modules/@docsearch/react": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.6.1.tgz", + "integrity": "sha512-qXZkEPvybVhSXj0K7U3bXc233tk5e8PfhoZ6MhPOiik/qUQxYC+Dn9DnoS7CxHQQhHfCvTiN0eY9M12oRghEXw==", + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-core": "1.9.3", + "@algolia/autocomplete-preset-algolia": "1.9.3", + "@docsearch/css": "3.6.1", + "algoliasearch": "^4.19.1" + }, + "peerDependencies": { + "@types/react": ">= 16.8.0 < 19.0.0", + "react": ">= 16.8.0 < 19.0.0", + "react-dom": ">= 16.8.0 < 19.0.0", + "search-insights": ">= 1 < 3" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "search-insights": { + "optional": true + } + } + }, + "node_modules/@docusaurus/core": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.4.0.tgz", + "integrity": "sha512-g+0wwmN2UJsBqy2fQRQ6fhXruoEa62JDeEa5d8IdTJlMoaDaEDfHh7WjwGRn4opuTQWpjAwP/fbcgyHKlE+64w==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.23.3", + "@babel/generator": "^7.23.3", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-transform-runtime": "^7.22.9", + "@babel/preset-env": "^7.22.9", + "@babel/preset-react": "^7.22.5", + "@babel/preset-typescript": "^7.22.5", + "@babel/runtime": "^7.22.6", + "@babel/runtime-corejs3": "^7.22.6", + "@babel/traverse": "^7.22.8", + "@docusaurus/cssnano-preset": "3.4.0", + "@docusaurus/logger": "3.4.0", + "@docusaurus/mdx-loader": "3.4.0", + "@docusaurus/utils": "3.4.0", + "@docusaurus/utils-common": "3.4.0", + "@docusaurus/utils-validation": "3.4.0", + "autoprefixer": "^10.4.14", + "babel-loader": "^9.1.3", + "babel-plugin-dynamic-import-node": "^2.3.3", + "boxen": "^6.2.1", + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "clean-css": "^5.3.2", + "cli-table3": "^0.6.3", + "combine-promises": "^1.1.0", + "commander": "^5.1.0", + "copy-webpack-plugin": "^11.0.0", + "core-js": "^3.31.1", + "css-loader": "^6.8.1", + "css-minimizer-webpack-plugin": "^5.0.1", + "cssnano": "^6.1.2", + "del": "^6.1.1", + "detect-port": "^1.5.1", + "escape-html": "^1.0.3", + "eta": "^2.2.0", + "eval": "^0.1.8", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "html-minifier-terser": "^7.2.0", + "html-tags": "^3.3.1", + "html-webpack-plugin": "^5.5.3", + "leven": "^3.1.0", + "lodash": "^4.17.21", + "mini-css-extract-plugin": "^2.7.6", + "p-map": "^4.0.0", + "postcss": "^8.4.26", + "postcss-loader": "^7.3.3", + "prompts": "^2.4.2", + "react-dev-utils": "^12.0.1", + "react-helmet-async": "^1.3.0", + "react-loadable": "npm:@docusaurus/react-loadable@6.0.0", + "react-loadable-ssr-addon-v5-slorber": "^1.0.1", + "react-router": "^5.3.4", + "react-router-config": "^5.1.1", + "react-router-dom": "^5.3.4", + "rtl-detect": "^1.0.4", + "semver": "^7.5.4", + "serve-handler": "^6.1.5", + "shelljs": "^0.8.5", + "terser-webpack-plugin": "^5.3.9", + "tslib": "^2.6.0", + "update-notifier": "^6.0.2", + "url-loader": "^4.1.1", + "webpack": "^5.88.1", + "webpack-bundle-analyzer": "^4.9.0", + "webpack-dev-server": "^4.15.1", + "webpack-merge": "^5.9.0", + "webpackbar": "^5.0.2" + }, + "bin": { + "docusaurus": "bin/docusaurus.mjs" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/cssnano-preset": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.4.0.tgz", + "integrity": "sha512-qwLFSz6v/pZHy/UP32IrprmH5ORce86BGtN0eBtG75PpzQJAzp9gefspox+s8IEOr0oZKuQ/nhzZ3xwyc3jYJQ==", + "license": "MIT", + "dependencies": { + "cssnano-preset-advanced": "^6.1.2", + "postcss": "^8.4.38", + "postcss-sort-media-queries": "^5.2.0", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + } + }, + "node_modules/@docusaurus/logger": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.4.0.tgz", + "integrity": "sha512-bZwkX+9SJ8lB9kVRkXw+xvHYSMGG4bpYHKGXeXFvyVc79NMeeBSGgzd4TQLHH+DYeOJoCdl8flrFJVxlZ0wo/Q==", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + } + }, + "node_modules/@docusaurus/mdx-loader": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.4.0.tgz", + "integrity": "sha512-kSSbrrk4nTjf4d+wtBA9H+FGauf2gCax89kV8SUSJu3qaTdSIKdWERlngsiHaCFgZ7laTJ8a67UFf+xlFPtuTw==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.4.0", + "@docusaurus/utils": "3.4.0", + "@docusaurus/utils-validation": "3.4.0", + "@mdx-js/mdx": "^3.0.0", + "@slorber/remark-comment": "^1.0.0", + "escape-html": "^1.0.3", + "estree-util-value-to-estree": "^3.0.1", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "image-size": "^1.0.2", + "mdast-util-mdx": "^3.0.0", + "mdast-util-to-string": "^4.0.0", + "rehype-raw": "^7.0.0", + "remark-directive": "^3.0.0", + "remark-emoji": "^4.0.0", + "remark-frontmatter": "^5.0.0", + "remark-gfm": "^4.0.0", + "stringify-object": "^3.3.0", + "tslib": "^2.6.0", + "unified": "^11.0.3", + "unist-util-visit": "^5.0.0", + "url-loader": "^4.1.1", + "vfile": "^6.0.1", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/module-type-aliases": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-3.4.0.tgz", + "integrity": "sha512-A1AyS8WF5Bkjnb8s+guTDuYmUiwJzNrtchebBHpc0gz0PyHJNMaybUlSrmJjHVcGrya0LKI4YcR3lBDQfXRYLw==", + "license": "MIT", + "dependencies": { + "@docusaurus/types": "3.4.0", + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router-config": "*", + "@types/react-router-dom": "*", + "react-helmet-async": "*", + "react-loadable": "npm:@docusaurus/react-loadable@6.0.0" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" + } + }, + "node_modules/@docusaurus/plugin-content-blog": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.4.0.tgz", + "integrity": "sha512-vv6ZAj78ibR5Jh7XBUT4ndIjmlAxkijM3Sx5MAAzC1gyv0vupDQNhzuFg1USQmQVj3P5I6bquk12etPV3LJ+Xw==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.4.0", + "@docusaurus/logger": "3.4.0", + "@docusaurus/mdx-loader": "3.4.0", + "@docusaurus/types": "3.4.0", + "@docusaurus/utils": "3.4.0", + "@docusaurus/utils-common": "3.4.0", + "@docusaurus/utils-validation": "3.4.0", + "cheerio": "^1.0.0-rc.12", + "feed": "^4.2.2", + "fs-extra": "^11.1.1", + "lodash": "^4.17.21", + "reading-time": "^1.5.0", + "srcset": "^4.0.0", + "tslib": "^2.6.0", + "unist-util-visit": "^5.0.0", + "utility-types": "^3.10.0", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/plugin-content-docs": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.4.0.tgz", + "integrity": "sha512-HkUCZffhBo7ocYheD9oZvMcDloRnGhBMOZRyVcAQRFmZPmNqSyISlXA1tQCIxW+r478fty97XXAGjNYzBjpCsg==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.4.0", + "@docusaurus/logger": "3.4.0", + "@docusaurus/mdx-loader": "3.4.0", + "@docusaurus/module-type-aliases": "3.4.0", + "@docusaurus/types": "3.4.0", + "@docusaurus/utils": "3.4.0", + "@docusaurus/utils-common": "3.4.0", + "@docusaurus/utils-validation": "3.4.0", + "@types/react-router-config": "^5.0.7", + "combine-promises": "^1.1.0", + "fs-extra": "^11.1.1", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "tslib": "^2.6.0", + "utility-types": "^3.10.0", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/plugin-content-pages": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.4.0.tgz", + "integrity": "sha512-h2+VN/0JjpR8fIkDEAoadNjfR3oLzB+v1qSXbIAKjQ46JAHx3X22n9nqS+BWSQnTnp1AjkjSvZyJMekmcwxzxg==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.4.0", + "@docusaurus/mdx-loader": "3.4.0", + "@docusaurus/types": "3.4.0", + "@docusaurus/utils": "3.4.0", + "@docusaurus/utils-validation": "3.4.0", + "fs-extra": "^11.1.1", + "tslib": "^2.6.0", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/plugin-debug": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-3.4.0.tgz", + "integrity": "sha512-uV7FDUNXGyDSD3PwUaf5YijX91T5/H9SX4ErEcshzwgzWwBtK37nUWPU3ZLJfeTavX3fycTOqk9TglpOLaWkCg==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.4.0", + "@docusaurus/types": "3.4.0", + "@docusaurus/utils": "3.4.0", + "fs-extra": "^11.1.1", + "react-json-view-lite": "^1.2.0", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/plugin-google-analytics": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.4.0.tgz", + "integrity": "sha512-mCArluxEGi3cmYHqsgpGGt3IyLCrFBxPsxNZ56Mpur0xSlInnIHoeLDH7FvVVcPJRPSQ9/MfRqLsainRw+BojA==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.4.0", + "@docusaurus/types": "3.4.0", + "@docusaurus/utils-validation": "3.4.0", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/plugin-google-gtag": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.4.0.tgz", + "integrity": "sha512-Dsgg6PLAqzZw5wZ4QjUYc8Z2KqJqXxHxq3vIoyoBWiLEEfigIs7wHR+oiWUQy3Zk9MIk6JTYj7tMoQU0Jm3nqA==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.4.0", + "@docusaurus/types": "3.4.0", + "@docusaurus/utils-validation": "3.4.0", + "@types/gtag.js": "^0.0.12", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/plugin-google-tag-manager": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.4.0.tgz", + "integrity": "sha512-O9tX1BTwxIhgXpOLpFDueYA9DWk69WCbDRrjYoMQtFHSkTyE7RhNgyjSPREUWJb9i+YUg3OrsvrBYRl64FCPCQ==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.4.0", + "@docusaurus/types": "3.4.0", + "@docusaurus/utils-validation": "3.4.0", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/plugin-sitemap": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.4.0.tgz", + "integrity": "sha512-+0VDvx9SmNrFNgwPoeoCha+tRoAjopwT0+pYO1xAbyLcewXSemq+eLxEa46Q1/aoOaJQ0qqHELuQM7iS2gp33Q==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.4.0", + "@docusaurus/logger": "3.4.0", + "@docusaurus/types": "3.4.0", + "@docusaurus/utils": "3.4.0", + "@docusaurus/utils-common": "3.4.0", + "@docusaurus/utils-validation": "3.4.0", + "fs-extra": "^11.1.1", + "sitemap": "^7.1.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/preset-classic": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-3.4.0.tgz", + "integrity": "sha512-Ohj6KB7siKqZaQhNJVMBBUzT3Nnp6eTKqO+FXO3qu/n1hJl3YLwVKTWBg28LF7MWrKu46UuYavwMRxud0VyqHg==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.4.0", + "@docusaurus/plugin-content-blog": "3.4.0", + "@docusaurus/plugin-content-docs": "3.4.0", + "@docusaurus/plugin-content-pages": "3.4.0", + "@docusaurus/plugin-debug": "3.4.0", + "@docusaurus/plugin-google-analytics": "3.4.0", + "@docusaurus/plugin-google-gtag": "3.4.0", + "@docusaurus/plugin-google-tag-manager": "3.4.0", + "@docusaurus/plugin-sitemap": "3.4.0", + "@docusaurus/theme-classic": "3.4.0", + "@docusaurus/theme-common": "3.4.0", + "@docusaurus/theme-search-algolia": "3.4.0", + "@docusaurus/types": "3.4.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/theme-classic": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-3.4.0.tgz", + "integrity": "sha512-0IPtmxsBYv2adr1GnZRdMkEQt1YW6tpzrUPj02YxNpvJ5+ju4E13J5tB4nfdaen/tfR1hmpSPlTFPvTf4kwy8Q==", + "license": "MIT", + "dependencies": { + "@docusaurus/core": "3.4.0", + "@docusaurus/mdx-loader": "3.4.0", + "@docusaurus/module-type-aliases": "3.4.0", + "@docusaurus/plugin-content-blog": "3.4.0", + "@docusaurus/plugin-content-docs": "3.4.0", + "@docusaurus/plugin-content-pages": "3.4.0", + "@docusaurus/theme-common": "3.4.0", + "@docusaurus/theme-translations": "3.4.0", + "@docusaurus/types": "3.4.0", + "@docusaurus/utils": "3.4.0", + "@docusaurus/utils-common": "3.4.0", + "@docusaurus/utils-validation": "3.4.0", + "@mdx-js/react": "^3.0.0", + "clsx": "^2.0.0", + "copy-text-to-clipboard": "^3.2.0", + "infima": "0.2.0-alpha.43", + "lodash": "^4.17.21", + "nprogress": "^0.2.0", + "postcss": "^8.4.26", + "prism-react-renderer": "^2.3.0", + "prismjs": "^1.29.0", + "react-router-dom": "^5.3.4", + "rtlcss": "^4.1.0", + "tslib": "^2.6.0", + "utility-types": "^3.10.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/theme-common": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-3.4.0.tgz", + "integrity": "sha512-0A27alXuv7ZdCg28oPE8nH/Iz73/IUejVaCazqu9elS4ypjiLhK3KfzdSQBnL/g7YfHSlymZKdiOHEo8fJ0qMA==", + "license": "MIT", + "dependencies": { + "@docusaurus/mdx-loader": "3.4.0", + "@docusaurus/module-type-aliases": "3.4.0", + "@docusaurus/plugin-content-blog": "3.4.0", + "@docusaurus/plugin-content-docs": "3.4.0", + "@docusaurus/plugin-content-pages": "3.4.0", + "@docusaurus/utils": "3.4.0", + "@docusaurus/utils-common": "3.4.0", + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router-config": "*", + "clsx": "^2.0.0", + "parse-numeric-range": "^1.3.0", + "prism-react-renderer": "^2.3.0", + "tslib": "^2.6.0", + "utility-types": "^3.10.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/theme-search-algolia": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.4.0.tgz", + "integrity": "sha512-aiHFx7OCw4Wck1z6IoShVdUWIjntC8FHCw9c5dR8r3q4Ynh+zkS8y2eFFunN/DL6RXPzpnvKCg3vhLQYJDmT9Q==", + "license": "MIT", + "dependencies": { + "@docsearch/react": "^3.5.2", + "@docusaurus/core": "3.4.0", + "@docusaurus/logger": "3.4.0", + "@docusaurus/plugin-content-docs": "3.4.0", + "@docusaurus/theme-common": "3.4.0", + "@docusaurus/theme-translations": "3.4.0", + "@docusaurus/utils": "3.4.0", + "@docusaurus/utils-validation": "3.4.0", + "algoliasearch": "^4.18.0", + "algoliasearch-helper": "^3.13.3", + "clsx": "^2.0.0", + "eta": "^2.2.0", + "fs-extra": "^11.1.1", + "lodash": "^4.17.21", + "tslib": "^2.6.0", + "utility-types": "^3.10.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/theme-translations": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-3.4.0.tgz", + "integrity": "sha512-zSxCSpmQCCdQU5Q4CnX/ID8CSUUI3fvmq4hU/GNP/XoAWtXo9SAVnM3TzpU8Gb//H3WCsT8mJcTfyOk3d9ftNg==", + "license": "MIT", + "dependencies": { + "fs-extra": "^11.1.1", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + } + }, + "node_modules/@docusaurus/types": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.4.0.tgz", + "integrity": "sha512-4jcDO8kXi5Cf9TcyikB/yKmz14f2RZ2qTRerbHAsS+5InE9ZgSLBNLsewtFTcTOXSVcbU3FoGOzcNWAmU1TR0A==", + "license": "MIT", + "dependencies": { + "@mdx-js/mdx": "^3.0.0", + "@types/history": "^4.7.11", + "@types/react": "*", + "commander": "^5.1.0", + "joi": "^17.9.2", + "react-helmet-async": "^1.3.0", + "utility-types": "^3.10.0", + "webpack": "^5.88.1", + "webpack-merge": "^5.9.0" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, + "node_modules/@docusaurus/utils": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.4.0.tgz", + "integrity": "sha512-fRwnu3L3nnWaXOgs88BVBmG1yGjcQqZNHG+vInhEa2Sz2oQB+ZjbEMO5Rh9ePFpZ0YDiDUhpaVjwmS+AU2F14g==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.4.0", + "@docusaurus/utils-common": "3.4.0", + "@svgr/webpack": "^8.1.0", + "escape-string-regexp": "^4.0.0", + "file-loader": "^6.2.0", + "fs-extra": "^11.1.1", + "github-slugger": "^1.5.0", + "globby": "^11.1.0", + "gray-matter": "^4.0.3", + "jiti": "^1.20.0", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "micromatch": "^4.0.5", + "prompts": "^2.4.2", + "resolve-pathname": "^3.0.0", + "shelljs": "^0.8.5", + "tslib": "^2.6.0", + "url-loader": "^4.1.1", + "utility-types": "^3.10.0", + "webpack": "^5.88.1" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "@docusaurus/types": "*" + }, + "peerDependenciesMeta": { + "@docusaurus/types": { + "optional": true + } + } + }, + "node_modules/@docusaurus/utils-common": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.4.0.tgz", + "integrity": "sha512-NVx54Wr4rCEKsjOH5QEVvxIqVvm+9kh7q8aYTU5WzUU9/Hctd6aTrcZ3G0Id4zYJ+AeaG5K5qHA4CY5Kcm2iyQ==", + "license": "MIT", + "dependencies": { + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "@docusaurus/types": "*" + }, + "peerDependenciesMeta": { + "@docusaurus/types": { + "optional": true + } + } + }, + "node_modules/@docusaurus/utils-validation": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.4.0.tgz", + "integrity": "sha512-hYQ9fM+AXYVTWxJOT1EuNaRnrR2WGpRdLDQG07O8UOpsvCPWUVOeo26Rbm0JWY2sGLfzAb+tvJ62yF+8F+TV0g==", + "license": "MIT", + "dependencies": { + "@docusaurus/logger": "3.4.0", + "@docusaurus/utils": "3.4.0", + "@docusaurus/utils-common": "3.4.0", + "fs-extra": "^11.2.0", + "joi": "^17.9.2", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "tslib": "^2.6.0" + }, + "engines": { + "node": ">=18.0" + } + }, + "node_modules/@hapi/hoek": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", + "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@hapi/topo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", + "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "license": "MIT", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@leichtgewicht/ip-codec": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz", + "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==", + "license": "MIT" + }, + "node_modules/@mdx-js/mdx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.0.1.tgz", + "integrity": "sha512-eIQ4QTrOWyL3LWEe/bu6Taqzq2HQvHcyTMaOrI95P2/LmJE7AsfPfgJGuFLPVqBUE1BC1rik3VIhU+s9u72arA==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdx": "^2.0.0", + "collapse-white-space": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-build-jsx": "^3.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "estree-util-to-js": "^2.0.0", + "estree-walker": "^3.0.0", + "hast-util-to-estree": "^3.0.0", + "hast-util-to-jsx-runtime": "^2.0.0", + "markdown-extensions": "^2.0.0", + "periscopic": "^3.0.0", + "remark-mdx": "^3.0.0", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.0.0", + "source-map": "^0.7.0", + "unified": "^11.0.0", + "unist-util-position-from-estree": "^2.0.0", + "unist-util-stringify-position": "^4.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@mdx-js/react": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.0.1.tgz", + "integrity": "sha512-9ZrPIU4MGf6et1m1ov3zKf+q9+deetI51zprKB1D/z3NOb+rUxxtEl3mCjW5wTGh6VhRdwPueh1oRzi6ezkA8A==", + "license": "MIT", + "dependencies": { + "@types/mdx": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "@types/react": ">=16", + "react": ">=16" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pnpm/config.env-replace": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz", + "integrity": "sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==", + "license": "MIT", + "engines": { + "node": ">=12.22.0" + } + }, + "node_modules/@pnpm/network.ca-file": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@pnpm/network.ca-file/-/network.ca-file-1.0.2.tgz", + "integrity": "sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==", + "license": "MIT", + "dependencies": { + "graceful-fs": "4.2.10" + }, + "engines": { + "node": ">=12.22.0" + } + }, + "node_modules/@pnpm/network.ca-file/node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "license": "ISC" + }, + "node_modules/@pnpm/npm-conf": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-2.2.2.tgz", + "integrity": "sha512-UA91GwWPhFExt3IizW6bOeY/pQ0BkuNwKjk9iQW9KqxluGCrg4VenZ0/L+2Y0+ZOtme72EVvg6v0zo3AMQRCeA==", + "license": "MIT", + "dependencies": { + "@pnpm/config.env-replace": "^1.1.0", + "@pnpm/network.ca-file": "^1.0.1", + "config-chain": "^1.1.11" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@polka/url": { + "version": "1.0.0-next.25", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.25.tgz", + "integrity": "sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==", + "license": "MIT" + }, + "node_modules/@sideway/address": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", + "integrity": "sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==", + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@sideway/formula": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", + "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==", + "license": "BSD-3-Clause" + }, + "node_modules/@sideway/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "license": "MIT" + }, + "node_modules/@sindresorhus/is": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@slorber/remark-comment": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@slorber/remark-comment/-/remark-comment-1.0.0.tgz", + "integrity": "sha512-RCE24n7jsOj1M0UPvIQCHTe7fI0sFL4S2nwKVWwHyVr/wI/H8GosgsJGyhnsZoGFnD/P2hLf1mSbrrgSLN93NA==", + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^1.0.0", + "micromark-util-character": "^1.1.0", + "micromark-util-symbol": "^1.0.1" + } + }, + "node_modules/@svgr/babel-plugin-add-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz", + "integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz", + "integrity": "sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-dynamic-title": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz", + "integrity": "sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-em-dimensions": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz", + "integrity": "sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-transform-react-native-svg": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-8.1.0.tgz", + "integrity": "sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-transform-svg-component": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-8.0.0.tgz", + "integrity": "sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-preset": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-8.1.0.tgz", + "integrity": "sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug==", + "license": "MIT", + "dependencies": { + "@svgr/babel-plugin-add-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-empty-expression": "8.0.0", + "@svgr/babel-plugin-replace-jsx-attribute-value": "8.0.0", + "@svgr/babel-plugin-svg-dynamic-title": "8.0.0", + "@svgr/babel-plugin-svg-em-dimensions": "8.0.0", + "@svgr/babel-plugin-transform-react-native-svg": "8.1.0", + "@svgr/babel-plugin-transform-svg-component": "8.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/core": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", + "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", + "camelcase": "^6.2.0", + "cosmiconfig": "^8.1.3", + "snake-case": "^3.0.4" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/hast-util-to-babel-ast": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz", + "integrity": "sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.21.3", + "entities": "^4.4.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/plugin-jsx": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-8.1.0.tgz", + "integrity": "sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", + "@svgr/hast-util-to-babel-ast": "8.0.0", + "svg-parser": "^2.0.4" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@svgr/core": "*" + } + }, + "node_modules/@svgr/plugin-svgo": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-8.1.0.tgz", + "integrity": "sha512-Ywtl837OGO9pTLIN/onoWLmDQ4zFUycI1g76vuKGEz6evR/ZTJlJuz3G/fIkb6OVBJ2g0o6CGJzaEjfmEo3AHA==", + "license": "MIT", + "dependencies": { + "cosmiconfig": "^8.1.3", + "deepmerge": "^4.3.1", + "svgo": "^3.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@svgr/core": "*" + } + }, + "node_modules/@svgr/webpack": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-8.1.0.tgz", + "integrity": "sha512-LnhVjMWyMQV9ZmeEy26maJk+8HTIbd59cH4F2MJ439k9DqejRisfFNGAPvRYlKETuh9LrImlS8aKsBgKjMA8WA==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.21.3", + "@babel/plugin-transform-react-constant-elements": "^7.21.3", + "@babel/preset-env": "^7.20.2", + "@babel/preset-react": "^7.18.6", + "@babel/preset-typescript": "^7.21.0", + "@svgr/core": "8.1.0", + "@svgr/plugin-jsx": "8.1.0", + "@svgr/plugin-svgo": "8.1.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@szmarczak/http-timer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz", + "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==", + "license": "MIT", + "dependencies": { + "defer-to-connect": "^2.0.1" + }, + "engines": { + "node": ">=14.16" + } + }, + "node_modules/@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "license": "ISC", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/@types/acorn": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@types/acorn/-/acorn-4.0.6.tgz", + "integrity": "sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ==", + "license": "MIT", + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "license": "MIT", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/bonjour": { + "version": "3.5.13", + "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.13.tgz", + "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/connect-history-api-fallback": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz", + "integrity": "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==", + "license": "MIT", + "dependencies": { + "@types/express-serve-static-core": "*", + "@types/node": "*" + } + }, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "license": "MIT", + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/eslint": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.0.tgz", + "integrity": "sha512-gi6WQJ7cHRgZxtkQEoyHMppPjq9Kxo5Tjn2prSKDSmZrCz8TZ3jSRCeTJm+WoM+oB0WG37bRqLzaaU3q7JypGg==", + "license": "MIT", + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "license": "MIT", + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==" + }, + "node_modules/@types/estree-jsx": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz", + "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==", + "license": "MIT", + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/@types/express": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "license": "MIT", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.19.5", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.5.tgz", + "integrity": "sha512-y6W03tvrACO72aijJ5uF02FRq5cgDR9lUxddQ8vyF+GvmjJQqbzDcJngEjURc+ZsG31VI3hODNZJ2URj86pzmg==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/gtag.js": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/@types/gtag.js/-/gtag.js-0.0.12.tgz", + "integrity": "sha512-YQV9bUsemkzG81Ea295/nF/5GijnD2Af7QhEofh7xu+kvCN6RdodgNwwGWXB5GMI3NoyvQo0odNctoH/qLMIpg==", + "license": "MIT" + }, + "node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/history": { + "version": "4.7.11", + "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.11.tgz", + "integrity": "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==", + "license": "MIT" + }, + "node_modules/@types/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==", + "license": "MIT" + }, + "node_modules/@types/http-cache-semantics": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", + "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", + "license": "MIT" + }, + "node_modules/@types/http-errors": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", + "license": "MIT" + }, + "node_modules/@types/http-proxy": { + "version": "1.17.14", + "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.14.tgz", + "integrity": "sha512-SSrD0c1OQzlFX7pGu1eXxSEjemej64aaNPRhhVYUGqXh0BtldAAx37MG8btcumvpgKyZp1F5Gn3JkktdxiFv6w==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "license": "MIT" + }, + "node_modules/@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/mdx": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.13.tgz", + "integrity": "sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==", + "license": "MIT" + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "license": "MIT" + }, + "node_modules/@types/ms": { + "version": "0.7.34", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", + "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==", + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "20.14.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.12.tgz", + "integrity": "sha512-r7wNXakLeSsGT0H1AU863vS2wa5wBOK4bWMjZz2wj+8nBx+m5PeIn0k8AloSLpRuiwdRQZwarZqHE4FNArPuJQ==", + "license": "MIT", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/node-forge": { + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz", + "integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/parse-json": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", + "license": "MIT" + }, + "node_modules/@types/prismjs": { + "version": "1.26.4", + "resolved": "https://registry.npmjs.org/@types/prismjs/-/prismjs-1.26.4.tgz", + "integrity": "sha512-rlAnzkW2sZOjbqZ743IHUhFcvzaGbqijwOu8QZnZCjfQzBqFE3s4lOTJEsxikImav9uzz/42I+O7YUs1mWgMlg==", + "license": "MIT" + }, + "node_modules/@types/prop-types": { + "version": "15.7.12", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", + "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==", + "license": "MIT" + }, + "node_modules/@types/qs": { + "version": "6.9.15", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz", + "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==", + "license": "MIT" + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "18.3.3", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz", + "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", + "license": "MIT", + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-router": { + "version": "5.1.20", + "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.20.tgz", + "integrity": "sha512-jGjmu/ZqS7FjSH6owMcD5qpq19+1RS9DeVRqfl1FeBMxTDQAGwlMWOcs52NDoXaNKyG3d1cYQFMs9rCrb88o9Q==", + "license": "MIT", + "dependencies": { + "@types/history": "^4.7.11", + "@types/react": "*" + } + }, + "node_modules/@types/react-router-config": { + "version": "5.0.11", + "resolved": "https://registry.npmjs.org/@types/react-router-config/-/react-router-config-5.0.11.tgz", + "integrity": "sha512-WmSAg7WgqW7m4x8Mt4N6ZyKz0BubSj/2tVUMsAHp+Yd2AMwcSbeFq9WympT19p5heCFmF97R9eD5uUR/t4HEqw==", + "license": "MIT", + "dependencies": { + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router": "^5.1.0" + } + }, + "node_modules/@types/react-router-dom": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.3.3.tgz", + "integrity": "sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==", + "license": "MIT", + "dependencies": { + "@types/history": "^4.7.11", + "@types/react": "*", + "@types/react-router": "*" + } + }, + "node_modules/@types/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", + "license": "MIT" + }, + "node_modules/@types/sax": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/sax/-/sax-1.2.7.tgz", + "integrity": "sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/send": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "license": "MIT", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-index": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.4.tgz", + "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==", + "license": "MIT", + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.7", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", + "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", + "license": "MIT", + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "*" + } + }, + "node_modules/@types/sockjs": { + "version": "0.3.36", + "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", + "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==", + "license": "MIT" + }, + "node_modules/@types/ws": { + "version": "8.5.11", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.11.tgz", + "integrity": "sha512-4+q7P5h3SpJxaBft0Dzpbr6lmMaqh0Jr2tbhJZ/luAwvD7ohSCniYkwz/pLxuT2h0EOa6QADgJj1Ko+TzRfZ+w==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/yargs": { + "version": "17.0.32", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", + "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "license": "MIT" + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "license": "ISC" + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", + "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", + "dependencies": { + "@webassemblyjs/helper-numbers": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", + "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==" + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", + "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==" + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", + "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==" + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", + "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.13.2", + "@webassemblyjs/helper-api-error": "1.13.2", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", + "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==" + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", + "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/wasm-gen": "1.14.1" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", + "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", + "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", + "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==" + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", + "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/helper-wasm-section": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-opt": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1", + "@webassemblyjs/wast-printer": "1.14.1" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", + "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", + "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", + "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-api-error": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", + "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/accepts/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/accepts/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.14.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", + "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.3", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.3.tgz", + "integrity": "sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==", + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/address": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/address/-/address-1.2.2.tgz", + "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==", + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "license": "MIT", + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/algoliasearch": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.24.0.tgz", + "integrity": "sha512-bf0QV/9jVejssFBmz2HQLxUadxk574t4iwjCKp5E7NBzwKkrDEhKPISIIjAU/p6K5qDx3qoeh4+26zWN1jmw3g==", + "license": "MIT", + "dependencies": { + "@algolia/cache-browser-local-storage": "4.24.0", + "@algolia/cache-common": "4.24.0", + "@algolia/cache-in-memory": "4.24.0", + "@algolia/client-account": "4.24.0", + "@algolia/client-analytics": "4.24.0", + "@algolia/client-common": "4.24.0", + "@algolia/client-personalization": "4.24.0", + "@algolia/client-search": "4.24.0", + "@algolia/logger-common": "4.24.0", + "@algolia/logger-console": "4.24.0", + "@algolia/recommend": "4.24.0", + "@algolia/requester-browser-xhr": "4.24.0", + "@algolia/requester-common": "4.24.0", + "@algolia/requester-node-http": "4.24.0", + "@algolia/transporter": "4.24.0" + } + }, + "node_modules/algoliasearch-helper": { + "version": "3.22.3", + "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.22.3.tgz", + "integrity": "sha512-2eoEz8mG4KHE+DzfrBTrCmDPxVXv7aZZWPojAJFtARpxxMO6lkos1dJ+XDCXdPvq7q3tpYWRi6xXmVQikejtpA==", + "license": "MIT", + "dependencies": { + "@algolia/events": "^4.0.1" + }, + "peerDependencies": { + "algoliasearch": ">= 3.1 < 6" + } + }, + "node_modules/ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "license": "ISC", + "dependencies": { + "string-width": "^4.1.0" + } + }, + "node_modules/ansi-align/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/ansi-align/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-html-community": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz", + "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==", + "engines": [ + "node >= 0.8.0" + ], + "license": "Apache-2.0", + "bin": { + "ansi-html": "bin/ansi-html" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "license": "MIT" + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "license": "MIT" + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/astring": { + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/astring/-/astring-1.8.6.tgz", + "integrity": "sha512-ISvCdHdlTDlH5IpxQJIex7BWBywFWgjJSVdwst+/iQCoEYnyOaQ95+X1JGshuBjGp6nxKUy1jMgE3zPqN7fQdg==", + "license": "MIT", + "bin": { + "astring": "bin/astring" + } + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "license": "ISC", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/autoprefixer": { + "version": "10.4.19", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.19.tgz", + "integrity": "sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.0", + "caniuse-lite": "^1.0.30001599", + "fraction.js": "^4.3.7", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.0", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/babel-loader": { + "version": "9.1.3", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-9.1.3.tgz", + "integrity": "sha512-xG3ST4DglodGf8qSwv0MdeWLhrDsw/32QMdTO5T1ZIp9gQur0HkCyFs7Awskr10JKXFXwpAhiCuYX5oGXnRGbw==", + "license": "MIT", + "dependencies": { + "find-cache-dir": "^4.0.0", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 14.15.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0", + "webpack": ">=5" + } + }, + "node_modules/babel-plugin-dynamic-import-node": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", + "license": "MIT", + "dependencies": { + "object.assign": "^4.1.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", + "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.6.2", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.4.tgz", + "integrity": "sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg==", + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.1", + "core-js-compat": "^3.36.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", + "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/bail": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", + "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, + "node_modules/batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==", + "license": "MIT" + }, + "node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/body-parser": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "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.13.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/bonjour-service": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.2.1.tgz", + "integrity": "sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "multicast-dns": "^7.2.5" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "license": "ISC" + }, + "node_modules/boxen": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-6.2.1.tgz", + "integrity": "sha512-H4PEsJXfFI/Pt8sjDWbHlQPx4zL/bvSQjcilJmaulGt5mLDorHOHpmdXAJcBcmru7PhYSp/cDMWRko4ZUMFkSw==", + "license": "MIT", + "dependencies": { + "ansi-align": "^3.0.1", + "camelcase": "^6.2.0", + "chalk": "^4.1.2", + "cli-boxes": "^3.0.0", + "string-width": "^5.0.1", + "type-fest": "^2.5.0", + "widest-line": "^4.0.1", + "wrap-ansi": "^8.0.1" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", + "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001688", + "electron-to-chromium": "^1.5.73", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.1" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "license": "MIT" + }, + "node_modules/bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cacheable-lookup": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz", + "integrity": "sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==", + "license": "MIT", + "engines": { + "node": ">=14.16" + } + }, + "node_modules/cacheable-request": { + "version": "10.2.14", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-10.2.14.tgz", + "integrity": "sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ==", + "license": "MIT", + "dependencies": { + "@types/http-cache-semantics": "^4.0.2", + "get-stream": "^6.0.1", + "http-cache-semantics": "^4.1.1", + "keyv": "^4.5.3", + "mimic-response": "^4.0.0", + "normalize-url": "^8.0.0", + "responselike": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "license": "MIT", + "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.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "license": "MIT", + "dependencies": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/caniuse-api": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", + "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.0.0", + "caniuse-lite": "^1.0.0", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001706", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001706.tgz", + "integrity": "sha512-3ZczoTApMAZwPKYWmwVbQMFpXBDds3/0VciVoUwPUbldlYyVLmRVuRs/PcUZtHpbLRpzzDvrvnFuREsGt6lUug==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/character-entities": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", + "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-html4": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-reference-invalid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", + "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/cheerio": { + "version": "1.0.0-rc.12", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", + "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", + "license": "MIT", + "dependencies": { + "cheerio-select": "^2.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "htmlparser2": "^8.0.1", + "parse5": "^7.0.0", + "parse5-htmlparser2-tree-adapter": "^7.0.0" + }, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/cheeriojs/cheerio?sponsor=1" + } + }, + "node_modules/cheerio-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", + "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-select": "^5.1.0", + "css-what": "^6.1.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", + "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", + "license": "MIT", + "engines": { + "node": ">=6.0" + } + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/clean-css": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", + "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==", + "license": "MIT", + "dependencies": { + "source-map": "~0.6.0" + }, + "engines": { + "node": ">= 10.0" + } + }, + "node_modules/clean-css/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-boxes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", + "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-table3": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", + "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", + "license": "MIT", + "dependencies": { + "string-width": "^4.2.0" + }, + "engines": { + "node": "10.* || >= 12.*" + }, + "optionalDependencies": { + "@colors/colors": "1.5.0" + } + }, + "node_modules/cli-table3/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/cli-table3/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "license": "MIT", + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/collapse-white-space": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-2.1.0.tgz", + "integrity": "sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/colord": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", + "license": "MIT" + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "license": "MIT" + }, + "node_modules/combine-promises": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/combine-promises/-/combine-promises-1.2.0.tgz", + "integrity": "sha512-VcQB1ziGD0NXrhKxiwyNbCDmRzs/OShMs2GqW2DlU2A/Sd0nQxE1oWDAE5O0ygSx5mgQOn9eIFh7yKPgFRVkPQ==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/comma-separated-tokens": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/common-path-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", + "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==", + "license": "ISC" + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "license": "MIT", + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compressible/node_modules/mime-db": { + "version": "1.53.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.53.0.tgz", + "integrity": "sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/compression/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/compression/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "license": "MIT" + }, + "node_modules/config-chain": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", + "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", + "license": "MIT", + "dependencies": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, + "node_modules/configstore": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-6.0.0.tgz", + "integrity": "sha512-cD31W1v3GqUlQvbBCGcXmd2Nj9SvLDOP1oQ0YFuLETufzSPaKp11rYBsSOm7rCsW3OnIRAFM3OxRhceaXNYHkA==", + "license": "BSD-2-Clause", + "dependencies": { + "dot-prop": "^6.0.1", + "graceful-fs": "^4.2.6", + "unique-string": "^3.0.0", + "write-file-atomic": "^3.0.3", + "xdg-basedir": "^5.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/yeoman/configstore?sponsor=1" + } + }, + "node_modules/connect-history-api-fallback": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz", + "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==", + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/consola": { + "version": "2.15.3", + "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", + "integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==", + "license": "MIT" + }, + "node_modules/content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "license": "MIT" + }, + "node_modules/cookie": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" + }, + "node_modules/copy-text-to-clipboard": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/copy-text-to-clipboard/-/copy-text-to-clipboard-3.2.0.tgz", + "integrity": "sha512-RnJFp1XR/LOBDckxTib5Qjr/PMfkatD0MUCQgdpqS8MdKiNUzBjAQBEN6oUy+jW7LI93BBG3DtMB2KOOKpGs2Q==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/copy-webpack-plugin": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz", + "integrity": "sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ==", + "license": "MIT", + "dependencies": { + "fast-glob": "^3.2.11", + "glob-parent": "^6.0.1", + "globby": "^13.1.1", + "normalize-path": "^3.0.0", + "schema-utils": "^4.0.0", + "serialize-javascript": "^6.0.0" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + } + }, + "node_modules/copy-webpack-plugin/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/copy-webpack-plugin/node_modules/globby": { + "version": "13.2.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz", + "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==", + "license": "MIT", + "dependencies": { + "dir-glob": "^3.0.1", + "fast-glob": "^3.3.0", + "ignore": "^5.2.4", + "merge2": "^1.4.1", + "slash": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/copy-webpack-plugin/node_modules/slash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", + "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/core-js": { + "version": "3.37.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.37.1.tgz", + "integrity": "sha512-Xn6qmxrQZyB0FFY8E3bgRXei3lWDJHhvI+u0q9TKIYM49G8pAr0FgnnrFRAmsbptZL1yxRADVXn+x5AGsbBfyw==", + "hasInstallScript": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-js-compat": { + "version": "3.37.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.37.1.tgz", + "integrity": "sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-js-pure": { + "version": "3.37.1", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.37.1.tgz", + "integrity": "sha512-J/r5JTHSmzTxbiYYrzXg9w1VpqrYt+gexenBE9pugeyhwPZTAEJddyiReJWsLO6uNQ8xJZFbod6XC7KKwatCiA==", + "hasInstallScript": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "license": "MIT" + }, + "node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "license": "MIT", + "dependencies": { + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/crypto-random-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz", + "integrity": "sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==", + "license": "MIT", + "dependencies": { + "type-fest": "^1.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/crypto-random-string/node_modules/type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/css-declaration-sorter": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-7.2.0.tgz", + "integrity": "sha512-h70rUM+3PNFuaBDTLe8wF/cdWu+dOZmb7pJt8Z2sedYbAcQVQV/tEchueg3GWxwqS0cxtbxmaHEdkNACqcvsow==", + "license": "ISC", + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.0.9" + } + }, + "node_modules/css-loader": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", + "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", + "license": "MIT", + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.33", + "postcss-modules-extract-imports": "^3.1.0", + "postcss-modules-local-by-default": "^4.0.5", + "postcss-modules-scope": "^3.2.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/css-minimizer-webpack-plugin": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-5.0.1.tgz", + "integrity": "sha512-3caImjKFQkS+ws1TGcFn0V1HyDJFq1Euy589JlD6/3rV2kj+w7r5G9WDMgSHvpvXHNZ2calVypZWuEDQd9wfLg==", + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", + "cssnano": "^6.0.1", + "jest-worker": "^29.4.3", + "postcss": "^8.4.24", + "schema-utils": "^4.0.1", + "serialize-javascript": "^6.0.1" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@parcel/css": { + "optional": true + }, + "@swc/css": { + "optional": true + }, + "clean-css": { + "optional": true + }, + "csso": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "lightningcss": { + "optional": true + } + } + }, + "node_modules/css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-tree": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", + "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", + "license": "MIT", + "dependencies": { + "mdn-data": "2.0.30", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cssnano": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-6.1.2.tgz", + "integrity": "sha512-rYk5UeX7VAM/u0lNqewCdasdtPK81CgX8wJFLEIXHbV2oldWRgJAsZrdhRXkV1NJzA2g850KiFm9mMU2HxNxMA==", + "license": "MIT", + "dependencies": { + "cssnano-preset-default": "^6.1.2", + "lilconfig": "^3.1.1" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/cssnano" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/cssnano-preset-advanced": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/cssnano-preset-advanced/-/cssnano-preset-advanced-6.1.2.tgz", + "integrity": "sha512-Nhao7eD8ph2DoHolEzQs5CfRpiEP0xa1HBdnFZ82kvqdmbwVBUr2r1QuQ4t1pi+D1ZpqpcO4T+wy/7RxzJ/WPQ==", + "license": "MIT", + "dependencies": { + "autoprefixer": "^10.4.19", + "browserslist": "^4.23.0", + "cssnano-preset-default": "^6.1.2", + "postcss-discard-unused": "^6.0.5", + "postcss-merge-idents": "^6.0.3", + "postcss-reduce-idents": "^6.0.3", + "postcss-zindex": "^6.0.2" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/cssnano-preset-default": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-6.1.2.tgz", + "integrity": "sha512-1C0C+eNaeN8OcHQa193aRgYexyJtU8XwbdieEjClw+J9d94E41LwT6ivKH0WT+fYwYWB0Zp3I3IZ7tI/BbUbrg==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.0", + "css-declaration-sorter": "^7.2.0", + "cssnano-utils": "^4.0.2", + "postcss-calc": "^9.0.1", + "postcss-colormin": "^6.1.0", + "postcss-convert-values": "^6.1.0", + "postcss-discard-comments": "^6.0.2", + "postcss-discard-duplicates": "^6.0.3", + "postcss-discard-empty": "^6.0.3", + "postcss-discard-overridden": "^6.0.2", + "postcss-merge-longhand": "^6.0.5", + "postcss-merge-rules": "^6.1.1", + "postcss-minify-font-values": "^6.1.0", + "postcss-minify-gradients": "^6.0.3", + "postcss-minify-params": "^6.1.0", + "postcss-minify-selectors": "^6.0.4", + "postcss-normalize-charset": "^6.0.2", + "postcss-normalize-display-values": "^6.0.2", + "postcss-normalize-positions": "^6.0.2", + "postcss-normalize-repeat-style": "^6.0.2", + "postcss-normalize-string": "^6.0.2", + "postcss-normalize-timing-functions": "^6.0.2", + "postcss-normalize-unicode": "^6.1.0", + "postcss-normalize-url": "^6.0.2", + "postcss-normalize-whitespace": "^6.0.2", + "postcss-ordered-values": "^6.0.2", + "postcss-reduce-initial": "^6.1.0", + "postcss-reduce-transforms": "^6.0.2", + "postcss-svgo": "^6.0.3", + "postcss-unique-selectors": "^6.0.4" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/cssnano-utils": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-4.0.2.tgz", + "integrity": "sha512-ZR1jHg+wZ8o4c3zqf1SIUSTIvm/9mU343FMR6Obe/unskbvpGhZOo1J6d/r8D1pzkRQYuwbcH3hToOuoA2G7oQ==", + "license": "MIT", + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/csso": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", + "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", + "license": "MIT", + "dependencies": { + "css-tree": "~2.2.0" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/css-tree": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", + "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", + "license": "MIT", + "dependencies": { + "mdn-data": "2.0.28", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/mdn-data": { + "version": "2.0.28", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", + "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", + "license": "CC0-1.0" + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "license": "MIT" + }, + "node_modules/debounce": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", + "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decode-named-character-reference": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz", + "integrity": "sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==", + "license": "MIT", + "dependencies": { + "character-entities": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/default-gateway": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", + "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==", + "license": "BSD-2-Clause", + "dependencies": { + "execa": "^5.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/del": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/del/-/del-6.1.1.tgz", + "integrity": "sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==", + "license": "MIT", + "dependencies": { + "globby": "^11.0.1", + "graceful-fs": "^4.2.4", + "is-glob": "^4.0.1", + "is-path-cwd": "^2.2.0", + "is-path-inside": "^3.0.2", + "p-map": "^4.0.0", + "rimraf": "^3.0.2", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "license": "MIT" + }, + "node_modules/detect-port": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/detect-port/-/detect-port-1.6.1.tgz", + "integrity": "sha512-CmnVc+Hek2egPx1PeTFVta2W78xy2K/9Rkf6cC4T59S50tVnzKj+tnx5mmx5lwvCkujZ4uRrpRSuV+IVs3f90Q==", + "license": "MIT", + "dependencies": { + "address": "^1.0.1", + "debug": "4" + }, + "bin": { + "detect": "bin/detect-port.js", + "detect-port": "bin/detect-port.js" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/detect-port-alt": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/detect-port-alt/-/detect-port-alt-1.1.6.tgz", + "integrity": "sha512-5tQykt+LqfJFBEYaDITx7S7cR7mJ/zQmLXZ2qt5w04ainYZw6tBf9dBunMjVeVOdYVRUzUOE4HkY5J7+uttb5Q==", + "license": "MIT", + "dependencies": { + "address": "^1.0.1", + "debug": "^2.6.0" + }, + "bin": { + "detect": "bin/detect-port", + "detect-port": "bin/detect-port" + }, + "engines": { + "node": ">= 4.2.1" + } + }, + "node_modules/detect-port-alt/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/detect-port-alt/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "license": "MIT", + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dns-packet": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", + "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==", + "license": "MIT", + "dependencies": { + "@leichtgewicht/ip-codec": "^2.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/dom-converter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", + "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", + "license": "MIT", + "dependencies": { + "utila": "~0.4" + } + }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "license": "MIT", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/dot-prop": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz", + "integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==", + "license": "MIT", + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/dot-prop/node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", + "license": "MIT" + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "license": "MIT" + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.120", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.120.tgz", + "integrity": "sha512-oTUp3gfX1gZI+xfD2djr2rzQdHCwHzPQrrK0CD7WpTdF0nPdQ/INcRVjWgLdCT4a9W3jFObR9DAfsuyFQnI8CQ==" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "license": "MIT" + }, + "node_modules/emojilib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/emojilib/-/emojilib-2.4.0.tgz", + "integrity": "sha512-5U0rVMU5Y2n2+ykNLQqMoqklN9ICBT/KsvC1Gz6vqHbz2AXXGkG+Pm5rMWk/8Vjrr/mY9985Hi8DYzn1F09Nyw==", + "license": "MIT" + }, + "node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/emoticon": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/emoticon/-/emoticon-4.0.1.tgz", + "integrity": "sha512-dqx7eA9YaqyvYtUhJwT4rC1HIp82j5ybS1/vQ42ur+jBe17dJMwZE4+gvL1XadSFfxaPFFGt3Xsw+Y8akThDlw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", + "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-module-lexer": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", + "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", + "license": "MIT" + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-goat": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-4.0.0.tgz", + "integrity": "sha512-2Sd4ShcWxbx6OY1IHyla/CVNwvg7XwZVoXZHcSu9w9SReNP1EzzD5T8NWKIR38fIqEns9kDWKUQTXXAmlDrdPg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-util-attach-comments": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/estree-util-attach-comments/-/estree-util-attach-comments-3.0.0.tgz", + "integrity": "sha512-cKUwm/HUcTDsYh/9FgnuFqpfquUbwIqwKM26BVCGDPVgvaCl/nDCCjUfiLlx6lsEZ3Z4RFxNbOQ60pkaEwFxGw==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-build-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/estree-util-build-jsx/-/estree-util-build-jsx-3.0.1.tgz", + "integrity": "sha512-8U5eiL6BTrPxp/CHbs2yMgP8ftMhR5ww1eIKoWRMlqvltHF8fZn5LRDvTKuxD3DUn+shRbLGqXemcP51oFCsGQ==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "estree-walker": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-is-identifier-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz", + "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-to-js": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/estree-util-to-js/-/estree-util-to-js-2.0.0.tgz", + "integrity": "sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "astring": "^1.8.0", + "source-map": "^0.7.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-value-to-estree": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/estree-util-value-to-estree/-/estree-util-value-to-estree-3.1.2.tgz", + "integrity": "sha512-S0gW2+XZkmsx00tU2uJ4L9hUT7IFabbml9pHh2WQqFmAbxit++YGZne0sKJbNwkj9Wvg9E4uqWl4nCIFQMmfag==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/remcohaszing" + } + }, + "node_modules/estree-util-visit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/estree-util-visit/-/estree-util-visit-2.0.0.tgz", + "integrity": "sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eta": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/eta/-/eta-2.2.0.tgz", + "integrity": "sha512-UVQ72Rqjy/ZKQalzV5dCCJP80GrmPrMxh6NlNf+erV6ObL0ZFkhCstWRawS85z3smdr3d2wXPsZEY7rDPfGd2g==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "url": "https://github.com/eta-dev/eta?sponsor=1" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eval": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/eval/-/eval-0.1.8.tgz", + "integrity": "sha512-EzV94NYKoO09GLXGjXj9JIlXijVck4ONSr5wiCWDvhsvj5jxSrzTmRU/9C1DyB6uToszLs8aifA6NQ7lEQdvFw==", + "dependencies": { + "@types/node": "*", + "require-like": ">= 0.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "license": "MIT" + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/express": { + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.3", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.7.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.3.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.12", + "proxy-addr": "~2.0.7", + "qs": "6.13.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.19.0", + "serve-static": "1.16.2", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/express/node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/express/node_modules/path-to-regexp": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==" + }, + "node_modules/express/node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "license": "MIT" + }, + "node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==", + "license": "MIT", + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "license": "MIT" + }, + "node_modules/fast-uri": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.1.tgz", + "integrity": "sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw==", + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fault": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fault/-/fault-2.0.1.tgz", + "integrity": "sha512-WtySTkS4OKev5JtpHXnib4Gxiurzh5NCGvWrFaZ34m6JehfTUhKZvn9njTfw48t6JumVQOmrKqpmGcdwxnhqBQ==", + "license": "MIT", + "dependencies": { + "format": "^0.2.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "license": "Apache-2.0", + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/feed": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/feed/-/feed-4.2.2.tgz", + "integrity": "sha512-u5/sxGfiMfZNtJ3OvQpXcvotFpYkL0n9u9mM2vkui2nGo8b4wvDkJ8gAkYqbA8QpGyFCv3RK0Z+Iv+9veCS9bQ==", + "license": "MIT", + "dependencies": { + "xml-js": "^1.6.11" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/file-loader": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", + "integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==", + "license": "MIT", + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/file-loader/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/file-loader/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "license": "MIT", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/file-loader/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "license": "MIT" + }, + "node_modules/file-loader/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/filesize": { + "version": "8.0.7", + "resolved": "https://registry.npmjs.org/filesize/-/filesize-8.0.7.tgz", + "integrity": "sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/find-cache-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-4.0.0.tgz", + "integrity": "sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg==", + "license": "MIT", + "dependencies": { + "common-path-prefix": "^3.0.0", + "pkg-dir": "^7.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/find-up": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", + "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", + "license": "MIT", + "dependencies": { + "locate-path": "^7.1.0", + "path-exists": "^5.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "license": "BSD-3-Clause", + "bin": { + "flat": "cli.js" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/fork-ts-checker-webpack-plugin": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.3.tgz", + "integrity": "sha512-SbH/l9ikmMWycd5puHJKTkZJKddF4iRLyW3DeZ08HTI7NGyLS38MXd/KGgeWumQO7YNQbW2u/NtPT2YowbPaGQ==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.8.3", + "@types/json-schema": "^7.0.5", + "chalk": "^4.1.0", + "chokidar": "^3.4.2", + "cosmiconfig": "^6.0.0", + "deepmerge": "^4.2.2", + "fs-extra": "^9.0.0", + "glob": "^7.1.6", + "memfs": "^3.1.2", + "minimatch": "^3.0.4", + "schema-utils": "2.7.0", + "semver": "^7.3.2", + "tapable": "^1.0.0" + }, + "engines": { + "node": ">=10", + "yarn": ">=1.0.0" + }, + "peerDependencies": { + "eslint": ">= 6", + "typescript": ">= 2.7", + "vue-template-compiler": "*", + "webpack": ">= 4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + }, + "vue-template-compiler": { + "optional": true + } + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "license": "MIT", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/cosmiconfig": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", + "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", + "license": "MIT", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.7.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "license": "MIT" + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/schema-utils": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", + "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.4", + "ajv": "^6.12.2", + "ajv-keywords": "^3.4.1" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/form-data-encoder": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz", + "integrity": "sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==", + "license": "MIT", + "engines": { + "node": ">= 14.17" + } + }, + "node_modules/format": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz", + "integrity": "sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==", + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fraction.js": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/fs-monkey": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.6.tgz", + "integrity": "sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==", + "license": "Unlicense" + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-own-enumerable-property-symbols": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", + "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==", + "license": "ISC" + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/github-slugger": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-1.5.0.tgz", + "integrity": "sha512-wIh+gKBI9Nshz2o46B0B3f5k/W+WI9ZAv6y5Dn5WJ5SK1t0TnDimB4WE5rmTD05ZAIn8HALCZVmCsvj0w0v0lw==", + "license": "ISC" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "license": "BSD-2-Clause" + }, + "node_modules/global-dirs": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", + "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==", + "license": "MIT", + "dependencies": { + "ini": "2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/global-dirs/node_modules/ini": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", + "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "license": "MIT", + "dependencies": { + "global-prefix": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "license": "MIT", + "dependencies": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/global-prefix/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "license": "MIT", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/got": { + "version": "12.6.1", + "resolved": "https://registry.npmjs.org/got/-/got-12.6.1.tgz", + "integrity": "sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==", + "license": "MIT", + "dependencies": { + "@sindresorhus/is": "^5.2.0", + "@szmarczak/http-timer": "^5.0.1", + "cacheable-lookup": "^7.0.0", + "cacheable-request": "^10.2.8", + "decompress-response": "^6.0.0", + "form-data-encoder": "^2.1.2", + "get-stream": "^6.0.1", + "http2-wrapper": "^2.1.10", + "lowercase-keys": "^3.0.0", + "p-cancelable": "^3.0.0", + "responselike": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, + "node_modules/got/node_modules/@sindresorhus/is": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-5.6.0.tgz", + "integrity": "sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==", + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, + "node_modules/gray-matter": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", + "integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==", + "license": "MIT", + "dependencies": { + "js-yaml": "^3.13.1", + "kind-of": "^6.0.2", + "section-matter": "^1.0.0", + "strip-bom-string": "^1.0.0" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/gray-matter/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/gray-matter/node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/gzip-size": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", + "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", + "license": "MIT", + "dependencies": { + "duplexer": "^0.1.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", + "license": "MIT" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-yarn": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-3.0.0.tgz", + "integrity": "sha512-IrsVwUHhEULx3R8f/aA8AHuEzAorplsab/v8HBzEiIukwq5i/EC+xmOW+HfP1OaDP+2JkgT1yILHN2O3UFIbcA==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hast-util-from-parse5": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.1.tgz", + "integrity": "sha512-Er/Iixbc7IEa7r/XLtuG52zoqn/b3Xng/w6aZQ0xGVxzhw5xUFxcRqdPzP6yFi/4HBYRaifaI5fQ1RH8n0ZeOQ==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "devlop": "^1.0.0", + "hastscript": "^8.0.0", + "property-information": "^6.0.0", + "vfile": "^6.0.0", + "vfile-location": "^5.0.0", + "web-namespaces": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-parse-selector": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz", + "integrity": "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-raw": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-9.0.4.tgz", + "integrity": "sha512-LHE65TD2YiNsHD3YuXcKPHXPLuYh/gjp12mOfU8jxSrm1f/yJpsb0F/KKljS6U9LJoP0Ux+tCe8iJ2AsPzTdgA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "@ungap/structured-clone": "^1.0.0", + "hast-util-from-parse5": "^8.0.0", + "hast-util-to-parse5": "^8.0.0", + "html-void-elements": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "parse5": "^7.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0", + "web-namespaces": "^2.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-estree": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hast-util-to-estree/-/hast-util-to-estree-3.1.0.tgz", + "integrity": "sha512-lfX5g6hqVh9kjS/B9E2gSkvHH4SZNiQFiqWS0x9fENzEl+8W12RqdRxX6d/Cwxi30tPQs3bIO+aolQJNp1bIyw==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-attach-comments": "^3.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-object": "^0.4.0", + "unist-util-position": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-jsx-runtime": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.0.tgz", + "integrity": "sha512-H/y0+IWPdsLLS738P8tDnrQ8Z+dj12zQQ6WC11TIM21C8WFVoIxcqWXf2H3hiTVZjF1AWqoimGwrTWecWrnmRQ==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-object": "^1.0.0", + "unist-util-position": "^5.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-jsx-runtime/node_modules/inline-style-parser": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.3.tgz", + "integrity": "sha512-qlD8YNDqyTKTyuITrDOffsl6Tdhv+UC4hcdAVuQsK4IMQ99nSgd1MIA/Q+jQYoh9r3hVUXhYh7urSRmXPkW04g==", + "license": "MIT" + }, + "node_modules/hast-util-to-jsx-runtime/node_modules/style-to-object": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.6.tgz", + "integrity": "sha512-khxq+Qm3xEyZfKd/y9L3oIWQimxuc4STrQKtQn8aSDRHb8mFgpukgX1hdzfrMEW6JCjyJ8p89x+IUMVnCBI1PA==", + "license": "MIT", + "dependencies": { + "inline-style-parser": "0.2.3" + } + }, + "node_modules/hast-util-to-parse5": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-8.0.0.tgz", + "integrity": "sha512-3KKrV5ZVI8if87DVSi1vDeByYrkGzg4mEfeu4alwgmmIeARiBLKCZS2uw5Gb6nU9x9Yufyj3iudm6i7nl52PFw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0", + "web-namespaces": "^2.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-whitespace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hastscript": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-8.0.0.tgz", + "integrity": "sha512-dMOtzCEd3ABUeSIISmrETiKuyydk1w0pa+gE/uormcTpSYuaNJPbX1NU3JLyscSLjwAQM8bWMhhIlnCqnRvDTw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-parse-selector": "^4.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "license": "MIT", + "bin": { + "he": "bin/he" + } + }, + "node_modules/history": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz", + "integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.1.2", + "loose-envify": "^1.2.0", + "resolve-pathname": "^3.0.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0", + "value-equal": "^1.0.1" + } + }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "license": "BSD-3-Clause", + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "node_modules/hpack.js/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT" + }, + "node_modules/hpack.js/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/hpack.js/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/hpack.js/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/html-entities": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz", + "integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ], + "license": "MIT" + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "license": "MIT" + }, + "node_modules/html-minifier-terser": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-7.2.0.tgz", + "integrity": "sha512-tXgn3QfqPIpGl9o+K5tpcj3/MN4SfLtsx2GWwBC3SSd0tXQGyF3gsSqad8loJgKZGM3ZxbYDd5yhiBIdWpmvLA==", + "license": "MIT", + "dependencies": { + "camel-case": "^4.1.2", + "clean-css": "~5.3.2", + "commander": "^10.0.0", + "entities": "^4.4.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.15.1" + }, + "bin": { + "html-minifier-terser": "cli.js" + }, + "engines": { + "node": "^14.13.1 || >=16.0.0" + } + }, + "node_modules/html-minifier-terser/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/html-tags": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", + "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/html-void-elements": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", + "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/html-webpack-plugin": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.0.tgz", + "integrity": "sha512-iwaY4wzbe48AfKLZ/Cc8k0L+FKG6oSNRaZ8x5A/T/IVDGyXcbHncM9TdDa93wn0FsSm82FhTKW7f3vS61thXAw==", + "license": "MIT", + "dependencies": { + "@types/html-minifier-terser": "^6.0.0", + "html-minifier-terser": "^6.0.2", + "lodash": "^4.17.21", + "pretty-error": "^4.0.0", + "tapable": "^2.0.0" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/html-webpack-plugin" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.20.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/html-webpack-plugin/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/html-webpack-plugin/node_modules/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", + "license": "MIT", + "dependencies": { + "camel-case": "^4.1.2", + "clean-css": "^5.2.2", + "commander": "^8.3.0", + "he": "^1.2.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.10.0" + }, + "bin": { + "html-minifier-terser": "cli.js" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/htmlparser2": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", + "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "entities": "^4.4.0" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "license": "BSD-2-Clause" + }, + "node_modules/http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==", + "license": "MIT" + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-parser-js": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", + "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==", + "license": "MIT" + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "license": "MIT", + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/http-proxy-middleware": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.7.tgz", + "integrity": "sha512-fgVY8AV7qU7z/MmXJ/rxwbrtQH4jBQ9m7kp3llF0liB7glmFeVZFBepQb32T3y8n8k2+AEYuMPCpinYW+/CuRA==", + "dependencies": { + "@types/http-proxy": "^1.17.8", + "http-proxy": "^1.18.1", + "is-glob": "^4.0.1", + "is-plain-obj": "^3.0.0", + "micromatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "@types/express": "^4.17.13" + }, + "peerDependenciesMeta": { + "@types/express": { + "optional": true + } + } + }, + "node_modules/http-proxy-middleware/node_modules/is-plain-obj": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", + "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/http2-wrapper": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.1.tgz", + "integrity": "sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==", + "license": "MIT", + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.2.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "license": "Apache-2.0", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "license": "ISC", + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/ignore": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/image-size": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.1.1.tgz", + "integrity": "sha512-541xKlUw6jr/6gGuk92F+mYM5zaFAc5ahphvkqvNe2bQ6gVBkd6bfrmVJ2t4KDAfikAYZyIqTnktX3i6/aQDrQ==", + "license": "MIT", + "dependencies": { + "queue": "6.0.2" + }, + "bin": { + "image-size": "bin/image-size.js" + }, + "engines": { + "node": ">=16.x" + } + }, + "node_modules/immer": { + "version": "9.0.21", + "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz", + "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-lazy": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", + "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/infima": { + "version": "0.2.0-alpha.43", + "resolved": "https://registry.npmjs.org/infima/-/infima-0.2.0-alpha.43.tgz", + "integrity": "sha512-2uw57LvUqW0rK/SWYnd/2rRfxNA5DDNOh33jxF7fy46VWoNhGxiUQyVZHbBMjQ33mQem0cjdDVwgWVAmlRfgyQ==", + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "license": "ISC" + }, + "node_modules/inline-style-parser": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz", + "integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==", + "license": "MIT" + }, + "node_modules/interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, + "node_modules/ipaddr.js": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz", + "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/is-alphabetical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", + "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-alphanumerical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", + "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", + "license": "MIT", + "dependencies": { + "is-alphabetical": "^2.0.0", + "is-decimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "license": "MIT" + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-ci": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", + "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", + "license": "MIT", + "dependencies": { + "ci-info": "^3.2.0" + }, + "bin": { + "is-ci": "bin.js" + } + }, + "node_modules/is-core-module": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.0.tgz", + "integrity": "sha512-Dd+Lb2/zvk9SKy1TGCt1wFJFo/MWBPMX5x7KcvLajWTGuomczdQX61PvY5yK6SVACwpoexWo81IfFyoKY2QnTA==", + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-decimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", + "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-hexadecimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", + "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-installed-globally": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", + "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", + "license": "MIT", + "dependencies": { + "global-dirs": "^3.0.0", + "is-path-inside": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-npm": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-6.0.0.tgz", + "integrity": "sha512-JEjxbSmtPSt1c8XTkVrlujcXdKV1/tvuQ7GwKcAlyiVLeYFQ2VHat8xfrDJsIkhCdF/tZ7CiIR3sy141c6+gPQ==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-path-cwd": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", + "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "license": "MIT", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-reference": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.2.tgz", + "integrity": "sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg==", + "license": "MIT", + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/is-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-root": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-root/-/is-root-2.1.0.tgz", + "integrity": "sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "license": "MIT" + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-yarn-global": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.4.1.tgz", + "integrity": "sha512-/kppl+R+LO5VmhYSEWARUFjodS25D68gvj8W7z0I7OWhUla5xWu8KL6CtB2V0R6yqhnRgbcaREMr4EEM6htLPQ==", + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/jiti": { + "version": "1.21.6", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", + "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", + "license": "MIT", + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/joi": { + "version": "17.13.3", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.13.3.tgz", + "integrity": "sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==", + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^9.3.0", + "@hapi/topo": "^5.1.0", + "@sideway/address": "^4.1.5", + "@sideway/formula": "^3.0.1", + "@sideway/pinpoint": "^2.0.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "license": "MIT" + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/latest-version": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-7.0.0.tgz", + "integrity": "sha512-KvNT4XqAMzdcL6ka6Tl3i2lYeFDgXNCuIX+xNx6ZMVR1dFq+idXd9FLKNMOIx0t9mJ9/HudyX4oZWXZQ0UJHeg==", + "license": "MIT", + "dependencies": { + "package-json": "^8.1.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/launch-editor": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.8.0.tgz", + "integrity": "sha512-vJranOAJrI/llyWGRQqiDM+adrw+k83fvmmx3+nV47g3+36xM15jE+zyZ6Ffel02+xSvuM0b2GDRosXZkbb6wA==", + "license": "MIT", + "dependencies": { + "picocolors": "^1.0.0", + "shell-quote": "^1.8.1" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/lilconfig": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", + "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "license": "MIT" + }, + "node_modules/loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "license": "MIT", + "engines": { + "node": ">=6.11.5" + } + }, + "node_modules/loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "license": "MIT", + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/locate-path": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", + "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", + "license": "MIT", + "dependencies": { + "p-locate": "^6.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "license": "MIT" + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", + "license": "MIT" + }, + "node_modules/lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", + "license": "MIT" + }, + "node_modules/longest-streak": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", + "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/lowercase-keys": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz", + "integrity": "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/markdown-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/markdown-extensions/-/markdown-extensions-2.0.0.tgz", + "integrity": "sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q==", + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/markdown-table": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.3.tgz", + "integrity": "sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mdast-util-directive": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-directive/-/mdast-util-directive-3.0.0.tgz", + "integrity": "sha512-JUpYOqKI4mM3sZcNxmF/ox04XYFFkNwr0CFlrQIkCwbvH0xzMCqkMqAde9wRd80VAhaUrwFwKm2nxretdT1h7Q==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "parse-entities": "^4.0.0", + "stringify-entities": "^4.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-find-and-replace": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.1.tgz", + "integrity": "sha512-SG21kZHGC3XRTSUhtofZkBzZTJNM5ecCi0SK2IMKmSXR8vO3peL+kb1O0z7Zl83jKtutG4k5Wv/W7V3/YHvzPA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "escape-string-regexp": "^5.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-find-and-replace/node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mdast-util-from-markdown": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.1.tgz", + "integrity": "sha512-aJEUyzZ6TzlsX2s5B4Of7lN7EQtAxvtradMMglCQDyaTFgse6CmtmdJ15ElnVRlCg1vpNyVtbem0PWzlNieZsA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark": "^4.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-from-markdown/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/mdast-util-frontmatter": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-frontmatter/-/mdast-util-frontmatter-2.0.1.tgz", + "integrity": "sha512-LRqI9+wdgC25P0URIJY9vwocIzCcksduHQ9OF2joxQoyTNVduwLAFUzjoopuRJbJAReaKrNQKAZKL3uCMugWJA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "escape-string-regexp": "^5.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "micromark-extension-frontmatter": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-frontmatter/node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mdast-util-gfm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.0.0.tgz", + "integrity": "sha512-dgQEX5Amaq+DuUqf26jJqSK9qgixgd6rYDHAv4aTBuA92cTknZlKpPfa86Z/s8Dj8xsAQpFfBmPUHWJBWqS4Bw==", + "license": "MIT", + "dependencies": { + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-gfm-autolink-literal": "^2.0.0", + "mdast-util-gfm-footnote": "^2.0.0", + "mdast-util-gfm-strikethrough": "^2.0.0", + "mdast-util-gfm-table": "^2.0.0", + "mdast-util-gfm-task-list-item": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-autolink-literal": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.0.tgz", + "integrity": "sha512-FyzMsduZZHSc3i0Px3PQcBT4WJY/X/RCtEJKuybiC6sjPqLv7h1yqAkmILZtuxMSsUyaLUWNp71+vQH2zqp5cg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "ccount": "^2.0.0", + "devlop": "^1.0.0", + "mdast-util-find-and-replace": "^3.0.0", + "micromark-util-character": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-autolink-literal/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/mdast-util-gfm-autolink-literal/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/mdast-util-gfm-footnote": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.0.0.tgz", + "integrity": "sha512-5jOT2boTSVkMnQ7LTrd6n/18kqwjmuYqo7JUPe+tRCY6O7dAuTFMtTPauYYrMPpox9hlN0uOx/FL8XvEfG9/mQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-strikethrough": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz", + "integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-table": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz", + "integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "markdown-table": "^3.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-task-list-item": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz", + "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx/-/mdast-util-mdx-3.0.0.tgz", + "integrity": "sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w==", + "license": "MIT", + "dependencies": { + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-expression": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.0.tgz", + "integrity": "sha512-fGCu8eWdKUKNu5mohVGkhBXCXGnOTLuFqOvGMvdikr+J1w7lDJgxThOKpwRWzzbyXAU2hhSwsmssOY4yTokluw==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-jsx": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.1.2.tgz", + "integrity": "sha512-eKMQDeywY2wlHc97k5eD8VC+9ASMjN8ItEZQNGwJ6E0XWKiW/Z0V5/H8pvoXUf+y+Mj0VIgeRRbujBmFn4FTyA==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "parse-entities": "^4.0.0", + "stringify-entities": "^4.0.0", + "unist-util-remove-position": "^5.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdxjs-esm": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz", + "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==", + "license": "MIT", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-phrasing": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", + "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-hast": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz", + "integrity": "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "trim-lines": "^3.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-markdown": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.0.tgz", + "integrity": "sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "longest-streak": "^3.0.0", + "mdast-util-phrasing": "^4.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark-util-decode-string": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", + "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdn-data": { + "version": "2.0.30", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", + "license": "CC0-1.0" + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/memfs": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", + "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", + "license": "Unlicense", + "dependencies": { + "fs-monkey": "^1.0.4" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "license": "MIT" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromark": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.0.tgz", + "integrity": "sha512-o/sd0nMof8kYff+TqcDx3VSrgBTcZpSvYcAHIfHhv5VAuNmisCxjhx6YmxS8PFEpb9z5WKWKPdzf0jM23ro3RQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/debug": "^4.0.0", + "debug": "^4.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.1.tgz", + "integrity": "sha512-CUQyKr1e///ZODyD1U3xit6zXwy1a8q2a1S1HKtIlmgvurrEpaw/Y9y6KSIbF8P59cn/NjzHyO+Q2fAyYLQrAA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-destination": "^2.0.0", + "micromark-factory-label": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-title": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-html-tag-name": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark/node_modules/micromark-factory-space": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", + "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-directive": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/micromark-extension-directive/-/micromark-extension-directive-3.0.1.tgz", + "integrity": "sha512-VGV2uxUzhEZmaP7NSFo2vtq7M2nUD+WfmYQD+d8i/1nHbzE+rMy9uzTvUybBbNiVbrhOZibg3gbyoARGqgDWyg==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "parse-entities": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-directive/node_modules/micromark-factory-space": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", + "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-directive/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-directive/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-frontmatter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-frontmatter/-/micromark-extension-frontmatter-2.0.0.tgz", + "integrity": "sha512-C4AkuM3dA58cgZha7zVnuVxBhDsbttIMiytjgsM2XbHAB2faRVaHRle40558FBN+DJcrLNCoqG5mlrpdU4cRtg==", + "license": "MIT", + "dependencies": { + "fault": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-frontmatter/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-frontmatter/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-gfm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz", + "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==", + "license": "MIT", + "dependencies": { + "micromark-extension-gfm-autolink-literal": "^2.0.0", + "micromark-extension-gfm-footnote": "^2.0.0", + "micromark-extension-gfm-strikethrough": "^2.0.0", + "micromark-extension-gfm-table": "^2.0.0", + "micromark-extension-gfm-tagfilter": "^2.0.0", + "micromark-extension-gfm-task-list-item": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-autolink-literal": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz", + "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==", + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-autolink-literal/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-autolink-literal/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-factory-space": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", + "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-footnote/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-gfm-strikethrough": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz", + "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-strikethrough/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-gfm-table": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.0.tgz", + "integrity": "sha512-Ub2ncQv+fwD70/l4ou27b4YzfNaCJOvyX4HxXU15m7mpYY+rjuWzsLIPZHJL253Z643RpbcP1oeIJlQ/SKW67g==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-table/node_modules/micromark-factory-space": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", + "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-table/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-table/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-gfm-tagfilter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz", + "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==", + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-task-list-item": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz", + "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==", + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-task-list-item/node_modules/micromark-factory-space": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", + "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-task-list-item/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-gfm-task-list-item/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-mdx-expression": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-3.0.0.tgz", + "integrity": "sha512-sI0nwhUDz97xyzqJAbHQhp5TfaxEvZZZ2JDqUo+7NvyIYG6BZ5CPPqj2ogUoPJlmXHBnyZUzISg9+oUmU6tUjQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-mdx-expression": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-mdx-expression/node_modules/micromark-factory-space": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", + "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-mdx-expression/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-mdx-expression/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-mdx-jsx": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-jsx/-/micromark-extension-mdx-jsx-3.0.0.tgz", + "integrity": "sha512-uvhhss8OGuzR4/N17L1JwvmJIpPhAd8oByMawEKx6NVdBCbesjH4t+vjEp3ZXft9DwvlKSD07fCeI44/N0Vf2w==", + "license": "MIT", + "dependencies": { + "@types/acorn": "^4.0.0", + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "micromark-factory-mdx-expression": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdx-jsx/node_modules/micromark-factory-space": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", + "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-mdx-jsx/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-mdx-jsx/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-extension-mdx-md": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-md/-/micromark-extension-mdx-md-2.0.0.tgz", + "integrity": "sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ==", + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdxjs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs/-/micromark-extension-mdxjs-3.0.0.tgz", + "integrity": "sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ==", + "license": "MIT", + "dependencies": { + "acorn": "^8.0.0", + "acorn-jsx": "^5.0.0", + "micromark-extension-mdx-expression": "^3.0.0", + "micromark-extension-mdx-jsx": "^3.0.0", + "micromark-extension-mdx-md": "^2.0.0", + "micromark-extension-mdxjs-esm": "^3.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdxjs-esm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs-esm/-/micromark-extension-mdxjs-esm-3.0.0.tgz", + "integrity": "sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-position-from-estree": "^2.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdxjs-esm/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-mdxjs-esm/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-factory-destination": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.0.tgz", + "integrity": "sha512-j9DGrQLm/Uhl2tCzcbLhy5kXsgkHUrjJHg4fFAeoMRwJmJerT9aw4FEhIbZStWN8A3qMwOp1uzHr4UL8AInxtA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-destination/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-destination/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-factory-label": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.0.tgz", + "integrity": "sha512-RR3i96ohZGde//4WSe/dJsxOX6vxIg9TimLAS3i4EhBAFx8Sm5SmqVfR8E87DPSR31nEAjZfbt91OMZWcNgdZw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-label/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-label/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-factory-mdx-expression": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-mdx-expression/-/micromark-factory-mdx-expression-2.0.1.tgz", + "integrity": "sha512-F0ccWIUHRLRrYp5TC9ZYXmZo+p2AM13ggbsW4T0b5CRKP8KHVRB8t4pwtBgTxtjRmwrK0Irwm7vs2JOZabHZfg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-position-from-estree": "^2.0.0", + "vfile-message": "^4.0.0" + } + }, + "node_modules/micromark-factory-mdx-expression/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-mdx-expression/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-factory-space": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-1.1.0.tgz", + "integrity": "sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/micromark-factory-space/node_modules/micromark-util-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.1.0.tgz", + "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-factory-title": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.0.tgz", + "integrity": "sha512-jY8CSxmpWLOxS+t8W+FG3Xigc0RDQA9bKMY/EwILvsesiRniiVMejYTE4wumNc2f4UbAa4WsHqe3J1QS1sli+A==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title/node_modules/micromark-factory-space": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", + "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-factory-whitespace": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.0.tgz", + "integrity": "sha512-28kbwaBjc5yAI1XadbdPYHX/eDnqaUFVikLwrO7FDnKG7lpgxnvk/XGRhX/PN0mOZ+dBSZ+LgunHS+6tYQAzhA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-whitespace/node_modules/micromark-factory-space": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", + "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-whitespace/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-whitespace/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-character": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-1.2.0.tgz", + "integrity": "sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^1.0.0", + "micromark-util-types": "^1.0.0" + } + }, + "node_modules/micromark-util-character/node_modules/micromark-util-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-1.1.0.tgz", + "integrity": "sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-chunked": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.0.tgz", + "integrity": "sha512-anK8SWmNphkXdaKgz5hJvGa7l00qmcaUQoMYsBwDlSKFKjc6gjGXPDw3FNL3Nbwq5L8gE+RCbGqTw49FK5Qyvg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-chunked/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-classify-character": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.0.tgz", + "integrity": "sha512-S0ze2R9GH+fu41FA7pbSqNWObo/kzwf8rN/+IGlW/4tC6oACOs8B++bh+i9bVyNnwCcuksbFwsBme5OCKXCwIw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-classify-character/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-classify-character/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-combine-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.0.tgz", + "integrity": "sha512-vZZio48k7ON0fVS3CUgFatWHoKbbLTK/rT7pzpJ4Bjp5JjkZeasRfrS9wsBdDJK2cJLHMckXZdzPSSr1B8a4oQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-chunked": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-numeric-character-reference": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.1.tgz", + "integrity": "sha512-bmkNc7z8Wn6kgjZmVHOX3SowGmVdhYS7yBpMnuMnPzDq/6xwVA604DuOXMZTO1lvq01g+Adfa0pE2UKGlxL1XQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-numeric-character-reference/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-decode-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.0.tgz", + "integrity": "sha512-r4Sc6leeUTn3P6gk20aFMj2ntPwn6qpDZqWvYmAG6NgvFTIlj4WtrAudLi65qYoaGdXYViXYw2pkmn7QnIFasA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-string/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-string/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-encode": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.0.tgz", + "integrity": "sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-events-to-acorn": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-events-to-acorn/-/micromark-util-events-to-acorn-2.0.2.tgz", + "integrity": "sha512-Fk+xmBrOv9QZnEDguL9OI9/NQQp6Hz4FuQ4YmCb/5V7+9eAh1s6AYSvL20kHkD67YIg7EpE54TiSlcsf3vyZgA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/acorn": "^4.0.0", + "@types/estree": "^1.0.0", + "@types/unist": "^3.0.0", + "devlop": "^1.0.0", + "estree-util-visit": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "vfile-message": "^4.0.0" + } + }, + "node_modules/micromark-util-events-to-acorn/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-html-tag-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.0.tgz", + "integrity": "sha512-xNn4Pqkj2puRhKdKTm8t1YHC/BAjx6CEwRFXntTaRf/x16aqka6ouVoutm+QdkISTlT7e2zU7U4ZdlDLJd2Mcw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-normalize-identifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.0.tgz", + "integrity": "sha512-2xhYT0sfo85FMrUPtHcPo2rrp1lwbDEEzpx7jiH2xXJLqBuy4H0GgXk5ToU8IEwoROtXuL8ND0ttVa4rNqYK3w==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-normalize-identifier/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-resolve-all": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.0.tgz", + "integrity": "sha512-6KU6qO7DZ7GJkaCgwBNtplXCvGkJToU86ybBAUdavvgsCiG8lSSvYxr9MhwmQ+udpzywHsl4RpGJsYWG1pDOcA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.0.tgz", + "integrity": "sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-sanitize-uri/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-sanitize-uri/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-subtokenize": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.0.1.tgz", + "integrity": "sha512-jZNtiFl/1aY73yS3UGQkutD0UbhTt68qnRpw2Pifmz5wV9h8gOVsN70v+Lq/f1rKaU/W8pxRe8y8Q9FX1AOe1Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-subtokenize/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-symbol": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-1.1.0.tgz", + "integrity": "sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.0.tgz", + "integrity": "sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark/node_modules/micromark-factory-space": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.0.tgz", + "integrity": "sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark/node_modules/micromark-util-character": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.0.tgz", + "integrity": "sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark/node_modules/micromark-util-symbol": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.0.tgz", + "integrity": "sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "license": "MIT", + "dependencies": { + "mime-db": "~1.33.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/mimic-response": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-4.0.0.tgz", + "integrity": "sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mini-css-extract-plugin": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.0.tgz", + "integrity": "sha512-Zs1YsZVfemekSZG+44vBsYTLQORkPMwnlv+aehcxK/NLKC+EGhDB39/YePYYqx/sTk6NnYpuqikhSn7+JIevTA==", + "license": "MIT", + "dependencies": { + "schema-utils": "^4.0.0", + "tapable": "^2.2.1" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "license": "ISC" + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mrmime": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz", + "integrity": "sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "license": "MIT" + }, + "node_modules/multicast-dns": { + "version": "7.2.5", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", + "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", + "license": "MIT", + "dependencies": { + "dns-packet": "^5.2.2", + "thunky": "^1.0.2" + }, + "bin": { + "multicast-dns": "cli.js" + } + }, + "node_modules/nanoid": { + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.10.tgz", + "integrity": "sha512-vSJJTG+t/dIKAUhUDw/dLdZ9s//5OxcHqLaDWWrW4Cdq7o6tdLIczUkMXt2MBNmk6sJRZBZRXVixs7URY1CmIg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "license": "MIT" + }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "license": "MIT", + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node_modules/node-emoji": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-2.1.3.tgz", + "integrity": "sha512-E2WEOVsgs7O16zsURJ/eH8BqhF029wGpEOnv7Urwdo2wmQanOACwJQh0devF9D9RhoZru0+9JXIS0dBXIAz+lA==", + "license": "MIT", + "dependencies": { + "@sindresorhus/is": "^4.6.0", + "char-regex": "^1.0.2", + "emojilib": "^2.4.0", + "skin-tone": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/node-forge": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "license": "(BSD-3-Clause OR GPL-2.0)", + "engines": { + "node": ">= 6.13.0" + } + }, + "node_modules/node-releases": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-url": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.1.tgz", + "integrity": "sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w==", + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nprogress": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/nprogress/-/nprogress-0.2.0.tgz", + "integrity": "sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA==", + "license": "MIT" + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "license": "MIT" + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "license": "MIT", + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/opener": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", + "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", + "license": "(WTFPL OR MIT)", + "bin": { + "opener": "bin/opener-bin.js" + } + }, + "node_modules/p-cancelable": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", + "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==", + "license": "MIT", + "engines": { + "node": ">=12.20" + } + }, + "node_modules/p-limit": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "license": "MIT", + "dependencies": { + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", + "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", + "license": "MIT", + "dependencies": { + "p-limit": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "license": "MIT", + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-retry": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", + "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", + "license": "MIT", + "dependencies": { + "@types/retry": "0.12.0", + "retry": "^0.13.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-8.1.1.tgz", + "integrity": "sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA==", + "license": "MIT", + "dependencies": { + "got": "^12.1.0", + "registry-auth-token": "^5.0.1", + "registry-url": "^6.0.0", + "semver": "^7.3.7" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "license": "MIT", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-entities": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.1.tgz", + "integrity": "sha512-SWzvYcSJh4d/SGLIOQfZ/CoNv6BTlI6YEQ7Nj82oDVnRpwe/Z/F1EMx42x3JAOwGBlCjeCH0BRJQbQ/opHL17w==", + "license": "MIT", + "dependencies": { + "@types/unist": "^2.0.0", + "character-entities": "^2.0.0", + "character-entities-legacy": "^3.0.0", + "character-reference-invalid": "^2.0.0", + "decode-named-character-reference": "^1.0.0", + "is-alphanumerical": "^2.0.0", + "is-decimal": "^2.0.0", + "is-hexadecimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/parse-entities/node_modules/@types/unist": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.10.tgz", + "integrity": "sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==", + "license": "MIT" + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-numeric-range": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/parse-numeric-range/-/parse-numeric-range-1.3.0.tgz", + "integrity": "sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ==", + "license": "ISC" + }, + "node_modules/parse5": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", + "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", + "license": "MIT", + "dependencies": { + "entities": "^4.4.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz", + "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==", + "license": "MIT", + "dependencies": { + "domhandler": "^5.0.2", + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "license": "MIT", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/path-exists": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", + "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==", + "license": "(WTFPL OR MIT)" + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "license": "MIT" + }, + "node_modules/path-to-regexp": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.9.0.tgz", + "integrity": "sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g==", + "dependencies": { + "isarray": "0.0.1" + } + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/periscopic": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/periscopic/-/periscopic-3.1.0.tgz", + "integrity": "sha512-vKiQ8RRtkl9P+r/+oefh25C3fhybptkHKCZSPlcXiJux2tJF55GnEj3BVn4A5gKfq9NWWXXrxkHBwVPUfH0opw==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^3.0.0", + "is-reference": "^3.0.0" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pkg-dir": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-7.0.0.tgz", + "integrity": "sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==", + "license": "MIT", + "dependencies": { + "find-up": "^6.3.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-up": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", + "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", + "license": "MIT", + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-up/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "license": "MIT", + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "license": "MIT", + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-up/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "license": "MIT", + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss": { + "version": "8.4.40", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.40.tgz", + "integrity": "sha512-YF2kKIUzAofPMpfH6hOi2cGnv/HrUlfucspc7pDyvv7kGdqXrfj8SCl/t8owkEgKEuu8ZcRjSOxFxVLqwChZ2Q==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.0.1", + "source-map-js": "^1.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-calc": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-9.0.1.tgz", + "integrity": "sha512-TipgjGyzP5QzEhsOZUaIkeO5mKeMFpebWzRogWG/ysonUlnHcq5aJe0jOjpfzUU8PeSaBQnrE8ehR0QA5vs8PQ==", + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.0.11", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.2.2" + } + }, + "node_modules/postcss-colormin": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-6.1.0.tgz", + "integrity": "sha512-x9yX7DOxeMAR+BgGVnNSAxmAj98NX/YxEMNFP+SDCEeNLb2r3i6Hh1ksMsnW8Ub5SLCpbescQqn9YEbE9554Sw==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.0", + "caniuse-api": "^3.0.0", + "colord": "^2.9.3", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-convert-values": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-6.1.0.tgz", + "integrity": "sha512-zx8IwP/ts9WvUM6NkVSkiU902QZL1bwPhaVaLynPtCsOTqp+ZKbNi+s6XJg3rfqpKGA/oc7Oxk5t8pOQJcwl/w==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-discard-comments": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-6.0.2.tgz", + "integrity": "sha512-65w/uIqhSBBfQmYnG92FO1mWZjJ4GL5b8atm5Yw2UgrwD7HiNiSSNwJor1eCFGzUgYnN/iIknhNRVqjrrpuglw==", + "license": "MIT", + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-discard-duplicates": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-6.0.3.tgz", + "integrity": "sha512-+JA0DCvc5XvFAxwx6f/e68gQu/7Z9ud584VLmcgto28eB8FqSFZwtrLwB5Kcp70eIoWP/HXqz4wpo8rD8gpsTw==", + "license": "MIT", + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-discard-empty": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-6.0.3.tgz", + "integrity": "sha512-znyno9cHKQsK6PtxL5D19Fj9uwSzC2mB74cpT66fhgOadEUPyXFkbgwm5tvc3bt3NAy8ltE5MrghxovZRVnOjQ==", + "license": "MIT", + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-discard-overridden": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-6.0.2.tgz", + "integrity": "sha512-j87xzI4LUggC5zND7KdjsI25APtyMuynXZSujByMaav2roV6OZX+8AaCUcZSWqckZpjAjRyFDdpqybgjFO0HJQ==", + "license": "MIT", + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-discard-unused": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/postcss-discard-unused/-/postcss-discard-unused-6.0.5.tgz", + "integrity": "sha512-wHalBlRHkaNnNwfC8z+ppX57VhvS+HWgjW508esjdaEYr3Mx7Gnn2xA4R/CKf5+Z9S5qsqC+Uzh4ueENWwCVUA==", + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.0.16" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-loader": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-7.3.4.tgz", + "integrity": "sha512-iW5WTTBSC5BfsBJ9daFMPVrLT36MrNiC6fqOZTTaHjBNX6Pfd5p+hSBqe/fEeNd7pc13QiAyGt7VdGMw4eRC4A==", + "license": "MIT", + "dependencies": { + "cosmiconfig": "^8.3.5", + "jiti": "^1.20.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "postcss": "^7.0.0 || ^8.0.1", + "webpack": "^5.0.0" + } + }, + "node_modules/postcss-merge-idents": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-merge-idents/-/postcss-merge-idents-6.0.3.tgz", + "integrity": "sha512-1oIoAsODUs6IHQZkLQGO15uGEbK3EAl5wi9SS8hs45VgsxQfMnxvt+L+zIr7ifZFIH14cfAeVe2uCTa+SPRa3g==", + "license": "MIT", + "dependencies": { + "cssnano-utils": "^4.0.2", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-merge-longhand": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-6.0.5.tgz", + "integrity": "sha512-5LOiordeTfi64QhICp07nzzuTDjNSO8g5Ksdibt44d+uvIIAE1oZdRn8y/W5ZtYgRH/lnLDlvi9F8btZcVzu3w==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0", + "stylehacks": "^6.1.1" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-merge-rules": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-6.1.1.tgz", + "integrity": "sha512-KOdWF0gju31AQPZiD+2Ar9Qjowz1LTChSjFFbS+e2sFgc4uHOp3ZvVX4sNeTlk0w2O31ecFGgrFzhO0RSWbWwQ==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.0", + "caniuse-api": "^3.0.0", + "cssnano-utils": "^4.0.2", + "postcss-selector-parser": "^6.0.16" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-minify-font-values": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-6.1.0.tgz", + "integrity": "sha512-gklfI/n+9rTh8nYaSJXlCo3nOKqMNkxuGpTn/Qm0gstL3ywTr9/WRKznE+oy6fvfolH6dF+QM4nCo8yPLdvGJg==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-minify-gradients": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-6.0.3.tgz", + "integrity": "sha512-4KXAHrYlzF0Rr7uc4VrfwDJ2ajrtNEpNEuLxFgwkhFZ56/7gaE4Nr49nLsQDZyUe+ds+kEhf+YAUolJiYXF8+Q==", + "license": "MIT", + "dependencies": { + "colord": "^2.9.3", + "cssnano-utils": "^4.0.2", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-minify-params": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-6.1.0.tgz", + "integrity": "sha512-bmSKnDtyyE8ujHQK0RQJDIKhQ20Jq1LYiez54WiaOoBtcSuflfK3Nm596LvbtlFcpipMjgClQGyGr7GAs+H1uA==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.0", + "cssnano-utils": "^4.0.2", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-minify-selectors": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-6.0.4.tgz", + "integrity": "sha512-L8dZSwNLgK7pjTto9PzWRoMbnLq5vsZSTu8+j1P/2GB8qdtGQfn+K1uSvFgYvgh83cbyxT5m43ZZhUMTJDSClQ==", + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.0.16" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-modules-extract-imports": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", + "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", + "license": "ISC", + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-local-by-default": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz", + "integrity": "sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw==", + "license": "MIT", + "dependencies": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-scope": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz", + "integrity": "sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ==", + "license": "ISC", + "dependencies": { + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "license": "ISC", + "dependencies": { + "icss-utils": "^5.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-normalize-charset": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-6.0.2.tgz", + "integrity": "sha512-a8N9czmdnrjPHa3DeFlwqst5eaL5W8jYu3EBbTTkI5FHkfMhFZh1EGbku6jhHhIzTA6tquI2P42NtZ59M/H/kQ==", + "license": "MIT", + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-display-values": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-6.0.2.tgz", + "integrity": "sha512-8H04Mxsb82ON/aAkPeq8kcBbAtI5Q2a64X/mnRRfPXBq7XeogoQvReqxEfc0B4WPq1KimjezNC8flUtC3Qz6jg==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-positions": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-6.0.2.tgz", + "integrity": "sha512-/JFzI441OAB9O7VnLA+RtSNZvQ0NCFZDOtp6QPFo1iIyawyXg0YI3CYM9HBy1WvwCRHnPep/BvI1+dGPKoXx/Q==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-repeat-style": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-6.0.2.tgz", + "integrity": "sha512-YdCgsfHkJ2jEXwR4RR3Tm/iOxSfdRt7jplS6XRh9Js9PyCR/aka/FCb6TuHT2U8gQubbm/mPmF6L7FY9d79VwQ==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-string": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-6.0.2.tgz", + "integrity": "sha512-vQZIivlxlfqqMp4L9PZsFE4YUkWniziKjQWUtsxUiVsSSPelQydwS8Wwcuw0+83ZjPWNTl02oxlIvXsmmG+CiQ==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-timing-functions": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-6.0.2.tgz", + "integrity": "sha512-a+YrtMox4TBtId/AEwbA03VcJgtyW4dGBizPl7e88cTFULYsprgHWTbfyjSLyHeBcK/Q9JhXkt2ZXiwaVHoMzA==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-unicode": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-6.1.0.tgz", + "integrity": "sha512-QVC5TQHsVj33otj8/JD869Ndr5Xcc/+fwRh4HAsFsAeygQQXm+0PySrKbr/8tkDKzW+EVT3QkqZMfFrGiossDg==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-url": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-6.0.2.tgz", + "integrity": "sha512-kVNcWhCeKAzZ8B4pv/DnrU1wNh458zBNp8dh4y5hhxih5RZQ12QWMuQrDgPRw3LRl8mN9vOVfHl7uhvHYMoXsQ==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-normalize-whitespace": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-6.0.2.tgz", + "integrity": "sha512-sXZ2Nj1icbJOKmdjXVT9pnyHQKiSAyuNQHSgRCUgThn2388Y9cGVDR+E9J9iAYbSbLHI+UUwLVl1Wzco/zgv0Q==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-ordered-values": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-6.0.2.tgz", + "integrity": "sha512-VRZSOB+JU32RsEAQrO94QPkClGPKJEL/Z9PCBImXMhIeK5KAYo6slP/hBYlLgrCjFxyqvn5VC81tycFEDBLG1Q==", + "license": "MIT", + "dependencies": { + "cssnano-utils": "^4.0.2", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-reduce-idents": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-reduce-idents/-/postcss-reduce-idents-6.0.3.tgz", + "integrity": "sha512-G3yCqZDpsNPoQgbDUy3T0E6hqOQ5xigUtBQyrmq3tn2GxlyiL0yyl7H+T8ulQR6kOcHJ9t7/9H4/R2tv8tJbMA==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-reduce-initial": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-6.1.0.tgz", + "integrity": "sha512-RarLgBK/CrL1qZags04oKbVbrrVK2wcxhvta3GCxrZO4zveibqbRPmm2VI8sSgCXwoUHEliRSbOfpR0b/VIoiw==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.0", + "caniuse-api": "^3.0.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-reduce-transforms": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-6.0.2.tgz", + "integrity": "sha512-sB+Ya++3Xj1WaT9+5LOOdirAxP7dJZms3GRcYheSPi1PiTMigsxHAdkrbItHxwYHr4kt1zL7mmcHstgMYT+aiA==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.1.tgz", + "integrity": "sha512-b4dlw/9V8A71rLIDsSwVmak9z2DuBUB7CA1/wSdelNEzqsjoSPeADTWNO09lpH49Diy3/JIZ2bSPB1dI3LJCHg==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-sort-media-queries": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/postcss-sort-media-queries/-/postcss-sort-media-queries-5.2.0.tgz", + "integrity": "sha512-AZ5fDMLD8SldlAYlvi8NIqo0+Z8xnXU2ia0jxmuhxAU+Lqt9K+AlmLNJ/zWEnE9x+Zx3qL3+1K20ATgNOr3fAA==", + "license": "MIT", + "dependencies": { + "sort-css-media-queries": "2.2.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.4.23" + } + }, + "node_modules/postcss-svgo": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-6.0.3.tgz", + "integrity": "sha512-dlrahRmxP22bX6iKEjOM+c8/1p+81asjKT+V5lrgOH944ryx/OHpclnIbGsKVd3uWOXFLYJwCVf0eEkJGvO96g==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.2.0", + "svgo": "^3.2.0" + }, + "engines": { + "node": "^14 || ^16 || >= 18" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-unique-selectors": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-6.0.4.tgz", + "integrity": "sha512-K38OCaIrO8+PzpArzkLKB42dSARtC2tmG6PvD4b1o1Q2E9Os8jzfWFfSy/rixsHwohtsDdFtAWGjFVFUdwYaMg==", + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.0.16" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "license": "MIT" + }, + "node_modules/postcss-zindex": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-zindex/-/postcss-zindex-6.0.2.tgz", + "integrity": "sha512-5BxW9l1evPB/4ZIc+2GobEBoKC+h8gPGCMi+jxsYvd2x0mjq7wazk6DrP71pStqxE9Foxh5TVnonbWpFZzXaYg==", + "license": "MIT", + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/pretty-error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", + "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", + "license": "MIT", + "dependencies": { + "lodash": "^4.17.20", + "renderkid": "^3.0.0" + } + }, + "node_modules/pretty-time": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pretty-time/-/pretty-time-1.1.0.tgz", + "integrity": "sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/prism-react-renderer": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/prism-react-renderer/-/prism-react-renderer-2.3.1.tgz", + "integrity": "sha512-Rdf+HzBLR7KYjzpJ1rSoxT9ioO85nZngQEoFIhL07XhtJHlCU3SOz0GJ6+qvMyQe0Se+BV3qpe6Yd/NmQF5Juw==", + "license": "MIT", + "dependencies": { + "@types/prismjs": "^1.26.0", + "clsx": "^2.0.0" + }, + "peerDependencies": { + "react": ">=16.0.0" + } + }, + "node_modules/prismjs": { + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz", + "integrity": "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==", + "engines": { + "node": ">=6" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "license": "MIT" + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "license": "MIT", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/property-information": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz", + "integrity": "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", + "license": "ISC" + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-addr/node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/pupa": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pupa/-/pupa-3.1.0.tgz", + "integrity": "sha512-FLpr4flz5xZTSJxSeaheeMKN/EDzMdK7b8PTOC6a5PYFKTucWbdqjgqaEyH0shFiSJrVB1+Qqi4Tk19ccU6Aug==", + "license": "MIT", + "dependencies": { + "escape-goat": "^4.0.0" + }, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", + "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==", + "license": "MIT", + "dependencies": { + "inherits": "~2.0.3" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha512-kA5WQoNVo4t9lNx2kQNFCxKeBl5IbbSNBl1M/tLkw9WCn+hxNBAW5Qh8gdhs63CJnhjJ2zQWFoqPJP2sK1AV5A==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dev-utils": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz", + "integrity": "sha512-84Ivxmr17KjUupyqzFode6xKhjwuEJDROWKJy/BthkL7Wn6NJ8h4WE6k/exAv6ImS+0oZLRRW5j/aINMHyeGeQ==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.16.0", + "address": "^1.1.2", + "browserslist": "^4.18.1", + "chalk": "^4.1.2", + "cross-spawn": "^7.0.3", + "detect-port-alt": "^1.1.6", + "escape-string-regexp": "^4.0.0", + "filesize": "^8.0.6", + "find-up": "^5.0.0", + "fork-ts-checker-webpack-plugin": "^6.5.0", + "global-modules": "^2.0.0", + "globby": "^11.0.4", + "gzip-size": "^6.0.0", + "immer": "^9.0.7", + "is-root": "^2.1.0", + "loader-utils": "^3.2.0", + "open": "^8.4.0", + "pkg-up": "^3.1.0", + "prompts": "^2.4.2", + "react-error-overlay": "^6.0.11", + "recursive-readdir": "^2.2.2", + "shell-quote": "^1.7.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/react-dev-utils/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-dev-utils/node_modules/loader-utils": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.3.1.tgz", + "integrity": "sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg==", + "license": "MIT", + "engines": { + "node": ">= 12.13.0" + } + }, + "node_modules/react-dev-utils/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-dev-utils/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-dev-utils/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-dev-utils/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/react-dev-utils/node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/react-error-overlay": { + "version": "6.0.11", + "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz", + "integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==", + "license": "MIT" + }, + "node_modules/react-fast-compare": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz", + "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==", + "license": "MIT" + }, + "node_modules/react-helmet-async": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/react-helmet-async/-/react-helmet-async-1.3.0.tgz", + "integrity": "sha512-9jZ57/dAn9t3q6hneQS0wukqC2ENOBgMNVEhb/ZG9ZSxUetzVIw4iAmEU38IaVg3QGYauQPhSeUTuIUtFglWpg==", + "license": "Apache-2.0", + "dependencies": { + "@babel/runtime": "^7.12.5", + "invariant": "^2.2.4", + "prop-types": "^15.7.2", + "react-fast-compare": "^3.2.0", + "shallowequal": "^1.1.0" + }, + "peerDependencies": { + "react": "^16.6.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.6.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "license": "MIT" + }, + "node_modules/react-json-view-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/react-json-view-lite/-/react-json-view-lite-1.4.0.tgz", + "integrity": "sha512-wh6F6uJyYAmQ4fK0e8dSQMEWuvTs2Wr3el3sLD9bambX1+pSWUVXIz1RFaoy3TI1mZ0FqdpKq9YgbgTTgyrmXA==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "react": "^16.13.1 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/react-loadable": { + "name": "@docusaurus/react-loadable", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-6.0.0.tgz", + "integrity": "sha512-YMMxTUQV/QFSnbgrP3tjDzLHRg7vsbMn8e9HAa8o/1iXoiomo48b7sk/kkmWEuWNDPJVlKSJRB6Y2fHqdJk+SQ==", + "license": "MIT", + "dependencies": { + "@types/react": "*" + }, + "peerDependencies": { + "react": "*" + } + }, + "node_modules/react-loadable-ssr-addon-v5-slorber": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/react-loadable-ssr-addon-v5-slorber/-/react-loadable-ssr-addon-v5-slorber-1.0.1.tgz", + "integrity": "sha512-lq3Lyw1lGku8zUEJPDxsNm1AfYHBrO9Y1+olAYwpUJ2IGFBskM0DMKok97A6LWUpHm+o7IvQBOWu9MLenp9Z+A==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.3" + }, + "engines": { + "node": ">=10.13.0" + }, + "peerDependencies": { + "react-loadable": "*", + "webpack": ">=4.41.1 || 5.x" + } + }, + "node_modules/react-router": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.3.4.tgz", + "integrity": "sha512-Ys9K+ppnJah3QuaRiLxk+jDWOR1MekYQrlytiXxC1RyfbdsZkS5pvKAzCCr031xHixZwpnsYNT5xysdFHQaYsA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.13", + "history": "^4.9.0", + "hoist-non-react-statics": "^3.1.0", + "loose-envify": "^1.3.1", + "path-to-regexp": "^1.7.0", + "prop-types": "^15.6.2", + "react-is": "^16.6.0", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + }, + "peerDependencies": { + "react": ">=15" + } + }, + "node_modules/react-router-config": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/react-router-config/-/react-router-config-5.1.1.tgz", + "integrity": "sha512-DuanZjaD8mQp1ppHjgnnUnyOlqYXZVjnov/JzFhjLEwd3Z4dYjMSnqrEzzGThH47vpCOqPPwJM2FtthLeJ8Pbg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.1.2" + }, + "peerDependencies": { + "react": ">=15", + "react-router": ">=5" + } + }, + "node_modules/react-router-dom": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.3.4.tgz", + "integrity": "sha512-m4EqFMHv/Ih4kpcBCONHbkT68KoAeHN4p3lAGoNryfHi0dMy0kCzEZakiKRsvg5wHZ/JLrLW8o8KomWiz/qbYQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.13", + "history": "^4.9.0", + "loose-envify": "^1.3.1", + "prop-types": "^15.6.2", + "react-router": "5.3.4", + "tiny-invariant": "^1.0.2", + "tiny-warning": "^1.0.0" + }, + "peerDependencies": { + "react": ">=15" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/reading-time": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/reading-time/-/reading-time-1.5.0.tgz", + "integrity": "sha512-onYyVhBNr4CmAxFsKS7bz+uTLRakypIe4R+5A824vBSkQy/hB3fZepoVEf8OVAxzLvK+H/jm9TzpI3ETSm64Kg==", + "license": "MIT" + }, + "node_modules/rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==", + "dependencies": { + "resolve": "^1.1.6" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/recursive-readdir": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.3.tgz", + "integrity": "sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==", + "license": "MIT", + "dependencies": { + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "license": "MIT" + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz", + "integrity": "sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==", + "license": "MIT", + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "license": "MIT" + }, + "node_modules/regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, + "node_modules/regexpu-core": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", + "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "license": "MIT", + "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" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/registry-auth-token": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-5.0.2.tgz", + "integrity": "sha512-o/3ikDxtXaA59BmZuZrJZDJv8NMDGSj+6j6XaeBmHw8eY1i1qd9+6H+LjVvQXx3HN6aRCGa1cUdJ9RaJZUugnQ==", + "license": "MIT", + "dependencies": { + "@pnpm/npm-conf": "^2.1.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/registry-url": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-6.0.1.tgz", + "integrity": "sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==", + "license": "MIT", + "dependencies": { + "rc": "1.2.8" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/regjsparser": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", + "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "license": "BSD-2-Clause", + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/rehype-raw": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/rehype-raw/-/rehype-raw-7.0.0.tgz", + "integrity": "sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-raw": "^9.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/remark-directive": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/remark-directive/-/remark-directive-3.0.0.tgz", + "integrity": "sha512-l1UyWJ6Eg1VPU7Hm/9tt0zKtReJQNOA4+iDMAxTyZNWnJnFlbS/7zhiel/rogTLQ2vMYwDzSJa4BiVNqGlqIMA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-directive": "^3.0.0", + "micromark-extension-directive": "^3.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-emoji": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/remark-emoji/-/remark-emoji-4.0.1.tgz", + "integrity": "sha512-fHdvsTR1dHkWKev9eNyhTo4EFwbUvJ8ka9SgeWkMPYFX4WoI7ViVBms3PjlQYgw5TLvNQso3GUB/b/8t3yo+dg==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.2", + "emoticon": "^4.0.1", + "mdast-util-find-and-replace": "^3.0.1", + "node-emoji": "^2.1.0", + "unified": "^11.0.4" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/remark-frontmatter": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/remark-frontmatter/-/remark-frontmatter-5.0.0.tgz", + "integrity": "sha512-XTFYvNASMe5iPN0719nPrdItC9aU0ssC4v14mH1BCi1u0n1gAocqcujWUrByftZTbLhRtiKRyjYTSIOcr69UVQ==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-frontmatter": "^2.0.0", + "micromark-extension-frontmatter": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-gfm": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.0.tgz", + "integrity": "sha512-U92vJgBPkbw4Zfu/IiW2oTZLSL3Zpv+uI7My2eq8JxKgqraFdU8YUGicEJCEgSbeaG+QDFqIcwwfMTOEelPxuA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-gfm": "^3.0.0", + "micromark-extension-gfm": "^3.0.0", + "remark-parse": "^11.0.0", + "remark-stringify": "^11.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-mdx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.0.1.tgz", + "integrity": "sha512-3Pz3yPQ5Rht2pM5R+0J2MrGoBSrzf+tJG94N+t/ilfdh8YLyyKYtidAYwTveB20BoHAcwIopOUqhcmh2F7hGYA==", + "license": "MIT", + "dependencies": { + "mdast-util-mdx": "^3.0.0", + "micromark-extension-mdxjs": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-parse": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", + "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-rehype": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.0.tgz", + "integrity": "sha512-z3tJrAs2kIs1AqIIy6pzHmAHlF1hWQ+OdY4/hv+Wxe35EhyLKcajL33iUEn3ScxtFox9nUvRufR/Zre8Q08H/g==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "mdast-util-to-hast": "^13.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-stringify": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz", + "integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==", + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-to-markdown": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/renderkid": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", + "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", + "license": "MIT", + "dependencies": { + "css-select": "^4.1.3", + "dom-converter": "^0.2.0", + "htmlparser2": "^6.1.0", + "lodash": "^4.17.21", + "strip-ansi": "^6.0.1" + } + }, + "node_modules/renderkid/node_modules/css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/renderkid/node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "license": "MIT", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/renderkid/node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "license": "BSD-2-Clause", + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/renderkid/node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "license": "BSD-2-Clause", + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/renderkid/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "license": "BSD-2-Clause", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/renderkid/node_modules/htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "MIT", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-like": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/require-like/-/require-like-0.1.2.tgz", + "integrity": "sha512-oyrU88skkMtDdauHDuKVrgR+zuItqr6/c//FXzvmxRGMexSDc6hNvJInGW3LL46n+8b50RykrvwSUIIQH2LQ5A==", + "engines": { + "node": "*" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "license": "MIT" + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "license": "MIT", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "license": "MIT" + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-pathname": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz", + "integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==", + "license": "MIT" + }, + "node_modules/responselike": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-3.0.0.tgz", + "integrity": "sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==", + "license": "MIT", + "dependencies": { + "lowercase-keys": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rtl-detect": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/rtl-detect/-/rtl-detect-1.1.2.tgz", + "integrity": "sha512-PGMBq03+TTG/p/cRB7HCLKJ1MgDIi07+QU1faSjiYRfmY5UsAttV9Hs08jDAHVwcOwmVLcSJkpwyfXszVjWfIQ==", + "license": "BSD-3-Clause" + }, + "node_modules/rtlcss": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/rtlcss/-/rtlcss-4.2.0.tgz", + "integrity": "sha512-AV+V3oOVvCrqyH5Q/6RuT1IDH1Xy5kJTkEWTWZPN5rdQ3HCFOd8SrbC7c6N5Y8bPpCfZSR6yYbUATXslvfvu5g==", + "license": "MIT", + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0", + "postcss": "^8.4.21", + "strip-json-comments": "^3.1.1" + }, + "bin": { + "rtlcss": "bin/rtlcss.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/sax": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", + "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==", + "license": "ISC" + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/schema-utils": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.0.tgz", + "integrity": "sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g==", + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/search-insights": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/search-insights/-/search-insights-2.15.0.tgz", + "integrity": "sha512-ch2sPCUDD4sbPQdknVl9ALSi9H7VyoeVbsxznYz6QV55jJ8CI3EtwpO1i84keN4+hF5IeHWIeGvc08530JkVXQ==", + "license": "MIT", + "peer": true + }, + "node_modules/section-matter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz", + "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==", + "license": "MIT", + "dependencies": { + "extend-shallow": "^2.0.1", + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==", + "license": "MIT" + }, + "node_modules/selfsigned": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz", + "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==", + "license": "MIT", + "dependencies": { + "@types/node-forge": "^1.3.0", + "node-forge": "^1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-4.0.0.tgz", + "integrity": "sha512-0Ju4+6A8iOnpL/Thra7dZsSlOHYAHIeMxfhWQRI1/VLcT3WDBZKKtQt/QkBOsiIN9ZpuvHE6cGZ0x4glCMmfiA==", + "license": "MIT", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "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" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/send/node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "license": "BSD-3-Clause", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/serve-handler": { + "version": "6.1.6", + "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.6.tgz", + "integrity": "sha512-x5RL9Y2p5+Sh3D38Fh9i/iQ5ZK+e4xuXRd/pGbM4D13tgo/MGwbttUk8emytcr1YYzBYs+apnUngBDFYfpjPuQ==", + "dependencies": { + "bytes": "3.0.0", + "content-disposition": "0.5.2", + "mime-types": "2.1.18", + "minimatch": "3.1.2", + "path-is-inside": "1.0.2", + "path-to-regexp": "3.3.0", + "range-parser": "1.2.0" + } + }, + "node_modules/serve-handler/node_modules/path-to-regexp": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.3.0.tgz", + "integrity": "sha512-qyCH421YQPS2WFDxDjftfc1ZR5WKQzVzqsp4n9M2kQhVOo/ByahFoUNJfl58kOcEGfQ//7weFTDhm+ss8Ecxgw==" + }, + "node_modules/serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/serve-index/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/serve-index/node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==", + "license": "MIT", + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", + "license": "ISC" + }, + "node_modules/serve-index/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/serve-index/node_modules/setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "license": "ISC" + }, + "node_modules/serve-index/node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "license": "MIT", + "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" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "license": "MIT", + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==", + "license": "MIT" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/shelljs": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", + "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", + "license": "BSD-3-Clause", + "dependencies": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + }, + "bin": { + "shjs": "bin/shjs" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC" + }, + "node_modules/sirv": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.4.tgz", + "integrity": "sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==", + "license": "MIT", + "dependencies": { + "@polka/url": "^1.0.0-next.24", + "mrmime": "^2.0.0", + "totalist": "^3.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "license": "MIT" + }, + "node_modules/sitemap": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/sitemap/-/sitemap-7.1.2.tgz", + "integrity": "sha512-ARCqzHJ0p4gWt+j7NlU5eDlIO9+Rkr/JhPFZKKQ1l5GCus7rJH4UdrlVAh0xC/gDS/Qir2UMxqYNHtsKr2rpCw==", + "license": "MIT", + "dependencies": { + "@types/node": "^17.0.5", + "@types/sax": "^1.2.1", + "arg": "^5.0.0", + "sax": "^1.2.4" + }, + "bin": { + "sitemap": "dist/cli.js" + }, + "engines": { + "node": ">=12.0.0", + "npm": ">=5.6.0" + } + }, + "node_modules/sitemap/node_modules/@types/node": { + "version": "17.0.45", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz", + "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==", + "license": "MIT" + }, + "node_modules/skin-tone": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/skin-tone/-/skin-tone-2.0.0.tgz", + "integrity": "sha512-kUMbT1oBJCpgrnKoSr0o6wPtvRWT9W9UKvGLwfJYO2WuahZRHOpEyL1ckyMGgMWh0UdpmaoFqKKD29WTomNEGA==", + "license": "MIT", + "dependencies": { + "unicode-emoji-modifier-base": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/snake-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", + "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", + "license": "MIT", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/sockjs": { + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz", + "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==", + "license": "MIT", + "dependencies": { + "faye-websocket": "^0.11.3", + "uuid": "^8.3.2", + "websocket-driver": "^0.7.4" + } + }, + "node_modules/sort-css-media-queries": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/sort-css-media-queries/-/sort-css-media-queries-2.2.0.tgz", + "integrity": "sha512-0xtkGhWCC9MGt/EzgnvbbbKhqWjl1+/rncmhTh5qCpbYguXh6S/qwePfv/JQ8jePXXmqingylxoC49pCkSPIbA==", + "license": "MIT", + "engines": { + "node": ">= 6.3.0" + } + }, + "node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">= 8" + } + }, + "node_modules/source-map-js": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "license": "MIT", + "dependencies": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "license": "MIT", + "dependencies": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "license": "BSD-3-Clause" + }, + "node_modules/srcset": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/srcset/-/srcset-4.0.0.tgz", + "integrity": "sha512-wvLeHgcVHKO8Sc/H/5lkGreJQVeYMm9rlmt8PuR1xE31rIuXhuzznUUqAt8MqLhB3MqJdFzlNAfpcWnxiFUcPw==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/std-env": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.7.0.tgz", + "integrity": "sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==", + "license": "MIT" + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/stringify-entities": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", + "license": "MIT", + "dependencies": { + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/stringify-object": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", + "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", + "license": "BSD-2-Clause", + "dependencies": { + "get-own-enumerable-property-symbols": "^3.0.0", + "is-obj": "^1.0.1", + "is-regexp": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", + "integrity": "sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/style-to-object": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-0.4.4.tgz", + "integrity": "sha512-HYNoHZa2GorYNyqiCaBgsxvcJIn7OHq6inEga+E6Ke3m5JkoqpQbnFssk4jwe+K7AhGa2fcha4wSOf1Kn01dMg==", + "license": "MIT", + "dependencies": { + "inline-style-parser": "0.1.1" + } + }, + "node_modules/stylehacks": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-6.1.1.tgz", + "integrity": "sha512-gSTTEQ670cJNoaeIp9KX6lZmm8LJ3jPB5yJmX8Zq/wQxOsAFXV3qjWzHas3YYk1qesuVIyYWWUpZ0vSE/dTSGg==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.0", + "postcss-selector-parser": "^6.0.16" + }, + "engines": { + "node": "^14 || ^16 || >=18.0" + }, + "peerDependencies": { + "postcss": "^8.4.31" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/svg-parser": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", + "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==", + "license": "MIT" + }, + "node_modules/svgo": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.3.2.tgz", + "integrity": "sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==", + "license": "MIT", + "dependencies": { + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^5.1.0", + "css-tree": "^2.3.1", + "css-what": "^6.1.0", + "csso": "^5.0.5", + "picocolors": "^1.0.0" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/svgo" + } + }, + "node_modules/svgo/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/terser": { + "version": "5.31.3", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.3.tgz", + "integrity": "sha512-pAfYn3NIZLyZpa83ZKigvj6Rn9c/vd5KfYGX7cN1mnzqgDcxWvrU5ZtAfIKhEXz9nRecw4z3LXkjaq96/qZqAA==", + "license": "BSD-2-Clause", + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.3.14", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.14.tgz", + "integrity": "sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw==", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.25", + "jest-worker": "^27.4.5", + "schema-utils": "^4.3.0", + "serialize-javascript": "^6.0.2", + "terser": "^5.31.1" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/terser-webpack-plugin/node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/terser-webpack-plugin/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "license": "MIT" + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "license": "MIT" + }, + "node_modules/thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", + "license": "MIT" + }, + "node_modules/tiny-invariant": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", + "license": "MIT" + }, + "node_modules/tiny-warning": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", + "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==", + "license": "MIT" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/totalist": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", + "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/trough": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", + "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/tslib": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", + "license": "0BSD" + }, + "node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/type-is/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/type-is/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "license": "MIT", + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, + "node_modules/typescript": { + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", + "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", + "license": "Apache-2.0", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "license": "MIT" + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-emoji-modifier-base": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unicode-emoji-modifier-base/-/unicode-emoji-modifier-base-1.0.0.tgz", + "integrity": "sha512-yLSH4py7oFH3oG/9K+XWrz1pSi3dfUrWEnInbxMfArOfc1+33BlGPQtLsOYwvdMy11AwUBetYuaRxSPqgkq+8g==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "license": "MIT", + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz", + "integrity": "sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/unified": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", + "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unique-string": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-3.0.0.tgz", + "integrity": "sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==", + "license": "MIT", + "dependencies": { + "crypto-random-string": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/unist-util-is": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position-from-estree": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position-from-estree/-/unist-util-position-from-estree-2.0.0.tgz", + "integrity": "sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-remove-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-5.0.0.tgz", + "integrity": "sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", + "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/update-notifier": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-6.0.2.tgz", + "integrity": "sha512-EDxhTEVPZZRLWYcJ4ZXjGFN0oP7qYvbXWzEgRm/Yql4dHX5wDbvh89YHP6PK1lzZJYrMtXUuZZz8XGK+U6U1og==", + "license": "BSD-2-Clause", + "dependencies": { + "boxen": "^7.0.0", + "chalk": "^5.0.1", + "configstore": "^6.0.0", + "has-yarn": "^3.0.0", + "import-lazy": "^4.0.0", + "is-ci": "^3.0.1", + "is-installed-globally": "^0.4.0", + "is-npm": "^6.0.0", + "is-yarn-global": "^0.4.0", + "latest-version": "^7.0.0", + "pupa": "^3.1.0", + "semver": "^7.3.7", + "semver-diff": "^4.0.0", + "xdg-basedir": "^5.1.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/yeoman/update-notifier?sponsor=1" + } + }, + "node_modules/update-notifier/node_modules/boxen": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-7.1.1.tgz", + "integrity": "sha512-2hCgjEmP8YLWQ130n2FerGv7rYpfBmnmp9Uy2Le1vge6X3gZIfSmEzP5QTDElFxcvVcXlEn8Aq6MU/PZygIOog==", + "license": "MIT", + "dependencies": { + "ansi-align": "^3.0.1", + "camelcase": "^7.0.1", + "chalk": "^5.2.0", + "cli-boxes": "^3.0.0", + "string-width": "^5.1.2", + "type-fest": "^2.13.0", + "widest-line": "^4.0.1", + "wrap-ansi": "^8.1.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/update-notifier/node_modules/camelcase": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-7.0.1.tgz", + "integrity": "sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==", + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/update-notifier/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/uri-js/node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/url-loader": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-4.1.1.tgz", + "integrity": "sha512-3BTV812+AVHHOJQO8O5MkWgZ5aosP7GnROJwvzLS9hWDj00lZ6Z0wNak423Lp9PBZN05N+Jk/N5Si8jRAlGyWA==", + "license": "MIT", + "dependencies": { + "loader-utils": "^2.0.0", + "mime-types": "^2.1.27", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "file-loader": "*", + "webpack": "^4.0.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "file-loader": { + "optional": true + } + } + }, + "node_modules/url-loader/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/url-loader/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "license": "MIT", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/url-loader/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "license": "MIT" + }, + "node_modules/url-loader/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/url-loader/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/url-loader/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/utila": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", + "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==", + "license": "MIT" + }, + "node_modules/utility-types": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.11.0.tgz", + "integrity": "sha512-6Z7Ma2aVEWisaL6TvBCy7P8rm2LQoPv6dJ7ecIaIixHcwfbJ0x7mWdbcwlIM5IGQxPZSFYeqRCqlOOeKoJYMkw==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/value-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz", + "integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==", + "license": "MIT" + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/vfile": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.2.tgz", + "integrity": "sha512-zND7NlS8rJYb/sPqkb13ZvbbUoExdbi4w3SfRrMq6R3FvnLQmmfpajJNITuuYm6AZ5uao9vy4BAos3EXBPf2rg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-location": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-5.0.3.tgz", + "integrity": "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", + "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/watchpack": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz", + "integrity": "sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==", + "license": "MIT", + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "license": "MIT", + "dependencies": { + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/web-namespaces": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz", + "integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/webpack": { + "version": "5.98.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.98.0.tgz", + "integrity": "sha512-UFynvx+gM44Gv9qFgj0acCQK2VE1CtdfwFdimkapco3hlPCJ/zeq73n2yVKimVbtm+TnApIugGhLJnkU6gjYXA==", + "dependencies": { + "@types/eslint-scope": "^3.7.7", + "@types/estree": "^1.0.6", + "@webassemblyjs/ast": "^1.14.1", + "@webassemblyjs/wasm-edit": "^1.14.1", + "@webassemblyjs/wasm-parser": "^1.14.1", + "acorn": "^8.14.0", + "browserslist": "^4.24.0", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.17.1", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.11", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^4.3.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.11", + "watchpack": "^2.4.1", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-bundle-analyzer": { + "version": "4.10.2", + "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.10.2.tgz", + "integrity": "sha512-vJptkMm9pk5si4Bv922ZbKLV8UTT4zib4FPgXMhgzUny0bfDDkLXAVQs3ly3fS4/TN9ROFtb0NFrm04UXFE/Vw==", + "license": "MIT", + "dependencies": { + "@discoveryjs/json-ext": "0.5.7", + "acorn": "^8.0.4", + "acorn-walk": "^8.0.0", + "commander": "^7.2.0", + "debounce": "^1.2.1", + "escape-string-regexp": "^4.0.0", + "gzip-size": "^6.0.0", + "html-escaper": "^2.0.2", + "opener": "^1.5.2", + "picocolors": "^1.0.0", + "sirv": "^2.0.3", + "ws": "^7.3.1" + }, + "bin": { + "webpack-bundle-analyzer": "lib/bin/analyzer.js" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/webpack-bundle-analyzer/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/webpack-dev-middleware": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.4.tgz", + "integrity": "sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q==", + "license": "MIT", + "dependencies": { + "colorette": "^2.0.10", + "memfs": "^3.4.3", + "mime-types": "^2.1.31", + "range-parser": "^1.2.1", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/webpack-dev-middleware/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/webpack-dev-middleware/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/webpack-dev-middleware/node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/webpack-dev-server": { + "version": "4.15.2", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.2.tgz", + "integrity": "sha512-0XavAZbNJ5sDrCbkpWL8mia0o5WPOd2YGtxrEiZkBK9FjLppIUK2TgxK6qGD2P3hUXTJNNPVibrerKcx5WkR1g==", + "license": "MIT", + "dependencies": { + "@types/bonjour": "^3.5.9", + "@types/connect-history-api-fallback": "^1.3.5", + "@types/express": "^4.17.13", + "@types/serve-index": "^1.9.1", + "@types/serve-static": "^1.13.10", + "@types/sockjs": "^0.3.33", + "@types/ws": "^8.5.5", + "ansi-html-community": "^0.0.8", + "bonjour-service": "^1.0.11", + "chokidar": "^3.5.3", + "colorette": "^2.0.10", + "compression": "^1.7.4", + "connect-history-api-fallback": "^2.0.0", + "default-gateway": "^6.0.3", + "express": "^4.17.3", + "graceful-fs": "^4.2.6", + "html-entities": "^2.3.2", + "http-proxy-middleware": "^2.0.3", + "ipaddr.js": "^2.0.1", + "launch-editor": "^2.6.0", + "open": "^8.0.9", + "p-retry": "^4.5.0", + "rimraf": "^3.0.2", + "schema-utils": "^4.0.0", + "selfsigned": "^2.1.1", + "serve-index": "^1.9.1", + "sockjs": "^0.3.24", + "spdy": "^4.0.2", + "webpack-dev-middleware": "^5.3.4", + "ws": "^8.13.0" + }, + "bin": { + "webpack-dev-server": "bin/webpack-dev-server.js" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.37.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + }, + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-dev-server/node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "license": "MIT", + "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 + } + } + }, + "node_modules/webpack-merge": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", + "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", + "license": "MIT", + "dependencies": { + "clone-deep": "^4.0.1", + "flat": "^5.0.2", + "wildcard": "^2.0.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "license": "MIT", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/webpack/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/webpackbar": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-5.0.2.tgz", + "integrity": "sha512-BmFJo7veBDgQzfWXl/wwYXr/VFus0614qZ8i9znqcl9fnEdiVkdbi0TedLQ6xAK92HZHDJ0QmyQ0fmuZPAgCYQ==", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "consola": "^2.15.3", + "pretty-time": "^1.1.0", + "std-env": "^3.0.1" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "webpack": "3 || 4 || 5" + } + }, + "node_modules/websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "license": "Apache-2.0", + "dependencies": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/widest-line": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-4.0.1.tgz", + "integrity": "sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==", + "license": "MIT", + "dependencies": { + "string-width": "^5.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/wildcard": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", + "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", + "license": "MIT" + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xdg-basedir": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-5.1.0.tgz", + "integrity": "sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/xml-js": { + "version": "1.6.11", + "resolved": "https://registry.npmjs.org/xml-js/-/xml-js-1.6.11.tgz", + "integrity": "sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==", + "license": "MIT", + "dependencies": { + "sax": "^1.2.4" + }, + "bin": { + "xml-js": "bin/cli.js" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "license": "ISC" + }, + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, + "node_modules/yocto-queue": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.1.1.tgz", + "integrity": "sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==", + "license": "MIT", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + } + } +} diff --git a/docs/package.json b/docs/package.json new file mode 100644 index 0000000..0b71a71 --- /dev/null +++ b/docs/package.json @@ -0,0 +1,44 @@ +{ + "name": "of-dl", + "version": "0.0.0", + "private": true, + "scripts": { + "docusaurus": "docusaurus", + "start": "docusaurus start", + "build": "docusaurus build", + "swizzle": "docusaurus swizzle", + "deploy": "docusaurus deploy", + "clear": "docusaurus clear", + "serve": "docusaurus serve", + "write-translations": "docusaurus write-translations", + "write-heading-ids": "docusaurus write-heading-ids" + }, + "dependencies": { + "@docusaurus/core": "3.4.0", + "@docusaurus/preset-classic": "3.4.0", + "@mdx-js/react": "^3.0.0", + "clsx": "^2.0.0", + "prism-react-renderer": "^2.3.0", + "react": "^18.0.0", + "react-dom": "^18.0.0" + }, + "devDependencies": { + "@docusaurus/module-type-aliases": "3.4.0", + "@docusaurus/types": "3.4.0" + }, + "browserslist": { + "production": [ + ">0.5%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 3 chrome version", + "last 3 firefox version", + "last 5 safari version" + ] + }, + "engines": { + "node": ">=18.0" + } +} diff --git a/docs/sidebars.js b/docs/sidebars.js new file mode 100644 index 0000000..82c8c13 --- /dev/null +++ b/docs/sidebars.js @@ -0,0 +1,33 @@ +/** + * Creating a sidebar enables you to: + - create an ordered group of docs + - render a sidebar for each doc of that group + - provide next/previous navigation + + The sidebars can be generated from the filesystem, or explicitly defined here. + + Create as many sidebars as you want. + */ + +// @ts-check + +/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ +const sidebars = { + // By default, Docusaurus generates a sidebar from the docs folder structure + generatedSidebar: [{type: 'autogenerated', dirName: '.'}], + + // But you can create a sidebar manually + /* + tutorialSidebar: [ + 'intro', + 'hello', + { + type: 'category', + label: 'Tutorial', + items: ['tutorial-basics/create-a-document'], + }, + ], + */ +}; + +export default sidebars; diff --git a/docs/src/pages/index.js b/docs/src/pages/index.js new file mode 100644 index 0000000..8510608 --- /dev/null +++ b/docs/src/pages/index.js @@ -0,0 +1,39 @@ +import clsx from 'clsx'; +import Link from '@docusaurus/Link'; +import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; +import Layout from '@theme/Layout'; + +import Heading from '@theme/Heading'; +import styles from './index.module.css'; + +function HomepageHeader() { + const {siteConfig} = useDocusaurusContext(); + return ( +
+
+ + {siteConfig.title} + +

{siteConfig.tagline}

+
+ + Installation + +
+
+
+ ); +} + +export default function Home() { + const {siteConfig} = useDocusaurusContext(); + return ( + + + + ); +} diff --git a/docs/src/pages/index.module.css b/docs/src/pages/index.module.css new file mode 100644 index 0000000..9f71a5d --- /dev/null +++ b/docs/src/pages/index.module.css @@ -0,0 +1,23 @@ +/** + * CSS files with the .module.css suffix will be treated as CSS modules + * and scoped locally. + */ + +.heroBanner { + padding: 4rem 0; + text-align: center; + position: relative; + overflow: hidden; +} + +@media screen and (max-width: 996px) { + .heroBanner { + padding: 2rem; + } +} + +.buttons { + display: flex; + align-items: center; + justify-content: center; +} diff --git a/docs/static/.nojekyll b/docs/static/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/docs/static/img/cli_menu.png b/docs/static/img/cli_menu.png new file mode 100644 index 0000000000000000000000000000000000000000..57b2d7e5ab1ea999fa302a4355c3de5611aed3a7 GIT binary patch literal 22758 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
N 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 literal 0 HcmV?d00001 diff --git a/docs/static/img/network_tab.png b/docs/static/img/network_tab.png new file mode 100644 index 0000000000000000000000000000000000000000..fadad6f0a4b8d63c744b977fc6779a702687056a GIT binary patch literal 18685 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 literal 0 HcmV?d00001 diff --git a/docs/static/img/request_headers.png b/docs/static/img/request_headers.png new file mode 100644 index 0000000000000000000000000000000000000000..2f563b3a0f28b708280655c69b1d543457d2b138 GIT binary patch literal 60208 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 literal 0 HcmV?d00001 diff --git a/docs/static/img/welcome_banner.png b/docs/static/img/welcome_banner.png new file mode 100644 index 0000000000000000000000000000000000000000..2e6925d3eb20fde6ee7054bba4059d2e2b2d7943 GIT binary patch literal 1740 zcmZ`(ZB&w19H*JH6;F0HE0-SWWtE*4YBjB+`KZ&-Dc~ZpG9ufSr3LdKX~>I~X1U7V zmZlbS7Oa`5Yuby39Z9h$NN1pwffhX~3QffaWb!AlUjA(Q0K9x%yE!P-hnSei@U2Ra}Lg2nmozJ0#E;M~Or2T96{f!r(ZCs+?WMg&RS!xscIkX-*U?)%BhlskeQEQ|Lr zta0$yl!jk}^zsE(tzai;!gZ|Fi6c_3HkmksRD|t$o`{o_l)fG+R%jfoFa0PE(I&>{ zKx@sbYYWC)qrkYT#NQ^vXw!(w{Sn`T0DIxzYBd3yr`MrS^StP8_ z-lHYN`uOpq9ho!w5!WO~R%c#6u>GYE`kNi|3%UMN*su^DegtDQl*TtLk=;uCS4M%z zPqpsP-W*WGxi2&zQGPa0T1eShn!Nr~+YA)>Xa%s9hih^o58=9 zu}-Xz-LwCC@3rElu(G9i@J#{cQ073HFS}tBXFtI4bYox4r#*%@`f)DNxaQAv{>nFy8YBb7v1{9zyH9e9TCinkLaxSM#f_XICrT z((k9N>OEl&y=HV8A%syUfkm0d2misL|Ht3<3KKN0ayW|{t}|_SPm+QHTJ)E4ngfUEy<&M!-}Po=zYS*~ z*wQIx*9(x_*dX6Wjvu%C9(C>z>KoGm?I`R|9gH4WS9 zu%IBfhN0s0w22iMntImEq3=}reJ45+isU-!l(B-or`BLjimEujL4CU!u6w7FRpebs zl?81CcMW7bFJ!`Eb;Qc_-_yC)r<)hY`!!}KV(LQL3PMNqVA-&-fOq;SOIt^5)!93Hg@)I4iXwf>_|*aBINorN zGEtbPv{_Pt%l&}3&S*_;c1Ax$DY@d&TPl7yc}p5j-Pb#DYxdwwtXd@=qTf7hWlb`Z zS&><(t&lF^`I$-lpOxOkl!@_VFALW(DtgEFyyD4O*FL#B?M(`m*cfq39h9__oz3h0 zYSgqg;|Q|@<_nsY3JlK=c@%LSL_PFr7A4n~%k@95R5_+Z!1solCx^prjcG0$aUrsb zyJnWTTz1`Ltf^)KXo}w6?eR#V`si7!N&@Y~SMzuWtJ8K5?0}_$c&?c63s&qC3Z$7dl-tGObOk8z3ulkn^ME=z~Jm#JJ zG@jiA?)92wPCR8rUyh`(H?ifdU5j9qT54f5 z#43M*@^&-XQK41pcj*{&!_;dc_`+g7AGVN|dE$F5T=~dgEU`!Mt JQWUZK$X|_)i+=zB literal 0 HcmV?d00001