From 40397e96a379d6b8f1ac5332a82bf89e739b2e5f Mon Sep 17 00:00:00 2001 From: bytedream Date: Mon, 7 Aug 2023 17:08:04 +0200 Subject: [PATCH 001/204] Fix arch release pipeline --- .github/scripts/PKGBUILD.binary | 10 ++++++---- .github/scripts/PKGBUILD.source | 10 +++++----- .github/workflows/publish.yml | 8 ++++---- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/.github/scripts/PKGBUILD.binary b/.github/scripts/PKGBUILD.binary index c9cc76e..832f4d0 100644 --- a/.github/scripts/PKGBUILD.binary +++ b/.github/scripts/PKGBUILD.binary @@ -9,6 +9,8 @@ pkgver=$CI_PKG_VERSION pkgrel=1 depends=('ffmpeg') +provides=('crunchy-cli') +conflicts=('crunchy-cli') source=( "crunchy-cli::https://github.com/crunchy-labs/crunchy-cli/releases/download/v${pkgver}/crunchy-cli-v${pkgver}-linux-x86_64" "manpages.zip::https://github.com/crunchy-labs/crunchy-cli/releases/download/v${pkgver}/crunchy-cli-v${pkgver}-manpages.zip" @@ -32,8 +34,8 @@ package() { install -Dm755 crunchy-cli $pkgdir/usr/bin/crunchy-cli install -Dm644 manpages/* -t $pkgdir/usr/share/man/man1 - install -Dm644 completions/crunchy-cli.bash $pkgdir/usr/share/bash-completions/completions/crunchy-cli - install -Dm644 completions/_crunchy-cli $pkgdir/usr/share/zsh/site-functions/_crunchy-cli - install -Dm644 completions/crunchy-cli.fish $pkgdir/usr/share/fish/vendor_completions.d/crunchy-cli.fish - install -Dm644 LICENSE $pkgdir/usr/share/licenses/crunchy-cli/LICENSE + install -Dm644 completions/crunchy-cli.bash -t $pkgdir/usr/share/bash-completions/completions/crunchy-cli + install -Dm644 completions/_crunchy-cli -t $pkgdir/usr/share/zsh/site-functions/_crunchy-cli + install -Dm644 completions/crunchy-cli.fish -t $pkgdir/usr/share/fish/vendor_completions.d/crunchy-cli.fish + install -Dm644 LICENSE -t $pkgdir/usr/share/licenses/crunchy-cli/LICENSE } diff --git a/.github/scripts/PKGBUILD.source b/.github/scripts/PKGBUILD.source index 737a699..beffe74 100644 --- a/.github/scripts/PKGBUILD.source +++ b/.github/scripts/PKGBUILD.source @@ -26,9 +26,9 @@ package() { cd "$srcdir/${pkgname}-$pkgver" install -Dm755 target/release/crunchy-cli $pkgdir/usr/bin/crunchy-cli - install -Dm644 target/release/manpages/* $pkgdir/usr/share/man/man1 - install -Dm644 target/release/completions/crunchy-cli.bash $pkgdir/usr/share/bash-completions/completions/crunchy-cli - install -Dm644 target/release/completions/_crunchy-cli $pkgdir/usr/share/zsh/site-functions/_crunchy-cli - install -Dm644 target/release/completions/crunchy-cli.fish $pkgdir/usr/share/fish/vendor_completions.d/crunchy-cli.fish - install -Dm644 LICENSE $pkgdir/usr/share/licenses/crunchy-cli/LICENSE + install -Dm644 target/release/manpages/* -t $pkgdir/usr/share/man/man1 + install -Dm644 target/release/completions/crunchy-cli.bash -t $pkgdir/usr/share/bash-completions/completions/crunchy-cli + install -Dm644 target/release/completions/_crunchy-cli -t $pkgdir/usr/share/zsh/site-functions/_crunchy-cli + install -Dm644 target/release/completions/crunchy-cli.fish -t $pkgdir/usr/share/fish/vendor_completions.d/crunchy-cli.fish + install -Dm644 LICENSE -t $pkgdir/usr/share/licenses/crunchy-cli/LICENSE } diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 37f4379..ddf4136 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -27,7 +27,7 @@ jobs: run: envsubst '$CI_PKG_VERSION,$CI_SHA_SUM' < .github/scripts/PKGBUILD.source > PKGBUILD - name: Publish crunchy-cli to AUR - uses: KSXGitHub/github-actions-deploy-aur@2.7.0 + uses: KSXGitHub/github-actions-deploy-aur@v2.7.0 with: pkgname: crunchy-cli pkgbuild: ./PKGBUILD @@ -39,7 +39,7 @@ jobs: - name: Generate crunchy-cli-bin sha sums run: | - curl -LO https://github.com/crunchy-labs/crunchy-cli/releases/download/${{ github.ref_name }}/crunchy-cli-${{ github.ref_name }}-x86_64-linux + curl -LO https://github.com/crunchy-labs/crunchy-cli/releases/download/${{ github.ref_name }}/crunchy-cli-${{ github.ref_name }}-linux-x86_64 curl -LO https://github.com/crunchy-labs/crunchy-cli/releases/download/${{ github.ref_name }}/crunchy-cli-${{ github.ref_name }}-completions.zip curl -LO https://github.com/crunchy-labs/crunchy-cli/releases/download/${{ github.ref_name }}/crunchy-cli-${{ github.ref_name }}-manpages.zip curl -LO https://raw.githubusercontent.com/crunchy-labs/crunchy-cli/${{ github.ref_name }}/LICENSE @@ -55,10 +55,10 @@ jobs: CI_MANPAGES_SHA_SUM: ${{ env.CRUNCHY_CLI_BIN_MANPAGES_SHA256 }} CI_COMPLETIONS_SHA_SUM: ${{ env.CRUNCHY_CLI_BIN_COMPLETIONS_SHA256 }} CI_LICENSE_SHA_SUM: ${{ env.CRUNCHY_CLI_BIN_LICENSE_SHA256 }} - run: envsubst '$CI_PKG_VERSION,$CI_SHA_SUM,$CI_COMPLETIONS_SHA_SUM,$CI_MANPAGES_SHA_SUM' < .github/scripts/PKGBUILD.binary > PKGBUILD + run: envsubst '$CI_PKG_VERSION,$CI_SHA_SUM,$CI_COMPLETIONS_SHA_SUM,$CI_MANPAGES_SHA_SUM,$CI_LICENSE_SHA_SUM' < .github/scripts/PKGBUILD.binary > PKGBUILD - name: Publish crunchy-cli-bin to AUR - uses: KSXGitHub/github-actions-deploy-aur@2.7.0 + uses: KSXGitHub/github-actions-deploy-aur@v2.7.0 with: pkgname: crunchy-cli-bin pkgbuild: ./PKGBUILD From b98332eae4096832bbfd5b5c7e7aee962df2493b Mon Sep 17 00:00:00 2001 From: bytedream Date: Mon, 7 Aug 2023 17:47:06 +0200 Subject: [PATCH 002/204] Add aarch64 support for arch release pipeline --- .github/scripts/PKGBUILD.binary | 13 ++++++++++--- .github/workflows/publish.yml | 9 ++++++--- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/.github/scripts/PKGBUILD.binary b/.github/scripts/PKGBUILD.binary index 832f4d0..08a0569 100644 --- a/.github/scripts/PKGBUILD.binary +++ b/.github/scripts/PKGBUILD.binary @@ -1,7 +1,7 @@ # Maintainer: ByteDream pkgname=crunchy-cli-bin pkgdesc="Command-line downloader for Crunchyroll" -arch=('x86_64') +arch=('x86_64', 'aarch64') url="https://github.com/crunchy-labs/crunchy-cli" license=('MIT') @@ -11,14 +11,21 @@ pkgrel=1 depends=('ffmpeg') provides=('crunchy-cli') conflicts=('crunchy-cli') -source=( +source_x86_64=( "crunchy-cli::https://github.com/crunchy-labs/crunchy-cli/releases/download/v${pkgver}/crunchy-cli-v${pkgver}-linux-x86_64" "manpages.zip::https://github.com/crunchy-labs/crunchy-cli/releases/download/v${pkgver}/crunchy-cli-v${pkgver}-manpages.zip" "completions.zip::https://github.com/crunchy-labs/crunchy-cli/releases/download/v${pkgver}/crunchy-cli-v${pkgver}-completions.zip" "LICENSE::https://raw.githubusercontent.com/crunchy-labs/crunchy-cli/v${pkgver}/LICENSE" ) +source_aarch64=( + "crunchy-cli::https://github.com/crunchy-labs/crunchy-cli/releases/download/v${pkgver}/crunchy-cli-v${pkgver}-linux-aarch64" + "manpages.zip::https://github.com/crunchy-labs/crunchy-cli/releases/download/v${pkgver}/crunchy-cli-v${pkgver}-manpages.zip" + "completions.zip::https://github.com/crunchy-labs/crunchy-cli/releases/download/v${pkgver}/crunchy-cli-v${pkgver}-completions.zip" + "LICENSE::https://raw.githubusercontent.com/crunchy-labs/crunchy-cli/v${pkgver}/LICENSE" +) noextract=("manpages.zip" "completions.zip") -sha256sums=('$CI_SHA_SUM' '$CI_MANPAGES_SHA_SUM' '$CI_COMPLETIONS_SHA_SUM' '$CI_LICENSE_SHA_SUM') +sha256sums_x86_64=('$CI_x86_64_SHA_SUM' '$CI_MANPAGES_SHA_SUM' '$CI_COMPLETIONS_SHA_SUM' '$CI_LICENSE_SHA_SUM') +sha256sums_aarch64=('$CI_aarch64_SHA_SUM' '$CI_MANPAGES_SHA_SUM' '$CI_COMPLETIONS_SHA_SUM' '$CI_LICENSE_SHA_SUM') package() { cd "$srcdir" diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index ddf4136..c2857a9 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -40,10 +40,12 @@ jobs: - name: Generate crunchy-cli-bin sha sums run: | curl -LO https://github.com/crunchy-labs/crunchy-cli/releases/download/${{ github.ref_name }}/crunchy-cli-${{ github.ref_name }}-linux-x86_64 + curl -LO https://github.com/crunchy-labs/crunchy-cli/releases/download/${{ github.ref_name }}/crunchy-cli-${{ github.ref_name }}-linux-aarch64 curl -LO https://github.com/crunchy-labs/crunchy-cli/releases/download/${{ github.ref_name }}/crunchy-cli-${{ github.ref_name }}-completions.zip curl -LO https://github.com/crunchy-labs/crunchy-cli/releases/download/${{ github.ref_name }}/crunchy-cli-${{ github.ref_name }}-manpages.zip curl -LO https://raw.githubusercontent.com/crunchy-labs/crunchy-cli/${{ github.ref_name }}/LICENSE - echo "CRUNCHY_CLI_BIN_SHA256=$(sha256sum crunchy-cli-${{ github.ref_name }}-x86_64-linux | cut -f 1 -d ' ')" >> $GITHUB_ENV + echo "CRUNCHY_CLI_BIN_x86_64_SHA256=$(sha256sum crunchy-cli-${{ github.ref_name }}-x86_64-linux | cut -f 1 -d ' ')" >> $GITHUB_ENV + echo "CRUNCHY_CLI_BIN_aarch64_SHA256=$(sha256sum crunchy-cli-${{ github.ref_name }}-aarch64-linux | cut -f 1 -d ' ')" >> $GITHUB_ENV echo "CRUNCHY_CLI_BIN_COMPLETIONS_SHA256=$(sha256sum crunchy-cli-${{ github.ref_name }}-completions.zip | cut -f 1 -d ' ')" >> $GITHUB_ENV echo "CRUNCHY_CLI_BIN_MANPAGES_SHA256=$(sha256sum crunchy-cli-${{ github.ref_name }}-manpages.zip | cut -f 1 -d ' ')" >> $GITHUB_ENV echo "CRUNCHY_CLI_BIN_LICENSE_SHA256=$(sha256sum LICENSE | cut -f 1 -d ' ')" >> $GITHUB_ENV @@ -51,11 +53,12 @@ jobs: - name: Generate crunchy-cli-bin PKGBUILD env: CI_PKG_VERSION: ${{ env.RELEASE_VERSION }} - CI_SHA_SUM: ${{ env.CRUNCHY_CLI_BIN_SHA256 }} + CI_x86_64_SHA_SUM: ${{ env.CRUNCHY_CLI_BIN_x86_64_SHA256 }} + CI_aarch64_SHA_SUM: ${{ env.CRUNCHY_CLI_BIN_aarch64_SHA256 }} CI_MANPAGES_SHA_SUM: ${{ env.CRUNCHY_CLI_BIN_MANPAGES_SHA256 }} CI_COMPLETIONS_SHA_SUM: ${{ env.CRUNCHY_CLI_BIN_COMPLETIONS_SHA256 }} CI_LICENSE_SHA_SUM: ${{ env.CRUNCHY_CLI_BIN_LICENSE_SHA256 }} - run: envsubst '$CI_PKG_VERSION,$CI_SHA_SUM,$CI_COMPLETIONS_SHA_SUM,$CI_MANPAGES_SHA_SUM,$CI_LICENSE_SHA_SUM' < .github/scripts/PKGBUILD.binary > PKGBUILD + run: envsubst '$CI_PKG_VERSION,$CI_x86_64_SHA_SUM,$CI_aarch64_SHA_SUM,$CI_COMPLETIONS_SHA_SUM,$CI_MANPAGES_SHA_SUM,$CI_LICENSE_SHA_SUM' < .github/scripts/PKGBUILD.binary > PKGBUILD - name: Publish crunchy-cli-bin to AUR uses: KSXGitHub/github-actions-deploy-aur@v2.7.0 From 9f9aec1f8a542af14a573933a1a930dd447b84c7 Mon Sep 17 00:00:00 2001 From: bytedream Date: Mon, 7 Aug 2023 17:48:30 +0200 Subject: [PATCH 003/204] Fix cross installation if cache is present --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3cdfd77..e34097d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,7 +33,7 @@ jobs: key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} - name: Install cross - run: cargo install cross + run: cargo install --force cross - name: Build run: cross build --release --all-features --target ${{ matrix.toolchain }} From 800df5ca6c8d339945181eec894a1db831a15fa2 Mon Sep 17 00:00:00 2001 From: bytedream Date: Tue, 8 Aug 2023 11:06:07 +0200 Subject: [PATCH 004/204] (Re-)add scoop install example --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index a8ec76e..967eecf 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,14 @@ Check out the [releases](https://github.com/crunchy-labs/crunchy-cli/releases) t $ nix github:crunchy-labs/crunchy-cli ``` +- [Scoop](https://scoop.sh/) + + For Windows users, we support the [scoop](https://scoop.sh/#/) command-line installer. + ```shell + $ scoop bucket add extras + $ scoop install extras/crunchy-cli + ``` + ### 🛠 Build it yourself Since we do not support every platform and architecture you may have to build the project yourself. From 448b633be853f8eca017c9b158a4c96e9b912044 Mon Sep 17 00:00:00 2001 From: bytedream Date: Tue, 8 Aug 2023 17:33:08 +0200 Subject: [PATCH 005/204] Fix AUR completion and license directory --- .github/scripts/PKGBUILD.binary | 8 ++++---- .github/scripts/PKGBUILD.source | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/scripts/PKGBUILD.binary b/.github/scripts/PKGBUILD.binary index 08a0569..0117723 100644 --- a/.github/scripts/PKGBUILD.binary +++ b/.github/scripts/PKGBUILD.binary @@ -41,8 +41,8 @@ package() { install -Dm755 crunchy-cli $pkgdir/usr/bin/crunchy-cli install -Dm644 manpages/* -t $pkgdir/usr/share/man/man1 - install -Dm644 completions/crunchy-cli.bash -t $pkgdir/usr/share/bash-completions/completions/crunchy-cli - install -Dm644 completions/_crunchy-cli -t $pkgdir/usr/share/zsh/site-functions/_crunchy-cli - install -Dm644 completions/crunchy-cli.fish -t $pkgdir/usr/share/fish/vendor_completions.d/crunchy-cli.fish - install -Dm644 LICENSE -t $pkgdir/usr/share/licenses/crunchy-cli/LICENSE + install -Dm644 completions/crunchy-cli.bash $pkgdir/usr/share/bash-completion/completions/crunchy-cli + install -Dm644 completions/_crunchy-cli $pkgdir/usr/share/zsh/site-functions/_crunchy-cli + install -Dm644 completions/crunchy-cli.fish $pkgdir/usr/share/fish/vendor_completions.d/crunchy-cli.fish + install -Dm644 LICENSE $pkgdir/usr/share/licenses/crunchy-cli/LICENSE } diff --git a/.github/scripts/PKGBUILD.source b/.github/scripts/PKGBUILD.source index beffe74..015efe3 100644 --- a/.github/scripts/PKGBUILD.source +++ b/.github/scripts/PKGBUILD.source @@ -27,8 +27,8 @@ package() { install -Dm755 target/release/crunchy-cli $pkgdir/usr/bin/crunchy-cli install -Dm644 target/release/manpages/* -t $pkgdir/usr/share/man/man1 - install -Dm644 target/release/completions/crunchy-cli.bash -t $pkgdir/usr/share/bash-completions/completions/crunchy-cli - install -Dm644 target/release/completions/_crunchy-cli -t $pkgdir/usr/share/zsh/site-functions/_crunchy-cli - install -Dm644 target/release/completions/crunchy-cli.fish -t $pkgdir/usr/share/fish/vendor_completions.d/crunchy-cli.fish - install -Dm644 LICENSE -t $pkgdir/usr/share/licenses/crunchy-cli/LICENSE + install -Dm644 target/release/completions/crunchy-cli.bash $pkgdir/usr/share/bash-completion/completions/crunchy-cli + install -Dm644 target/release/completions/_crunchy-cli $pkgdir/usr/share/zsh/site-functions/_crunchy-cli + install -Dm644 target/release/completions/crunchy-cli.fish $pkgdir/usr/share/fish/vendor_completions.d/crunchy-cli.fish + install -Dm644 LICENSE $pkgdir/usr/share/licenses/crunchy-cli/LICENSE } From a45833f5a2234ec4750d6b9a7c4c6c17bb534b03 Mon Sep 17 00:00:00 2001 From: bytedream Date: Mon, 14 Aug 2023 00:45:18 +0200 Subject: [PATCH 006/204] Update dependencies and version --- Cargo.lock | 242 +++++++++++++++++++++--------------- Cargo.toml | 4 +- crunchy-cli-core/Cargo.lock | 157 ++++++++--------------- crunchy-cli-core/Cargo.toml | 9 +- crunchy-cli-core/src/lib.rs | 25 ++-- 5 files changed, 216 insertions(+), 221 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e56716b..47b0102 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -30,9 +30,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" +checksum = "86b8f9420f797f2d9e935edf629310eb938a0d839f984e25327f3c7eed22300c" dependencies = [ "memchr", ] @@ -93,9 +93,9 @@ dependencies = [ [[package]] name = "anstyle-wincon" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188" +checksum = "c677ab05e09154296dd37acecd46420c17b9713e8366facafa8fc0885167cf4c" dependencies = [ "anstyle", "windows-sys 0.48.0", @@ -109,9 +109,9 @@ checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854" [[package]] name = "async-trait" -version = "0.1.72" +version = "0.1.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc6dde6e4ed435a4c1ee4e73592f5ba9da2151af10076cc04858746af9352d09" +checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" dependencies = [ "proc-macro2", "quote", @@ -163,9 +163,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.3.3" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" +checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" [[package]] name = "block-padding" @@ -199,9 +199,12 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.79" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "305fe645edc1442a0fa8b6726ba61d422798d37a52e12eaecf4b022ebbb88f01" +dependencies = [ + "libc", +] [[package]] name = "cfg-if" @@ -237,9 +240,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.3.17" +version = "4.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0827b011f6f8ab38590295339817b0d26f344aa4932c3ced71b45b0c54b4a9" +checksum = "c27cdf28c0f604ba3f512b0c9a409f8de8513e4816705deb0498b627e7c3a3fd" dependencies = [ "clap_builder", "clap_derive", @@ -248,9 +251,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.3.17" +version = "4.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9441b403be87be858db6a23edb493e7f694761acdc3343d5a0fcaafd304cbc9e" +checksum = "08a9f1ab5e9f01a9b81f202e8562eb9a10de70abf9eaeac1be465c28b75aa4aa" dependencies = [ "anstream", "anstyle", @@ -321,7 +324,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e859cd57d0710d9e06c381b550c06e76992472a8c6d527aecd2fc673dcc231fb" dependencies = [ "percent-encoding", - "time 0.3.23", + "time 0.3.25", "version_check", ] @@ -338,7 +341,7 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "time 0.3.23", + "time 0.3.25", "url", ] @@ -369,7 +372,7 @@ dependencies = [ [[package]] name = "crunchy-cli" -version = "3.0.0" +version = "3.0.1" dependencies = [ "chrono", "clap", @@ -381,7 +384,7 @@ dependencies = [ [[package]] name = "crunchy-cli-core" -version = "3.0.0" +version = "3.0.1" dependencies = [ "anyhow", "async-trait", @@ -412,9 +415,9 @@ dependencies = [ [[package]] name = "crunchyroll-rs" -version = "0.5.1" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0b33d2464e990dec5d3e6265cc892a88ab89971cfd177b7d7c7d0e9f8cde817" +checksum = "6560e2f721420854d34b94b8bc35b316e3ff6bc83cb7cbf24750ddf55a21d45a" dependencies = [ "aes", "async-trait", @@ -434,14 +437,14 @@ dependencies = [ "serde_urlencoded", "smart-default", "tokio", - "webpki-roots 0.25.0", + "webpki-roots 0.25.2", ] [[package]] name = "crunchyroll-rs-internal" -version = "0.5.1" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cab3e4af975066a3dc3dd0bb50b1a29c4a3cdee5365e8b6559d21aa15d9ace6a" +checksum = "b1398807cd10094f08c1d31423f7979e74c25f772c203d477dfa6ddc4ceb81f2" dependencies = [ "darling", "quote", @@ -505,9 +508,9 @@ dependencies = [ [[package]] name = "dash-mpd" -version = "0.12.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58b55cd4a2bd4b541906e88adbd2242bda9a697517f638c844fa47fb56fe2f17" +checksum = "5d0c74b03285fe95649f588140b6009dc10bc4f747bd774818ed8e9cc6b5cbb6" dependencies = [ "base64", "base64-serde", @@ -525,6 +528,15 @@ dependencies = [ "xattr", ] +[[package]] +name = "deranged" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7684a49fb1af197853ef7b2ee694bc1f5b4179556f1e5710e1760c5db6f5e929" +dependencies = [ + "serde", +] + [[package]] name = "derive_setters" version = "0.1.6" @@ -570,9 +582,9 @@ dependencies = [ [[package]] name = "either" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "encode_unicode" @@ -590,10 +602,16 @@ dependencies = [ ] [[package]] -name = "errno" -version = "0.3.1" +name = "equivalent" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f" dependencies = [ "errno-dragonfly", "libc", @@ -753,7 +771,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap", + "indexmap 1.9.3", "slab", "tokio", "tokio-util", @@ -766,6 +784,12 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +[[package]] +name = "hashbrown" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" + [[package]] name = "heck" version = "0.4.1" @@ -814,9 +838,9 @@ checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" [[package]] name = "httpdate" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" @@ -835,7 +859,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2", + "socket2 0.4.9", "tokio", "tower-service", "tracing", @@ -936,15 +960,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", - "hashbrown", + "hashbrown 0.12.3", + "serde", +] + +[[package]] +name = "indexmap" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +dependencies = [ + "equivalent", + "hashbrown 0.14.0", "serde", ] [[package]] name = "indicatif" -version = "0.17.5" +version = "0.17.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ff8cc23a7393a397ed1d7f56e6365cba772aba9f9912ab968b03043c395d057" +checksum = "0b297dc40733f23a0e52728a58fa9489a5b7638a324932de16b41adc3ef80730" dependencies = [ "console", "instant", @@ -1027,15 +1062,15 @@ checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" [[package]] name = "linux-raw-sys" -version = "0.4.3" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0" +checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503" [[package]] name = "log" -version = "0.4.19" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "m3u8-rs" @@ -1184,9 +1219,9 @@ checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] name = "openssl" -version = "0.10.55" +version = "0.10.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "345df152bc43501c5eb9e4654ff05f794effb78d4efe3d53abc158baddc0703d" +checksum = "729b745ad4a5575dd06a3e1af1414bd330ee561c01b3899eb584baeaa8def17e" dependencies = [ "bitflags 1.3.2", "cfg-if", @@ -1216,18 +1251,18 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-src" -version = "111.26.0+1.1.1u" +version = "111.27.0+1.1.1v" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efc62c9f12b22b8f5208c23a7200a442b2e5999f8bdf80233852122b5a4f6f37" +checksum = "06e8f197c82d7511c5b014030c9b1efeda40d7d5f99d23b4ceed3524a5e63f02" dependencies = [ "cc", ] [[package]] name = "openssl-sys" -version = "0.9.90" +version = "0.9.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374533b0e45f3a7ced10fcaeccca020e66656bc03dac384f852e4e5a7a8104a6" +checksum = "866b5f16f90776b9bb8dc1e1802ac6f0513de3a7a7465867bfbc563dc737faac" dependencies = [ "cc", "libc", @@ -1250,9 +1285,9 @@ checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" [[package]] name = "pin-project-lite" -version = "0.2.10" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c40d25201921e5ff0c862a505c6557ea88568a4e3ace775ab55e93f2f4f9d57" +checksum = "12cc1b0bf1727a77a54b6654e7b5f1af8604923edc8b81885f8ec92f9e3f0a05" [[package]] name = "pin-utils" @@ -1268,9 +1303,9 @@ checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" [[package]] name = "portable-atomic" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edc55135a600d700580e406b4de0d59cb9ad25e344a3a091a97ded2622ec4ec6" +checksum = "f32154ba0af3a075eefa1eda8bb414ee928f62303a54ea85b8d6638ff1a6ee9e" [[package]] name = "proc-macro2" @@ -1299,9 +1334,9 @@ dependencies = [ [[package]] name = "quick-xml" -version = "0.29.0" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81b9228215d82c7b61490fec1de287136b5de6f5700f6e58ea9ad61a7964ca51" +checksum = "eff6510e86862b57b210fd8cbe8ed3f0d7d600b9c2863cd4549a2e033c66e956" dependencies = [ "memchr", "serde", @@ -1309,9 +1344,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.31" +version = "1.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fe8a65d69dd0808184ebb5f836ab526bb259db23c657efa38711b1072ee47f0" +checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965" dependencies = [ "proc-macro2", ] @@ -1347,9 +1382,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.9.1" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575" +checksum = "81bc1d4caf89fac26a70747fe603c130093b53c773888797a6329091246d651a" dependencies = [ "aho-corasick", "memchr", @@ -1359,9 +1394,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.3.3" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39354c10dd07468c2e73926b23bb9c2caca74c5501e38a35da70406f1d923310" +checksum = "fed1ceff11a1dddaee50c9dc8e4938bd106e9d89ae372f192311e7da498e3b69" dependencies = [ "aho-corasick", "memchr", @@ -1448,11 +1483,11 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustix" -version = "0.38.4" +version = "0.38.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a962918ea88d644592894bc6dc55acc6c0956488adcebbfb6e273506b7fd6e5" +checksum = "19ed4fa021d81c8392ce04db050a3da9a60299050b7ae1cf482d862b54a7218f" dependencies = [ - "bitflags 2.3.3", + "bitflags 2.4.0", "errno", "libc", "linux-raw-sys", @@ -1461,9 +1496,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.5" +version = "0.21.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79ea77c539259495ce8ca47f53e66ae0330a8819f67e23ac96ca02f50e7b7d36" +checksum = "1d1feddffcfcc0b33f5c6ce9a29e341e4cd59c3f78e7ee45f4a40c038b1d6cbb" dependencies = [ "log", "ring", @@ -1482,9 +1517,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.101.1" +version = "0.101.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15f36a6828982f422756984e47912a7a51dcbc2a197aa791158f8ca61cd8204e" +checksum = "261e9e0888cba427c3316e6322805653c9425240b6fd96cee7cb671ab70ab8d0" dependencies = [ "ring", "untrusted", @@ -1527,9 +1562,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.9.1" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc758eb7bffce5b308734e9b0c1468893cae9ff70ebf13e7090be8dcbcc83a8" +checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" dependencies = [ "bitflags 1.3.2", "core-foundation", @@ -1540,9 +1575,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.0" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f51d0c0d83bec45f16480d0ce0058397a69e48fcdc52d1dc8855fb68acbd31a7" +checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" dependencies = [ "core-foundation-sys", "libc", @@ -1550,18 +1585,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.174" +version = "1.0.183" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b88756493a5bd5e5395d53baa70b194b05764ab85b59e43e4b8f4e1192fa9b1" +checksum = "32ac8da02677876d532745a130fc9d8e6edfa81a269b107c5b00829b91d8eb3c" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.174" +version = "1.0.183" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e5c3a298c7f978e53536f95a63bdc4c4a64550582f31a0359a9afda6aede62e" +checksum = "aafe972d60b0b9bee71a91b92fee2d4fb3c9d7e8f6b179aa99f27203d99a4816" dependencies = [ "proc-macro2", "quote", @@ -1570,9 +1605,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.103" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d03b412469450d4404fe8499a268edd7f8b79fecb074b0d812ad64ca21f4031b" +checksum = "076066c5f1078eac5b722a31827a8832fe108bed65dfa75e233c89f8206e976c" dependencies = [ "itoa", "ryu", @@ -1602,25 +1637,26 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.1.0" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21e47d95bc83ed33b2ecf84f4187ad1ab9685d18ff28db000c99deac8ce180e3" +checksum = "1402f54f9a3b9e2efe71c1cea24e648acce55887983553eeb858cf3115acfd49" dependencies = [ "base64", "chrono", "hex", - "indexmap", + "indexmap 1.9.3", + "indexmap 2.0.0", "serde", "serde_json", "serde_with_macros", - "time 0.3.23", + "time 0.3.25", ] [[package]] name = "serde_with_macros" -version = "3.1.0" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea3cee93715c2e266b9338b7544da68a9f24e227722ba482bd1c024367c77c65" +checksum = "9197f1ad0e3c173a0222d3c4404fb04c3afe87e962bcb327af73e8301fa203c7" dependencies = [ "darling", "proc-macro2", @@ -1670,6 +1706,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "socket2" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2538b18701741680e0322a2302176d3253a35388e2e62f172f64f4f16605f877" +dependencies = [ + "libc", + "windows-sys 0.48.0", +] + [[package]] name = "spin" version = "0.5.2" @@ -1690,9 +1736,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" -version = "2.0.27" +version = "2.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b60f673f44a8255b9c8c657daf66a596d435f2da81a555b06dc644d080ba45e0" +checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567" dependencies = [ "proc-macro2", "quote", @@ -1711,9 +1757,9 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.7.0" +version = "3.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5486094ee78b2e5038a6382ed7645bc084dc2ec433426ca4c3cb61e2007b8998" +checksum = "dc02fddf48964c42031a0b3fe0428320ecf3a73c401040fc0096f97794310651" dependencies = [ "cfg-if", "fastrand", @@ -1755,10 +1801,11 @@ dependencies = [ [[package]] name = "time" -version = "0.3.23" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59e399c068f43a5d116fedaf73b203fa4f9c519f17e2b34f63221d3792f81446" +checksum = "b0fdd63d58b18d663fbdf70e049f00a22c8e42be082203be7f26589213cd75ea" dependencies = [ + "deranged", "itoa", "serde", "time-core", @@ -1773,9 +1820,9 @@ checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" [[package]] name = "time-macros" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96ba15a897f3c86766b757e5ac7221554c6750054d74d5b28844fce5fb36a6c4" +checksum = "eb71511c991639bb078fd5bf97757e03914361c48100d52878b8e52b46fb92cd" dependencies = [ "time-core", ] @@ -1797,18 +1844,17 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.29.1" +version = "1.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" +checksum = "40de3a2ba249dcb097e01be5e67a5ff53cf250397715a071a81543e8a832a920" dependencies = [ - "autocfg", "backtrace", "bytes", "libc", "mio", "num_cpus", "pin-project-lite", - "socket2", + "socket2 0.5.3", "tokio-macros", "windows-sys 0.48.0", ] @@ -2088,9 +2134,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.25.0" +version = "0.25.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a4ac452058d835c2b7ff6d74f0ad9f40e172bb1ce661b1444f397eeb1d19e6d" +checksum = "14247bb57be4f377dfb94c72830b8ce8fc6beac03cf4bf7b9732eadd414123fc" [[package]] name = "winapi" @@ -2266,9 +2312,9 @@ dependencies = [ [[package]] name = "xattr" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea263437ca03c1522846a4ddafbca2542d0ad5ed9b784909d4b27b76f62bc34a" +checksum = "f4686009f71ff3e5c4dbcf1a282d0a44db3f021ba69350cd42086b3e5f1c6985" dependencies = [ "libc", ] diff --git a/Cargo.toml b/Cargo.toml index d1c1868..eb15425 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "crunchy-cli" authors = ["Crunchy Labs Maintainers"] -version = "3.0.0" +version = "3.0.1" edition = "2021" license = "MIT" @@ -12,7 +12,7 @@ openssl = ["crunchy-cli-core/openssl"] openssl-static = ["crunchy-cli-core/openssl-static"] [dependencies] -tokio = { version = "1.29", features = ["macros", "rt-multi-thread", "time"], default-features = false } +tokio = { version = "1.31", features = ["macros", "rt-multi-thread", "time"], default-features = false } crunchy-cli-core = { path = "./crunchy-cli-core" } diff --git a/crunchy-cli-core/Cargo.lock b/crunchy-cli-core/Cargo.lock index b26b645..5ba4511 100644 --- a/crunchy-cli-core/Cargo.lock +++ b/crunchy-cli-core/Cargo.lock @@ -30,9 +30,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41" +checksum = "86b8f9420f797f2d9e935edf629310eb938a0d839f984e25327f3c7eed22300c" dependencies = [ "memchr", ] @@ -93,9 +93,9 @@ dependencies = [ [[package]] name = "anstyle-wincon" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188" +checksum = "c677ab05e09154296dd37acecd46420c17b9713e8366facafa8fc0885167cf4c" dependencies = [ "anstyle", "windows-sys 0.48.0", @@ -109,9 +109,9 @@ checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854" [[package]] name = "async-trait" -version = "0.1.72" +version = "0.1.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc6dde6e4ed435a4c1ee4e73592f5ba9da2151af10076cc04858746af9352d09" +checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" dependencies = [ "proc-macro2", "quote", @@ -163,9 +163,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.3.3" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" +checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" [[package]] name = "block-padding" @@ -240,9 +240,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.3.19" +version = "4.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd304a20bff958a57f04c4e96a2e7594cc4490a0e809cbd48bb6437edaa452d" +checksum = "c27cdf28c0f604ba3f512b0c9a409f8de8513e4816705deb0498b627e7c3a3fd" dependencies = [ "clap_builder", "clap_derive", @@ -251,9 +251,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.3.19" +version = "4.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01c6a3f08f1fe5662a35cfe393aec09c4df95f60ee93b7556505260f75eee9e1" +checksum = "08a9f1ab5e9f01a9b81f202e8562eb9a10de70abf9eaeac1be465c28b75aa4aa" dependencies = [ "anstream", "anstyle", @@ -326,16 +326,6 @@ dependencies = [ "url", ] -[[package]] -name = "core-foundation" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "core-foundation-sys" version = "0.8.4" @@ -353,7 +343,7 @@ dependencies = [ [[package]] name = "crunchy-cli-core" -version = "3.0.0" +version = "3.0.1" dependencies = [ "anyhow", "async-trait", @@ -368,7 +358,7 @@ dependencies = [ "indicatif", "lazy_static", "log", - "native-tls 0.2.11 (git+https://github.com/crunchy-labs/rust-not-so-native-tls.git?rev=570100d)", + "native-tls", "num_cpus", "regex", "reqwest", @@ -384,9 +374,9 @@ dependencies = [ [[package]] name = "crunchyroll-rs" -version = "0.5.1" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0b33d2464e990dec5d3e6265cc892a88ab89971cfd177b7d7c7d0e9f8cde817" +checksum = "6560e2f721420854d34b94b8bc35b316e3ff6bc83cb7cbf24750ddf55a21d45a" dependencies = [ "aes", "async-trait", @@ -406,14 +396,14 @@ dependencies = [ "serde_urlencoded", "smart-default", "tokio", - "webpki-roots 0.25.1", + "webpki-roots 0.25.2", ] [[package]] name = "crunchyroll-rs-internal" -version = "0.5.1" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cab3e4af975066a3dc3dd0bb50b1a29c4a3cdee5365e8b6559d21aa15d9ace6a" +checksum = "b1398807cd10094f08c1d31423f7979e74c25f772c203d477dfa6ddc4ceb81f2" dependencies = [ "darling", "quote", @@ -477,9 +467,9 @@ dependencies = [ [[package]] name = "dash-mpd" -version = "0.12.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58b55cd4a2bd4b541906e88adbd2242bda9a697517f638c844fa47fb56fe2f17" +checksum = "5d0c74b03285fe95649f588140b6009dc10bc4f747bd774818ed8e9cc6b5cbb6" dependencies = [ "base64", "base64-serde", @@ -807,9 +797,9 @@ checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" [[package]] name = "httpdate" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" @@ -828,7 +818,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2", + "socket2 0.4.9", "tokio", "tower-service", "tracing", @@ -857,7 +847,7 @@ checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" dependencies = [ "bytes", "hyper", - "native-tls 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "native-tls", "tokio", "tokio-native-tls", ] @@ -1037,9 +1027,9 @@ checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503" [[package]] name = "log" -version = "0.4.19" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "m3u8-rs" @@ -1095,24 +1085,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "native-tls" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" -dependencies = [ - "lazy_static", - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - [[package]] name = "native-tls" version = "0.2.11" @@ -1254,9 +1226,9 @@ checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" [[package]] name = "pin-project-lite" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c516611246607d0c04186886dbb3a754368ef82c79e9827a802c6d836dd111c" +checksum = "12cc1b0bf1727a77a54b6654e7b5f1af8604923edc8b81885f8ec92f9e3f0a05" [[package]] name = "pin-utils" @@ -1303,9 +1275,9 @@ dependencies = [ [[package]] name = "quick-xml" -version = "0.29.0" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81b9228215d82c7b61490fec1de287136b5de6f5700f6e58ea9ad61a7964ca51" +checksum = "eff6510e86862b57b210fd8cbe8ed3f0d7d600b9c2863cd4549a2e033c66e956" dependencies = [ "memchr", "serde", @@ -1401,7 +1373,7 @@ dependencies = [ "js-sys", "log", "mime", - "native-tls 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "native-tls", "once_cell", "percent-encoding", "pin-project-lite", @@ -1446,11 +1418,11 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustix" -version = "0.38.7" +version = "0.38.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "172891ebdceb05aa0005f533a6cbfca599ddd7d966f6f5d4d9b2e70478e70399" +checksum = "19ed4fa021d81c8392ce04db050a3da9a60299050b7ae1cf482d862b54a7218f" dependencies = [ - "bitflags 2.3.3", + "bitflags 2.4.0", "errno", "libc", "linux-raw-sys", @@ -1480,9 +1452,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.101.2" +version = "0.101.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "513722fd73ad80a71f72b61009ea1b584bcfa1483ca93949c8f290298837fa59" +checksum = "261e9e0888cba427c3316e6322805653c9425240b6fd96cee7cb671ab70ab8d0" dependencies = [ "ring", "untrusted", @@ -1504,15 +1476,6 @@ dependencies = [ "regex", ] -[[package]] -name = "schannel" -version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" -dependencies = [ - "windows-sys 0.48.0", -] - [[package]] name = "sct" version = "0.7.0" @@ -1523,29 +1486,6 @@ dependencies = [ "untrusted", ] -[[package]] -name = "security-framework" -version = "2.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "serde" version = "1.0.183" @@ -1669,6 +1609,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "socket2" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2538b18701741680e0322a2302176d3253a35388e2e62f172f64f4f16605f877" +dependencies = [ + "libc", + "windows-sys 0.48.0", +] + [[package]] name = "spin" version = "0.5.2" @@ -1797,18 +1747,17 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.29.1" +version = "1.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" +checksum = "40de3a2ba249dcb097e01be5e67a5ff53cf250397715a071a81543e8a832a920" dependencies = [ - "autocfg", "backtrace", "bytes", "libc", "mio", "num_cpus", "pin-project-lite", - "socket2", + "socket2 0.5.3", "tokio-macros", "windows-sys 0.48.0", ] @@ -1830,7 +1779,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" dependencies = [ - "native-tls 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "native-tls", "tokio", ] @@ -2088,9 +2037,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.25.1" +version = "0.25.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9c6eda1c830a36f361e7721c87fd79ea84293b54f8c48c959f85ec636f0f196" +checksum = "14247bb57be4f377dfb94c72830b8ce8fc6beac03cf4bf7b9732eadd414123fc" [[package]] name = "winapi" diff --git a/crunchy-cli-core/Cargo.toml b/crunchy-cli-core/Cargo.toml index c9ebb25..5f60474 100644 --- a/crunchy-cli-core/Cargo.toml +++ b/crunchy-cli-core/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "crunchy-cli-core" authors = ["Crunchy Labs Maintainers"] -version = "3.0.0" +version = "3.0.1" edition = "2021" license = "MIT" @@ -14,7 +14,7 @@ anyhow = "1.0" async-trait = "0.1" clap = { version = "4.3", features = ["derive", "string"] } chrono = "0.4" -crunchyroll-rs = { version = "0.5.1", features = ["dash-stream"] } +crunchyroll-rs = { version = "0.6.1", features = ["dash-stream"] } ctrlc = "3.4" dialoguer = { version = "0.10", default-features = false } dirs = "5.0" @@ -32,7 +32,7 @@ serde_json = "1.0" serde_plain = "1.0" shlex = "1.1" tempfile = "3.7" -tokio = { version = "1.29", features = ["macros", "rt-multi-thread", "time"] } +tokio = { version = "1.31", features = ["macros", "rt-multi-thread", "time"] } sys-locale = "0.3" # fork of the `native-tls` crate which uses openssl as backend on every platform. this is done as `reqwest` only supports @@ -41,3 +41,6 @@ native-tls = { git = "https://github.com/crunchy-labs/rust-not-so-native-tls.git [build-dependencies] chrono = "0.4" + +[patch.crates-io] +native-tls = { git = "https://github.com/crunchy-labs/rust-not-so-native-tls.git", rev = "570100d" } diff --git a/crunchy-cli-core/src/lib.rs b/crunchy-cli-core/src/lib.rs index 9132204..793e946 100644 --- a/crunchy-cli-core/src/lib.rs +++ b/crunchy-cli-core/src/lib.rs @@ -5,7 +5,7 @@ use anyhow::bail; use anyhow::Result; use clap::{Parser, Subcommand}; use crunchyroll_rs::crunchyroll::CrunchyrollBuilder; -use crunchyroll_rs::error::CrunchyrollError; +use crunchyroll_rs::error::Error; use crunchyroll_rs::{Crunchyroll, Locale}; use log::{debug, error, warn, LevelFilter}; use reqwest::Proxy; @@ -205,20 +205,17 @@ async fn pre_check_executor(executor: &mut impl Execute) { } async fn execute_executor(executor: impl Execute, ctx: Context) { - if let Err(err) = executor.execute(ctx).await { - error!("a unexpected error occurred: {}", err); - - if let Some(crunchy_error) = err.downcast_ref::() { - let message = match crunchy_error { - CrunchyrollError::Internal(i) => &i.message, - CrunchyrollError::Request(r) => &r.message, - CrunchyrollError::Decode(d) => &d.message, - CrunchyrollError::Authentication(a) => &a.message, - CrunchyrollError::Input(i) => &i.message, - }; - if message.contains("content.get_video_streams_v2.cms_service_error") { - error!("You've probably hit a rate limit. Try again later, generally after 10-20 minutes the rate limit is over and you can continue to use the cli") + if let Err(mut err) = executor.execute(ctx).await { + if let Some(crunchy_error) = err.downcast_mut::() { + if let Error::Block { message, .. } = crunchy_error { + *message = "Triggered Cloudflare bot protection. Try again later or use a VPN or proxy to spoof your location".to_string() + } else if let Error::Request { message, .. } = crunchy_error { + *message = "You've probably hit a rate limit. Try again later, generally after 10-20 minutes the rate limit is over and you can continue to use the cli".to_string() } + + error!("An error occurred: {}", crunchy_error) + } else { + error!("An error occurred: {}", err) } std::process::exit(1) From 6da292f0135a5fad6da0ff99632aeb78d48c0b1f Mon Sep 17 00:00:00 2001 From: bytedream Date: Mon, 14 Aug 2023 15:46:14 +0200 Subject: [PATCH 007/204] Do not test PKGBUILD on arch release pipeline --- .github/workflows/publish.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index c2857a9..80cb5bb 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -35,7 +35,6 @@ jobs: commit_email: ${{ secrets.AUR_EMAIL }} ssh_private_key: ${{ secrets.AUR_SSH_PRIVATE_KEY }} commit_message: Update to version {{ env.RELEASE_VERSION }} - test: true - name: Generate crunchy-cli-bin sha sums run: | @@ -69,4 +68,3 @@ jobs: commit_email: ${{ secrets.AUR_EMAIL }} ssh_private_key: ${{ secrets.AUR_SSH_PRIVATE_KEY }} commit_message: Update to version {{ env.RELEASE_VERSION }} - test: true From f45bb19cd79f766ed3664e20cbc017f4d40bccfd Mon Sep 17 00:00:00 2001 From: bytedream Date: Wed, 16 Aug 2023 16:55:16 +0200 Subject: [PATCH 008/204] Remove duplicated native-tls entry (#235) --- Cargo.lock | 18 +++--------------- crunchy-cli-core/Cargo.lock | 1 - crunchy-cli-core/Cargo.toml | 10 ++++------ 3 files changed, 7 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 47b0102..a9119d3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -399,7 +399,6 @@ dependencies = [ "indicatif", "lazy_static", "log", - "native-tls 0.2.11 (git+https://github.com/crunchy-labs/rust-not-so-native-tls.git?rev=570100d)", "num_cpus", "regex", "reqwest", @@ -888,7 +887,7 @@ checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" dependencies = [ "bytes", "hyper", - "native-tls 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "native-tls", "tokio", "tokio-native-tls", ] @@ -1144,17 +1143,6 @@ dependencies = [ "tempfile", ] -[[package]] -name = "native-tls" -version = "0.2.11" -source = "git+https://github.com/crunchy-labs/rust-not-so-native-tls.git?rev=570100d#570100d3391bd9aab7a390cfef0d1a28e8efe200" -dependencies = [ - "log", - "openssl", - "openssl-probe", - "openssl-sys", -] - [[package]] name = "nix" version = "0.26.2" @@ -1432,7 +1420,7 @@ dependencies = [ "js-sys", "log", "mime", - "native-tls 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "native-tls", "once_cell", "percent-encoding", "pin-project-lite", @@ -1876,7 +1864,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" dependencies = [ - "native-tls 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "native-tls", "tokio", ] diff --git a/crunchy-cli-core/Cargo.lock b/crunchy-cli-core/Cargo.lock index 5ba4511..0a14466 100644 --- a/crunchy-cli-core/Cargo.lock +++ b/crunchy-cli-core/Cargo.lock @@ -358,7 +358,6 @@ dependencies = [ "indicatif", "lazy_static", "log", - "native-tls", "num_cpus", "regex", "reqwest", diff --git a/crunchy-cli-core/Cargo.toml b/crunchy-cli-core/Cargo.toml index 5f60474..5787f39 100644 --- a/crunchy-cli-core/Cargo.toml +++ b/crunchy-cli-core/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" license = "MIT" [features] -openssl = ["dep:native-tls", "reqwest/native-tls-alpn"] -openssl-static = ["dep:native-tls", "native-tls?/vendored", "reqwest/native-tls-alpn", "reqwest/native-tls-vendored"] +openssl = ["reqwest/native-tls-alpn"] +openssl-static = ["reqwest/native-tls-alpn", "reqwest/native-tls-vendored"] [dependencies] anyhow = "1.0" @@ -35,12 +35,10 @@ tempfile = "3.7" tokio = { version = "1.31", features = ["macros", "rt-multi-thread", "time"] } sys-locale = "0.3" -# fork of the `native-tls` crate which uses openssl as backend on every platform. this is done as `reqwest` only supports -# `rustls` and `native-tls` as tls backend -native-tls = { git = "https://github.com/crunchy-labs/rust-not-so-native-tls.git", rev = "570100d", features = ["alpn"], optional = true } - [build-dependencies] chrono = "0.4" [patch.crates-io] +# fork of the `native-tls` crate which uses openssl as backend on every platform. this is done as `reqwest` only supports +# `rustls` and `native-tls` as tls backend native-tls = { git = "https://github.com/crunchy-labs/rust-not-so-native-tls.git", rev = "570100d" } From 31fe1460f19b0b928c40e9cbba5ad5ea6c033278 Mon Sep 17 00:00:00 2001 From: bytedream Date: Wed, 16 Aug 2023 16:57:35 +0200 Subject: [PATCH 009/204] Replace native-tls its internal fork in the root crate --- Cargo.lock | 51 +-------------------------------------------------- Cargo.toml | 5 +++++ 2 files changed, 6 insertions(+), 50 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a9119d3..d307294 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -345,16 +345,6 @@ dependencies = [ "url", ] -[[package]] -name = "core-foundation" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "core-foundation-sys" version = "0.8.4" @@ -1128,19 +1118,12 @@ dependencies = [ [[package]] name = "native-tls" version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +source = "git+https://github.com/crunchy-labs/rust-not-so-native-tls.git?rev=570100d#570100d3391bd9aab7a390cfef0d1a28e8efe200" dependencies = [ - "lazy_static", - "libc", "log", "openssl", "openssl-probe", "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", ] [[package]] @@ -1529,15 +1512,6 @@ dependencies = [ "regex", ] -[[package]] -name = "schannel" -version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" -dependencies = [ - "windows-sys 0.48.0", -] - [[package]] name = "sct" version = "0.7.0" @@ -1548,29 +1522,6 @@ dependencies = [ "untrusted", ] -[[package]] -name = "security-framework" -version = "2.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "serde" version = "1.0.183" diff --git a/Cargo.toml b/Cargo.toml index eb15425..114de49 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,11 @@ clap_mangen = "0.2" crunchy-cli-core = { path = "./crunchy-cli-core" } +[patch.crates-io] +# fork of the `native-tls` crate which uses openssl as backend on every platform. this is done as `reqwest` only supports +# `rustls` and `native-tls` as tls backend +native-tls = { git = "https://github.com/crunchy-labs/rust-not-so-native-tls.git", rev = "570100d" } + [profile.release] strip = true opt-level = "z" From d295a57f842f0fdeb348884c5b3e3d1dabc350f4 Mon Sep 17 00:00:00 2001 From: bytedream Date: Wed, 16 Aug 2023 17:26:03 +0200 Subject: [PATCH 010/204] Use dynamically linked openssl when running with nix --- flake.lock | 6 +++--- flake.nix | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 91bbf3d..90e07bf 100644 --- a/flake.lock +++ b/flake.lock @@ -2,11 +2,11 @@ "nodes": { "nixpkgs": { "locked": { - "lastModified": 1685866647, - "narHash": "sha256-4jKguNHY/edLYImB+uL8jKPL/vpfOvMmSlLAGfxSrnY=", + "lastModified": 1692128808, + "narHash": "sha256-Di1Zm/P042NuwThMiZNrtmaAjd4Tm2qBOKHX7xUOfMk=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "a53a3bec10deef6e1cc1caba5bc60f53b959b1e8", + "rev": "4ed9856be002a730234a1a1ed9dcd9dd10cbdb40", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 4a48dec..2c297f7 100644 --- a/flake.nix +++ b/flake.nix @@ -30,6 +30,9 @@ allowBuiltinFetchGit = true; }; + buildNoDefaultFeatures = true; + buildFeatures = [ "openssl" ]; + nativeBuildInputs = [ pkgs.pkg-config ] ++ pkgs.lib.optionals pkgs.stdenv.isDarwin [ From 92ed4bd87d0cb137e48398134eeaa5e4a0b3eb99 Mon Sep 17 00:00:00 2001 From: bytedream Date: Wed, 16 Aug 2023 19:08:13 +0200 Subject: [PATCH 011/204] Revert "Replace native-tls its internal fork in the root crate" This reverts commit 31fe1460f19b0b928c40e9cbba5ad5ea6c033278. --- Cargo.lock | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++- Cargo.toml | 5 ----- 2 files changed, 50 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d307294..a9119d3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -345,6 +345,16 @@ dependencies = [ "url", ] +[[package]] +name = "core-foundation" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.8.4" @@ -1118,12 +1128,19 @@ dependencies = [ [[package]] name = "native-tls" version = "0.2.11" -source = "git+https://github.com/crunchy-labs/rust-not-so-native-tls.git?rev=570100d#570100d3391bd9aab7a390cfef0d1a28e8efe200" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" dependencies = [ + "lazy_static", + "libc", "log", "openssl", "openssl-probe", "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", ] [[package]] @@ -1512,6 +1529,15 @@ dependencies = [ "regex", ] +[[package]] +name = "schannel" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" +dependencies = [ + "windows-sys 0.48.0", +] + [[package]] name = "sct" version = "0.7.0" @@ -1522,6 +1548,29 @@ dependencies = [ "untrusted", ] +[[package]] +name = "security-framework" +version = "2.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "serde" version = "1.0.183" diff --git a/Cargo.toml b/Cargo.toml index 114de49..eb15425 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,11 +24,6 @@ clap_mangen = "0.2" crunchy-cli-core = { path = "./crunchy-cli-core" } -[patch.crates-io] -# fork of the `native-tls` crate which uses openssl as backend on every platform. this is done as `reqwest` only supports -# `rustls` and `native-tls` as tls backend -native-tls = { git = "https://github.com/crunchy-labs/rust-not-so-native-tls.git", rev = "570100d" } - [profile.release] strip = true opt-level = "z" From 6a6b981979bfd62d46eae40ef81831bd3b5c2741 Mon Sep 17 00:00:00 2001 From: StepBroBD Date: Wed, 16 Aug 2023 14:29:39 -0400 Subject: [PATCH 012/204] Fix nix flake overlays (#236) --- flake.lock | 6 +++--- flake.nix | 23 +++++++++-------------- 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/flake.lock b/flake.lock index 90e07bf..b9c63db 100644 --- a/flake.lock +++ b/flake.lock @@ -41,11 +41,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1685518550, - "narHash": "sha256-o2d0KcvaXzTrPRIo0kOLV0/QXHhDQ5DTi+OxcjO8xqY=", + "lastModified": 1689068808, + "narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=", "owner": "numtide", "repo": "flake-utils", - "rev": "a1720a10a6cfe8234c0e93907ffe81be440f4cef", + "rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 2c297f7..2ca105a 100644 --- a/flake.nix +++ b/flake.nix @@ -4,17 +4,12 @@ utils.url = "flake:flake-utils"; }; - outputs = { self, nixpkgs, utils, ... }: utils.lib.eachSystem [ - "aarch64-darwin" - "x86_64-darwin" - "aarch64-linux" - "x86_64-linux" - ] + outputs = { self, nixpkgs, utils }: utils.lib.eachDefaultSystem (system: let - pkgs = nixpkgs.legacyPackages.${system}; - # enable musl on Linux makes the build time 100x slower - # since it will trigger a toolchain rebuild + # enable musl on Linux will trigger a toolchain rebuild + # making the build very slow + pkgs = import nixpkgs { inherit system; }; # if nixpkgs.legacyPackages.${system}.stdenv.hostPlatform.isLinux # then nixpkgs.legacyPackages.${system}.pkgsMusl # else nixpkgs.legacyPackages.${system}; @@ -49,10 +44,6 @@ { packages.default = crunchy-cli; - overlays.default = _: prev: { - crunchy-cli = prev.crunchy-cli.override { }; - }; - devShells.default = pkgs.mkShell { packages = with pkgs; [ cargo @@ -77,5 +68,9 @@ formatter = pkgs.nixpkgs-fmt; } - ); + ) // { + overlays.default = final: prev: { + inherit (self.packages.${final.system}) crunchy-cli; + }; + }; } From 70b41b4dd5881d66208e1ec2ac8bcfc5ef236e03 Mon Sep 17 00:00:00 2001 From: bytedream Date: Thu, 17 Aug 2023 11:53:57 +0200 Subject: [PATCH 013/204] Show an error message if no url was given --- crunchy-cli-core/src/archive/command.rs | 1 + crunchy-cli-core/src/download/command.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/crunchy-cli-core/src/archive/command.rs b/crunchy-cli-core/src/archive/command.rs index 10133f2..b7cd8b7 100644 --- a/crunchy-cli-core/src/archive/command.rs +++ b/crunchy-cli-core/src/archive/command.rs @@ -99,6 +99,7 @@ pub struct Archive { pub(crate) yes: bool, #[arg(help = "Crunchyroll series url(s)")] + #[arg(required = true)] pub(crate) urls: Vec, } diff --git a/crunchy-cli-core/src/download/command.rs b/crunchy-cli-core/src/download/command.rs index 1ce731d..df4e616 100644 --- a/crunchy-cli-core/src/download/command.rs +++ b/crunchy-cli-core/src/download/command.rs @@ -81,6 +81,7 @@ pub struct Download { pub(crate) force_hardsub: bool, #[arg(help = "Url(s) to Crunchyroll episodes or series")] + #[arg(required = true)] pub(crate) urls: Vec, } From 596fcc2342bdc8feec64c0fdc0da99afe6e983c2 Mon Sep 17 00:00:00 2001 From: bytedream Date: Thu, 17 Aug 2023 11:54:00 +0200 Subject: [PATCH 014/204] Fix relative episode number exceeding actual episode count (#238) --- crunchy-cli-core/src/archive/filter.rs | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/crunchy-cli-core/src/archive/filter.rs b/crunchy-cli-core/src/archive/filter.rs index 38fed32..851b4b5 100644 --- a/crunchy-cli-core/src/archive/filter.rs +++ b/crunchy-cli-core/src/archive/filter.rs @@ -18,7 +18,7 @@ pub(crate) struct ArchiveFilter { url_filter: UrlFilter, archive: Archive, interactive_input: bool, - season_episode_count: HashMap>, + season_episode_count: HashMap>, season_subtitles_missing: Vec, season_sorting: Vec, visited: Visited, @@ -229,7 +229,7 @@ impl Filter for ArchiveFilter { if Format::has_relative_episodes_fmt(&self.archive.output) { for episode in episodes.iter() { self.season_episode_count - .entry(episode.season_number) + .entry(episode.season_id.clone()) .or_insert(vec![]) .push(episode.id.clone()) } @@ -300,20 +300,16 @@ impl Filter for ArchiveFilter { } let relative_episode_number = if Format::has_relative_episodes_fmt(&self.archive.output) { - if self - .season_episode_count - .get(&episode.season_number) - .is_none() - { + if self.season_episode_count.get(&episode.season_id).is_none() { let season_episodes = episode.season().await?.episodes().await?; self.season_episode_count.insert( - episode.season_number, + episode.season_id.clone(), season_episodes.into_iter().map(|e| e.id).collect(), ); } let relative_episode_number = self .season_episode_count - .get(&episode.season_number) + .get(&episode.season_id) .unwrap() .iter() .position(|id| id == &episode.id) From 2f57b075591b2906992f32b451dbec90f30a0e69 Mon Sep 17 00:00:00 2001 From: bytedream Date: Thu, 17 Aug 2023 11:58:11 +0200 Subject: [PATCH 015/204] Change ci cargo cache key --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e34097d..bb2f797 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,7 +30,7 @@ jobs: ~/.cargo/registry/cache/ ~/.cargo/git/db/ target/ - key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} + key: ${{ matrix.toolchain }}-cargo-${{ hashFiles('**/Cargo.lock') }} - name: Install cross run: cargo install --force cross @@ -74,7 +74,7 @@ jobs: ~/.cargo/registry/cache/ ~/.cargo/git/db/ target/ - key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} + key: x86_64-apple-darwin-cargo-${{ hashFiles('**/Cargo.lock') }} - name: Install toolchain uses: dtolnay/rust-toolchain@stable @@ -107,7 +107,7 @@ jobs: ~/.cargo/registry/cache/ ~/.cargo/git/db/ target/ - key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} + key: x86_64-pc-windows-gnu-cargo-${{ hashFiles('**/Cargo.lock') }} - name: Install system dependencies uses: msys2/setup-msys2@v2 From a80f6e5df484a14008fd46d787cef773531ab84a Mon Sep 17 00:00:00 2001 From: bytedream Date: Fri, 25 Aug 2023 14:24:12 +0200 Subject: [PATCH 016/204] Use workspace instead of separate Cargo.lock file --- Cargo.lock | 293 ++--- Cargo.toml | 8 + crunchy-cli-core/Cargo.lock | 2222 ----------------------------------- crunchy-cli-core/Cargo.toml | 5 - 4 files changed, 115 insertions(+), 2413 deletions(-) delete mode 100644 crunchy-cli-core/Cargo.lock diff --git a/Cargo.lock b/Cargo.lock index a9119d3..b07d41b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.20.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" dependencies = [ "gimli", ] @@ -30,9 +30,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b8f9420f797f2d9e935edf629310eb938a0d839f984e25327f3c7eed22300c" +checksum = "6748e8def348ed4d14996fa801f4122cd763fff530258cdc03f64b25f89d3a5a" dependencies = [ "memchr", ] @@ -54,24 +54,23 @@ dependencies = [ [[package]] name = "anstream" -version = "0.3.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163" +checksum = "b1f58811cfac344940f1a400b6e6231ce35171f614f26439e80f8c1465c5cc0c" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", - "is-terminal", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd" +checksum = "15c4c2c83f81532e5845a733998b6971faca23490340a418e9b72a3ec9de12ea" [[package]] name = "anstyle-parse" @@ -93,9 +92,9 @@ dependencies = [ [[package]] name = "anstyle-wincon" -version = "1.0.2" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c677ab05e09154296dd37acecd46420c17b9713e8366facafa8fc0885167cf4c" +checksum = "58f54d10c6dfa51283a066ceab3ec1ab78d13fae00aa49243a45e4571fb79dfd" dependencies = [ "anstyle", "windows-sys 0.48.0", @@ -103,9 +102,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.72" +version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854" +checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" [[package]] name = "async-trait" @@ -126,9 +125,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.68" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" dependencies = [ "addr2line", "cc", @@ -199,9 +198,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.82" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "305fe645edc1442a0fa8b6726ba61d422798d37a52e12eaecf4b022ebbb88f01" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" dependencies = [ "libc", ] @@ -240,9 +239,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.3.21" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c27cdf28c0f604ba3f512b0c9a409f8de8513e4816705deb0498b627e7c3a3fd" +checksum = "1d5f1946157a96594eb2d2c10eb7ad9a2b27518cb3000209dec700c35df9197d" dependencies = [ "clap_builder", "clap_derive", @@ -251,9 +250,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.3.21" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08a9f1ab5e9f01a9b81f202e8562eb9a10de70abf9eaeac1be465c28b75aa4aa" +checksum = "78116e32a042dd73c2901f0dc30790d20ff3447f3e3472fad359e8c3d282bcd6" dependencies = [ "anstream", "anstyle", @@ -263,18 +262,18 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.3.2" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fc443334c81a804575546c5a8a79b4913b50e28d69232903604cada1de817ce" +checksum = "586a385f7ef2f8b4d86bddaa0c094794e7ccbfe5ffef1f434fe928143fc783a5" dependencies = [ "clap", ] [[package]] name = "clap_derive" -version = "4.3.12" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54a9bb5758fc5dfe728d1019941681eccaf0cf8a4189b692a0ee2f2ecf90a050" +checksum = "c9fd1a5729c4548118d7d70ff234a44868d00489a4b6597b0b020918a0e91a1a" dependencies = [ "heck", "proc-macro2", @@ -284,15 +283,15 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" +checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961" [[package]] name = "clap_mangen" -version = "0.2.12" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f2e32b579dae093c2424a8b7e2bea09c89da01e1ce5065eb2f0a6f1cc15cc1f" +checksum = "cf8e5f34d85d9e0bbe2491d100a7a7c1007bb2467b518080bfe311e8947197a9" dependencies = [ "clap", "roff", @@ -324,7 +323,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e859cd57d0710d9e06c381b550c06e76992472a8c6d527aecd2fc673dcc231fb" dependencies = [ "percent-encoding", - "time 0.3.25", + "time 0.3.27", "version_check", ] @@ -341,20 +340,10 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "time 0.3.25", + "time 0.3.27", "url", ] -[[package]] -name = "core-foundation" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "core-foundation-sys" version = "0.8.4" @@ -436,7 +425,7 @@ dependencies = [ "serde_urlencoded", "smart-default", "tokio", - "webpki-roots 0.25.2", + "webpki-roots", ] [[package]] @@ -507,9 +496,9 @@ dependencies = [ [[package]] name = "dash-mpd" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d0c74b03285fe95649f588140b6009dc10bc4f747bd774818ed8e9cc6b5cbb6" +checksum = "b18de4d072c5be455129422f6a69eb17c032467750d857820cb0c9a92e86a4ed" dependencies = [ "base64", "base64-serde", @@ -529,9 +518,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7684a49fb1af197853ef7b2ee694bc1f5b4179556f1e5710e1760c5db6f5e929" +checksum = "f2696e8a945f658fd14dc3b87242e6b80cd0f36ff04ea560fa39082368847946" dependencies = [ "serde", ] @@ -593,9 +582,9 @@ checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" [[package]] name = "encoding_rs" -version = "0.8.32" +version = "0.8.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" +checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" dependencies = [ "cfg-if", ] @@ -754,15 +743,15 @@ dependencies = [ [[package]] name = "gimli" -version = "0.27.3" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" +checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" [[package]] name = "h2" -version = "0.3.20" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97ec8491ebaf99c8eaa73058b045fe58073cd6be7f596ac993ced0b0a0c01049" +checksum = "91fc23aa11be92976ef4729127f1a74adf36d8436f7816b185d18df956790833" dependencies = [ "bytes", "fnv", @@ -1012,17 +1001,6 @@ version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" -[[package]] -name = "is-terminal" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" -dependencies = [ - "hermit-abi", - "rustix", - "windows-sys 0.48.0", -] - [[package]] name = "iso8601" version = "0.6.1" @@ -1128,19 +1106,12 @@ dependencies = [ [[package]] name = "native-tls" version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +source = "git+https://github.com/crunchy-labs/rust-not-so-native-tls.git?rev=570100d#570100d3391bd9aab7a390cfef0d1a28e8efe200" dependencies = [ - "lazy_static", - "libc", "log", "openssl", "openssl-probe", "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", ] [[package]] @@ -1192,9 +1163,9 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] name = "object" -version = "0.31.1" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" +checksum = "77ac5bbd07aea88c60a577a1ce218075ffd59208b2d7ca97adf9bfc5aeb21ebe" dependencies = [ "memchr", ] @@ -1332,9 +1303,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.32" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ "proc-macro2", ] @@ -1399,9 +1370,9 @@ checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" [[package]] name = "reqwest" -version = "0.11.18" +version = "0.11.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55" +checksum = "3e9ad3fe7488d7e34558a2033d45a0c90b72d97b4f80705666fea71472e2e6a1" dependencies = [ "base64", "bytes", @@ -1438,7 +1409,7 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "webpki-roots 0.22.6", + "webpki-roots", "winreg", ] @@ -1505,9 +1476,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.101.3" +version = "0.101.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "261e9e0888cba427c3316e6322805653c9425240b6fd96cee7cb671ab70ab8d0" +checksum = "7d93931baf2d282fff8d3a532bbfd7653f734643161b87e3e01e59a04439bf0d" dependencies = [ "ring", "untrusted", @@ -1529,15 +1500,6 @@ dependencies = [ "regex", ] -[[package]] -name = "schannel" -version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" -dependencies = [ - "windows-sys 0.48.0", -] - [[package]] name = "sct" version = "0.7.0" @@ -1548,43 +1510,20 @@ dependencies = [ "untrusted", ] -[[package]] -name = "security-framework" -version = "2.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "serde" -version = "1.0.183" +version = "1.0.186" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32ac8da02677876d532745a130fc9d8e6edfa81a269b107c5b00829b91d8eb3c" +checksum = "9f5db24220c009de9bd45e69fb2938f4b6d2df856aa9304ce377b3180f83b7c1" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.183" +version = "1.0.186" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aafe972d60b0b9bee71a91b92fee2d4fb3c9d7e8f6b179aa99f27203d99a4816" +checksum = "5ad697f7e0b65af4983a4ce8f56ed5b357e8d3c36651bf6a7e13639c17b8e670" dependencies = [ "proc-macro2", "quote", @@ -1593,9 +1532,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.104" +version = "1.0.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "076066c5f1078eac5b722a31827a8832fe108bed65dfa75e233c89f8206e976c" +checksum = "693151e1ac27563d6dbcec9dee9fbd5da8539b20fa14ad3752b2e6d363ace360" dependencies = [ "itoa", "ryu", @@ -1625,9 +1564,9 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.2.0" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1402f54f9a3b9e2efe71c1cea24e648acce55887983553eeb858cf3115acfd49" +checksum = "1ca3b16a3d82c4088f343b7480a93550b3eabe1a358569c2dfe38bbcead07237" dependencies = [ "base64", "chrono", @@ -1637,14 +1576,14 @@ dependencies = [ "serde", "serde_json", "serde_with_macros", - "time 0.3.25", + "time 0.3.27", ] [[package]] name = "serde_with_macros" -version = "3.2.0" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9197f1ad0e3c173a0222d3c4404fb04c3afe87e962bcb327af73e8301fa203c7" +checksum = "2e6be15c453eb305019bfa438b1593c731f36a289a7853f7707ee29e870b3b3c" dependencies = [ "darling", "proc-macro2", @@ -1666,9 +1605,9 @@ checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" [[package]] name = "slab" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" dependencies = [ "autocfg", ] @@ -1724,9 +1663,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" -version = "2.0.28" +version = "2.0.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567" +checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a" dependencies = [ "proc-macro2", "quote", @@ -1745,9 +1684,9 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.7.1" +version = "3.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc02fddf48964c42031a0b3fe0428320ecf3a73c401040fc0096f97794310651" +checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" dependencies = [ "cfg-if", "fastrand", @@ -1758,18 +1697,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.44" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "611040a08a0439f8248d1990b111c95baa9c704c805fa1f62104b39655fd7f90" +checksum = "97a802ec30afc17eee47b2855fc72e0c4cd62be9b4efe6591edde0ec5bd68d8f" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.44" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96" +checksum = "6bb623b56e39ab7dcd4b1b98bb6c8f8d907ed255b18de254088016b27a8ee19b" dependencies = [ "proc-macro2", "quote", @@ -1789,9 +1728,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.25" +version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fdd63d58b18d663fbdf70e049f00a22c8e42be082203be7f26589213cd75ea" +checksum = "0bb39ee79a6d8de55f48f2293a830e040392f1c5f16e336bdd1788cd0aadce07" dependencies = [ "deranged", "itoa", @@ -1808,9 +1747,9 @@ checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" [[package]] name = "time-macros" -version = "0.2.11" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb71511c991639bb078fd5bf97757e03914361c48100d52878b8e52b46fb92cd" +checksum = "733d258752e9303d392b94b75230d07b0b9c489350c69b851fc6c065fde3e8f9" dependencies = [ "time-core", ] @@ -1832,9 +1771,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.31.0" +version = "1.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40de3a2ba249dcb097e01be5e67a5ff53cf250397715a071a81543e8a832a920" +checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9" dependencies = [ "backtrace", "bytes", @@ -2101,25 +2040,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "webpki" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "webpki-roots" -version = "0.22.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87" -dependencies = [ - "webpki", -] - [[package]] name = "webpki-roots" version = "0.25.2" @@ -2154,7 +2074,7 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" dependencies = [ - "windows-targets 0.48.1", + "windows-targets 0.48.5", ] [[package]] @@ -2172,7 +2092,7 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets 0.48.1", + "windows-targets 0.48.5", ] [[package]] @@ -2192,17 +2112,17 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.48.1" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", ] [[package]] @@ -2213,9 +2133,9 @@ checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_msvc" @@ -2225,9 +2145,9 @@ checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" [[package]] name = "windows_aarch64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_i686_gnu" @@ -2237,9 +2157,9 @@ checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" [[package]] name = "windows_i686_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_msvc" @@ -2249,9 +2169,9 @@ checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" [[package]] name = "windows_i686_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_x86_64_gnu" @@ -2261,9 +2181,9 @@ checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" [[package]] name = "windows_x86_64_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnullvm" @@ -2273,9 +2193,9 @@ checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_msvc" @@ -2285,17 +2205,18 @@ checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" [[package]] name = "windows_x86_64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "winreg" -version = "0.10.1" +version = "0.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" dependencies = [ - "winapi", + "cfg-if", + "windows-sys 0.48.0", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index eb15425..6aa5ce0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,14 @@ clap_mangen = "0.2" crunchy-cli-core = { path = "./crunchy-cli-core" } +[workspace] +members = ["crunchy-cli-core"] + +[patch.crates-io] +# fork of the `native-tls` crate which uses openssl as backend on every platform. this is done as `reqwest` only supports +# `rustls` and `native-tls` as tls backend +native-tls = { git = "https://github.com/crunchy-labs/rust-not-so-native-tls.git", rev = "570100d" } + [profile.release] strip = true opt-level = "z" diff --git a/crunchy-cli-core/Cargo.lock b/crunchy-cli-core/Cargo.lock deleted file mode 100644 index 0a14466..0000000 --- a/crunchy-cli-core/Cargo.lock +++ /dev/null @@ -1,2222 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "aes" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2" -dependencies = [ - "cfg-if", - "cipher", - "cpufeatures", -] - -[[package]] -name = "aho-corasick" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b8f9420f797f2d9e935edf629310eb938a0d839f984e25327f3c7eed22300c" -dependencies = [ - "memchr", -] - -[[package]] -name = "android-tzdata" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" - -[[package]] -name = "android_system_properties" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" -dependencies = [ - "libc", -] - -[[package]] -name = "anstream" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163" -dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "is-terminal", - "utf8parse", -] - -[[package]] -name = "anstyle" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd" - -[[package]] -name = "anstyle-parse" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" -dependencies = [ - "utf8parse", -] - -[[package]] -name = "anstyle-query" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" -dependencies = [ - "windows-sys 0.48.0", -] - -[[package]] -name = "anstyle-wincon" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c677ab05e09154296dd37acecd46420c17b9713e8366facafa8fc0885167cf4c" -dependencies = [ - "anstyle", - "windows-sys 0.48.0", -] - -[[package]] -name = "anyhow" -version = "1.0.72" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854" - -[[package]] -name = "async-trait" -version = "0.1.73" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] -name = "backtrace" -version = "0.3.68" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - -[[package]] -name = "base64" -version = "0.21.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" - -[[package]] -name = "base64-serde" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba368df5de76a5bea49aaf0cf1b39ccfbbef176924d1ba5db3e4135216cbe3c7" -dependencies = [ - "base64", - "serde", -] - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" - -[[package]] -name = "block-padding" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" -dependencies = [ - "generic-array", -] - -[[package]] -name = "bumpalo" -version = "3.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" - -[[package]] -name = "bytes" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" - -[[package]] -name = "cbc" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6" -dependencies = [ - "cipher", -] - -[[package]] -name = "cc" -version = "1.0.82" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "305fe645edc1442a0fa8b6726ba61d422798d37a52e12eaecf4b022ebbb88f01" -dependencies = [ - "libc", -] - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "chrono" -version = "0.4.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5" -dependencies = [ - "android-tzdata", - "iana-time-zone", - "js-sys", - "num-traits", - "serde", - "time 0.1.45", - "wasm-bindgen", - "winapi", -] - -[[package]] -name = "cipher" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" -dependencies = [ - "crypto-common", - "inout", -] - -[[package]] -name = "clap" -version = "4.3.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c27cdf28c0f604ba3f512b0c9a409f8de8513e4816705deb0498b627e7c3a3fd" -dependencies = [ - "clap_builder", - "clap_derive", - "once_cell", -] - -[[package]] -name = "clap_builder" -version = "4.3.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08a9f1ab5e9f01a9b81f202e8562eb9a10de70abf9eaeac1be465c28b75aa4aa" -dependencies = [ - "anstream", - "anstyle", - "clap_lex", - "strsim", -] - -[[package]] -name = "clap_derive" -version = "4.3.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54a9bb5758fc5dfe728d1019941681eccaf0cf8a4189b692a0ee2f2ecf90a050" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "clap_lex" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b" - -[[package]] -name = "colorchoice" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" - -[[package]] -name = "console" -version = "0.15.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8" -dependencies = [ - "encode_unicode", - "lazy_static", - "libc", - "unicode-width", - "windows-sys 0.45.0", -] - -[[package]] -name = "cookie" -version = "0.16.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e859cd57d0710d9e06c381b550c06e76992472a8c6d527aecd2fc673dcc231fb" -dependencies = [ - "percent-encoding", - "time 0.3.25", - "version_check", -] - -[[package]] -name = "cookie_store" -version = "0.16.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d606d0fba62e13cf04db20536c05cb7f13673c161cb47a47a82b9b9e7d3f1daa" -dependencies = [ - "cookie", - "idna 0.2.3", - "log", - "publicsuffix", - "serde", - "serde_derive", - "serde_json", - "time 0.3.25", - "url", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" - -[[package]] -name = "cpufeatures" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" -dependencies = [ - "libc", -] - -[[package]] -name = "crunchy-cli-core" -version = "3.0.1" -dependencies = [ - "anyhow", - "async-trait", - "chrono", - "clap", - "crunchyroll-rs", - "ctrlc", - "derive_setters", - "dialoguer", - "dirs", - "fs2", - "indicatif", - "lazy_static", - "log", - "num_cpus", - "regex", - "reqwest", - "sanitize-filename", - "serde", - "serde_json", - "serde_plain", - "shlex", - "sys-locale", - "tempfile", - "tokio", -] - -[[package]] -name = "crunchyroll-rs" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6560e2f721420854d34b94b8bc35b316e3ff6bc83cb7cbf24750ddf55a21d45a" -dependencies = [ - "aes", - "async-trait", - "cbc", - "chrono", - "crunchyroll-rs-internal", - "dash-mpd", - "futures-util", - "http", - "lazy_static", - "m3u8-rs", - "regex", - "reqwest", - "rustls", - "serde", - "serde_json", - "serde_urlencoded", - "smart-default", - "tokio", - "webpki-roots 0.25.2", -] - -[[package]] -name = "crunchyroll-rs-internal" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1398807cd10094f08c1d31423f7979e74c25f772c203d477dfa6ddc4ceb81f2" -dependencies = [ - "darling", - "quote", - "syn", -] - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "ctrlc" -version = "3.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a011bbe2c35ce9c1f143b7af6f94f29a167beb4cd1d29e6740ce836f723120e" -dependencies = [ - "nix", - "windows-sys 0.48.0", -] - -[[package]] -name = "darling" -version = "0.20.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" -dependencies = [ - "darling_core", - "darling_macro", -] - -[[package]] -name = "darling_core" -version = "0.20.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn", -] - -[[package]] -name = "darling_macro" -version = "0.20.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" -dependencies = [ - "darling_core", - "quote", - "syn", -] - -[[package]] -name = "dash-mpd" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d0c74b03285fe95649f588140b6009dc10bc4f747bd774818ed8e9cc6b5cbb6" -dependencies = [ - "base64", - "base64-serde", - "chrono", - "fs-err", - "iso8601", - "log", - "num-traits", - "quick-xml", - "regex", - "serde", - "serde_with", - "thiserror", - "tokio", - "xattr", -] - -[[package]] -name = "deranged" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7684a49fb1af197853ef7b2ee694bc1f5b4179556f1e5710e1760c5db6f5e929" -dependencies = [ - "serde", -] - -[[package]] -name = "derive_setters" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e8ef033054e131169b8f0f9a7af8f5533a9436fadf3c500ed547f730f07090d" -dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "dialoguer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59c6f2989294b9a498d3ad5491a79c6deb604617378e1cdc4bfc1c1361fe2f87" -dependencies = [ - "console", - "shell-words", -] - -[[package]] -name = "dirs" -version = "5.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" -dependencies = [ - "dirs-sys", -] - -[[package]] -name = "dirs-sys" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" -dependencies = [ - "libc", - "option-ext", - "redox_users", - "windows-sys 0.48.0", -] - -[[package]] -name = "either" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" - -[[package]] -name = "encode_unicode" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" - -[[package]] -name = "encoding_rs" -version = "0.8.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "equivalent" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" - -[[package]] -name = "errno" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f" -dependencies = [ - "errno-dragonfly", - "libc", - "windows-sys 0.48.0", -] - -[[package]] -name = "errno-dragonfly" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" -dependencies = [ - "cc", - "libc", -] - -[[package]] -name = "fastrand" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - -[[package]] -name = "form_urlencoded" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "fs-err" -version = "2.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0845fa252299212f0389d64ba26f34fa32cfe41588355f21ed507c59a0f64541" - -[[package]] -name = "fs2" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "futures-channel" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" -dependencies = [ - "futures-core", -] - -[[package]] -name = "futures-core" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" - -[[package]] -name = "futures-macro" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "futures-sink" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" - -[[package]] -name = "futures-task" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" - -[[package]] -name = "futures-util" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" -dependencies = [ - "futures-core", - "futures-macro", - "futures-task", - "pin-project-lite", - "pin-utils", - "slab", -] - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "getrandom" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.11.0+wasi-snapshot-preview1", -] - -[[package]] -name = "gimli" -version = "0.27.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" - -[[package]] -name = "h2" -version = "0.3.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97ec8491ebaf99c8eaa73058b045fe58073cd6be7f596ac993ced0b0a0c01049" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http", - "indexmap 1.9.3", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - -[[package]] -name = "hashbrown" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" - -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - -[[package]] -name = "hermit-abi" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "http" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http-body" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" -dependencies = [ - "bytes", - "http", - "pin-project-lite", -] - -[[package]] -name = "httparse" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" - -[[package]] -name = "httpdate" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" - -[[package]] -name = "hyper" -version = "0.14.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" -dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "socket2 0.4.9", - "tokio", - "tower-service", - "tracing", - "want", -] - -[[package]] -name = "hyper-rustls" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d78e1e73ec14cf7375674f74d7dde185c8206fd9dea6fb6295e8a98098aaa97" -dependencies = [ - "futures-util", - "http", - "hyper", - "rustls", - "tokio", - "tokio-rustls", -] - -[[package]] -name = "hyper-tls" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" -dependencies = [ - "bytes", - "hyper", - "native-tls", - "tokio", - "tokio-native-tls", -] - -[[package]] -name = "iana-time-zone" -version = "0.1.57" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "wasm-bindgen", - "windows", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" -dependencies = [ - "cc", -] - -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - -[[package]] -name = "idna" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" -dependencies = [ - "matches", - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "idna" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "idna" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", - "serde", -] - -[[package]] -name = "indexmap" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" -dependencies = [ - "equivalent", - "hashbrown 0.14.0", - "serde", -] - -[[package]] -name = "indicatif" -version = "0.17.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b297dc40733f23a0e52728a58fa9489a5b7638a324932de16b41adc3ef80730" -dependencies = [ - "console", - "instant", - "number_prefix", - "portable-atomic", - "unicode-width", -] - -[[package]] -name = "inout" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" -dependencies = [ - "block-padding", - "generic-array", -] - -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "ipnet" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" - -[[package]] -name = "is-terminal" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" -dependencies = [ - "hermit-abi", - "rustix", - "windows-sys 0.48.0", -] - -[[package]] -name = "iso8601" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "924e5d73ea28f59011fec52a0d12185d496a9b075d360657aed2a5707f701153" -dependencies = [ - "nom", -] - -[[package]] -name = "itoa" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" - -[[package]] -name = "js-sys" -version = "0.3.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "libc" -version = "0.2.147" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" - -[[package]] -name = "linux-raw-sys" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503" - -[[package]] -name = "log" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" - -[[package]] -name = "m3u8-rs" -version = "5.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d39af8845edca961e3286dcbafeb9e6407d3df6a616ef086847162d46f438d75" -dependencies = [ - "chrono", - "nom", -] - -[[package]] -name = "matches" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" - -[[package]] -name = "memchr" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" - -[[package]] -name = "mime" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" - -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - -[[package]] -name = "miniz_oxide" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" -dependencies = [ - "adler", -] - -[[package]] -name = "mio" -version = "0.8.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" -dependencies = [ - "libc", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.48.0", -] - -[[package]] -name = "native-tls" -version = "0.2.11" -source = "git+https://github.com/crunchy-labs/rust-not-so-native-tls.git?rev=570100d#570100d3391bd9aab7a390cfef0d1a28e8efe200" -dependencies = [ - "log", - "openssl", - "openssl-probe", - "openssl-sys", -] - -[[package]] -name = "nix" -version = "0.26.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" -dependencies = [ - "bitflags 1.3.2", - "cfg-if", - "libc", - "static_assertions", -] - -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - -[[package]] -name = "num-traits" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" -dependencies = [ - "autocfg", -] - -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "number_prefix" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" - -[[package]] -name = "object" -version = "0.31.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" -dependencies = [ - "memchr", -] - -[[package]] -name = "once_cell" -version = "1.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" - -[[package]] -name = "openssl" -version = "0.10.56" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "729b745ad4a5575dd06a3e1af1414bd330ee561c01b3899eb584baeaa8def17e" -dependencies = [ - "bitflags 1.3.2", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "openssl-probe" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" - -[[package]] -name = "openssl-src" -version = "111.27.0+1.1.1v" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06e8f197c82d7511c5b014030c9b1efeda40d7d5f99d23b4ceed3524a5e63f02" -dependencies = [ - "cc", -] - -[[package]] -name = "openssl-sys" -version = "0.9.91" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "866b5f16f90776b9bb8dc1e1802ac6f0513de3a7a7465867bfbc563dc737faac" -dependencies = [ - "cc", - "libc", - "openssl-src", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "option-ext" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" - -[[package]] -name = "percent-encoding" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" - -[[package]] -name = "pin-project-lite" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12cc1b0bf1727a77a54b6654e7b5f1af8604923edc8b81885f8ec92f9e3f0a05" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "pkg-config" -version = "0.3.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" - -[[package]] -name = "portable-atomic" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f32154ba0af3a075eefa1eda8bb414ee928f62303a54ea85b8d6638ff1a6ee9e" - -[[package]] -name = "proc-macro2" -version = "1.0.66" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "psl-types" -version = "2.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33cb294fe86a74cbcf50d4445b37da762029549ebeea341421c7c70370f86cac" - -[[package]] -name = "publicsuffix" -version = "2.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96a8c1bda5ae1af7f99a2962e49df150414a43d62404644d98dd5c3a93d07457" -dependencies = [ - "idna 0.3.0", - "psl-types", -] - -[[package]] -name = "quick-xml" -version = "0.30.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eff6510e86862b57b210fd8cbe8ed3f0d7d600b9c2863cd4549a2e033c66e956" -dependencies = [ - "memchr", - "serde", -] - -[[package]] -name = "quote" -version = "1.0.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "redox_syscall" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_syscall" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_users" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" -dependencies = [ - "getrandom", - "redox_syscall 0.2.16", - "thiserror", -] - -[[package]] -name = "regex" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81bc1d4caf89fac26a70747fe603c130093b53c773888797a6329091246d651a" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed1ceff11a1dddaee50c9dc8e4938bd106e9d89ae372f192311e7da498e3b69" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" - -[[package]] -name = "reqwest" -version = "0.11.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55" -dependencies = [ - "base64", - "bytes", - "cookie", - "cookie_store", - "encoding_rs", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "hyper", - "hyper-rustls", - "hyper-tls", - "ipnet", - "js-sys", - "log", - "mime", - "native-tls", - "once_cell", - "percent-encoding", - "pin-project-lite", - "rustls", - "rustls-pemfile", - "serde", - "serde_json", - "serde_urlencoded", - "tokio", - "tokio-native-tls", - "tokio-rustls", - "tokio-socks", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "webpki-roots 0.22.6", - "winreg", -] - -[[package]] -name = "ring" -version = "0.16.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" -dependencies = [ - "cc", - "libc", - "once_cell", - "spin", - "untrusted", - "web-sys", - "winapi", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" - -[[package]] -name = "rustix" -version = "0.38.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ed4fa021d81c8392ce04db050a3da9a60299050b7ae1cf482d862b54a7218f" -dependencies = [ - "bitflags 2.4.0", - "errno", - "libc", - "linux-raw-sys", - "windows-sys 0.48.0", -] - -[[package]] -name = "rustls" -version = "0.21.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d1feddffcfcc0b33f5c6ce9a29e341e4cd59c3f78e7ee45f4a40c038b1d6cbb" -dependencies = [ - "log", - "ring", - "rustls-webpki", - "sct", -] - -[[package]] -name = "rustls-pemfile" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" -dependencies = [ - "base64", -] - -[[package]] -name = "rustls-webpki" -version = "0.101.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "261e9e0888cba427c3316e6322805653c9425240b6fd96cee7cb671ab70ab8d0" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "ryu" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" - -[[package]] -name = "sanitize-filename" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ed72fbaf78e6f2d41744923916966c4fbe3d7c74e3037a8ee482f1115572603" -dependencies = [ - "lazy_static", - "regex", -] - -[[package]] -name = "sct" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "serde" -version = "1.0.183" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32ac8da02677876d532745a130fc9d8e6edfa81a269b107c5b00829b91d8eb3c" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.183" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aafe972d60b0b9bee71a91b92fee2d4fb3c9d7e8f6b179aa99f27203d99a4816" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_json" -version = "1.0.104" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "076066c5f1078eac5b722a31827a8832fe108bed65dfa75e233c89f8206e976c" -dependencies = [ - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "serde_plain" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6018081315db179d0ce57b1fe4b62a12a0028c9cf9bbef868c9cf477b3c34ae" -dependencies = [ - "serde", -] - -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "serde_with" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1402f54f9a3b9e2efe71c1cea24e648acce55887983553eeb858cf3115acfd49" -dependencies = [ - "base64", - "chrono", - "hex", - "indexmap 1.9.3", - "indexmap 2.0.0", - "serde", - "serde_json", - "serde_with_macros", - "time 0.3.25", -] - -[[package]] -name = "serde_with_macros" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9197f1ad0e3c173a0222d3c4404fb04c3afe87e962bcb327af73e8301fa203c7" -dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "shell-words" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" - -[[package]] -name = "shlex" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" - -[[package]] -name = "slab" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" -dependencies = [ - "autocfg", -] - -[[package]] -name = "smart-default" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eb01866308440fc64d6c44d9e86c5cc17adfe33c4d6eed55da9145044d0ffc1" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "socket2" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "socket2" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2538b18701741680e0322a2302176d3253a35388e2e62f172f64f4f16605f877" -dependencies = [ - "libc", - "windows-sys 0.48.0", -] - -[[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - -[[package]] -name = "syn" -version = "2.0.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "sys-locale" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea0b9eefabb91675082b41eb94c3ecd91af7656caee3fb4961a07c0ec8c7ca6f" -dependencies = [ - "libc", - "windows-sys 0.45.0", -] - -[[package]] -name = "tempfile" -version = "3.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc02fddf48964c42031a0b3fe0428320ecf3a73c401040fc0096f97794310651" -dependencies = [ - "cfg-if", - "fastrand", - "redox_syscall 0.3.5", - "rustix", - "windows-sys 0.48.0", -] - -[[package]] -name = "thiserror" -version = "1.0.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "611040a08a0439f8248d1990b111c95baa9c704c805fa1f62104b39655fd7f90" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "time" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" -dependencies = [ - "libc", - "wasi 0.10.0+wasi-snapshot-preview1", - "winapi", -] - -[[package]] -name = "time" -version = "0.3.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fdd63d58b18d663fbdf70e049f00a22c8e42be082203be7f26589213cd75ea" -dependencies = [ - "deranged", - "itoa", - "serde", - "time-core", - "time-macros", -] - -[[package]] -name = "time-core" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" - -[[package]] -name = "time-macros" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb71511c991639bb078fd5bf97757e03914361c48100d52878b8e52b46fb92cd" -dependencies = [ - "time-core", -] - -[[package]] -name = "tinyvec" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - -[[package]] -name = "tokio" -version = "1.31.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40de3a2ba249dcb097e01be5e67a5ff53cf250397715a071a81543e8a832a920" -dependencies = [ - "backtrace", - "bytes", - "libc", - "mio", - "num_cpus", - "pin-project-lite", - "socket2 0.5.3", - "tokio-macros", - "windows-sys 0.48.0", -] - -[[package]] -name = "tokio-macros" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tokio-native-tls" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" -dependencies = [ - "native-tls", - "tokio", -] - -[[package]] -name = "tokio-rustls" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" -dependencies = [ - "rustls", - "tokio", -] - -[[package]] -name = "tokio-socks" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51165dfa029d2a65969413a6cc96f354b86b464498702f174a4efa13608fd8c0" -dependencies = [ - "either", - "futures-util", - "thiserror", - "tokio", -] - -[[package]] -name = "tokio-util" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", - "tokio", - "tracing", -] - -[[package]] -name = "tower-service" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" - -[[package]] -name = "tracing" -version = "0.1.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" -dependencies = [ - "cfg-if", - "pin-project-lite", - "tracing-core", -] - -[[package]] -name = "tracing-core" -version = "0.1.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" -dependencies = [ - "once_cell", -] - -[[package]] -name = "try-lock" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" - -[[package]] -name = "typenum" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" - -[[package]] -name = "unicode-bidi" -version = "0.3.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" - -[[package]] -name = "unicode-ident" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" - -[[package]] -name = "unicode-normalization" -version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" -dependencies = [ - "tinyvec", -] - -[[package]] -name = "unicode-width" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" - -[[package]] -name = "untrusted" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" - -[[package]] -name = "url" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" -dependencies = [ - "form_urlencoded", - "idna 0.4.0", - "percent-encoding", -] - -[[package]] -name = "utf8parse" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" - -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "want" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" -dependencies = [ - "try-lock", -] - -[[package]] -name = "wasi" -version = "0.10.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "wasm-bindgen" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" -dependencies = [ - "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" -dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" - -[[package]] -name = "web-sys" -version = "0.3.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "webpki" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "webpki-roots" -version = "0.22.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87" -dependencies = [ - "webpki", -] - -[[package]] -name = "webpki-roots" -version = "0.25.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14247bb57be4f377dfb94c72830b8ce8fc6beac03cf4bf7b9732eadd414123fc" - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" -dependencies = [ - "windows-targets 0.48.1", -] - -[[package]] -name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets 0.42.2", -] - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.1", -] - -[[package]] -name = "windows-targets" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", -] - -[[package]] -name = "windows-targets" -version = "0.48.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" -dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" - -[[package]] -name = "windows_i686_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" - -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" - -[[package]] -name = "winreg" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" -dependencies = [ - "winapi", -] - -[[package]] -name = "xattr" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4686009f71ff3e5c4dbcf1a282d0a44db3f021ba69350cd42086b3e5f1c6985" -dependencies = [ - "libc", -] diff --git a/crunchy-cli-core/Cargo.toml b/crunchy-cli-core/Cargo.toml index 5787f39..c66aa1e 100644 --- a/crunchy-cli-core/Cargo.toml +++ b/crunchy-cli-core/Cargo.toml @@ -37,8 +37,3 @@ sys-locale = "0.3" [build-dependencies] chrono = "0.4" - -[patch.crates-io] -# fork of the `native-tls` crate which uses openssl as backend on every platform. this is done as `reqwest` only supports -# `rustls` and `native-tls` as tls backend -native-tls = { git = "https://github.com/crunchy-labs/rust-not-so-native-tls.git", rev = "570100d" } From 70b3a7a3e1d0c935ccc6c8f3decc8e5948114b7a Mon Sep 17 00:00:00 2001 From: bytedream Date: Fri, 25 Aug 2023 14:34:16 +0200 Subject: [PATCH 017/204] Remove toolchain setup step from apple build action --- .github/workflows/ci.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bb2f797..f020b68 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -76,12 +76,6 @@ jobs: target/ key: x86_64-apple-darwin-cargo-${{ hashFiles('**/Cargo.lock') }} - - name: Install toolchain - uses: dtolnay/rust-toolchain@stable - with: - toolchain: stable - target: x86_64-apple-darwin - - name: Build run: cargo build --release --all-features --target x86_64-apple-darwin From e06e6b2b01b13eac73e714e2bef8e6b5f71d5f14 Mon Sep 17 00:00:00 2001 From: Simon <47527944+Frooastside@users.noreply.github.com> Date: Fri, 25 Aug 2023 15:21:37 +0200 Subject: [PATCH 018/204] Update README.md (#240) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 967eecf..7a620cb 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # crunchy-cli -👇 A Command-line downloader for Crunchyroll [Crunchyroll](https://www.crunchyroll.com). +👇 A Command-line downloader for [Crunchyroll](https://www.crunchyroll.com).

From 3ae6fe4a1a43b034a9e9fe17c67441eed5b5ba8e Mon Sep 17 00:00:00 2001 From: bytedream Date: Fri, 25 Aug 2023 17:14:44 +0200 Subject: [PATCH 019/204] Fmt --- crunchy-cli-core/src/archive/command.rs | 3 ++- crunchy-cli-core/src/download/command.rs | 3 ++- crunchy-cli-core/src/utils/format.rs | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/crunchy-cli-core/src/archive/command.rs b/crunchy-cli-core/src/archive/command.rs index b7cd8b7..7ce1658 100644 --- a/crunchy-cli-core/src/archive/command.rs +++ b/crunchy-cli-core/src/archive/command.rs @@ -213,7 +213,8 @@ async fn get_format( for single_format in single_formats { let stream = single_format.stream().await?; - let Some((video, audio)) = variant_data_from_stream(&stream, &archive.resolution).await? else { + let Some((video, audio)) = variant_data_from_stream(&stream, &archive.resolution).await? + else { if single_format.is_episode() { bail!( "Resolution ({}) is not available for episode {} ({}) of {} season {}", diff --git a/crunchy-cli-core/src/download/command.rs b/crunchy-cli-core/src/download/command.rs index df4e616..031ed04 100644 --- a/crunchy-cli-core/src/download/command.rs +++ b/crunchy-cli-core/src/download/command.rs @@ -185,7 +185,8 @@ async fn get_format( single_format: &SingleFormat, ) -> Result<(DownloadFormat, Format)> { let stream = single_format.stream().await?; - let Some((video, audio)) = variant_data_from_stream(&stream, &download.resolution).await? else { + let Some((video, audio)) = variant_data_from_stream(&stream, &download.resolution).await? + else { if single_format.is_episode() { bail!( "Resolution ({}) is not available for episode {} ({}) of {} season {}", diff --git a/crunchy-cli-core/src/utils/format.rs b/crunchy-cli-core/src/utils/format.rs index d975042..b6dcf35 100644 --- a/crunchy-cli-core/src/utils/format.rs +++ b/crunchy-cli-core/src/utils/format.rs @@ -297,8 +297,8 @@ impl Iterator for SingleFormatCollectionIterator { type Item = Vec; fn next(&mut self) -> Option { - let Some((_, episodes)) = self.0.0.iter_mut().next() else { - return None + let Some((_, episodes)) = self.0 .0.iter_mut().next() else { + return None; }; let value = episodes.pop_first().unwrap().1; From 18f891efd2aa7d91a944c2620adb9c66014388a1 Mon Sep 17 00:00:00 2001 From: bytedream Date: Fri, 25 Aug 2023 17:15:06 +0200 Subject: [PATCH 020/204] Use system certs when using openssl --- Cargo.lock | 67 +++++++++++++++++++++++++++++++++---- crunchy-cli-core/Cargo.toml | 9 ++--- crunchy-cli-core/src/lib.rs | 12 ++++++- 3 files changed, 77 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b07d41b..5fccedf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -344,6 +344,16 @@ dependencies = [ "url", ] +[[package]] +name = "core-foundation" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.8.4" @@ -391,6 +401,7 @@ dependencies = [ "num_cpus", "regex", "reqwest", + "rustls-native-certs", "sanitize-filename", "serde", "serde_json", @@ -403,9 +414,9 @@ dependencies = [ [[package]] name = "crunchyroll-rs" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6560e2f721420854d34b94b8bc35b316e3ff6bc83cb7cbf24750ddf55a21d45a" +checksum = "771cd92c5a4cc050f301674d77bca6c23f8f260ef346bd06c11b4b05ab9e0166" dependencies = [ "aes", "async-trait", @@ -430,9 +441,9 @@ dependencies = [ [[package]] name = "crunchyroll-rs-internal" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1398807cd10094f08c1d31423f7979e74c25f772c203d477dfa6ddc4ceb81f2" +checksum = "b260191f1125c7ba31e35071524938de5c6b0c2d248e5a35c62c4605e2da427e" dependencies = [ "darling", "quote", @@ -1244,9 +1255,9 @@ checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" [[package]] name = "pin-project-lite" -version = "0.2.12" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12cc1b0bf1727a77a54b6654e7b5f1af8604923edc8b81885f8ec92f9e3f0a05" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" [[package]] name = "pin-utils" @@ -1465,6 +1476,18 @@ dependencies = [ "sct", ] +[[package]] +name = "rustls-native-certs" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" +dependencies = [ + "openssl-probe", + "rustls-pemfile", + "schannel", + "security-framework", +] + [[package]] name = "rustls-pemfile" version = "1.0.3" @@ -1500,6 +1523,15 @@ dependencies = [ "regex", ] +[[package]] +name = "schannel" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" +dependencies = [ + "windows-sys 0.48.0", +] + [[package]] name = "sct" version = "0.7.0" @@ -1510,6 +1542,29 @@ dependencies = [ "untrusted", ] +[[package]] +name = "security-framework" +version = "2.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "serde" version = "1.0.186" diff --git a/crunchy-cli-core/Cargo.toml b/crunchy-cli-core/Cargo.toml index c66aa1e..6c9b59c 100644 --- a/crunchy-cli-core/Cargo.toml +++ b/crunchy-cli-core/Cargo.toml @@ -6,15 +6,15 @@ edition = "2021" license = "MIT" [features] -openssl = ["reqwest/native-tls-alpn"] -openssl-static = ["reqwest/native-tls-alpn", "reqwest/native-tls-vendored"] +openssl = ["reqwest/native-tls-alpn", "dep:rustls-native-certs"] +openssl-static = ["reqwest/native-tls-alpn", "reqwest/native-tls-vendored", "dep:rustls-native-certs"] [dependencies] anyhow = "1.0" async-trait = "0.1" clap = { version = "4.3", features = ["derive", "string"] } chrono = "0.4" -crunchyroll-rs = { version = "0.6.1", features = ["dash-stream"] } +crunchyroll-rs = { version = "0.6.2", features = ["dash-stream"] } ctrlc = "3.4" dialoguer = { version = "0.10", default-features = false } dirs = "5.0" @@ -31,9 +31,10 @@ serde = "1.0" serde_json = "1.0" serde_plain = "1.0" shlex = "1.1" +sys-locale = "0.3" tempfile = "3.7" tokio = { version = "1.31", features = ["macros", "rt-multi-thread", "time"] } -sys-locale = "0.3" +rustls-native-certs = { version = "0.6", optional = true } [build-dependencies] chrono = "0.4" diff --git a/crunchy-cli-core/src/lib.rs b/crunchy-cli-core/src/lib.rs index 793e946..bae3bed 100644 --- a/crunchy-cli-core/src/lib.rs +++ b/crunchy-cli-core/src/lib.rs @@ -271,7 +271,17 @@ async fn crunchyroll_session(cli: &mut Cli) -> Result { CrunchyrollBuilder::predefined_client_builder() }; #[cfg(any(feature = "openssl", feature = "openssl-static"))] - let client = builder.use_native_tls().build().unwrap(); + let client = { + let mut builder = builder.use_native_tls().tls_built_in_root_certs(false); + + for certificate in rustls_native_certs::load_native_certs().unwrap() { + builder = builder.add_root_certificate( + reqwest::Certificate::from_der(certificate.0.as_slice()).unwrap(), + ) + } + + builder.build().unwrap() + }; #[cfg(not(any(feature = "openssl", feature = "openssl-static")))] let client = builder.build().unwrap(); From b477ca982cd25d009f80bb4aa631128a906635dd Mon Sep 17 00:00:00 2001 From: bytedream Date: Wed, 6 Sep 2023 02:55:04 +0200 Subject: [PATCH 021/204] Add options to get drm dash and hls url with search --- crunchy-cli-core/src/search/command.rs | 2 ++ crunchy-cli-core/src/search/format.rs | 28 ++++++++++++++++++-------- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/crunchy-cli-core/src/search/command.rs b/crunchy-cli-core/src/search/command.rs index 0159c05..1ec4cb9 100644 --- a/crunchy-cli-core/src/search/command.rs +++ b/crunchy-cli-core/src/search/command.rs @@ -87,7 +87,9 @@ pub struct Search { /// /// stream.locale → Stream locale/language /// stream.dash_url → Stream url in DASH format + /// stream.drm_dash_url → Stream url in DRM protected DASH format /// stream.hls_url → Stream url in HLS format + /// stream.drm_hls_url → Stream url in DRM protected HLS format /// /// subtitle.locale → Subtitle locale/language /// subtitle.url → Url to the subtitle diff --git a/crunchy-cli-core/src/search/format.rs b/crunchy-cli-core/src/search/format.rs index 3574597..55cba7c 100644 --- a/crunchy-cli-core/src/search/format.rs +++ b/crunchy-cli-core/src/search/format.rs @@ -163,25 +163,37 @@ impl From<&Concert> for FormatConcert { struct FormatStream { pub locale: Locale, pub dash_url: String, + pub drm_dash_url: String, pub hls_url: String, + pub drm_hls_url: String, } impl From<&Stream> for FormatStream { fn from(value: &Stream) -> Self { - let (dash_url, hls_url) = value.variants.get(&Locale::Custom("".to_string())).map_or( - ("".to_string(), "".to_string()), - |v| { + let (dash_url, drm_dash_url, hls_url, drm_hls_url) = + value.variants.get(&Locale::Custom("".to_string())).map_or( ( - v.adaptive_dash.clone().unwrap_or_default().url, - v.adaptive_hls.clone().unwrap_or_default().url, - ) - }, - ); + "".to_string(), + "".to_string(), + "".to_string(), + "".to_string(), + ), + |v| { + ( + v.adaptive_dash.clone().unwrap_or_default().url, + v.drm_adaptive_dash.clone().unwrap_or_default().url, + v.adaptive_hls.clone().unwrap_or_default().url, + v.drm_adaptive_hls.clone().unwrap_or_default().url, + ) + }, + ); Self { locale: value.audio_locale.clone(), dash_url, + drm_dash_url, hls_url, + drm_hls_url, } } } From 0f7e6c9120506ba502e653e64928176e66d31108 Mon Sep 17 00:00:00 2001 From: bytedream Date: Wed, 6 Sep 2023 03:02:40 +0200 Subject: [PATCH 022/204] Add root flag to set custom user agent --- crunchy-cli-core/src/lib.rs | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/crunchy-cli-core/src/lib.rs b/crunchy-cli-core/src/lib.rs index bae3bed..50b1e4c 100644 --- a/crunchy-cli-core/src/lib.rs +++ b/crunchy-cli-core/src/lib.rs @@ -63,6 +63,10 @@ pub struct Cli { #[arg(value_parser = crate::utils::clap::clap_parse_proxy)] proxy: Option, + #[arg(help = "Use custom user agent")] + #[clap(long)] + user_agent: Option, + #[clap(subcommand)] command: Command, } @@ -261,15 +265,17 @@ async fn crunchyroll_session(cli: &mut Cli) -> Result { lang }; - let proxy = cli.proxy.clone(); let mut builder = Crunchyroll::builder() .locale(locale) .client({ - let builder = if let Some(p) = &proxy { - CrunchyrollBuilder::predefined_client_builder().proxy(p.clone()) - } else { - CrunchyrollBuilder::predefined_client_builder() - }; + let mut builder = CrunchyrollBuilder::predefined_client_builder(); + if let Some(p) = &cli.proxy { + builder = builder.proxy(p.clone()) + } + if let Some(ua) = &cli.user_agent { + builder = builder.user_agent(ua) + } + #[cfg(any(feature = "openssl", feature = "openssl-static"))] let client = { let mut builder = builder.use_native_tls().tls_built_in_root_certs(false); @@ -292,14 +298,6 @@ async fn crunchyroll_session(cli: &mut Cli) -> Result { if let Command::Download(download) = &cli.command { builder = builder.preferred_audio_locale(download.audio.clone()) } - if let Some(p) = &cli.proxy { - builder = builder.client( - CrunchyrollBuilder::predefined_client_builder() - .proxy(p.clone()) - .build() - .unwrap(), - ) - } let root_login_methods_count = cli.login_method.credentials.is_some() as u8 + cli.login_method.etp_rt.is_some() as u8 From 7485bd8e76aa6e5fda7e5850c4342556b46d57d1 Mon Sep 17 00:00:00 2001 From: bytedream Date: Fri, 8 Sep 2023 21:41:25 +0200 Subject: [PATCH 023/204] Update dependencies and version --- Cargo.lock | 179 +++++++++++++++--------------------- Cargo.toml | 8 +- crunchy-cli-core/Cargo.toml | 10 +- 3 files changed, 85 insertions(+), 112 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5fccedf..b7e3911 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -30,9 +30,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6748e8def348ed4d14996fa801f4122cd763fff530258cdc03f64b25f89d3a5a" +checksum = "0c378d78423fdad8089616f827526ee33c19f2fddbd5de1629152c9593ba4783" dependencies = [ "memchr", ] @@ -140,9 +140,9 @@ dependencies = [ [[package]] name = "base64" -version = "0.21.2" +version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" +checksum = "414dcefbc63d77c526a76b3afcf6fbb9b5e2791c19c3aa2297733208750c6e53" [[package]] name = "base64-serde" @@ -183,9 +183,9 @@ checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" [[package]] name = "bytes" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" [[package]] name = "cbc" @@ -213,18 +213,17 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.26" +version = "0.4.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5" +checksum = "defd4e7873dbddba6c7c91e199c7fcb946abc4a6a4ac3195400bcfb01b5de877" dependencies = [ "android-tzdata", "iana-time-zone", "js-sys", "num-traits", "serde", - "time 0.1.45", "wasm-bindgen", - "winapi", + "windows-targets 0.48.5", ] [[package]] @@ -239,20 +238,19 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.0" +version = "4.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d5f1946157a96594eb2d2c10eb7ad9a2b27518cb3000209dec700c35df9197d" +checksum = "6a13b88d2c62ff462f88e4a121f17a82c1af05693a2f192b5c38d14de73c19f6" dependencies = [ "clap_builder", "clap_derive", - "once_cell", ] [[package]] name = "clap_builder" -version = "4.4.0" +version = "4.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78116e32a042dd73c2901f0dc30790d20ff3447f3e3472fad359e8c3d282bcd6" +checksum = "2bb9faaa7c2ef94b2743a21f5a29e6f0010dff4caa69ac8e9d6cf8b6fa74da08" dependencies = [ "anstream", "anstyle", @@ -262,18 +260,18 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.4.0" +version = "4.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "586a385f7ef2f8b4d86bddaa0c094794e7ccbfe5ffef1f434fe928143fc783a5" +checksum = "4110a1e6af615a9e6d0a36f805d5c99099f8bab9b8042f5bc1fa220a4a89e36f" dependencies = [ "clap", ] [[package]] name = "clap_derive" -version = "4.4.0" +version = "4.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9fd1a5729c4548118d7d70ff234a44868d00489a4b6597b0b020918a0e91a1a" +checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873" dependencies = [ "heck", "proc-macro2", @@ -323,7 +321,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e859cd57d0710d9e06c381b550c06e76992472a8c6d527aecd2fc673dcc231fb" dependencies = [ "percent-encoding", - "time 0.3.27", + "time", "version_check", ] @@ -340,7 +338,7 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "time 0.3.27", + "time", "url", ] @@ -371,7 +369,7 @@ dependencies = [ [[package]] name = "crunchy-cli" -version = "3.0.1" +version = "3.0.2" dependencies = [ "chrono", "clap", @@ -383,7 +381,7 @@ dependencies = [ [[package]] name = "crunchy-cli-core" -version = "3.0.1" +version = "3.0.2" dependencies = [ "anyhow", "async-trait", @@ -462,9 +460,9 @@ dependencies = [ [[package]] name = "ctrlc" -version = "3.4.0" +version = "3.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a011bbe2c35ce9c1f143b7af6f94f29a167beb4cd1d29e6740ce836f723120e" +checksum = "82e95fbd621905b854affdc67943b043a0fbb6ed7385fd5a25650d19a8a6cfdf" dependencies = [ "nix", "windows-sys 0.48.0", @@ -608,9 +606,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f" +checksum = "136526188508e25c6fef639d7927dfb3e0e3084488bf202267829cf7fc23dbdd" dependencies = [ "errno-dragonfly", "libc", @@ -749,7 +747,7 @@ checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", ] [[package]] @@ -1078,9 +1076,9 @@ checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" [[package]] name = "memchr" -version = "2.5.0" +version = "2.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" [[package]] name = "mime" @@ -1110,7 +1108,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", "windows-sys 0.48.0", ] @@ -1127,14 +1125,13 @@ dependencies = [ [[package]] name = "nix" -version = "0.26.2" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" +checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.4.0", "cfg-if", "libc", - "static_assertions", ] [[package]] @@ -1174,9 +1171,9 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] name = "object" -version = "0.32.0" +version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ac5bbd07aea88c60a577a1ce218075ffd59208b2d7ca97adf9bfc5aeb21ebe" +checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" dependencies = [ "memchr", ] @@ -1189,11 +1186,11 @@ checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] name = "openssl" -version = "0.10.56" +version = "0.10.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "729b745ad4a5575dd06a3e1af1414bd330ee561c01b3899eb584baeaa8def17e" +checksum = "bac25ee399abb46215765b1cb35bc0212377e58a061560d8b29b024fd0430e7c" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.4.0", "cfg-if", "foreign-types", "libc", @@ -1221,18 +1218,18 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-src" -version = "111.27.0+1.1.1v" +version = "300.1.3+3.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06e8f197c82d7511c5b014030c9b1efeda40d7d5f99d23b4ceed3524a5e63f02" +checksum = "cd2c101a165fff9935e34def4669595ab1c7847943c42be86e21503e482be107" dependencies = [ "cc", ] [[package]] name = "openssl-sys" -version = "0.9.91" +version = "0.9.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "866b5f16f90776b9bb8dc1e1802ac6f0513de3a7a7465867bfbc563dc737faac" +checksum = "db4d56a4c0478783083cfafcc42493dd4a981d41669da64b4572a2a089b51b1d" dependencies = [ "cc", "libc", @@ -1273,9 +1270,9 @@ checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" [[package]] name = "portable-atomic" -version = "1.4.2" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f32154ba0af3a075eefa1eda8bb414ee928f62303a54ea85b8d6638ff1a6ee9e" +checksum = "31114a898e107c51bb1609ffaf55a0e011cf6a4d7f1170d0015a165082c0338b" [[package]] name = "proc-macro2" @@ -1352,9 +1349,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.9.3" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81bc1d4caf89fac26a70747fe603c130093b53c773888797a6329091246d651a" +checksum = "697061221ea1b4a94a624f67d0ae2bfe4e22b8a17b6a192afb11046542cc8c47" dependencies = [ "aho-corasick", "memchr", @@ -1364,9 +1361,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.3.6" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed1ceff11a1dddaee50c9dc8e4938bd106e9d89ae372f192311e7da498e3b69" +checksum = "c2f401f4955220693b56f8ec66ee9c78abffd8d1c4f23dc41a23839eb88f0795" dependencies = [ "aho-corasick", "memchr", @@ -1375,9 +1372,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" +checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" [[package]] name = "reqwest" @@ -1453,9 +1450,9 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustix" -version = "0.38.8" +version = "0.38.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ed4fa021d81c8392ce04db050a3da9a60299050b7ae1cf482d862b54a7218f" +checksum = "c0c3dde1fc030af041adc40e79c0e7fbcf431dd24870053d187d7c66e4b87453" dependencies = [ "bitflags 2.4.0", "errno", @@ -1466,9 +1463,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.6" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d1feddffcfcc0b33f5c6ce9a29e341e4cd59c3f78e7ee45f4a40c038b1d6cbb" +checksum = "cd8d6c9f025a446bc4d18ad9632e69aec8f287aa84499ee335599fabd20c3fd8" dependencies = [ "log", "ring", @@ -1567,18 +1564,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.186" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f5db24220c009de9bd45e69fb2938f4b6d2df856aa9304ce377b3180f83b7c1" +checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.186" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ad697f7e0b65af4983a4ce8f56ed5b357e8d3c36651bf6a7e13639c17b8e670" +checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" dependencies = [ "proc-macro2", "quote", @@ -1598,9 +1595,9 @@ dependencies = [ [[package]] name = "serde_plain" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6018081315db179d0ce57b1fe4b62a12a0028c9cf9bbef868c9cf477b3c34ae" +checksum = "9ce1fc6db65a611022b23a0dec6975d63fb80a302cb3388835ff02c097258d50" dependencies = [ "serde", ] @@ -1631,7 +1628,7 @@ dependencies = [ "serde", "serde_json", "serde_with_macros", - "time 0.3.27", + "time", ] [[package]] @@ -1654,9 +1651,9 @@ checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" [[package]] name = "shlex" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" +checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380" [[package]] name = "slab" @@ -1704,12 +1701,6 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - [[package]] name = "strsim" version = "0.10.0" @@ -1718,9 +1709,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" -version = "2.0.29" +version = "2.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a" +checksum = "718fa2415bcb8d8bd775917a1bf12a7931b6dfa890753378538118181e0cb398" dependencies = [ "proc-macro2", "quote", @@ -1729,12 +1720,11 @@ dependencies = [ [[package]] name = "sys-locale" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea0b9eefabb91675082b41eb94c3ecd91af7656caee3fb4961a07c0ec8c7ca6f" +checksum = "e801cf239ecd6ccd71f03d270d67dd53d13e90aab208bf4b8fe4ad957ea949b0" dependencies = [ "libc", - "windows-sys 0.45.0", ] [[package]] @@ -1752,18 +1742,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.47" +version = "1.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97a802ec30afc17eee47b2855fc72e0c4cd62be9b4efe6591edde0ec5bd68d8f" +checksum = "9d6d7a740b8a666a7e828dd00da9c0dc290dff53154ea77ac109281de90589b7" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.47" +version = "1.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bb623b56e39ab7dcd4b1b98bb6c8f8d907ed255b18de254088016b27a8ee19b" +checksum = "49922ecae66cc8a249b77e68d1d0623c1b2c514f0060c27cdc68bd62a1219d35" dependencies = [ "proc-macro2", "quote", @@ -1772,20 +1762,9 @@ dependencies = [ [[package]] name = "time" -version = "0.1.45" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" -dependencies = [ - "libc", - "wasi 0.10.0+wasi-snapshot-preview1", - "winapi", -] - -[[package]] -name = "time" -version = "0.3.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bb39ee79a6d8de55f48f2293a830e040392f1c5f16e336bdd1788cd0aadce07" +checksum = "17f6bb557fd245c28e6411aa56b6403c689ad95061f50e4be16c274e70a17e48" dependencies = [ "deranged", "itoa", @@ -1802,9 +1781,9 @@ checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" [[package]] name = "time-macros" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "733d258752e9303d392b94b75230d07b0b9c489350c69b851fc6c065fde3e8f9" +checksum = "1a942f44339478ef67935ab2bbaec2fb0322496cf3cbe84b261e06ac3814c572" dependencies = [ "time-core", ] @@ -1971,9 +1950,9 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" [[package]] name = "url" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" +checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" dependencies = [ "form_urlencoded", "idna 0.4.0", @@ -2007,12 +1986,6 @@ dependencies = [ "try-lock", ] -[[package]] -name = "wasi" -version = "0.10.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" diff --git a/Cargo.toml b/Cargo.toml index 6aa5ce0..be15b04 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "crunchy-cli" authors = ["Crunchy Labs Maintainers"] -version = "3.0.1" +version = "3.0.2" edition = "2021" license = "MIT" @@ -12,14 +12,14 @@ openssl = ["crunchy-cli-core/openssl"] openssl-static = ["crunchy-cli-core/openssl-static"] [dependencies] -tokio = { version = "1.31", features = ["macros", "rt-multi-thread", "time"], default-features = false } +tokio = { version = "1.32", features = ["macros", "rt-multi-thread", "time"], default-features = false } crunchy-cli-core = { path = "./crunchy-cli-core" } [build-dependencies] chrono = "0.4" -clap = { version = "4.3", features = ["string"] } -clap_complete = "4.3" +clap = { version = "4.4", features = ["string"] } +clap_complete = "4.4" clap_mangen = "0.2" crunchy-cli-core = { path = "./crunchy-cli-core" } diff --git a/crunchy-cli-core/Cargo.toml b/crunchy-cli-core/Cargo.toml index 6c9b59c..f75c57d 100644 --- a/crunchy-cli-core/Cargo.toml +++ b/crunchy-cli-core/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "crunchy-cli-core" authors = ["Crunchy Labs Maintainers"] -version = "3.0.1" +version = "3.0.2" edition = "2021" license = "MIT" @@ -12,7 +12,7 @@ openssl-static = ["reqwest/native-tls-alpn", "reqwest/native-tls-vendored", "dep [dependencies] anyhow = "1.0" async-trait = "0.1" -clap = { version = "4.3", features = ["derive", "string"] } +clap = { version = "4.4", features = ["derive", "string"] } chrono = "0.4" crunchyroll-rs = { version = "0.6.2", features = ["dash-stream"] } ctrlc = "3.4" @@ -30,10 +30,10 @@ sanitize-filename = "0.5" serde = "1.0" serde_json = "1.0" serde_plain = "1.0" -shlex = "1.1" +shlex = "1.2" sys-locale = "0.3" -tempfile = "3.7" -tokio = { version = "1.31", features = ["macros", "rt-multi-thread", "time"] } +tempfile = "3.8" +tokio = { version = "1.32", features = ["macros", "rt-multi-thread", "time"] } rustls-native-certs = { version = "0.6", optional = true } [build-dependencies] From 185b65fc9b58a5085d1fe538f1c2519eb7e63de5 Mon Sep 17 00:00:00 2001 From: bytedream Date: Fri, 8 Sep 2023 22:49:58 +0200 Subject: [PATCH 024/204] Remove invalid character from AUR binary PKGBUILD --- .github/scripts/PKGBUILD.binary | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/scripts/PKGBUILD.binary b/.github/scripts/PKGBUILD.binary index 0117723..3493ee6 100644 --- a/.github/scripts/PKGBUILD.binary +++ b/.github/scripts/PKGBUILD.binary @@ -1,7 +1,7 @@ # Maintainer: ByteDream pkgname=crunchy-cli-bin pkgdesc="Command-line downloader for Crunchyroll" -arch=('x86_64', 'aarch64') +arch=('x86_64' 'aarch64') url="https://github.com/crunchy-labs/crunchy-cli" license=('MIT') From 8eda8df3f7dd048f9c5aae672f4cbb242d05b1bc Mon Sep 17 00:00:00 2001 From: bytedream Date: Thu, 21 Sep 2023 13:46:23 +0200 Subject: [PATCH 025/204] Use native tls as default tls backend, add features to use rustls or openssl instead --- Cargo.lock | 98 ++++++++++++++++++++----------------- Cargo.toml | 20 +++++--- build.rs | 23 +++++++++ crunchy-cli-core/Cargo.toml | 6 ++- crunchy-cli-core/src/lib.rs | 4 +- src/main.rs | 8 +++ 6 files changed, 103 insertions(+), 56 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b7e3911..506097c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -30,9 +30,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.0.5" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c378d78423fdad8089616f827526ee33c19f2fddbd5de1629152c9593ba4783" +checksum = "ea5d730647d4fadd988536d06fecce94b7b4f2a7efdae548f1cf4b63205518ab" dependencies = [ "memchr", ] @@ -68,9 +68,9 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15c4c2c83f81532e5845a733998b6971faca23490340a418e9b72a3ec9de12ea" +checksum = "b84bf0a05bbb2a83e5eb6fa36bb6e87baa08193c35ff52bbf6b38d8af2890e46" [[package]] name = "anstyle-parse" @@ -140,9 +140,9 @@ dependencies = [ [[package]] name = "base64" -version = "0.21.3" +version = "0.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "414dcefbc63d77c526a76b3afcf6fbb9b5e2791c19c3aa2297733208750c6e53" +checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2" [[package]] name = "base64-serde" @@ -177,9 +177,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.13.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" [[package]] name = "bytes" @@ -213,9 +213,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.30" +version = "0.4.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "defd4e7873dbddba6c7c91e199c7fcb946abc4a6a4ac3195400bcfb01b5de877" +checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" dependencies = [ "android-tzdata", "iana-time-zone", @@ -238,9 +238,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.2" +version = "4.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a13b88d2c62ff462f88e4a121f17a82c1af05693a2f192b5c38d14de73c19f6" +checksum = "b1d7b8d5ec32af0fadc644bf1fd509a688c2103b185644bb1e29d164e0703136" dependencies = [ "clap_builder", "clap_derive", @@ -248,9 +248,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.2" +version = "4.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bb9faaa7c2ef94b2743a21f5a29e6f0010dff4caa69ac8e9d6cf8b6fa74da08" +checksum = "5179bb514e4d7c2051749d8fcefa2ed6d06a9f4e6d69faf3805f5d80b8cf8d56" dependencies = [ "anstream", "anstyle", @@ -287,9 +287,9 @@ checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961" [[package]] name = "clap_mangen" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf8e5f34d85d9e0bbe2491d100a7a7c1007bb2467b518080bfe311e8947197a9" +checksum = "b44f35c514163027542f7147797ff930523eea288e03642727348ef1a9666f6b" dependencies = [ "clap", "roff", @@ -376,6 +376,7 @@ dependencies = [ "clap_complete", "clap_mangen", "crunchy-cli-core", + "native-tls", "tokio", ] @@ -795,9 +796,9 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" +checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" [[package]] name = "hex" @@ -1042,15 +1043,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.147" +version = "0.2.148" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" [[package]] name = "linux-raw-sys" -version = "0.4.5" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503" +checksum = "1a9bad9f94746442c783ca431b22403b519cd7fbeed0533fdd6328b2f2212128" [[package]] name = "log" @@ -1115,12 +1116,17 @@ dependencies = [ [[package]] name = "native-tls" version = "0.2.11" -source = "git+https://github.com/crunchy-labs/rust-not-so-native-tls.git?rev=570100d#570100d3391bd9aab7a390cfef0d1a28e8efe200" +source = "git+https://github.com/crunchy-labs/rust-not-so-native-tls.git?rev=fdba246#fdba246a79986607cbdf573733445498bb6da2a9" dependencies = [ + "libc", "log", "openssl", "openssl-probe", "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", ] [[package]] @@ -1218,9 +1224,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-src" -version = "300.1.3+3.1.2" +version = "300.1.5+3.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd2c101a165fff9935e34def4669595ab1c7847943c42be86e21503e482be107" +checksum = "559068e4c12950d7dcaa1857a61725c0d38d4fc03ff8e070ab31a75d6e316491" dependencies = [ "cc", ] @@ -1276,9 +1282,9 @@ checksum = "31114a898e107c51bb1609ffaf55a0e011cf6a4d7f1170d0015a165082c0338b" [[package]] name = "proc-macro2" -version = "1.0.66" +version = "1.0.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" dependencies = [ "unicode-ident", ] @@ -1450,9 +1456,9 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustix" -version = "0.38.11" +version = "0.38.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0c3dde1fc030af041adc40e79c0e7fbcf431dd24870053d187d7c66e4b87453" +checksum = "747c788e9ce8e92b12cd485c49ddf90723550b654b32508f979b71a7b1ecda4f" dependencies = [ "bitflags 2.4.0", "errno", @@ -1496,9 +1502,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.101.4" +version = "0.101.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d93931baf2d282fff8d3a532bbfd7653f734643161b87e3e01e59a04439bf0d" +checksum = "45a27e3b59326c16e23d30aeb7a36a24cc0d29e71d68ff611cdfb4a01d013bed" dependencies = [ "ring", "untrusted", @@ -1584,9 +1590,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.105" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693151e1ac27563d6dbcec9dee9fbd5da8539b20fa14ad3752b2e6d363ace360" +checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" dependencies = [ "itoa", "ryu", @@ -1687,9 +1693,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2538b18701741680e0322a2302176d3253a35388e2e62f172f64f4f16605f877" +checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e" dependencies = [ "libc", "windows-sys 0.48.0", @@ -1709,9 +1715,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" -version = "2.0.31" +version = "2.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "718fa2415bcb8d8bd775917a1bf12a7931b6dfa890753378538118181e0cb398" +checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" dependencies = [ "proc-macro2", "quote", @@ -1815,7 +1821,7 @@ dependencies = [ "mio", "num_cpus", "pin-project-lite", - "socket2 0.5.3", + "socket2 0.5.4", "tokio-macros", "windows-sys 0.48.0", ] @@ -1865,9 +1871,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.8" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" +checksum = "1d68074620f57a0b21594d9735eb2e98ab38b17f80d3fcb189fca266771ca60d" dependencies = [ "bytes", "futures-core", @@ -1911,9 +1917,9 @@ checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" [[package]] name = "typenum" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unicode-bidi" @@ -1923,9 +1929,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-ident" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" @@ -1938,9 +1944,9 @@ dependencies = [ [[package]] name = "unicode-width" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" [[package]] name = "untrusted" diff --git a/Cargo.toml b/Cargo.toml index be15b04..099bc6f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,14 +6,22 @@ edition = "2021" license = "MIT" [features] -default = ["openssl-static"] +default = ["native-tls"] -openssl = ["crunchy-cli-core/openssl"] -openssl-static = ["crunchy-cli-core/openssl-static"] +rustls-tls = ["crunchy-cli-core/rustls-tls"] +native-tls = ["crunchy-cli-core/native-tls"] +openssl-tls = ["dep:native-tls", "native-tls/openssl", "crunchy-cli-core/openssl-tls"] +openssl-tls-static = ["dep:native-tls", "native-tls/openssl", "crunchy-cli-core/openssl-tls-static"] + +# deprecated +openssl = ["openssl-tls"] +openssl-static = ["openssl-tls-static"] [dependencies] tokio = { version = "1.32", features = ["macros", "rt-multi-thread", "time"], default-features = false } +native-tls = { version = "0.2.11", optional = true } + crunchy-cli-core = { path = "./crunchy-cli-core" } [build-dependencies] @@ -28,9 +36,9 @@ crunchy-cli-core = { path = "./crunchy-cli-core" } members = ["crunchy-cli-core"] [patch.crates-io] -# fork of the `native-tls` crate which uses openssl as backend on every platform. this is done as `reqwest` only supports -# `rustls` and `native-tls` as tls backend -native-tls = { git = "https://github.com/crunchy-labs/rust-not-so-native-tls.git", rev = "570100d" } +# fork of the `native-tls` crate which can use openssl as backend on every platform. this is done as `reqwest` only +# supports `rustls` and `native-tls` as tls backend +native-tls = { git = "https://github.com/crunchy-labs/rust-not-so-native-tls.git", rev = "fdba246" } [profile.release] strip = true diff --git a/build.rs b/build.rs index 7056c67..5b464c4 100644 --- a/build.rs +++ b/build.rs @@ -3,6 +3,29 @@ use clap_complete::shells; use std::path::{Path, PathBuf}; fn main() -> std::io::Result<()> { + let rustls_tls = cfg!(feature = "rustls-tls"); + let native_tls = cfg!(feature = "native-tls"); + let openssl_tls = cfg!(any(feature = "openssl-tls", feature = "openssl-tls-static")); + + if rustls_tls as u8 + native_tls as u8 + openssl_tls as u8 > 1 { + let active_tls_backend = if openssl_tls { + "openssl" + } else if native_tls { + "native tls" + } else { + "rustls" + }; + + println!("cargo:warning=Multiple tls backends are activated (through the '*-tls' features). Consider to activate only one as it is not possible to change the backend during runtime. The active backend for this build will be '{}'.", active_tls_backend) + } + + if cfg!(feature = "openssl") { + println!("cargo:warning=The 'openssl' feature is deprecated and will be removed in a future version. Use the 'openssl-tls' feature instead.") + } + if cfg!(feature = "openssl-static") { + println!("cargo:warning=The 'openssl-static' feature is deprecated and will be removed in a future version. Use the 'openssl-tls-static' feature instead.") + } + // note that we're using an anti-pattern here / violate the rust conventions. build script are // not supposed to write outside of 'OUT_DIR'. to have the generated files in the build "root" // (the same directory where the output binary lives) is much simpler than in 'OUT_DIR' since diff --git a/crunchy-cli-core/Cargo.toml b/crunchy-cli-core/Cargo.toml index f75c57d..8288bf1 100644 --- a/crunchy-cli-core/Cargo.toml +++ b/crunchy-cli-core/Cargo.toml @@ -6,8 +6,10 @@ edition = "2021" license = "MIT" [features] -openssl = ["reqwest/native-tls-alpn", "dep:rustls-native-certs"] -openssl-static = ["reqwest/native-tls-alpn", "reqwest/native-tls-vendored", "dep:rustls-native-certs"] +rustls-tls = ["reqwest/rustls-tls"] +native-tls = ["reqwest/native-tls", "reqwest/native-tls-alpn"] +openssl-tls = ["reqwest/native-tls", "reqwest/native-tls-alpn", "dep:rustls-native-certs"] +openssl-tls-static = ["reqwest/native-tls", "reqwest/native-tls-alpn", "reqwest/native-tls-vendored", "dep:rustls-native-certs"] [dependencies] anyhow = "1.0" diff --git a/crunchy-cli-core/src/lib.rs b/crunchy-cli-core/src/lib.rs index 50b1e4c..02bef6f 100644 --- a/crunchy-cli-core/src/lib.rs +++ b/crunchy-cli-core/src/lib.rs @@ -276,7 +276,7 @@ async fn crunchyroll_session(cli: &mut Cli) -> Result { builder = builder.user_agent(ua) } - #[cfg(any(feature = "openssl", feature = "openssl-static"))] + #[cfg(any(feature = "openssl-tls", feature = "openssl-tls-static"))] let client = { let mut builder = builder.use_native_tls().tls_built_in_root_certs(false); @@ -288,7 +288,7 @@ async fn crunchyroll_session(cli: &mut Cli) -> Result { builder.build().unwrap() }; - #[cfg(not(any(feature = "openssl", feature = "openssl-static")))] + #[cfg(not(any(feature = "openssl-tls", feature = "openssl-tls-static")))] let client = builder.build().unwrap(); client diff --git a/src/main.rs b/src/main.rs index 5e1d695..da3c699 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,11 @@ +#[cfg(not(any( + feature = "rustls-tls", + feature = "native-tls", + feature = "openssl-tls", + feature = "openssl-tls-static" +)))] +compile_error!("At least one tls feature must be activated"); + #[tokio::main] async fn main() { crunchy_cli_core::cli_entrypoint().await From 64428ea7d175a2137b755456662914adc73f0c6a Mon Sep 17 00:00:00 2001 From: bytedream Date: Thu, 21 Sep 2023 19:18:29 +0200 Subject: [PATCH 026/204] Rename native-tls crate to prevent false-positive build warnings --- Cargo.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 099bc6f..b5ae0a6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,8 +10,8 @@ default = ["native-tls"] rustls-tls = ["crunchy-cli-core/rustls-tls"] native-tls = ["crunchy-cli-core/native-tls"] -openssl-tls = ["dep:native-tls", "native-tls/openssl", "crunchy-cli-core/openssl-tls"] -openssl-tls-static = ["dep:native-tls", "native-tls/openssl", "crunchy-cli-core/openssl-tls-static"] +openssl-tls = ["dep:native-tls-crate", "native-tls-crate/openssl", "crunchy-cli-core/openssl-tls"] +openssl-tls-static = ["dep:native-tls-crate", "native-tls-crate/openssl", "crunchy-cli-core/openssl-tls-static"] # deprecated openssl = ["openssl-tls"] @@ -20,7 +20,7 @@ openssl-static = ["openssl-tls-static"] [dependencies] tokio = { version = "1.32", features = ["macros", "rt-multi-thread", "time"], default-features = false } -native-tls = { version = "0.2.11", optional = true } +native-tls-crate = { package = "native-tls", version = "0.2.11", optional = true } crunchy-cli-core = { path = "./crunchy-cli-core" } From 01913e0db3ba9f9dc78f1759734ce59f1c6c8790 Mon Sep 17 00:00:00 2001 From: bytedream Date: Thu, 21 Sep 2023 19:20:00 +0200 Subject: [PATCH 027/204] Adjust ci and PKGBUILD build args to feature changes --- .github/scripts/PKGBUILD.source | 2 +- .github/workflows/ci.yml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/scripts/PKGBUILD.source b/.github/scripts/PKGBUILD.source index 015efe3..af6b8e1 100644 --- a/.github/scripts/PKGBUILD.source +++ b/.github/scripts/PKGBUILD.source @@ -19,7 +19,7 @@ build() { export CARGO_HOME="$srcdir/cargo-home" export RUSTUP_TOOLCHAIN=stable - cargo build --release --no-default-features --features openssl + cargo build --release } package() { diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f020b68..7493041 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,7 +36,7 @@ jobs: run: cargo install --force cross - name: Build - run: cross build --release --all-features --target ${{ matrix.toolchain }} + run: cross build --release --no-default-features --features openssl-tls-static --target ${{ matrix.toolchain }} - name: Upload binary artifact uses: actions/upload-artifact@v3 @@ -77,7 +77,7 @@ jobs: key: x86_64-apple-darwin-cargo-${{ hashFiles('**/Cargo.lock') }} - name: Build - run: cargo build --release --all-features --target x86_64-apple-darwin + run: cargo build --release --target x86_64-apple-darwin - name: Upload binary artifact uses: actions/upload-artifact@v3 @@ -110,7 +110,7 @@ jobs: - name: Build shell: msys2 {0} - run: cargo build --release --all-features --target x86_64-pc-windows-gnu + run: cargo build --release --target x86_64-pc-windows-gnu - name: Upload binary artifact uses: actions/upload-artifact@v3 From 3e21ca4fe7c1831e857118a391bd01e2146c36ab Mon Sep 17 00:00:00 2001 From: bytedream Date: Fri, 22 Sep 2023 11:52:39 +0200 Subject: [PATCH 028/204] Update dependencies and version --- Cargo.lock | 17 +++++++++-------- Cargo.toml | 2 +- crunchy-cli-core/Cargo.toml | 4 ++-- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 506097c..09cad3e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -369,7 +369,7 @@ dependencies = [ [[package]] name = "crunchy-cli" -version = "3.0.2" +version = "3.0.3" dependencies = [ "chrono", "clap", @@ -382,7 +382,7 @@ dependencies = [ [[package]] name = "crunchy-cli-core" -version = "3.0.2" +version = "3.0.3" dependencies = [ "anyhow", "async-trait", @@ -549,12 +549,13 @@ dependencies = [ [[package]] name = "dialoguer" -version = "0.10.4" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59c6f2989294b9a498d3ad5491a79c6deb604617378e1cdc4bfc1c1361fe2f87" +checksum = "658bce805d770f407bc62102fca7c2c64ceef2fbcb2b8bd19d2765ce093980de" dependencies = [ "console", "shell-words", + "thiserror", ] [[package]] @@ -975,9 +976,9 @@ dependencies = [ [[package]] name = "indicatif" -version = "0.17.6" +version = "0.17.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b297dc40733f23a0e52728a58fa9489a5b7638a324932de16b41adc3ef80730" +checksum = "fb28741c9db9a713d93deb3bb9515c20788cef5815265bee4980e87bde7e0f25" dependencies = [ "console", "instant", @@ -1502,9 +1503,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.101.5" +version = "0.101.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45a27e3b59326c16e23d30aeb7a36a24cc0d29e71d68ff611cdfb4a01d013bed" +checksum = "3c7d5dece342910d9ba34d259310cae3e0154b873b35408b787b59bce53d34fe" dependencies = [ "ring", "untrusted", diff --git a/Cargo.toml b/Cargo.toml index b5ae0a6..e5882d6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "crunchy-cli" authors = ["Crunchy Labs Maintainers"] -version = "3.0.2" +version = "3.0.3" edition = "2021" license = "MIT" diff --git a/crunchy-cli-core/Cargo.toml b/crunchy-cli-core/Cargo.toml index 8288bf1..fc298f3 100644 --- a/crunchy-cli-core/Cargo.toml +++ b/crunchy-cli-core/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "crunchy-cli-core" authors = ["Crunchy Labs Maintainers"] -version = "3.0.2" +version = "3.0.3" edition = "2021" license = "MIT" @@ -18,7 +18,7 @@ clap = { version = "4.4", features = ["derive", "string"] } chrono = "0.4" crunchyroll-rs = { version = "0.6.2", features = ["dash-stream"] } ctrlc = "3.4" -dialoguer = { version = "0.10", default-features = false } +dialoguer = { version = "0.11", default-features = false } dirs = "5.0" derive_setters = "0.1" fs2 = "0.4" From a93a1fa807758cf41829233281ca5832a52c6151 Mon Sep 17 00:00:00 2001 From: bytedream Date: Fri, 22 Sep 2023 12:11:00 +0200 Subject: [PATCH 029/204] Fix env variable resolving in publish pipeline --- .github/workflows/publish.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 80cb5bb..1599111 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -34,7 +34,7 @@ jobs: commit_username: release-action commit_email: ${{ secrets.AUR_EMAIL }} ssh_private_key: ${{ secrets.AUR_SSH_PRIVATE_KEY }} - commit_message: Update to version {{ env.RELEASE_VERSION }} + commit_message: Update to version ${{ env.RELEASE_VERSION }} - name: Generate crunchy-cli-bin sha sums run: | @@ -67,4 +67,4 @@ jobs: commit_username: release-action commit_email: ${{ secrets.AUR_EMAIL }} ssh_private_key: ${{ secrets.AUR_SSH_PRIVATE_KEY }} - commit_message: Update to version {{ env.RELEASE_VERSION }} + commit_message: Update to version ${{ env.RELEASE_VERSION }} From d79197edc6fb9bf2bac699d2f6b55bfae4d7dea7 Mon Sep 17 00:00:00 2001 From: bytedream Date: Sat, 23 Sep 2023 16:56:38 +0200 Subject: [PATCH 030/204] Use async mutex and channel instead of the std equivalents --- crunchy-cli-core/src/utils/download.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/crunchy-cli-core/src/utils/download.rs b/crunchy-cli-core/src/utils/download.rs index 4531c69..29f160a 100644 --- a/crunchy-cli-core/src/utils/download.rs +++ b/crunchy-cli-core/src/utils/download.rs @@ -17,9 +17,11 @@ use std::env; use std::io::Write; use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; -use std::sync::{mpsc, Arc, Mutex}; +use std::sync::Arc; use std::time::Duration; use tempfile::TempPath; +use tokio::sync::mpsc::unbounded_channel; +use tokio::sync::Mutex; use tokio::task::JoinSet; #[derive(Clone, Debug)] @@ -576,7 +578,7 @@ pub async fn download_segments( segs[i - ((i / cpus) * cpus)].push(segment); } - let (sender, receiver) = mpsc::channel(); + let (sender, mut receiver) = unbounded_channel(); let mut join_set: JoinSet> = JoinSet::new(); for num in 0..cpus { @@ -629,7 +631,7 @@ pub async fn download_segments( buf = VariantSegment::decrypt(buf.borrow_mut(), segment.key)?.to_vec(); - let mut c = thread_count.lock().unwrap(); + let mut c = thread_count.lock().await; debug!( "Downloaded and decrypted segment [{}/{} {:.2}%] {}", num + (i * cpus) + 1, @@ -663,7 +665,7 @@ pub async fn download_segments( // the segment number and the values the corresponding bytes let mut data_pos = 0; let mut buf: BTreeMap> = BTreeMap::new(); - for (pos, bytes) in receiver.iter() { + while let Some((pos, bytes)) = receiver.recv().await { // if the position is lower than 0, an error occurred in the sending download thread if pos < 0 { break; From f48474ba776bce8a6d00e6f0c97f38cf047b8eb4 Mon Sep 17 00:00:00 2001 From: bytedream Date: Wed, 27 Sep 2023 00:03:26 +0200 Subject: [PATCH 031/204] Remove numbers from binary PKGBUILD env variables --- .github/scripts/PKGBUILD.binary | 4 ++-- .github/workflows/publish.yml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/scripts/PKGBUILD.binary b/.github/scripts/PKGBUILD.binary index 3493ee6..00fee47 100644 --- a/.github/scripts/PKGBUILD.binary +++ b/.github/scripts/PKGBUILD.binary @@ -24,8 +24,8 @@ source_aarch64=( "LICENSE::https://raw.githubusercontent.com/crunchy-labs/crunchy-cli/v${pkgver}/LICENSE" ) noextract=("manpages.zip" "completions.zip") -sha256sums_x86_64=('$CI_x86_64_SHA_SUM' '$CI_MANPAGES_SHA_SUM' '$CI_COMPLETIONS_SHA_SUM' '$CI_LICENSE_SHA_SUM') -sha256sums_aarch64=('$CI_aarch64_SHA_SUM' '$CI_MANPAGES_SHA_SUM' '$CI_COMPLETIONS_SHA_SUM' '$CI_LICENSE_SHA_SUM') +sha256sums_x86_64=('$CI_AMD_BINARY_SHA_SUM' '$CI_MANPAGES_SHA_SUM' '$CI_COMPLETIONS_SHA_SUM' '$CI_LICENSE_SHA_SUM') +sha256sums_aarch64=('$CI_ARM_BINARY_SHA_SUM' '$CI_MANPAGES_SHA_SUM' '$CI_COMPLETIONS_SHA_SUM' '$CI_LICENSE_SHA_SUM') package() { cd "$srcdir" diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 1599111..f777f9e 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -52,12 +52,12 @@ jobs: - name: Generate crunchy-cli-bin PKGBUILD env: CI_PKG_VERSION: ${{ env.RELEASE_VERSION }} - CI_x86_64_SHA_SUM: ${{ env.CRUNCHY_CLI_BIN_x86_64_SHA256 }} - CI_aarch64_SHA_SUM: ${{ env.CRUNCHY_CLI_BIN_aarch64_SHA256 }} + CI_AMD_BINARY_SHA_SUM: ${{ env.CRUNCHY_CLI_BIN_x86_64_SHA256 }} + CI_ARM_BINARY_SHA_SUM: ${{ env.CRUNCHY_CLI_BIN_aarch64_SHA256 }} CI_MANPAGES_SHA_SUM: ${{ env.CRUNCHY_CLI_BIN_MANPAGES_SHA256 }} CI_COMPLETIONS_SHA_SUM: ${{ env.CRUNCHY_CLI_BIN_COMPLETIONS_SHA256 }} CI_LICENSE_SHA_SUM: ${{ env.CRUNCHY_CLI_BIN_LICENSE_SHA256 }} - run: envsubst '$CI_PKG_VERSION,$CI_x86_64_SHA_SUM,$CI_aarch64_SHA_SUM,$CI_COMPLETIONS_SHA_SUM,$CI_MANPAGES_SHA_SUM,$CI_LICENSE_SHA_SUM' < .github/scripts/PKGBUILD.binary > PKGBUILD + run: envsubst '$CI_PKG_VERSION,$CI_AMD_BINARY_SHA_SUM,$CI_ARM_BINARY_SHA_SUM,$CI_COMPLETIONS_SHA_SUM,$CI_MANPAGES_SHA_SUM,$CI_LICENSE_SHA_SUM' < .github/scripts/PKGBUILD.binary > PKGBUILD - name: Publish crunchy-cli-bin to AUR uses: KSXGitHub/github-actions-deploy-aur@v2.7.0 From 9596175f7fe2a40fe2f0c20772d373aa13150a0f Mon Sep 17 00:00:00 2001 From: Valentine Briese Date: Wed, 11 Oct 2023 18:24:45 -0700 Subject: [PATCH 032/204] Add FFmpeg Apple hardware acceleration --- crunchy-cli-core/src/utils/ffmpeg.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/crunchy-cli-core/src/utils/ffmpeg.rs b/crunchy-cli-core/src/utils/ffmpeg.rs index 210b0f7..3407d91 100644 --- a/crunchy-cli-core/src/utils/ffmpeg.rs +++ b/crunchy-cli-core/src/utils/ffmpeg.rs @@ -66,7 +66,8 @@ ffmpeg_enum! { ffmpeg_enum! { enum FFmpegHwAccel { - Nvidia + Nvidia, + Apple } } @@ -275,6 +276,9 @@ impl FFmpegPreset { ]); output.extend(["-c:v", "h264_nvenc", "-c:a", "copy"]) } + FFmpegHwAccel::Apple => { + output.extend(["-c:v", "h264_videotoolbox", "-c:a", "copy"]) + } } } else { output.extend(["-c:v", "libx264", "-c:a", "copy"]) @@ -300,6 +304,9 @@ impl FFmpegPreset { ]); output.extend(["-c:v", "hevc_nvenc", "-c:a", "copy"]) } + FFmpegHwAccel::Apple => { + output.extend(["-c:v", "hevc_videotoolbox", "-c:a", "copy"]) + } } } else { output.extend(["-c:v", "libx265", "-c:a", "copy"]) From 610593a79547b577b46707f996adefa7cf27db15 Mon Sep 17 00:00:00 2001 From: Valentine Briese Date: Wed, 11 Oct 2023 18:26:51 -0700 Subject: [PATCH 033/204] Make H265 codec compatible with Apple HEVC standards --- crunchy-cli-core/src/utils/ffmpeg.rs | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/crunchy-cli-core/src/utils/ffmpeg.rs b/crunchy-cli-core/src/utils/ffmpeg.rs index 3407d91..6145fcf 100644 --- a/crunchy-cli-core/src/utils/ffmpeg.rs +++ b/crunchy-cli-core/src/utils/ffmpeg.rs @@ -302,14 +302,26 @@ impl FFmpegPreset { "-c:v", "h264_cuvid", ]); - output.extend(["-c:v", "hevc_nvenc", "-c:a", "copy"]) - } - FFmpegHwAccel::Apple => { - output.extend(["-c:v", "hevc_videotoolbox", "-c:a", "copy"]) + output.extend([ + "-c:v", + "hevc_nvenc", + "-c:a", + "copy", + "-tag:v", + "hvc1", + ]) } + FFmpegHwAccel::Apple => output.extend([ + "-c:v", + "hevc_videotoolbox", + "-c:a", + "copy", + "-tag:v", + "hvc1", + ]), } } else { - output.extend(["-c:v", "libx265", "-c:a", "copy"]) + output.extend(["-c:v", "libx265", "-c:a", "copy", "-tag:v", "hvc1"]) } match quality { From 7095e2b8b6464edeb9d79a21540365d02133a93b Mon Sep 17 00:00:00 2001 From: Valentine Briese Date: Wed, 11 Oct 2023 18:54:47 -0700 Subject: [PATCH 034/204] Use `-q:v` FFmpeg option for Apple hardware acceleration --- crunchy-cli-core/src/utils/ffmpeg.rs | 65 +++++++++++++++++++--------- 1 file changed, 45 insertions(+), 20 deletions(-) diff --git a/crunchy-cli-core/src/utils/ffmpeg.rs b/crunchy-cli-core/src/utils/ffmpeg.rs index 6145fcf..af29bfd 100644 --- a/crunchy-cli-core/src/utils/ffmpeg.rs +++ b/crunchy-cli-core/src/utils/ffmpeg.rs @@ -263,6 +263,12 @@ impl FFmpegPreset { match codec { FFmpegCodec::H264 => { + let mut crf_quality = || match quality { + FFmpegQuality::Lossless => output.extend(["-crf", "18"]), + FFmpegQuality::Normal => (), + FFmpegQuality::Low => output.extend(["-crf", "35"]), + }; + if let Some(hwaccel) = hwaccel_opt { match hwaccel { FFmpegHwAccel::Nvidia => { @@ -274,23 +280,37 @@ impl FFmpegPreset { "-c:v", "h264_cuvid", ]); + crf_quality(); output.extend(["-c:v", "h264_nvenc", "-c:a", "copy"]) } FFmpegHwAccel::Apple => { + // Apple's Video Toolbox encoders ignore `-crf`, + // use `-q:v` instead. It's on a scale of 1-100, + // 100 being lossless. Just did some math + // ((-a/51+1)*99+1 where `a` is the old crf value) + // so these settings very likely need some more + // tweeking. + match quality { + FFmpegQuality::Lossless => output.extend(["-q:v", "65"]), + FFmpegQuality::Normal => (), + FFmpegQuality::Low => output.extend(["-q:v", "32"]), + } + output.extend(["-c:v", "h264_videotoolbox", "-c:a", "copy"]) } } } else { + crf_quality(); output.extend(["-c:v", "libx264", "-c:a", "copy"]) } - - match quality { - FFmpegQuality::Lossless => output.extend(["-crf", "18"]), - FFmpegQuality::Normal => (), - FFmpegQuality::Low => output.extend(["-crf", "35"]), - } } FFmpegCodec::H265 => { + let mut crf_quality = || match quality { + FFmpegQuality::Lossless => output.extend(["-crf", "20"]), + FFmpegQuality::Normal => (), + FFmpegQuality::Low => output.extend(["-crf", "35"]), + }; + if let Some(hwaccel) = hwaccel_opt { match hwaccel { FFmpegHwAccel::Nvidia => { @@ -302,6 +322,7 @@ impl FFmpegPreset { "-c:v", "h264_cuvid", ]); + crf_quality(); output.extend([ "-c:v", "hevc_nvenc", @@ -311,24 +332,28 @@ impl FFmpegPreset { "hvc1", ]) } - FFmpegHwAccel::Apple => output.extend([ - "-c:v", - "hevc_videotoolbox", - "-c:a", - "copy", - "-tag:v", - "hvc1", - ]), + FFmpegHwAccel::Apple => { + // See the comment that starts on line 287. + match quality { + FFmpegQuality::Lossless => output.extend(["-q:v", "61"]), + FFmpegQuality::Normal => (), + FFmpegQuality::Low => output.extend(["-q:v", "32"]), + } + + output.extend([ + "-c:v", + "hevc_videotoolbox", + "-c:a", + "copy", + "-tag:v", + "hvc1", + ]) + } } } else { + crf_quality(); output.extend(["-c:v", "libx265", "-c:a", "copy", "-tag:v", "hvc1"]) } - - match quality { - FFmpegQuality::Lossless => output.extend(["-crf", "20"]), - FFmpegQuality::Normal => (), - FFmpegQuality::Low => output.extend(["-crf", "35"]), - } } FFmpegCodec::Av1 => { output.extend(["-c:v", "libsvtav1", "-c:a", "copy"]); From e5db8e95043c7d9dabeb6e05c0f2f6311563a58d Mon Sep 17 00:00:00 2001 From: Valentine Briese Date: Thu, 12 Oct 2023 12:20:06 -0700 Subject: [PATCH 035/204] Fix `ffmpeg-preset` option in `download` command (#254) --- crunchy-cli-core/src/download/command.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crunchy-cli-core/src/download/command.rs b/crunchy-cli-core/src/download/command.rs index 031ed04..baf27bf 100644 --- a/crunchy-cli-core/src/download/command.rs +++ b/crunchy-cli-core/src/download/command.rs @@ -148,7 +148,8 @@ impl Execute for Download { Some("mpegts".to_string()) } else { None - }); + }) + .ffmpeg_preset(self.ffmpeg_preset.clone().unwrap_or_default()); for mut single_formats in single_format_collection.into_iter() { // the vec contains always only one item From 13335c020b19f80cde7e56455d4380c9921a681f Mon Sep 17 00:00:00 2001 From: bytedream Date: Fri, 13 Oct 2023 11:41:56 +0200 Subject: [PATCH 036/204] Sanitize the full output filename (#253) --- crunchy-cli-core/src/utils/format.rs | 80 +++++++++++++--------------- 1 file changed, 36 insertions(+), 44 deletions(-) diff --git a/crunchy-cli-core/src/utils/format.rs b/crunchy-cli-core/src/utils/format.rs index b6dcf35..618f7d5 100644 --- a/crunchy-cli-core/src/utils/format.rs +++ b/crunchy-cli-core/src/utils/format.rs @@ -371,51 +371,43 @@ impl Format { /// Formats the given string if it has specific pattern in it. It's possible to sanitize it which /// removes characters which can cause failures if the output string is used as a file name. pub fn format_path(&self, path: PathBuf, sanitize: bool) -> PathBuf { - let sanitize_func = if sanitize { - |s: &str| sanitize_filename::sanitize(s) + let path = path + .to_string_lossy() + .to_string() + .replace("{title}", &self.title) + .replace( + "{audio}", + &self + .locales + .iter() + .map(|(a, _)| a.to_string()) + .collect::>() + .join("|"), + ) + .replace("{resolution}", &self.resolution.to_string()) + .replace("{series_id}", &self.series_id) + .replace("{series_name}", &self.series_name) + .replace("{season_id}", &self.season_id) + .replace("{season_name}", &self.season_title) + .replace( + "{season_number}", + &format!("{:0>2}", self.season_number.to_string()), + ) + .replace("{episode_id}", &self.episode_id) + .replace( + "{episode_number}", + &format!("{:0>2}", self.episode_number.to_string()), + ) + .replace( + "{relative_episode_number}", + &self.relative_episode_number.unwrap_or_default().to_string(), + ); + + if sanitize { + PathBuf::from(sanitize_filename::sanitize(path)) } else { - // converting this to a string is actually unnecessary - |s: &str| s.to_string() - }; - - let as_string = path.to_string_lossy().to_string(); - - PathBuf::from( - as_string - .replace("{title}", &sanitize_func(&self.title)) - .replace( - "{audio}", - &sanitize_func( - &self - .locales - .iter() - .map(|(a, _)| a.to_string()) - .collect::>() - .join("|"), - ), - ) - .replace("{resolution}", &sanitize_func(&self.resolution.to_string())) - .replace("{series_id}", &sanitize_func(&self.series_id)) - .replace("{series_name}", &sanitize_func(&self.series_name)) - .replace("{season_id}", &sanitize_func(&self.season_id)) - .replace("{season_name}", &sanitize_func(&self.season_title)) - .replace( - "{season_number}", - &sanitize_func(&format!("{:0>2}", self.season_number.to_string())), - ) - .replace("{episode_id}", &sanitize_func(&self.episode_id)) - .replace( - "{episode_number}", - &sanitize_func(&format!("{:0>2}", self.episode_number.to_string())), - ) - .replace( - "{relative_episode_number}", - &sanitize_func(&format!( - "{:0>2}", - self.relative_episode_number.unwrap_or_default().to_string() - )), - ), - ) + PathBuf::from(path) + } } pub fn visual_output(&self, dst: &Path) { From 81385ef6ce257522dc197d2ce8dd9a252d2f99c7 Mon Sep 17 00:00:00 2001 From: bytedream Date: Sun, 15 Oct 2023 20:49:03 +0200 Subject: [PATCH 037/204] Add relative_sequence_number format option (#206, #241, #246) --- crunchy-cli-core/src/archive/command.rs | 24 +++++---- crunchy-cli-core/src/archive/filter.rs | 64 +++++++++++++++--------- crunchy-cli-core/src/download/command.rs | 24 +++++---- crunchy-cli-core/src/download/filter.rs | 60 +++++++++++----------- crunchy-cli-core/src/utils/format.rs | 33 +++++++++--- 5 files changed, 122 insertions(+), 83 deletions(-) diff --git a/crunchy-cli-core/src/archive/command.rs b/crunchy-cli-core/src/archive/command.rs index 7ce1658..ffdc00c 100644 --- a/crunchy-cli-core/src/archive/command.rs +++ b/crunchy-cli-core/src/archive/command.rs @@ -39,17 +39,19 @@ pub struct Archive { #[arg(help = "Name of the output file")] #[arg(long_help = "Name of the output file.\ If you use one of the following pattern they will get replaced:\n \ - {title} → Title of the video\n \ - {series_name} → Name of the series\n \ - {season_name} → Name of the season\n \ - {audio} → Audio language of the video\n \ - {resolution} → Resolution of the video\n \ - {season_number} → Number of the season\n \ - {episode_number} → Number of the episode\n \ - {relative_episode_number} → Number of the episode relative to its season\n \ - {series_id} → ID of the series\n \ - {season_id} → ID of the season\n \ - {episode_id} → ID of the episode")] + {title} → Title of the video\n \ + {series_name} → Name of the series\n \ + {season_name} → Name of the season\n \ + {audio} → Audio language of the video\n \ + {resolution} → Resolution of the video\n \ + {season_number} → Number of the season\n \ + {episode_number} → Number of the episode\n \ + {relative_episode_number} → Number of the episode relative to its season\n \ + {sequence_number} → Like '{episode_number}' but without possible non-number characters\n \ + {relative_sequence_number} → Like '{relative_episode_number}' but with support for episode 0's and .5's\n \ + {series_id} → ID of the series\n \ + {season_id} → ID of the season\n \ + {episode_id} → ID of the episode")] #[arg(short, long, default_value = "{title}.mkv")] pub(crate) output: String, diff --git a/crunchy-cli-core/src/archive/filter.rs b/crunchy-cli-core/src/archive/filter.rs index 851b4b5..c2cc206 100644 --- a/crunchy-cli-core/src/archive/filter.rs +++ b/crunchy-cli-core/src/archive/filter.rs @@ -18,7 +18,7 @@ pub(crate) struct ArchiveFilter { url_filter: UrlFilter, archive: Archive, interactive_input: bool, - season_episode_count: HashMap>, + season_episodes: HashMap>, season_subtitles_missing: Vec, season_sorting: Vec, visited: Visited, @@ -30,7 +30,7 @@ impl ArchiveFilter { url_filter, archive, interactive_input, - season_episode_count: HashMap::new(), + season_episodes: HashMap::new(), season_subtitles_missing: vec![], season_sorting: vec![], visited: Visited::None, @@ -226,12 +226,12 @@ impl Filter for ArchiveFilter { episodes.extend(eps) } - if Format::has_relative_episodes_fmt(&self.archive.output) { + if Format::has_relative_fmt(&self.archive.output) { for episode in episodes.iter() { - self.season_episode_count + self.season_episodes .entry(episode.season_id.clone()) .or_insert(vec![]) - .push(episode.id.clone()) + .push(episode.clone()) } } @@ -299,22 +299,34 @@ impl Filter for ArchiveFilter { episodes.push((episode.clone(), episode.subtitle_locales.clone())) } - let relative_episode_number = if Format::has_relative_episodes_fmt(&self.archive.output) { - if self.season_episode_count.get(&episode.season_id).is_none() { - let season_episodes = episode.season().await?.episodes().await?; - self.season_episode_count.insert( - episode.season_id.clone(), - season_episodes.into_iter().map(|e| e.id).collect(), - ); + let mut relative_episode_number = None; + let mut relative_sequence_number = None; + // get the relative episode number. only done if the output string has the pattern to include + // the relative episode number as this requires some extra fetching + if Format::has_relative_fmt(&self.archive.output) { + let season_eps = match self.season_episodes.get(&episode.season_id) { + Some(eps) => eps, + None => { + self.season_episodes.insert( + episode.season_id.clone(), + episode.season().await?.episodes().await?, + ); + self.season_episodes.get(&episode.season_id).unwrap() + } + }; + let mut non_integer_sequence_number_count = 0; + for (i, ep) in season_eps.iter().enumerate() { + if ep.sequence_number.fract() != 0.0 || ep.sequence_number == 0.0 { + non_integer_sequence_number_count += 1; + } + if ep.id == episode.id { + relative_episode_number = Some(i + 1); + relative_sequence_number = + Some((i + 1 - non_integer_sequence_number_count) as f32); + break; + } } - let relative_episode_number = self - .season_episode_count - .get(&episode.season_id) - .unwrap() - .iter() - .position(|id| id == &episode.id) - .map(|index| index + 1); - if relative_episode_number.is_none() { + if relative_episode_number.is_none() || relative_sequence_number.is_none() { warn!( "Failed to get relative episode number for episode {} ({}) of {} season {}", episode.episode_number, @@ -323,16 +335,18 @@ impl Filter for ArchiveFilter { episode.season_number, ) } - relative_episode_number - } else { - None - }; + } Ok(Some( episodes .into_iter() .map(|(e, s)| { - SingleFormat::new_from_episode(e, s, relative_episode_number.map(|n| n as u32)) + SingleFormat::new_from_episode( + e, + s, + relative_episode_number.map(|n| n as u32), + relative_sequence_number, + ) }) .collect(), )) diff --git a/crunchy-cli-core/src/download/command.rs b/crunchy-cli-core/src/download/command.rs index baf27bf..6d059ef 100644 --- a/crunchy-cli-core/src/download/command.rs +++ b/crunchy-cli-core/src/download/command.rs @@ -35,17 +35,19 @@ pub struct Download { #[arg(help = "Name of the output file")] #[arg(long_help = "Name of the output file.\ If you use one of the following pattern they will get replaced:\n \ - {title} → Title of the video\n \ - {series_name} → Name of the series\n \ - {season_name} → Name of the season\n \ - {audio} → Audio language of the video\n \ - {resolution} → Resolution of the video\n \ - {season_number} → Number of the season\n \ - {episode_number} → Number of the episode\n \ - {relative_episode_number} → Number of the episode relative to its season\n \ - {series_id} → ID of the series\n \ - {season_id} → ID of the season\n \ - {episode_id} → ID of the episode")] + {title} → Title of the video\n \ + {series_name} → Name of the series\n \ + {season_name} → Name of the season\n \ + {audio} → Audio language of the video\n \ + {resolution} → Resolution of the video\n \ + {season_number} → Number of the season\n \ + {episode_number} → Number of the episode\n \ + {relative_episode_number} → Number of the episode relative to its season\n \ + {sequence_number} → Like '{episode_number}' but without possible non-number characters\n \ + {relative_sequence_number} → Like '{relative_episode_number}' but with support for episode 0's and .5's\n \ + {series_id} → ID of the series\n \ + {season_id} → ID of the season\n \ + {episode_id} → ID of the episode")] #[arg(short, long, default_value = "{title}.mp4")] pub(crate) output: String, diff --git a/crunchy-cli-core/src/download/filter.rs b/crunchy-cli-core/src/download/filter.rs index 31c0db6..c5aef7e 100644 --- a/crunchy-cli-core/src/download/filter.rs +++ b/crunchy-cli-core/src/download/filter.rs @@ -12,7 +12,7 @@ pub(crate) struct DownloadFilter { url_filter: UrlFilter, download: Download, interactive_input: bool, - season_episode_count: HashMap>, + season_episodes: HashMap>, season_subtitles_missing: Vec, season_visited: bool, } @@ -23,7 +23,7 @@ impl DownloadFilter { url_filter, download, interactive_input, - season_episode_count: HashMap::new(), + season_episodes: HashMap::new(), season_subtitles_missing: vec![], season_visited: false, } @@ -107,12 +107,12 @@ impl Filter for DownloadFilter { let mut episodes = season.episodes().await?; - if Format::has_relative_episodes_fmt(&self.download.output) { + if Format::has_relative_fmt(&self.download.output) { for episode in episodes.iter() { - self.season_episode_count + self.season_episodes .entry(episode.season_number) .or_insert(vec![]) - .push(episode.id.clone()) + .push(episode.clone()) } } @@ -189,28 +189,34 @@ impl Filter for DownloadFilter { } } + let mut relative_episode_number = None; + let mut relative_sequence_number = None; // get the relative episode number. only done if the output string has the pattern to include // the relative episode number as this requires some extra fetching - let relative_episode_number = if Format::has_relative_episodes_fmt(&self.download.output) { - if self - .season_episode_count - .get(&episode.season_number) - .is_none() - { - let season_episodes = episode.season().await?.episodes().await?; - self.season_episode_count.insert( - episode.season_number, - season_episodes.into_iter().map(|e| e.id).collect(), - ); + if Format::has_relative_fmt(&self.download.output) { + let season_eps = match self.season_episodes.get(&episode.season_number) { + Some(eps) => eps, + None => { + self.season_episodes.insert( + episode.season_number, + episode.season().await?.episodes().await?, + ); + self.season_episodes.get(&episode.season_number).unwrap() + } + }; + let mut non_integer_sequence_number_count = 0; + for (i, ep) in season_eps.iter().enumerate() { + if ep.sequence_number.fract() != 0.0 || ep.sequence_number == 0.0 { + non_integer_sequence_number_count += 1; + } + if ep.id == episode.id { + relative_episode_number = Some(i + 1); + relative_sequence_number = + Some((i + 1 - non_integer_sequence_number_count) as f32); + break; + } } - let relative_episode_number = self - .season_episode_count - .get(&episode.season_number) - .unwrap() - .iter() - .position(|id| id == &episode.id) - .map(|index| index + 1); - if relative_episode_number.is_none() { + if relative_episode_number.is_none() || relative_sequence_number.is_none() { warn!( "Failed to get relative episode number for episode {} ({}) of {} season {}", episode.episode_number, @@ -219,10 +225,7 @@ impl Filter for DownloadFilter { episode.season_number, ) } - relative_episode_number - } else { - None - }; + } Ok(Some(SingleFormat::new_from_episode( episode.clone(), @@ -234,6 +237,7 @@ impl Filter for DownloadFilter { } }), relative_episode_number.map(|n| n as u32), + relative_sequence_number, ))) } diff --git a/crunchy-cli-core/src/utils/format.rs b/crunchy-cli-core/src/utils/format.rs index 618f7d5..f32d82a 100644 --- a/crunchy-cli-core/src/utils/format.rs +++ b/crunchy-cli-core/src/utils/format.rs @@ -29,8 +29,9 @@ pub struct SingleFormat { pub episode_id: String, pub episode_number: String, - pub sequence_number: f32, pub relative_episode_number: Option, + pub sequence_number: f32, + pub relative_sequence_number: Option, pub duration: Duration, @@ -42,6 +43,7 @@ impl SingleFormat { episode: Episode, subtitles: Vec, relative_episode_number: Option, + relative_sequence_number: Option, ) -> Self { Self { identifier: if episode.identifier.is_empty() { @@ -73,6 +75,7 @@ impl SingleFormat { }, sequence_number: episode.sequence_number, relative_episode_number, + relative_sequence_number, duration: episode.duration, source: episode.into(), } @@ -92,8 +95,9 @@ impl SingleFormat { season_number: 1, episode_id: movie.id.clone(), episode_number: "1".to_string(), - sequence_number: 1.0, relative_episode_number: Some(1), + sequence_number: 1.0, + relative_sequence_number: Some(1.0), duration: movie.duration, source: movie.into(), } @@ -113,8 +117,9 @@ impl SingleFormat { season_number: 1, episode_id: music_video.id.clone(), episode_number: "1".to_string(), - sequence_number: 1.0, relative_episode_number: Some(1), + sequence_number: 1.0, + relative_sequence_number: Some(1.0), duration: music_video.duration, source: music_video.into(), } @@ -134,8 +139,9 @@ impl SingleFormat { season_number: 1, episode_id: concert.id.clone(), episode_number: "1".to_string(), - sequence_number: 1.0, relative_episode_number: Some(1), + sequence_number: 1.0, + relative_sequence_number: Some(1.0), duration: concert.duration, source: concert.into(), } @@ -328,8 +334,9 @@ pub struct Format { pub episode_id: String, pub episode_number: String, - pub sequence_number: f32, pub relative_episode_number: Option, + pub sequence_number: f32, + pub relative_sequence_number: Option, } impl Format { @@ -363,8 +370,9 @@ impl Format { season_number: first_format.season_number, episode_id: first_format.episode_id, episode_number: first_format.episode_number, - sequence_number: first_format.sequence_number, relative_episode_number: first_format.relative_episode_number, + sequence_number: first_format.sequence_number, + relative_sequence_number: first_format.relative_sequence_number, } } @@ -401,6 +409,14 @@ impl Format { .replace( "{relative_episode_number}", &self.relative_episode_number.unwrap_or_default().to_string(), + ) + .replace("{sequence_number}", &self.sequence_number.to_string()) + .replace( + "{relative_sequence_number}", + &self + .relative_sequence_number + .unwrap_or_default() + .to_string(), ); if sanitize { @@ -447,7 +463,8 @@ impl Format { tab_info!("FPS: {:.2}", self.fps) } - pub fn has_relative_episodes_fmt>(s: S) -> bool { - return s.as_ref().contains("{relative_episode_number}"); + pub fn has_relative_fmt>(s: S) -> bool { + return s.as_ref().contains("{relative_episode_number}") + || s.as_ref().contains("{relative_sequence_number}"); } } From bbb5a7876520384e2e7725d1adb6bb08faa9caa5 Mon Sep 17 00:00:00 2001 From: Valentine Briese Date: Sun, 15 Oct 2023 11:52:53 -0700 Subject: [PATCH 038/204] Add `--threads` (`-t`) option to downloading commands (#256) * Add `single-threaded` option to downloading commands * Replace `--single-threaded` boolean option with `--threads` optional `usize` option * Simplify `threads` field unwrapping * Make `--threads` `usize` with a default value --- crunchy-cli-core/src/archive/command.rs | 7 +- crunchy-cli-core/src/download/command.rs | 7 +- crunchy-cli-core/src/utils/download.rs | 301 ++++++++++++----------- 3 files changed, 166 insertions(+), 149 deletions(-) diff --git a/crunchy-cli-core/src/archive/command.rs b/crunchy-cli-core/src/archive/command.rs index 7ce1658..bb4794f 100644 --- a/crunchy-cli-core/src/archive/command.rs +++ b/crunchy-cli-core/src/archive/command.rs @@ -98,6 +98,10 @@ pub struct Archive { #[arg(short, long, default_value_t = false)] pub(crate) yes: bool, + #[arg(help = "The number of threads used to download")] + #[arg(short, long, default_value_t = num_cpus::get())] + pub(crate) threads: usize, + #[arg(help = "Crunchyroll series url(s)")] #[arg(required = true)] pub(crate) urls: Vec, @@ -158,7 +162,8 @@ impl Execute for Archive { .ffmpeg_preset(self.ffmpeg_preset.clone().unwrap_or_default()) .output_format(Some("matroska".to_string())) .audio_sort(Some(self.audio.clone())) - .subtitle_sort(Some(self.subtitle.clone())); + .subtitle_sort(Some(self.subtitle.clone())) + .threads(self.threads); for single_formats in single_format_collection.into_iter() { let (download_formats, mut format) = get_format(&self, &single_formats).await?; diff --git a/crunchy-cli-core/src/download/command.rs b/crunchy-cli-core/src/download/command.rs index baf27bf..760bf38 100644 --- a/crunchy-cli-core/src/download/command.rs +++ b/crunchy-cli-core/src/download/command.rs @@ -80,6 +80,10 @@ pub struct Download { #[arg(long, default_value_t = false)] pub(crate) force_hardsub: bool, + #[arg(help = "The number of threads used to download")] + #[arg(short, long, default_value_t = num_cpus::get())] + pub(crate) threads: usize, + #[arg(help = "Url(s) to Crunchyroll episodes or series")] #[arg(required = true)] pub(crate) urls: Vec, @@ -149,7 +153,8 @@ impl Execute for Download { } else { None }) - .ffmpeg_preset(self.ffmpeg_preset.clone().unwrap_or_default()); + .ffmpeg_preset(self.ffmpeg_preset.clone().unwrap_or_default()) + .threads(self.threads); for mut single_formats in single_format_collection.into_iter() { // the vec contains always only one item diff --git a/crunchy-cli-core/src/utils/download.rs b/crunchy-cli-core/src/utils/download.rs index 29f160a..ff9f240 100644 --- a/crunchy-cli-core/src/utils/download.rs +++ b/crunchy-cli-core/src/utils/download.rs @@ -50,6 +50,7 @@ pub struct DownloadBuilder { audio_sort: Option>, subtitle_sort: Option>, force_hardsub: bool, + threads: usize, } impl DownloadBuilder { @@ -61,6 +62,7 @@ impl DownloadBuilder { audio_sort: None, subtitle_sort: None, force_hardsub: false, + threads: num_cpus::get(), } } @@ -73,6 +75,7 @@ impl DownloadBuilder { subtitle_sort: self.subtitle_sort, force_hardsub: self.force_hardsub, + threads: self.threads, formats: vec![], } @@ -99,6 +102,7 @@ pub struct Downloader { subtitle_sort: Option>, force_hardsub: bool, + threads: usize, formats: Vec, } @@ -502,7 +506,8 @@ impl Downloader { let tempfile = tempfile(".mp4")?; let (mut file, path) = tempfile.into_parts(); - download_segments(ctx, &mut file, message, variant_data).await?; + self.download_segments(ctx, &mut file, message, variant_data) + .await?; Ok(path) } @@ -516,7 +521,8 @@ impl Downloader { let tempfile = tempfile(".m4a")?; let (mut file, path) = tempfile.into_parts(); - download_segments(ctx, &mut file, message, variant_data).await?; + self.download_segments(ctx, &mut file, message, variant_data) + .await?; Ok(path) } @@ -537,188 +543,189 @@ impl Downloader { Ok(path) } -} -pub async fn download_segments( - ctx: &Context, - writer: &mut impl Write, - message: String, - variant_data: &VariantData, -) -> Result<()> { - let segments = variant_data.segments().await?; - let total_segments = segments.len(); + async fn download_segments( + &self, + ctx: &Context, + writer: &mut impl Write, + message: String, + variant_data: &VariantData, + ) -> Result<()> { + let segments = variant_data.segments().await?; + let total_segments = segments.len(); - let client = Arc::new(ctx.crunchy.client()); - let count = Arc::new(Mutex::new(0)); + let client = Arc::new(ctx.crunchy.client()); + let count = Arc::new(Mutex::new(0)); - let progress = if log::max_level() == LevelFilter::Info { - let estimated_file_size = estimate_variant_file_size(variant_data, &segments); + let progress = if log::max_level() == LevelFilter::Info { + let estimated_file_size = estimate_variant_file_size(variant_data, &segments); - let progress = ProgressBar::new(estimated_file_size) - .with_style( - ProgressStyle::with_template( - ":: {msg} {bytes:>10} {bytes_per_sec:>12} [{wide_bar}] {percent:>3}%", + let progress = ProgressBar::new(estimated_file_size) + .with_style( + ProgressStyle::with_template( + ":: {msg} {bytes:>10} {bytes_per_sec:>12} [{wide_bar}] {percent:>3}%", + ) + .unwrap() + .progress_chars("##-"), ) - .unwrap() - .progress_chars("##-"), - ) - .with_message(message) - .with_finish(ProgressFinish::Abandon); - Some(progress) - } else { - None - }; + .with_message(message) + .with_finish(ProgressFinish::Abandon); + Some(progress) + } else { + None + }; - let cpus = num_cpus::get(); - let mut segs: Vec> = Vec::with_capacity(cpus); - for _ in 0..cpus { - segs.push(vec![]) - } - for (i, segment) in segments.clone().into_iter().enumerate() { - segs[i - ((i / cpus) * cpus)].push(segment); - } + let cpus = self.threads; + let mut segs: Vec> = Vec::with_capacity(cpus); + for _ in 0..cpus { + segs.push(vec![]) + } + for (i, segment) in segments.clone().into_iter().enumerate() { + segs[i - ((i / cpus) * cpus)].push(segment); + } - let (sender, mut receiver) = unbounded_channel(); + let (sender, mut receiver) = unbounded_channel(); - let mut join_set: JoinSet> = JoinSet::new(); - for num in 0..cpus { - let thread_client = client.clone(); - let thread_sender = sender.clone(); - let thread_segments = segs.remove(0); - let thread_count = count.clone(); - join_set.spawn(async move { - let after_download_sender = thread_sender.clone(); + let mut join_set: JoinSet> = JoinSet::new(); + for num in 0..cpus { + let thread_client = client.clone(); + let thread_sender = sender.clone(); + let thread_segments = segs.remove(0); + let thread_count = count.clone(); + join_set.spawn(async move { + let after_download_sender = thread_sender.clone(); - // the download process is encapsulated in its own function. this is done to easily - // catch errors which get returned with `...?` and `bail!(...)` and that the thread - // itself can report that an error has occurred - let download = || async move { - for (i, segment) in thread_segments.into_iter().enumerate() { - let mut retry_count = 0; - let mut buf = loop { - let request = thread_client - .get(&segment.url) - .timeout(Duration::from_secs(60)) - .send(); + // the download process is encapsulated in its own function. this is done to easily + // catch errors which get returned with `...?` and `bail!(...)` and that the thread + // itself can report that an error has occurred + let download = || async move { + for (i, segment) in thread_segments.into_iter().enumerate() { + let mut retry_count = 0; + let mut buf = loop { + let request = thread_client + .get(&segment.url) + .timeout(Duration::from_secs(60)) + .send(); - let response = match request.await { - Ok(r) => r, - Err(e) => { - if retry_count == 5 { - bail!("Max retry count reached ({}), multiple errors occurred while receiving segment {}: {}", retry_count, num + (i * cpus), e) - } - debug!("Failed to download segment {} ({}). Retrying, {} out of 5 retries left", num + (i * cpus), e, 5 - retry_count); - continue - } - }; - - match response.bytes().await { - Ok(b) => break b.to_vec(), - Err(e) => { - if e.is_body() { + let response = match request.await { + Ok(r) => r, + Err(e) => { if retry_count == 5 { bail!("Max retry count reached ({}), multiple errors occurred while receiving segment {}: {}", retry_count, num + (i * cpus), e) } - debug!("Failed to download segment {} ({}). Retrying, {} out of 5 retries left", num + (i * cpus), e, 5 - retry_count) - } else { - bail!("{}", e) + debug!("Failed to download segment {} ({}). Retrying, {} out of 5 retries left", num + (i * cpus), e, 5 - retry_count); + continue + } + }; + + match response.bytes().await { + Ok(b) => break b.to_vec(), + Err(e) => { + if e.is_body() { + if retry_count == 5 { + bail!("Max retry count reached ({}), multiple errors occurred while receiving segment {}: {}", retry_count, num + (i * cpus), e) + } + debug!("Failed to download segment {} ({}). Retrying, {} out of 5 retries left", num + (i * cpus), e, 5 - retry_count) + } else { + bail!("{}", e) + } } } - } - retry_count += 1; - }; + retry_count += 1; + }; - buf = VariantSegment::decrypt(buf.borrow_mut(), segment.key)?.to_vec(); + buf = VariantSegment::decrypt(buf.borrow_mut(), segment.key)?.to_vec(); - let mut c = thread_count.lock().await; - debug!( - "Downloaded and decrypted segment [{}/{} {:.2}%] {}", - num + (i * cpus) + 1, - total_segments, - ((*c + 1) as f64 / total_segments as f64) * 100f64, - segment.url - ); + let mut c = thread_count.lock().await; + debug!( + "Downloaded and decrypted segment [{}/{} {:.2}%] {}", + num + (i * cpus) + 1, + total_segments, + ((*c + 1) as f64 / total_segments as f64) * 100f64, + segment.url + ); - thread_sender.send((num as i32 + (i * cpus) as i32, buf))?; + thread_sender.send((num as i32 + (i * cpus) as i32, buf))?; - *c += 1; + *c += 1; + } + Ok(()) + }; + + + let result = download().await; + if result.is_err() { + after_download_sender.send((-1 as i32, vec![]))?; } - Ok(()) - }; + result + }); + } + // drop the sender already here so it does not outlive all download threads which are the only + // real consumers of it + drop(sender); - let result = download().await; - if result.is_err() { - after_download_sender.send((-1 as i32, vec![]))?; + // this is the main loop which writes the data. it uses a BTreeMap as a buffer as the write + // happens synchronized. the download consist of multiple segments. the map keys are representing + // the segment number and the values the corresponding bytes + let mut data_pos = 0; + let mut buf: BTreeMap> = BTreeMap::new(); + while let Some((pos, bytes)) = receiver.recv().await { + // if the position is lower than 0, an error occurred in the sending download thread + if pos < 0 { + break; } - result - }); - } - // drop the sender already here so it does not outlive all download threads which are the only - // real consumers of it - drop(sender); + if let Some(p) = &progress { + let progress_len = p.length().unwrap(); + let estimated_segment_len = (variant_data.bandwidth / 8) + * segments.get(pos as usize).unwrap().length.as_secs(); + let bytes_len = bytes.len() as u64; - // this is the main loop which writes the data. it uses a BTreeMap as a buffer as the write - // happens synchronized. the download consist of multiple segments. the map keys are representing - // the segment number and the values the corresponding bytes - let mut data_pos = 0; - let mut buf: BTreeMap> = BTreeMap::new(); - while let Some((pos, bytes)) = receiver.recv().await { - // if the position is lower than 0, an error occurred in the sending download thread - if pos < 0 { - break; + p.set_length(progress_len - estimated_segment_len + bytes_len); + p.inc(bytes_len) + } + + // check if the currently sent bytes are the next in the buffer. if so, write them directly + // to the target without first adding them to the buffer. + // if not, add them to the buffer + if data_pos == pos { + writer.write_all(bytes.borrow())?; + data_pos += 1; + } else { + buf.insert(pos, bytes); + } + // check if the buffer contains the next segment(s) + while let Some(b) = buf.remove(&data_pos) { + writer.write_all(b.borrow())?; + data_pos += 1; + } } - if let Some(p) = &progress { - let progress_len = p.length().unwrap(); - let estimated_segment_len = - (variant_data.bandwidth / 8) * segments.get(pos as usize).unwrap().length.as_secs(); - let bytes_len = bytes.len() as u64; - - p.set_length(progress_len - estimated_segment_len + bytes_len); - p.inc(bytes_len) + // if any error has occurred while downloading it gets returned here + while let Some(joined) = join_set.join_next().await { + joined?? } - // check if the currently sent bytes are the next in the buffer. if so, write them directly - // to the target without first adding them to the buffer. - // if not, add them to the buffer - if data_pos == pos { - writer.write_all(bytes.borrow())?; - data_pos += 1; - } else { - buf.insert(pos, bytes); - } - // check if the buffer contains the next segment(s) + // write the remaining buffer, if existent while let Some(b) = buf.remove(&data_pos) { writer.write_all(b.borrow())?; data_pos += 1; } - } - // if any error has occurred while downloading it gets returned here - while let Some(joined) = join_set.join_next().await { - joined?? - } + if !buf.is_empty() { + bail!( + "Download buffer is not empty. Remaining segments: {}", + buf.into_keys() + .map(|k| k.to_string()) + .collect::>() + .join(", ") + ) + } - // write the remaining buffer, if existent - while let Some(b) = buf.remove(&data_pos) { - writer.write_all(b.borrow())?; - data_pos += 1; + Ok(()) } - - if !buf.is_empty() { - bail!( - "Download buffer is not empty. Remaining segments: {}", - buf.into_keys() - .map(|k| k.to_string()) - .collect::>() - .join(", ") - ) - } - - Ok(()) } fn estimate_variant_file_size(variant_data: &VariantData, segments: &Vec) -> u64 { From 568bce00085cc301029d0b39c39cf15b97aa1d3d Mon Sep 17 00:00:00 2001 From: bytedream Date: Sun, 15 Oct 2023 22:39:53 +0200 Subject: [PATCH 039/204] Manually implement filename sanitizing to allow the usage of file separators --- Cargo.lock | 11 ----- crunchy-cli-core/Cargo.toml | 1 - crunchy-cli-core/src/archive/command.rs | 2 +- crunchy-cli-core/src/download/command.rs | 2 +- crunchy-cli-core/src/utils/format.rs | 55 ++++++++++++------------ crunchy-cli-core/src/utils/os.rs | 48 +++++++++++++++++++++ 6 files changed, 77 insertions(+), 42 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 09cad3e..409a005 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -401,7 +401,6 @@ dependencies = [ "regex", "reqwest", "rustls-native-certs", - "sanitize-filename", "serde", "serde_json", "serde_plain", @@ -1517,16 +1516,6 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" -[[package]] -name = "sanitize-filename" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ed72fbaf78e6f2d41744923916966c4fbe3d7c74e3037a8ee482f1115572603" -dependencies = [ - "lazy_static", - "regex", -] - [[package]] name = "schannel" version = "0.1.22" diff --git a/crunchy-cli-core/Cargo.toml b/crunchy-cli-core/Cargo.toml index fc298f3..e38cb1a 100644 --- a/crunchy-cli-core/Cargo.toml +++ b/crunchy-cli-core/Cargo.toml @@ -28,7 +28,6 @@ log = { version = "0.4", features = ["std"] } num_cpus = "1.16" regex = "1.9" reqwest = { version = "0.11", default-features = false, features = ["socks"] } -sanitize-filename = "0.5" serde = "1.0" serde_json = "1.0" serde_plain = "1.0" diff --git a/crunchy-cli-core/src/archive/command.rs b/crunchy-cli-core/src/archive/command.rs index bb4794f..3f455ed 100644 --- a/crunchy-cli-core/src/archive/command.rs +++ b/crunchy-cli-core/src/archive/command.rs @@ -173,7 +173,7 @@ impl Execute for Archive { downloader.add_format(download_format) } - let formatted_path = format.format_path((&self.output).into(), true); + let formatted_path = format.format_path((&self.output).into()); let (path, changed) = free_file(formatted_path.clone()); if changed && self.skip_existing { diff --git a/crunchy-cli-core/src/download/command.rs b/crunchy-cli-core/src/download/command.rs index 760bf38..9c9ecb4 100644 --- a/crunchy-cli-core/src/download/command.rs +++ b/crunchy-cli-core/src/download/command.rs @@ -165,7 +165,7 @@ impl Execute for Download { let mut downloader = download_builder.clone().build(); downloader.add_format(download_format); - let formatted_path = format.format_path((&self.output).into(), true); + let formatted_path = format.format_path((&self.output).into()); let (path, changed) = free_file(formatted_path.clone()); if changed && self.skip_existing { diff --git a/crunchy-cli-core/src/utils/format.rs b/crunchy-cli-core/src/utils/format.rs index 618f7d5..f462263 100644 --- a/crunchy-cli-core/src/utils/format.rs +++ b/crunchy-cli-core/src/utils/format.rs @@ -1,6 +1,6 @@ use crate::utils::filter::real_dedup_vec; use crate::utils::log::tab_info; -use crate::utils::os::is_special_file; +use crate::utils::os::{is_special_file, sanitize}; use anyhow::Result; use chrono::Duration; use crunchyroll_rs::media::{Resolution, Stream, Subtitle, VariantData}; @@ -368,46 +368,45 @@ impl Format { } } - /// Formats the given string if it has specific pattern in it. It's possible to sanitize it which - /// removes characters which can cause failures if the output string is used as a file name. - pub fn format_path(&self, path: PathBuf, sanitize: bool) -> PathBuf { - let path = path - .to_string_lossy() - .to_string() - .replace("{title}", &self.title) + /// Formats the given string if it has specific pattern in it. It also sanitizes the filename. + pub fn format_path(&self, path: PathBuf) -> PathBuf { + let mut path = sanitize(path.to_string_lossy(), false); + path = path + .replace("{title}", &sanitize(&self.title, true)) .replace( "{audio}", - &self - .locales - .iter() - .map(|(a, _)| a.to_string()) - .collect::>() - .join("|"), + &sanitize( + self.locales + .iter() + .map(|(a, _)| a.to_string()) + .collect::>() + .join("|"), + true, + ), ) - .replace("{resolution}", &self.resolution.to_string()) - .replace("{series_id}", &self.series_id) - .replace("{series_name}", &self.series_name) - .replace("{season_id}", &self.season_id) - .replace("{season_name}", &self.season_title) + .replace("{resolution}", &sanitize(self.resolution.to_string(), true)) + .replace("{series_id}", &sanitize(&self.series_id, true)) + .replace("{series_name}", &sanitize(&self.series_name, true)) + .replace("{season_id}", &sanitize(&self.season_id, true)) + .replace("{season_name}", &sanitize(&self.season_title, true)) .replace( "{season_number}", - &format!("{:0>2}", self.season_number.to_string()), + &format!("{:0>2}", sanitize(self.season_number.to_string(), true)), ) - .replace("{episode_id}", &self.episode_id) + .replace("{episode_id}", &sanitize(&self.episode_id, true)) .replace( "{episode_number}", - &format!("{:0>2}", self.episode_number.to_string()), + &format!("{:0>2}", sanitize(&self.episode_number, true)), ) .replace( "{relative_episode_number}", - &self.relative_episode_number.unwrap_or_default().to_string(), + &sanitize( + self.relative_episode_number.unwrap_or_default().to_string(), + true, + ), ); - if sanitize { - PathBuf::from(sanitize_filename::sanitize(path)) - } else { - PathBuf::from(path) - } + PathBuf::from(path) } pub fn visual_output(&self, dst: &Path) { diff --git a/crunchy-cli-core/src/utils/os.rs b/crunchy-cli-core/src/utils/os.rs index f6d9ad0..1f76b90 100644 --- a/crunchy-cli-core/src/utils/os.rs +++ b/crunchy-cli-core/src/utils/os.rs @@ -1,4 +1,6 @@ use log::debug; +use regex::{Regex, RegexBuilder}; +use std::borrow::Cow; use std::io::ErrorKind; use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; @@ -78,3 +80,49 @@ pub fn free_file(mut path: PathBuf) -> (PathBuf, bool) { pub fn is_special_file>(path: P) -> bool { path.as_ref().exists() && !path.as_ref().is_file() && !path.as_ref().is_dir() } + +lazy_static::lazy_static! { + static ref ILLEGAL_RE: Regex = Regex::new(r#"[\?<>:\*\|":]"#).unwrap(); + static ref CONTROL_RE: Regex = Regex::new(r"[\x00-\x1f\x80-\x9f]").unwrap(); + static ref RESERVED_RE: Regex = Regex::new(r"^\.+$").unwrap(); + static ref WINDOWS_RESERVED_RE: Regex = RegexBuilder::new(r"(?i)^(con|prn|aux|nul|com[0-9]|lpt[0-9])(\..*)?$") + .case_insensitive(true) + .build() + .unwrap(); + static ref WINDOWS_TRAILING_RE: Regex = Regex::new(r"[\. ]+$").unwrap(); +} + +/// Sanitizes a filename with the option to include/exclude the path separator from sanitizing. This +/// is based of the implementation of the +/// [`sanitize-filename`](https://crates.io/crates/sanitize-filename) crate. +pub fn sanitize>(path: S, include_path_separator: bool) -> String { + let path = Cow::from(path.as_ref()); + + let path = ILLEGAL_RE.replace_all(&path, ""); + let path = CONTROL_RE.replace_all(&path, ""); + let path = RESERVED_RE.replace(&path, ""); + + let collect = |name: String| { + if name.len() > 255 { + name[..255].to_string() + } else { + name + } + }; + + if cfg!(windows) { + let path = WINDOWS_RESERVED_RE.replace(&path, ""); + let path = WINDOWS_TRAILING_RE.replace(&path, ""); + let mut path = path.to_string(); + if include_path_separator { + path = path.replace(['\\', '/'], ""); + } + collect(path) + } else { + let mut path = path.to_string(); + if include_path_separator { + path = path.replace('/', ""); + } + collect(path) + } +} From 685c79d673538aa981515806595cbba2da4decbf Mon Sep 17 00:00:00 2001 From: bytedream Date: Sun, 15 Oct 2023 22:55:44 +0200 Subject: [PATCH 040/204] Add 2-digit padding to relative_episode_number, sequence_number and relative_sequence_number format option --- crunchy-cli-core/src/utils/format.rs | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/crunchy-cli-core/src/utils/format.rs b/crunchy-cli-core/src/utils/format.rs index 1ba8136..4679878 100644 --- a/crunchy-cli-core/src/utils/format.rs +++ b/crunchy-cli-core/src/utils/format.rs @@ -408,22 +408,28 @@ impl Format { ) .replace( "{relative_episode_number}", - &sanitize( - self.relative_episode_number.unwrap_or_default().to_string(), - true, + &format!( + "{:0>2}", + sanitize( + self.relative_episode_number.unwrap_or_default().to_string(), + true, + ) ), ) .replace( "{sequence_number}", - &sanitize(self.sequence_number.to_string(), true), + &format!("{:0>2}", sanitize(self.sequence_number.to_string(), true)), ) .replace( "{relative_sequence_number}", - &sanitize( - self.relative_sequence_number - .unwrap_or_default() - .to_string(), - true, + &format!( + "{:0>2}", + sanitize( + self.relative_sequence_number + .unwrap_or_default() + .to_string(), + true, + ) ), ); From d0fe7f54f6c0e74f87d13a6d072599c12aad8367 Mon Sep 17 00:00:00 2001 From: bytedream Date: Sun, 15 Oct 2023 23:34:22 +0200 Subject: [PATCH 041/204] Show fractal in relative_sequence_number if present --- crunchy-cli-core/src/archive/filter.rs | 8 +++++--- crunchy-cli-core/src/download/filter.rs | 8 +++++--- crunchy-cli-core/src/utils/parse.rs | 10 ++++++++++ 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/crunchy-cli-core/src/archive/filter.rs b/crunchy-cli-core/src/archive/filter.rs index c2cc206..024ad17 100644 --- a/crunchy-cli-core/src/archive/filter.rs +++ b/crunchy-cli-core/src/archive/filter.rs @@ -2,7 +2,7 @@ use crate::archive::command::Archive; use crate::utils::filter::{real_dedup_vec, Filter}; use crate::utils::format::{Format, SingleFormat, SingleFormatCollection}; use crate::utils::interactive_select::{check_for_duplicated_seasons, get_duplicated_seasons}; -use crate::utils::parse::UrlFilter; +use crate::utils::parse::{fract, UrlFilter}; use anyhow::Result; use crunchyroll_rs::{Concert, Episode, Locale, Movie, MovieListing, MusicVideo, Season, Series}; use log::{info, warn}; @@ -321,8 +321,10 @@ impl Filter for ArchiveFilter { } if ep.id == episode.id { relative_episode_number = Some(i + 1); - relative_sequence_number = - Some((i + 1 - non_integer_sequence_number_count) as f32); + relative_sequence_number = Some( + (i + 1 - non_integer_sequence_number_count) as f32 + + fract(ep.sequence_number), + ); break; } } diff --git a/crunchy-cli-core/src/download/filter.rs b/crunchy-cli-core/src/download/filter.rs index c5aef7e..ff3c2ff 100644 --- a/crunchy-cli-core/src/download/filter.rs +++ b/crunchy-cli-core/src/download/filter.rs @@ -2,7 +2,7 @@ use crate::download::Download; use crate::utils::filter::Filter; use crate::utils::format::{Format, SingleFormat, SingleFormatCollection}; use crate::utils::interactive_select::{check_for_duplicated_seasons, get_duplicated_seasons}; -use crate::utils::parse::UrlFilter; +use crate::utils::parse::{fract, UrlFilter}; use anyhow::{bail, Result}; use crunchyroll_rs::{Concert, Episode, Movie, MovieListing, MusicVideo, Season, Series}; use log::{error, info, warn}; @@ -211,8 +211,10 @@ impl Filter for DownloadFilter { } if ep.id == episode.id { relative_episode_number = Some(i + 1); - relative_sequence_number = - Some((i + 1 - non_integer_sequence_number_count) as f32); + relative_sequence_number = Some( + (i + 1 - non_integer_sequence_number_count) as f32 + + fract(ep.sequence_number), + ); break; } } diff --git a/crunchy-cli-core/src/utils/parse.rs b/crunchy-cli-core/src/utils/parse.rs index f85d8c2..c0ac2b0 100644 --- a/crunchy-cli-core/src/utils/parse.rs +++ b/crunchy-cli-core/src/utils/parse.rs @@ -192,3 +192,13 @@ pub fn parse_resolution(mut resolution: String) -> Result { bail!("Could not find resolution") } } + +/// Dirty implementation of [`f32::fract`] with more accuracy. +pub fn fract(input: f32) -> f32 { + if input.fract() == 0.0 { + return 0.0; + } + format!("0.{}", input.to_string().split('.').last().unwrap()) + .parse::() + .unwrap() +} From 5a3a30444329548134ca998eebaa20e96eb88634 Mon Sep 17 00:00:00 2001 From: bytedream Date: Sun, 15 Oct 2023 23:52:44 +0200 Subject: [PATCH 042/204] Use episode sequence number as filter number for url episode filtering --- crunchy-cli-core/src/archive/filter.rs | 2 +- crunchy-cli-core/src/download/filter.rs | 4 ++-- crunchy-cli-core/src/search/filter.rs | 2 +- crunchy-cli-core/src/utils/parse.rs | 10 +++++----- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/crunchy-cli-core/src/archive/filter.rs b/crunchy-cli-core/src/archive/filter.rs index 024ad17..91023a3 100644 --- a/crunchy-cli-core/src/archive/filter.rs +++ b/crunchy-cli-core/src/archive/filter.rs @@ -241,7 +241,7 @@ impl Filter for ArchiveFilter { async fn visit_episode(&mut self, mut episode: Episode) -> Result> { if !self .url_filter - .is_episode_valid(episode.episode_number, episode.season_number) + .is_episode_valid(episode.sequence_number, episode.season_number) { return Ok(None); } diff --git a/crunchy-cli-core/src/download/filter.rs b/crunchy-cli-core/src/download/filter.rs index ff3c2ff..55b1e8b 100644 --- a/crunchy-cli-core/src/download/filter.rs +++ b/crunchy-cli-core/src/download/filter.rs @@ -118,7 +118,7 @@ impl Filter for DownloadFilter { episodes.retain(|e| { self.url_filter - .is_episode_valid(e.episode_number, season.season_number) + .is_episode_valid(e.sequence_number, season.season_number) }); Ok(episodes) @@ -127,7 +127,7 @@ impl Filter for DownloadFilter { async fn visit_episode(&mut self, mut episode: Episode) -> Result> { if !self .url_filter - .is_episode_valid(episode.episode_number, episode.season_number) + .is_episode_valid(episode.sequence_number, episode.season_number) { return Ok(None); } diff --git a/crunchy-cli-core/src/search/filter.rs b/crunchy-cli-core/src/search/filter.rs index 0b31823..264b31d 100644 --- a/crunchy-cli-core/src/search/filter.rs +++ b/crunchy-cli-core/src/search/filter.rs @@ -24,7 +24,7 @@ impl FilterOptions { self.check_audio_language(&vec![e.audio_locale.clone()]) && self .url_filter - .is_episode_valid(e.episode_number, e.season_number) + .is_episode_valid(e.sequence_number, e.season_number) }); episodes } diff --git a/crunchy-cli-core/src/utils/parse.rs b/crunchy-cli-core/src/utils/parse.rs index c0ac2b0..3fc7e7c 100644 --- a/crunchy-cli-core/src/utils/parse.rs +++ b/crunchy-cli-core/src/utils/parse.rs @@ -10,8 +10,8 @@ use regex::Regex; /// If `to_*` is [`None`] they're set to [`u32::MAX`]. #[derive(Debug, Default)] pub struct InnerUrlFilter { - from_episode: Option, - to_episode: Option, + from_episode: Option, + to_episode: Option, from_season: Option, to_season: Option, } @@ -39,10 +39,10 @@ impl UrlFilter { }) } - pub fn is_episode_valid(&self, episode: u32, season: u32) -> bool { + pub fn is_episode_valid(&self, episode: f32, season: u32) -> bool { self.inner.iter().any(|f| { - let from_episode = f.from_episode.unwrap_or(u32::MIN); - let to_episode = f.to_episode.unwrap_or(u32::MAX); + let from_episode = f.from_episode.unwrap_or(f32::MIN); + let to_episode = f.to_episode.unwrap_or(f32::MAX); let from_season = f.from_season.unwrap_or(u32::MIN); let to_season = f.to_season.unwrap_or(u32::MAX); From f56d9ecabf356ab9870c94f8ca5f3b46a2a39484 Mon Sep 17 00:00:00 2001 From: Catd <34575742+Nannk@users.noreply.github.com> Date: Mon, 16 Oct 2023 15:04:45 +0000 Subject: [PATCH 043/204] Changes in Readme regarding subtitles and flag usage (#255) * Update README.md updated Flags and subtitles sections * Update README.md * Update README.md Comma in a better place --- README.md | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 7a620cb..df285cc 100644 --- a/README.md +++ b/README.md @@ -92,6 +92,8 @@ $ cargo install --force --path . > All shown commands are examples 🧑🏼‍🍳 +### Global Flags + crunchy-cli requires you to log in. Though you can use a non-premium account, you will not have access to premium content without a subscription. You can authenticate with your credentials (user:password) or by using a refresh token. @@ -99,7 +101,7 @@ You can authenticate with your credentials (user:password) or by using a refresh - Credentials ```shell - $ crunchy-cli --credentials "user:password" + $ crunchy-cli --credentials "user:password" ``` - Refresh Token @@ -107,13 +109,13 @@ You can authenticate with your credentials (user:password) or by using a refresh The easiest way to get it is via a browser extension which lets you export your cookies, like [Cookie-Editor](https://cookie-editor.cgagnier.ca/) ([Firefox](https://addons.mozilla.org/en-US/firefox/addon/cookie-editor/) / [Chrome](https://chrome.google.com/webstore/detail/cookie-editor/hlkenndednhfkekhgcdicdfddnkalmdm)). When installed, look for the `etp_rt` entry and extract its value. ```shell - $ crunchy-cli --etp-rt "4ebf1690-53a4-491a-a2ac-488309120f5d" + $ crunchy-cli --etp-rt "4ebf1690-53a4-491a-a2ac-488309120f5d" ``` - Stay Anonymous Login without an account (you won't be able to access premium content): ```shell - $ crunchy-cli --anonymous + $ crunchy-cli --anonymous ``` ### Global settings @@ -124,7 +126,7 @@ You can set specific settings which will be If you want to include debug information in the output, use the `-v` / `--verbose` flag to show it. ```shell - $ crunchy-cli -v + $ crunchy-cli -v ``` This flag can't be used with `-q` / `--quiet`. @@ -133,7 +135,7 @@ You can set specific settings which will be If you want to hide all output, use the `-q` / `--quiet` flag to do so. This is especially useful if you want to pipe the output video to an external program (like a video player). ```shell - $ crunchy-cli -q + $ crunchy-cli -q ``` - Language @@ -141,7 +143,7 @@ You can set specific settings which will be By default, the resulting metadata like title or description are shown in your system language (if Crunchyroll supports it, else in English). If you want to show the results in another language, use the `--lang` flag to set it. ```shell - $ crunchy-cli --lang de-DE + $ crunchy-cli --lang de-DE ``` - Experimental fixes @@ -150,7 +152,7 @@ You can set specific settings which will be The `--experimental-fixes` flag tries to fix some of those issues. As the *experimental* in `--experimental-fixes` states, these fixes may or may not break other functionality. ```shell - $ crunchy-cli --experimental-fixes + $ crunchy-cli --experimental-fixes ``` For an overview which parts this flag affects, see the [documentation](https://docs.rs/crunchyroll-rs/latest/crunchyroll_rs/crunchyroll/struct.CrunchyrollBuilder.html) of the underlying Crunchyroll library, all functions beginning with `stabilization_` are applied. @@ -159,7 +161,7 @@ You can set specific settings which will be The `--proxy` flag supports https and socks5 proxies to route all your traffic through. This may be helpful to bypass the geo-restrictions Crunchyroll has on certain series. ```shell - $ crunchy-cli --proxy socks5://127.0.0.1:8080 + $ crunchy-cli --proxy socks5://127.0.0.1:8080 ``` Make sure that proxy can either forward TLS requests, which is needed to bypass the (cloudflare) bot protection, or that it is configured so that the proxy can bypass the protection itself. @@ -204,7 +206,7 @@ The `download` command lets you download episodes with a specific audio language - Subtitle language Besides the audio, you can specify the subtitle language by using the `-s` / `--subtitle` flag. - The subtitles will be burned into the video track (cf. [hardsub](https://www.urbandictionary.com/define.php?term=hardsub)) and thus can not be turned off. + In formats that support it (.mp4, .mov and .mkv ), subtitles are stored as soft-subs. All other formats are hardsubbed: the subtitles will be burned into the video track (cf. [hardsub](https://www.urbandictionary.com/define.php?term=hardsub)) and thus can not be turned off. ```shell $ crunchy-cli download -s de-DE https://www.crunchyroll.com/series/GY8VEQ95Y/darling-in-the-franxx ``` From d8b76f8cc7985d5c838d6081985e686042051bd5 Mon Sep 17 00:00:00 2001 From: kennedy <854543+kennedy@users.noreply.github.com> Date: Sun, 29 Oct 2023 05:12:25 +0000 Subject: [PATCH 044/204] Add homebrew instructions (#261) Added details about homebrew and what archs are supported. made minor style linting: add space surrounding shell code blocks, and headers. --- README.md | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index df285cc..aa99c45 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,7 @@ Check out the [releases](https://github.com/crunchy-labs/crunchy-cli/releases) t If you're using Arch or an Arch based Linux distribution you are able to install our [AUR](https://aur.archlinux.org/) package. You need an [AUR helper](https://wiki.archlinux.org/title/AUR_helpers) like [yay](https://github.com/Jguer/yay) to install it. + ```shell # this package builds crunchy-cli manually (recommended) $ yay -S crunchy-cli @@ -63,6 +64,7 @@ Check out the [releases](https://github.com/crunchy-labs/crunchy-cli/releases) t - [Nix](https://nixos.org/) This requires [nix](https://nixos.org) and you'll probably need `--extra-experimental-features "nix-command flakes"`, depending on your configurations. + ```shell $ nix github:crunchy-labs/crunchy-cli ``` @@ -70,15 +72,27 @@ Check out the [releases](https://github.com/crunchy-labs/crunchy-cli/releases) t - [Scoop](https://scoop.sh/) For Windows users, we support the [scoop](https://scoop.sh/#/) command-line installer. + ```shell $ scoop bucket add extras $ scoop install extras/crunchy-cli ``` +- [Homebrew](https://brew.sh/) + + For macOS/linux users, we support the [brew](https://brew.sh/#/) command-line installer. Packages are compile by the [homebrew project](https://github.com/Homebrew/homebrew-core/pkgs/container/core%2Fcrunchy-cli), and will also install the `openssl@3` and `ffmpeg` dependencies. + + ```shell + $ brew install crunchy-cli + ``` + + Supported archs: `x86_64_linux`, `arm64_monterey`, `sonoma`, `ventura` + ### 🛠 Build it yourself Since we do not support every platform and architecture you may have to build the project yourself. This requires [git](https://git-scm.com/) and [Cargo](https://doc.rust-lang.org/cargo). + ```shell $ git clone https://github.com/crunchy-labs/crunchy-cli $ cd crunchy-cli @@ -103,18 +117,22 @@ You can authenticate with your credentials (user:password) or by using a refresh ```shell $ crunchy-cli --credentials "user:password" ``` + - Refresh Token To obtain a refresh token, you have to log in at [crunchyroll.com](https://www.crunchyroll.com/) and extract the `etp_rt` cookie. The easiest way to get it is via a browser extension which lets you export your cookies, like [Cookie-Editor](https://cookie-editor.cgagnier.ca/) ([Firefox](https://addons.mozilla.org/en-US/firefox/addon/cookie-editor/) / [Chrome](https://chrome.google.com/webstore/detail/cookie-editor/hlkenndednhfkekhgcdicdfddnkalmdm)). When installed, look for the `etp_rt` entry and extract its value. + ```shell $ crunchy-cli --etp-rt "4ebf1690-53a4-491a-a2ac-488309120f5d" ``` + - Stay Anonymous Login without an account (you won't be able to access premium content): - ```shell + + ```shell $ crunchy-cli --anonymous ``` @@ -125,15 +143,18 @@ You can set specific settings which will be - Verbose output If you want to include debug information in the output, use the `-v` / `--verbose` flag to show it. + ```shell $ crunchy-cli -v ``` + This flag can't be used with `-q` / `--quiet`. - Quiet output If you want to hide all output, use the `-q` / `--quiet` flag to do so. This is especially useful if you want to pipe the output video to an external program (like a video player). + ```shell $ crunchy-cli -q ``` @@ -142,6 +163,7 @@ You can set specific settings which will be By default, the resulting metadata like title or description are shown in your system language (if Crunchyroll supports it, else in English). If you want to show the results in another language, use the `--lang` flag to set it. + ```shell $ crunchy-cli --lang de-DE ``` @@ -151,18 +173,22 @@ You can set specific settings which will be Crunchyroll constantly changes and breaks its services or just delivers incorrect answers. The `--experimental-fixes` flag tries to fix some of those issues. As the *experimental* in `--experimental-fixes` states, these fixes may or may not break other functionality. + ```shell $ crunchy-cli --experimental-fixes ``` + For an overview which parts this flag affects, see the [documentation](https://docs.rs/crunchyroll-rs/latest/crunchyroll_rs/crunchyroll/struct.CrunchyrollBuilder.html) of the underlying Crunchyroll library, all functions beginning with `stabilization_` are applied. - Proxy The `--proxy` flag supports https and socks5 proxies to route all your traffic through. This may be helpful to bypass the geo-restrictions Crunchyroll has on certain series. + ```shell $ crunchy-cli --proxy socks5://127.0.0.1:8080 ``` + Make sure that proxy can either forward TLS requests, which is needed to bypass the (cloudflare) bot protection, or that it is configured so that the proxy can bypass the protection itself. ### Login @@ -184,6 +210,7 @@ With the session stored, you do not need to pass `--credentials` / `--etp-rt` / The `download` command lets you download episodes with a specific audio language and optional subtitles. **Supported urls** + - Single episode (with [episode filtering](#episode-filtering)) ```shell $ crunchy-cli download https://www.crunchyroll.com/watch/GRDQPM1ZY/alone-and-lonesome @@ -194,38 +221,47 @@ The `download` command lets you download episodes with a specific audio language ``` **Options** + - Audio language Set the audio language with the `-a` / `--audio` flag. This only works if the url points to a series since episode urls are language specific. + ```shell $ crunchy-cli download -a de-DE https://www.crunchyroll.com/series/GY8VEQ95Y/darling-in-the-franxx ``` + Default is your system locale. If not supported by Crunchyroll, `en-US` (American English) is the default. - Subtitle language Besides the audio, you can specify the subtitle language by using the `-s` / `--subtitle` flag. In formats that support it (.mp4, .mov and .mkv ), subtitles are stored as soft-subs. All other formats are hardsubbed: the subtitles will be burned into the video track (cf. [hardsub](https://www.urbandictionary.com/define.php?term=hardsub)) and thus can not be turned off. + ```shell $ crunchy-cli download -s de-DE https://www.crunchyroll.com/series/GY8VEQ95Y/darling-in-the-franxx ``` + Default is none. - Output template Define an output template by using the `-o` / `--output` flag. + ```shell $ crunchy-cli download -o "ditf.mp4" https://www.crunchyroll.com/watch/GRDQPM1ZY/alone-and-lonesome ``` + Default is `{title}.mp4`. See the [Template Options section](#output-template-options) below for more options. - Resolution The resolution for videos can be set via the `-r` / `--resolution` flag. + ```shell $ crunchy-cli download -r worst https://www.crunchyroll.com/watch/GRDQPM1ZY/alone-and-lonesome ``` + Default is `best`. - FFmpeg Preset @@ -233,6 +269,7 @@ The `download` command lets you download episodes with a specific audio language You can specify specific built-in presets with the `--ffmpeg-preset` flag to convert videos to a specific coding while downloading. Multiple predefined presets how videos should be encoded (h264, h265, av1, ...) are available, you can see them with `crunchy-cli download --help`. If you need more specific ffmpeg customizations you could either convert the output file manually or use ffmpeg output arguments as value for this flag. + ```shell $ crunchy-cli downlaod --ffmpeg-preset av1-lossless https://www.crunchyroll.com/watch/GRDQPM1ZY/alone-and-lonesome ``` @@ -240,6 +277,7 @@ The `download` command lets you download episodes with a specific audio language - Skip existing If you re-download a series but want to skip episodes you've already downloaded, the `--skip-existing` flag skips the already existing/downloaded files. + ```shell $ crunchy-cli download --skip-existing https://www.crunchyroll.com/series/GY8VEQ95Y/darling-in-the-franxx ``` @@ -248,14 +286,17 @@ The `download` command lets you download episodes with a specific audio language Sometimes different seasons have the same season number (e.g. Sword Art Online Alicization and Alicization War of Underworld are both marked as season 3), in such cases an interactive prompt is shown which needs user further user input to decide which season to download. The `--yes` flag suppresses this interactive prompt and just downloads all seasons. + ```shell $ crunchy-cli download --yes https://www.crunchyroll.com/series/GR49G9VP6/sword-art-online ``` + If you've passed the `-q` / `--quiet` [global flag](#global-settings), this flag is automatically set. - Force hardsub If you want to burn-in the subtitles, even if the output format/container supports soft-subs (e.g. `.mp4`), use the `--force-hardsub` flag to do so. + ```shell $ crunchy-cli download --force-hardsub -s en-US https://www.crunchyroll.com/watch/GRDQPM1ZY/alone-and-lonesome ``` @@ -265,6 +306,7 @@ The `download` command lets you download episodes with a specific audio language The `archive` command lets you download episodes with multiple audios and subtitles and merges it into a `.mkv` file. **Supported urls** + - Single episode (with [episode filtering](#episode-filtering)) ```shell $ crunchy-cli archive https://www.crunchyroll.com/watch/GRDQPM1ZY/alone-and-lonesome @@ -275,37 +317,46 @@ The `archive` command lets you download episodes with multiple audios and subtit ``` **Options** + - Audio languages Set the audio language with the `-a` / `--audio` flag. Can be used multiple times. + ```shell $ crunchy-cli archive -a ja-JP -a de-DE https://www.crunchyroll.com/series/GY8VEQ95Y/darling-in-the-franxx ``` + Default is your system locale (if not supported by Crunchyroll, `en-US` (American English) and `ja-JP` (Japanese) are used). - Subtitle languages Besides the audio, you can specify the subtitle language by using the `-s` / `--subtitle` flag. + ```shell $ crunchy-cli archive -s de-DE https://www.crunchyroll.com/series/GY8VEQ95Y/darling-in-the-franxx ``` + Default is `all` subtitles. - Output template Define an output template by using the `-o` / `--output` flag. crunchy-cli uses the [`.mkv`](https://en.wikipedia.org/wiki/Matroska) container format, because of it's ability to store multiple audio, video and subtitle tracks at once. + ```shell $ crunchy-cli archive -o "{title}.mkv" https://www.crunchyroll.com/series/GY8VEQ95Y/darling-in-the-franxx ``` + Default is `{title}.mkv`. See the [Template Options section](#output-template-options) below for more options. - Resolution The resolution for videos can be set via the `-r` / `--resolution` flag. + ```shell $ crunchy-cli archive -r worst https://www.crunchyroll.com/series/GY8VEQ95Y/darling-in-the-franxx ``` + Default is `best`. - Merge behavior @@ -316,9 +367,11 @@ The `archive` command lets you download episodes with multiple audios and subtit With the `-m` / `--merge` flag you can define the behaviour when an episodes' video tracks differ in length. Valid options are `audio` - store one video and all other languages as audio only; `video` - store the video + audio for every language; `auto` - detect if videos differ in length: if so, behave like `video` - otherwise like `audio`. Subtitles will always match the primary audio and video. + ```shell $ crunchy-cli archive -m audio https://www.crunchyroll.com/series/GY8VEQ95Y/darling-in-the-franxx ``` + Default is `auto`. - FFmpeg Preset @@ -326,6 +379,7 @@ The `archive` command lets you download episodes with multiple audios and subtit You can specify specific built-in presets with the `--ffmpeg-preset` flag to convert videos to a specific coding while downloading. Multiple predefined presets how videos should be encoded (h264, h265, av1, ...) are available, you can see them with `crunchy-cli archive --help`. If you need more specific ffmpeg customizations you could either convert the output file manually or use ffmpeg output arguments as value for this flag. + ```shell $ crunchy-cli archive --ffmpeg-preset av1-lossless https://www.crunchyroll.com/watch/GRDQPM1ZY/alone-and-lonesome ``` @@ -333,14 +387,17 @@ The `archive` command lets you download episodes with multiple audios and subtit - Default subtitle `--default-subtitle` Set which subtitle language is to be flagged as **default** and **forced**. + ```shell $ crunchy-cli archive --default-subtitle en-US https://www.crunchyroll.com/series/GY8VEQ95Y/darling-in-the-franxx ``` + Default is none. - Skip existing If you re-download a series but want to skip episodes you've already downloaded, the `--skip-existing` flag skips the already existing/downloaded files. + ```shell $ crunchy-cli archive --skip-existing https://www.crunchyroll.com/series/GY8VEQ95Y/darling-in-the-franxx ``` @@ -349,14 +406,17 @@ The `archive` command lets you download episodes with multiple audios and subtit Sometimes different seasons have the same season number (e.g. Sword Art Online Alicization and Alicization War of Underworld are both marked as season 3), in such cases an interactive prompt is shown which needs user further user input to decide which season to download. The `--yes` flag suppresses this interactive prompt and just downloads all seasons. + ```shell $ crunchy-cli archive --yes https://www.crunchyroll.com/series/GR49G9VP6/sword-art-online ``` + If you've passed the `-q` / `--quiet` [global flag](#global-settings), this flag is automatically set. ### Search **Supported urls/input** + - Single episode (with [episode filtering](#episode-filtering)) ```shell $ crunchy-cli search https://www.crunchyroll.com/watch/GRDQPM1ZY/alone-and-lonesome @@ -371,12 +431,15 @@ The `archive` command lets you download episodes with multiple audios and subtit ``` **Options** + - Audio Set the audio language to search via the `--audio` flag. Can be used multiple times. + ```shell $ crunchy-cli search --audio en-US https://www.crunchyroll.com/series/GY8VEQ95Y/darling-in-the-franxx ``` + Default is your system locale. - Result limit @@ -384,6 +447,7 @@ The `archive` command lets you download episodes with multiple audios and subtit If your input is a search term instead of an url, you have multiple options to control which results to process. The `--search-top-results-limit` flag sets the limit of top search results to process. `--search-series-limit` sets the limit of only series, `--search-movie-listing-limit` of only movie listings, `--search-episode-limit` of only episodes and `--search-music-limit` of only concerts and music videos. + ```shell $ crunchy-cli search --search-top-results-limit 10 "darling in the franxx" # only return series which have 'darling' in it. do not return top results which might also be non-series items @@ -391,6 +455,7 @@ The `archive` command lets you download episodes with multiple audios and subtit # this returns 2 top results, 3 movie listings, 5 episodes and 1 music item as result $ crunchy-cli search --search-top-results-limit 2 --search-movie-listing-limit 3 --search-episode-limit 5 --search-music-limit 1 "test" ``` + Default is `5` for `--search-top-results-limit`, `0` for all others. - Output template @@ -401,9 +466,11 @@ The `archive` command lets you download episodes with multiple audios and subtit The required pattern for this begins with `{{`, then the keyword, and closes with `}}` (e.g. `{{episode.title}}`). For example, if you want to get the title of an episode, you can use `Title: {{episode.title}}` and `{{episode.title}}` will be replaced with the episode title. You can see all supported keywords with `crunchy-cli search --help`. + ```shell $ crunchy-cli search -o "{{series.title}}" https://www.crunchyroll.com/series/GY8VEQ95Y/darling-in-the-franxx ``` + Default is `S{{season.number}}E{{episode.number}} - {{episode.title}}`. --- @@ -425,6 +492,7 @@ You can use various template options to change how the filename is processed. Th - `{episode_id}` → ID of the episode Example: + ```shell $ crunchy-cli archive -o "[S{season_number}E{episode_number}] {title}.mkv" https://www.crunchyroll.com/series/G8DHV7W21/dragon-ball # Output file: '[S01E01] Secret of the Dragon Ball.mkv' @@ -438,6 +506,7 @@ A filter pattern may consist of either a season, an episode, or a combination of When used in combination, seasons `S` must be defined before episodes `E`. There are many possible patterns, for example: + - `...[E5]` - Download the fifth episode. - `...[S1]` - Download the whole first season. - `...[-S2]` - Download the first two seasons. @@ -447,6 +516,7 @@ There are many possible patterns, for example: - `...[S1-S3,S4E2-S4E6]` - Download season one to three, then episodes two to six from season four. In practice, it would look like this: + ``` https://www.crunchyroll.com/series/GY8VEQ95Y/darling-in-the-franxx[E1-E5] ``` From 7594412f5845d0746df755b9536413432ed3a36a Mon Sep 17 00:00:00 2001 From: kennedy <854543+kennedy@users.noreply.github.com> Date: Thu, 2 Nov 2023 08:37:40 -0400 Subject: [PATCH 045/204] updated brew url (#263) * updated brew url Its most appropriate to forward users to the brew's information page generated for crunchy-cli. There are stats on amount of downloads, see where the manifest is location, and what architectures are built for it. * Update README.md Co-authored-by: ByteDream <63594396+ByteDream@users.noreply.github.com> --------- Co-authored-by: ByteDream <63594396+ByteDream@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index aa99c45..3cbb8c9 100644 --- a/README.md +++ b/README.md @@ -80,7 +80,7 @@ Check out the [releases](https://github.com/crunchy-labs/crunchy-cli/releases) t - [Homebrew](https://brew.sh/) - For macOS/linux users, we support the [brew](https://brew.sh/#/) command-line installer. Packages are compile by the [homebrew project](https://github.com/Homebrew/homebrew-core/pkgs/container/core%2Fcrunchy-cli), and will also install the `openssl@3` and `ffmpeg` dependencies. + For macOS/linux users, we support the [brew](https://brew.sh/#/) command-line installer. Packages are compiled by the [homebrew project](https://formulae.brew.sh/formula/crunchy-cli), and will also install the `openssl@3` and `ffmpeg` dependencies. ```shell $ brew install crunchy-cli From 787d8ab02c206a763b2e5a81b413aee11bfe11b5 Mon Sep 17 00:00:00 2001 From: bytedream Date: Sat, 4 Nov 2023 15:24:14 +0100 Subject: [PATCH 046/204] Add --special-output and --skip-specials flag --- crunchy-cli-core/src/archive/command.rs | 36 ++++++++++++++++--- crunchy-cli-core/src/archive/filter.rs | 16 ++++++++- crunchy-cli-core/src/download/command.rs | 44 +++++++++++++++++++++--- crunchy-cli-core/src/download/filter.rs | 16 ++++++++- crunchy-cli-core/src/utils/format.rs | 4 +++ 5 files changed, 106 insertions(+), 10 deletions(-) diff --git a/crunchy-cli-core/src/archive/command.rs b/crunchy-cli-core/src/archive/command.rs index 7d28e2e..f6da256 100644 --- a/crunchy-cli-core/src/archive/command.rs +++ b/crunchy-cli-core/src/archive/command.rs @@ -54,6 +54,11 @@ pub struct Archive { {episode_id} → ID of the episode")] #[arg(short, long, default_value = "{title}.mkv")] pub(crate) output: String, + #[arg(help = "Name of the output file if the episode is a special")] + #[arg(long_help = "Name of the output file if the episode is a special. \ + If not set, the '-o'/'--output' flag will be used as name template")] + #[arg(long)] + pub(crate) special_output: Option, #[arg(help = "Video resolution")] #[arg(long_help = "The video resolution.\ @@ -95,6 +100,9 @@ pub struct Archive { #[arg(help = "Skip files which are already existing")] #[arg(long, default_value_t = false)] pub(crate) skip_existing: bool, + #[arg(help = "Skip special episodes")] + #[arg(long, default_value_t = false)] + pub(crate) skip_specials: bool, #[arg(help = "Skip any interactive input")] #[arg(short, long, default_value_t = false)] @@ -123,6 +131,17 @@ impl Execute for Archive { && self.output != "-" { bail!("File extension is not '.mkv'. Currently only matroska / '.mkv' files are supported") + } else if let Some(special_output) = &self.special_output { + if PathBuf::from(special_output) + .extension() + .unwrap_or_default() + .to_string_lossy() + != "mkv" + && !is_special_file(special_output) + && special_output != "-" + { + bail!("File extension for special episodes is not '.mkv'. Currently only matroska / '.mkv' files are supported") + } } self.audio = all_locale_in_locales(self.audio.clone()); @@ -147,9 +166,10 @@ impl Execute for Archive { for (i, (media_collection, url_filter)) in parsed_urls.into_iter().enumerate() { let progress_handler = progress!("Fetching series details"); - let single_format_collection = ArchiveFilter::new(url_filter, self.clone(), !self.yes) - .visit(media_collection) - .await?; + let single_format_collection = + ArchiveFilter::new(url_filter, self.clone(), !self.yes, self.skip_specials) + .visit(media_collection) + .await?; if single_format_collection.is_empty() { progress_handler.stop(format!("Skipping url {} (no matching videos found)", i + 1)); @@ -175,7 +195,15 @@ impl Execute for Archive { downloader.add_format(download_format) } - let formatted_path = format.format_path((&self.output).into()); + let formatted_path = if format.is_special() { + format.format_path( + self.special_output + .as_ref() + .map_or((&self.output).into(), |so| so.into()), + ) + } else { + format.format_path((&self.output).into()) + }; let (path, changed) = free_file(formatted_path.clone()); if changed && self.skip_existing { diff --git a/crunchy-cli-core/src/archive/filter.rs b/crunchy-cli-core/src/archive/filter.rs index 91023a3..a4e3188 100644 --- a/crunchy-cli-core/src/archive/filter.rs +++ b/crunchy-cli-core/src/archive/filter.rs @@ -18,6 +18,7 @@ pub(crate) struct ArchiveFilter { url_filter: UrlFilter, archive: Archive, interactive_input: bool, + skip_special: bool, season_episodes: HashMap>, season_subtitles_missing: Vec, season_sorting: Vec, @@ -25,11 +26,17 @@ pub(crate) struct ArchiveFilter { } impl ArchiveFilter { - pub(crate) fn new(url_filter: UrlFilter, archive: Archive, interactive_input: bool) -> Self { + pub(crate) fn new( + url_filter: UrlFilter, + archive: Archive, + interactive_input: bool, + skip_special: bool, + ) -> Self { Self { url_filter, archive, interactive_input, + skip_special, season_episodes: HashMap::new(), season_subtitles_missing: vec![], season_sorting: vec![], @@ -246,6 +253,13 @@ impl Filter for ArchiveFilter { return Ok(None); } + // skip the episode if it's a special + if self.skip_special + && (episode.sequence_number == 0.0 || episode.sequence_number.fract() != 0.0) + { + return Ok(None); + } + let mut episodes = vec![]; if !matches!(self.visited, Visited::Series) && !matches!(self.visited, Visited::Season) { if self.archive.audio.contains(&episode.audio_locale) { diff --git a/crunchy-cli-core/src/download/command.rs b/crunchy-cli-core/src/download/command.rs index 376cc2d..da885c3 100644 --- a/crunchy-cli-core/src/download/command.rs +++ b/crunchy-cli-core/src/download/command.rs @@ -50,6 +50,11 @@ pub struct Download { {episode_id} → ID of the episode")] #[arg(short, long, default_value = "{title}.mp4")] pub(crate) output: String, + #[arg(help = "Name of the output file if the episode is a special")] + #[arg(long_help = "Name of the output file if the episode is a special. \ + If not set, the '-o'/'--output' flag will be used as name template")] + #[arg(long)] + pub(crate) special_output: Option, #[arg(help = "Video resolution")] #[arg(long_help = "The video resolution.\ @@ -73,6 +78,9 @@ pub struct Download { #[arg(help = "Skip files which are already existing")] #[arg(long, default_value_t = false)] pub(crate) skip_existing: bool, + #[arg(help = "Skip special episodes")] + #[arg(long, default_value_t = false)] + pub(crate) skip_specials: bool, #[arg(help = "Skip any interactive input")] #[arg(short, long, default_value_t = false)] @@ -116,6 +124,25 @@ impl Execute for Download { } } + if let Some(special_output) = &self.special_output { + if Path::new(special_output) + .extension() + .unwrap_or_default() + .is_empty() + && !is_special_file(special_output) + && special_output != "-" + { + bail!("No file extension found. Please specify a file extension (via `--special-output`) for the output file") + } + if let Some(ext) = Path::new(special_output).extension() { + if self.force_hardsub { + warn!("Hardsubs are forced for special episodes. Adding subtitles may take a while") + } else if !["mkv", "mov", "mp4"].contains(&ext.to_string_lossy().as_ref()) { + warn!("Detected a container which does not support softsubs. Adding subtitles for special episodes may take a while") + } + } + } + Ok(()) } @@ -135,9 +162,10 @@ impl Execute for Download { for (i, (media_collection, url_filter)) in parsed_urls.into_iter().enumerate() { let progress_handler = progress!("Fetching series details"); - let single_format_collection = DownloadFilter::new(url_filter, self.clone(), !self.yes) - .visit(media_collection) - .await?; + let single_format_collection = + DownloadFilter::new(url_filter, self.clone(), !self.yes, self.skip_specials) + .visit(media_collection) + .await?; if single_format_collection.is_empty() { progress_handler.stop(format!("Skipping url {} (no matching videos found)", i + 1)); @@ -167,7 +195,15 @@ impl Execute for Download { let mut downloader = download_builder.clone().build(); downloader.add_format(download_format); - let formatted_path = format.format_path((&self.output).into()); + let formatted_path = if format.is_special() { + format.format_path( + self.special_output + .as_ref() + .map_or((&self.output).into(), |so| so.into()), + ) + } else { + format.format_path((&self.output).into()) + }; let (path, changed) = free_file(formatted_path.clone()); if changed && self.skip_existing { diff --git a/crunchy-cli-core/src/download/filter.rs b/crunchy-cli-core/src/download/filter.rs index 55b1e8b..626896c 100644 --- a/crunchy-cli-core/src/download/filter.rs +++ b/crunchy-cli-core/src/download/filter.rs @@ -12,17 +12,24 @@ pub(crate) struct DownloadFilter { url_filter: UrlFilter, download: Download, interactive_input: bool, + skip_special: bool, season_episodes: HashMap>, season_subtitles_missing: Vec, season_visited: bool, } impl DownloadFilter { - pub(crate) fn new(url_filter: UrlFilter, download: Download, interactive_input: bool) -> Self { + pub(crate) fn new( + url_filter: UrlFilter, + download: Download, + interactive_input: bool, + skip_special: bool, + ) -> Self { Self { url_filter, download, interactive_input, + skip_special, season_episodes: HashMap::new(), season_subtitles_missing: vec![], season_visited: false, @@ -132,6 +139,13 @@ impl Filter for DownloadFilter { return Ok(None); } + // skip the episode if it's a special + if self.skip_special + && (episode.sequence_number == 0.0 || episode.sequence_number.fract() != 0.0) + { + return Ok(None); + } + // check if the audio locale is correct. // should only be incorrect if the console input was a episode url. otherwise // `DownloadFilter::visit_season` returns the correct episodes with matching audio diff --git a/crunchy-cli-core/src/utils/format.rs b/crunchy-cli-core/src/utils/format.rs index 4679878..4afaa07 100644 --- a/crunchy-cli-core/src/utils/format.rs +++ b/crunchy-cli-core/src/utils/format.rs @@ -473,6 +473,10 @@ impl Format { tab_info!("FPS: {:.2}", self.fps) } + pub fn is_special(&self) -> bool { + self.sequence_number == 0.0 || self.sequence_number.fract() != 0.0 + } + pub fn has_relative_fmt>(s: S) -> bool { return s.as_ref().contains("{relative_episode_number}") || s.as_ref().contains("{relative_sequence_number}"); From e5d9c27af7bf2056dfd96ca87bbe34506674a73f Mon Sep 17 00:00:00 2001 From: bytedream Date: Mon, 6 Nov 2023 21:10:15 +0100 Subject: [PATCH 047/204] Fix ass filter path escape on windows (#262) --- crunchy-cli-core/src/utils/download.rs | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/crunchy-cli-core/src/utils/download.rs b/crunchy-cli-core/src/utils/download.rs index ff9f240..23d5863 100644 --- a/crunchy-cli-core/src/utils/download.rs +++ b/crunchy-cli-core/src/utils/download.rs @@ -378,8 +378,27 @@ impl Downloader { output_presets.extend([ "-vf".to_string(), format!( - "ass={}", - subtitles.get(position).unwrap().path.to_str().unwrap() + "ass='{}'", + // ffmpeg doesn't removes all ':' and '\' from the filename when using + // the ass filter. well, on windows these characters are used in + // absolute paths, so they have to be correctly escaped here + if cfg!(windows) { + subtitles + .get(position) + .unwrap() + .path + .to_str() + .unwrap() + .replace('\\', "\\\\") + .replace(':', "\\:") + } else { + subtitles + .get(position) + .unwrap() + .path + .to_string_lossy() + .to_string() + } ), ]) } From f31437fba2bc675fbfeb431f30b01dac5463708f Mon Sep 17 00:00:00 2001 From: bytedream Date: Mon, 6 Nov 2023 21:20:43 +0100 Subject: [PATCH 048/204] Remove leading and trailing whitespaces from output file --- crunchy-cli-core/src/utils/os.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crunchy-cli-core/src/utils/os.rs b/crunchy-cli-core/src/utils/os.rs index 1f76b90..0596789 100644 --- a/crunchy-cli-core/src/utils/os.rs +++ b/crunchy-cli-core/src/utils/os.rs @@ -96,7 +96,7 @@ lazy_static::lazy_static! { /// is based of the implementation of the /// [`sanitize-filename`](https://crates.io/crates/sanitize-filename) crate. pub fn sanitize>(path: S, include_path_separator: bool) -> String { - let path = Cow::from(path.as_ref()); + let path = Cow::from(path.as_ref().trim()); let path = ILLEGAL_RE.replace_all(&path, ""); let path = CONTROL_RE.replace_all(&path, ""); From cd35dfe2766f6448ea43747dcfe1c24c2f599c51 Mon Sep 17 00:00:00 2001 From: bytedream Date: Mon, 6 Nov 2023 21:48:49 +0100 Subject: [PATCH 049/204] Rename --special-output to --output-specials --- crunchy-cli-core/src/archive/command.rs | 6 +++--- crunchy-cli-core/src/download/command.rs | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/crunchy-cli-core/src/archive/command.rs b/crunchy-cli-core/src/archive/command.rs index f6da256..0ee723e 100644 --- a/crunchy-cli-core/src/archive/command.rs +++ b/crunchy-cli-core/src/archive/command.rs @@ -58,7 +58,7 @@ pub struct Archive { #[arg(long_help = "Name of the output file if the episode is a special. \ If not set, the '-o'/'--output' flag will be used as name template")] #[arg(long)] - pub(crate) special_output: Option, + pub(crate) output_specials: Option, #[arg(help = "Video resolution")] #[arg(long_help = "The video resolution.\ @@ -131,7 +131,7 @@ impl Execute for Archive { && self.output != "-" { bail!("File extension is not '.mkv'. Currently only matroska / '.mkv' files are supported") - } else if let Some(special_output) = &self.special_output { + } else if let Some(special_output) = &self.output_specials { if PathBuf::from(special_output) .extension() .unwrap_or_default() @@ -197,7 +197,7 @@ impl Execute for Archive { let formatted_path = if format.is_special() { format.format_path( - self.special_output + self.output_specials .as_ref() .map_or((&self.output).into(), |so| so.into()), ) diff --git a/crunchy-cli-core/src/download/command.rs b/crunchy-cli-core/src/download/command.rs index da885c3..18355cd 100644 --- a/crunchy-cli-core/src/download/command.rs +++ b/crunchy-cli-core/src/download/command.rs @@ -54,7 +54,7 @@ pub struct Download { #[arg(long_help = "Name of the output file if the episode is a special. \ If not set, the '-o'/'--output' flag will be used as name template")] #[arg(long)] - pub(crate) special_output: Option, + pub(crate) output_specials: Option, #[arg(help = "Video resolution")] #[arg(long_help = "The video resolution.\ @@ -124,7 +124,7 @@ impl Execute for Download { } } - if let Some(special_output) = &self.special_output { + if let Some(special_output) = &self.output_specials { if Path::new(special_output) .extension() .unwrap_or_default() @@ -132,7 +132,7 @@ impl Execute for Download { && !is_special_file(special_output) && special_output != "-" { - bail!("No file extension found. Please specify a file extension (via `--special-output`) for the output file") + bail!("No file extension found. Please specify a file extension (via `--output-specials`) for the output file") } if let Some(ext) = Path::new(special_output).extension() { if self.force_hardsub { @@ -197,7 +197,7 @@ impl Execute for Download { let formatted_path = if format.is_special() { format.format_path( - self.special_output + self.output_specials .as_ref() .map_or((&self.output).into(), |so| so.into()), ) From 56411c6547223e59c8cb4e8c61d6a29627889537 Mon Sep 17 00:00:00 2001 From: bytedream Date: Mon, 6 Nov 2023 22:01:44 +0100 Subject: [PATCH 050/204] Add missing whitespaces in command help --- crunchy-cli-core/src/archive/command.rs | 4 ++-- crunchy-cli-core/src/download/command.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crunchy-cli-core/src/archive/command.rs b/crunchy-cli-core/src/archive/command.rs index 0ee723e..7add620 100644 --- a/crunchy-cli-core/src/archive/command.rs +++ b/crunchy-cli-core/src/archive/command.rs @@ -37,7 +37,7 @@ pub struct Archive { pub(crate) subtitle: Vec, #[arg(help = "Name of the output file")] - #[arg(long_help = "Name of the output file.\ + #[arg(long_help = "Name of the output file. \ If you use one of the following pattern they will get replaced:\n \ {title} → Title of the video\n \ {series_name} → Name of the series\n \ @@ -61,7 +61,7 @@ pub struct Archive { pub(crate) output_specials: Option, #[arg(help = "Video resolution")] - #[arg(long_help = "The video resolution.\ + #[arg(long_help = "The video resolution. \ Can either be specified via the pixels (e.g. 1920x1080), the abbreviation for pixels (e.g. 1080p) or 'common-use' words (e.g. best). \ Specifying the exact pixels is not recommended, use one of the other options instead. \ Crunchyroll let you choose the quality with pixel abbreviation on their clients, so you might be already familiar with the available options. \ diff --git a/crunchy-cli-core/src/download/command.rs b/crunchy-cli-core/src/download/command.rs index 18355cd..4f189c5 100644 --- a/crunchy-cli-core/src/download/command.rs +++ b/crunchy-cli-core/src/download/command.rs @@ -33,7 +33,7 @@ pub struct Download { pub(crate) subtitle: Option, #[arg(help = "Name of the output file")] - #[arg(long_help = "Name of the output file.\ + #[arg(long_help = "Name of the output file. \ If you use one of the following pattern they will get replaced:\n \ {title} → Title of the video\n \ {series_name} → Name of the series\n \ From fc6511a361b7ee98830385bf273cd2ce464b1058 Mon Sep 17 00:00:00 2001 From: bytedream Date: Mon, 6 Nov 2023 22:09:21 +0100 Subject: [PATCH 051/204] Format code --- crunchy-cli-core/src/archive/command.rs | 4 ++-- crunchy-cli-core/src/archive/filter.rs | 16 +++++++--------- crunchy-cli-core/src/download/command.rs | 2 +- crunchy-cli-core/src/download/filter.rs | 19 +++++++++---------- crunchy-cli-core/src/lib.rs | 4 ++-- crunchy-cli-core/src/search/filter.rs | 4 ++-- crunchy-cli-core/src/search/format.rs | 1 + crunchy-cli-core/src/utils/download.rs | 13 ++++++------- crunchy-cli-core/src/utils/ffmpeg.rs | 6 +++--- crunchy-cli-core/src/utils/format.rs | 15 +++++++-------- crunchy-cli-core/src/utils/locale.rs | 3 +-- crunchy-cli-core/src/utils/log.rs | 1 - crunchy-cli-core/src/utils/os.rs | 2 +- 13 files changed, 42 insertions(+), 48 deletions(-) diff --git a/crunchy-cli-core/src/archive/command.rs b/crunchy-cli-core/src/archive/command.rs index 7add620..3585e9c 100644 --- a/crunchy-cli-core/src/archive/command.rs +++ b/crunchy-cli-core/src/archive/command.rs @@ -306,8 +306,8 @@ async fn get_format( } MergeBehavior::Audio => download_formats.push(DownloadFormat { video: ( - (*format_pairs.first().unwrap()).1.clone(), - (*format_pairs.first().unwrap()).0.audio.clone(), + format_pairs.first().unwrap().1.clone(), + format_pairs.first().unwrap().0.audio.clone(), ), audios: format_pairs .iter() diff --git a/crunchy-cli-core/src/archive/filter.rs b/crunchy-cli-core/src/archive/filter.rs index a4e3188..01612b9 100644 --- a/crunchy-cli-core/src/archive/filter.rs +++ b/crunchy-cli-core/src/archive/filter.rs @@ -103,7 +103,7 @@ impl Filter for ArchiveFilter { seasons.retain(|s| !remove_ids.contains(&s.id)); let duplicated_seasons = get_duplicated_seasons(&seasons); - if duplicated_seasons.len() > 0 { + if !duplicated_seasons.is_empty() { if self.interactive_input { check_for_duplicated_seasons(&mut seasons); } else { @@ -139,8 +139,7 @@ impl Filter for ArchiveFilter { if !matches!(self.visited, Visited::Series) { let mut audio_locales: Vec = seasons .iter() - .map(|s| s.audio_locales.clone()) - .flatten() + .flat_map(|s| s.audio_locales.clone()) .collect(); real_dedup_vec(&mut audio_locales); let missing_audio = missing_locales(&audio_locales, &self.archive.audio); @@ -158,8 +157,7 @@ impl Filter for ArchiveFilter { let subtitle_locales: Vec = seasons .iter() - .map(|s| s.subtitle_locales.clone()) - .flatten() + .flat_map(|s| s.subtitle_locales.clone()) .collect(); let missing_subtitle = missing_locales(&subtitle_locales, &self.archive.subtitle); if !missing_subtitle.is_empty() { @@ -211,7 +209,7 @@ impl Filter for ArchiveFilter { } } if eps.len() < before_len { - if eps.len() == 0 { + if eps.is_empty() { if matches!(self.visited, Visited::Series) { warn!( "Season {} is not available with {} audio", @@ -237,7 +235,7 @@ impl Filter for ArchiveFilter { for episode in episodes.iter() { self.season_episodes .entry(episode.season_id.clone()) - .or_insert(vec![]) + .or_default() .push(episode.clone()) } } @@ -290,7 +288,7 @@ impl Filter for ArchiveFilter { } let mut subtitle_locales: Vec = - episodes.iter().map(|(_, s)| s.clone()).flatten().collect(); + episodes.iter().flat_map(|(_, s)| s.clone()).collect(); real_dedup_vec(&mut subtitle_locales); let missing_subtitles = missing_locales(&subtitle_locales, &self.archive.subtitle); if !missing_subtitles.is_empty() @@ -435,6 +433,6 @@ impl Filter for ArchiveFilter { } } -fn missing_locales<'a>(available: &Vec, searched: &'a Vec) -> Vec<&'a Locale> { +fn missing_locales<'a>(available: &[Locale], searched: &'a [Locale]) -> Vec<&'a Locale> { searched.iter().filter(|p| !available.contains(p)).collect() } diff --git a/crunchy-cli-core/src/download/command.rs b/crunchy-cli-core/src/download/command.rs index 4f189c5..82cb8f8 100644 --- a/crunchy-cli-core/src/download/command.rs +++ b/crunchy-cli-core/src/download/command.rs @@ -251,7 +251,7 @@ async fn get_format( }; let subtitle = if let Some(subtitle_locale) = &download.subtitle { - stream.subtitles.get(subtitle_locale).map(|s| s.clone()) + stream.subtitles.get(subtitle_locale).cloned() } else { None }; diff --git a/crunchy-cli-core/src/download/filter.rs b/crunchy-cli-core/src/download/filter.rs index 626896c..fb2e563 100644 --- a/crunchy-cli-core/src/download/filter.rs +++ b/crunchy-cli-core/src/download/filter.rs @@ -45,14 +45,13 @@ impl Filter for DownloadFilter { async fn visit_series(&mut self, series: Series) -> Result> { // `series.audio_locales` isn't always populated b/c of crunchyrolls api. so check if the // audio is matching only if the field is populated - if !series.audio_locales.is_empty() { - if !series.audio_locales.contains(&self.download.audio) { - error!( - "Series {} is not available with {} audio", - series.title, self.download.audio - ); - return Ok(vec![]); - } + if !series.audio_locales.is_empty() && !series.audio_locales.contains(&self.download.audio) + { + error!( + "Series {} is not available with {} audio", + series.title, self.download.audio + ); + return Ok(vec![]); } let mut seasons = vec![]; @@ -91,7 +90,7 @@ impl Filter for DownloadFilter { } let duplicated_seasons = get_duplicated_seasons(&seasons); - if duplicated_seasons.len() > 0 { + if !duplicated_seasons.is_empty() { if self.interactive_input { check_for_duplicated_seasons(&mut seasons); } else { @@ -118,7 +117,7 @@ impl Filter for DownloadFilter { for episode in episodes.iter() { self.season_episodes .entry(episode.season_number) - .or_insert(vec![]) + .or_default() .push(episode.clone()) } } diff --git a/crunchy-cli-core/src/lib.rs b/crunchy-cli-core/src/lib.rs index 02bef6f..d6c2220 100644 --- a/crunchy-cli-core/src/lib.rs +++ b/crunchy-cli-core/src/lib.rs @@ -77,7 +77,7 @@ fn version() -> String { let build_date = env!("BUILD_DATE"); if git_commit_hash.is_empty() { - format!("{}", package_version) + package_version.to_string() } else { format!("{} ({} {})", package_version, git_commit_hash, build_date) } @@ -250,7 +250,7 @@ async fn crunchyroll_session(cli: &mut Cli) -> Result { "Via `--lang` specified language is not supported. Supported languages: {}", supported_langs .iter() - .map(|l| format!("`{}` ({})", l.to_string(), l.to_human_readable())) + .map(|l| format!("`{}` ({})", l, l.to_human_readable())) .collect::>() .join(", ") ) diff --git a/crunchy-cli-core/src/search/filter.rs b/crunchy-cli-core/src/search/filter.rs index 264b31d..3bb6d9f 100644 --- a/crunchy-cli-core/src/search/filter.rs +++ b/crunchy-cli-core/src/search/filter.rs @@ -21,7 +21,7 @@ impl FilterOptions { pub fn filter_episodes(&self, mut episodes: Vec) -> Vec { episodes.retain(|e| { - self.check_audio_language(&vec![e.audio_locale.clone()]) + self.check_audio_language(&[e.audio_locale.clone()]) && self .url_filter .is_episode_valid(e.sequence_number, e.season_number) @@ -38,7 +38,7 @@ impl FilterOptions { ) } - fn check_audio_language(&self, audio: &Vec) -> bool { + fn check_audio_language(&self, audio: &[Locale]) -> bool { if !self.audio.is_empty() { return self.audio.iter().any(|a| audio.contains(a)); } diff --git a/crunchy-cli-core/src/search/format.rs b/crunchy-cli-core/src/search/format.rs index 55cba7c..f9746b1 100644 --- a/crunchy-cli-core/src/search/format.rs +++ b/crunchy-cli-core/src/search/format.rs @@ -372,6 +372,7 @@ impl Format { let stream_empty = self.check_pattern_count_empty(Scope::Stream) && self.check_pattern_count_empty(Scope::Subtitle); + #[allow(clippy::type_complexity)] let mut tree: Vec<(Season, Vec<(Episode, Vec)>)> = vec![]; let series = if !series_empty { diff --git a/crunchy-cli-core/src/utils/download.rs b/crunchy-cli-core/src/utils/download.rs index 23d5863..945cc14 100644 --- a/crunchy-cli-core/src/utils/download.rs +++ b/crunchy-cli-core/src/utils/download.rs @@ -296,7 +296,7 @@ impl Downloader { ]); // the empty language metadata is created to avoid that metadata from the original track // is copied - metadata.extend([format!("-metadata:s:v:{}", i), format!("language=")]) + metadata.extend([format!("-metadata:s:v:{}", i), "language=".to_string()]) } for (i, meta) in audios.iter().enumerate() { input.extend(["-i".to_string(), meta.path.to_string_lossy().to_string()]); @@ -675,7 +675,7 @@ impl Downloader { let result = download().await; if result.is_err() { - after_download_sender.send((-1 as i32, vec![]))?; + after_download_sender.send((-1, vec![]))?; } result @@ -747,7 +747,7 @@ impl Downloader { } } -fn estimate_variant_file_size(variant_data: &VariantData, segments: &Vec) -> u64 { +fn estimate_variant_file_size(variant_data: &VariantData, segments: &[VariantSegment]) -> u64 { (variant_data.bandwidth / 8) * segments.iter().map(|s| s.length.as_secs()).sum::() } @@ -788,9 +788,8 @@ pub fn get_video_length(path: &Path) -> Result { /// [crunchy-labs/crunchy-cli#208](https://github.com/crunchy-labs/crunchy-cli/issues/208) for more /// information. fn fix_subtitles(raw: &mut Vec, max_length: NaiveTime) { - let re = - Regex::new(r#"^Dialogue:\s\d+,(?P\d+:\d+:\d+\.\d+),(?P\d+:\d+:\d+\.\d+),"#) - .unwrap(); + let re = Regex::new(r"^Dialogue:\s\d+,(?P\d+:\d+:\d+\.\d+),(?P\d+:\d+:\d+\.\d+),") + .unwrap(); // chrono panics if we try to format NaiveTime with `%2f` and the nano seconds has more than 2 // digits so them have to be reduced manually to avoid the panic @@ -832,7 +831,7 @@ fn fix_subtitles(raw: &mut Vec, max_length: NaiveTime) { line, format!( "Dialogue: {},{},", - format_naive_time(start.clone()), + format_naive_time(start), &length_as_string ), ) diff --git a/crunchy-cli-core/src/utils/ffmpeg.rs b/crunchy-cli-core/src/utils/ffmpeg.rs index af29bfd..787c79a 100644 --- a/crunchy-cli-core/src/utils/ffmpeg.rs +++ b/crunchy-cli-core/src/utils/ffmpeg.rs @@ -134,7 +134,7 @@ impl FFmpegPreset { description_details.push(format!("{} video quality/compression", q.to_string())) } - let description = if description_details.len() == 0 { + let description = if description_details.is_empty() { format!( "{} encoded with default video quality/compression", codec.to_string() @@ -239,7 +239,7 @@ impl FFmpegPreset { hwaccel.clone(), quality.clone(), )) { - return Err(format!("ffmpeg preset is not supported")); + return Err("ffmpeg preset is not supported".to_string()); } Ok(FFmpegPreset::Predefined( c, @@ -247,7 +247,7 @@ impl FFmpegPreset { quality.unwrap_or(FFmpegQuality::Normal), )) } else { - Err(format!("cannot use ffmpeg preset with without a codec")) + Err("cannot use ffmpeg preset with without a codec".to_string()) } } diff --git a/crunchy-cli-core/src/utils/format.rs b/crunchy-cli-core/src/utils/format.rs index 4afaa07..4c8d3c8 100644 --- a/crunchy-cli-core/src/utils/format.rs +++ b/crunchy-cli-core/src/utils/format.rs @@ -170,10 +170,7 @@ impl SingleFormat { } pub fn is_episode(&self) -> bool { - match self.source { - MediaCollection::Episode(_) => true, - _ => false, - } + matches!(self.source, MediaCollection::Episode(_)) } } @@ -181,7 +178,7 @@ struct SingleFormatCollectionEpisodeKey(f32); impl PartialOrd for SingleFormatCollectionEpisodeKey { fn partial_cmp(&self, other: &Self) -> Option { - self.0.partial_cmp(&other.0) + Some(self.cmp(other)) } } impl Ord for SingleFormatCollectionEpisodeKey { @@ -198,6 +195,7 @@ impl Eq for SingleFormatCollectionEpisodeKey {} struct SingleFormatCollectionSeasonKey((u32, String)); +#[allow(clippy::incorrect_partial_ord_impl_on_ord_type)] impl PartialOrd for SingleFormatCollectionSeasonKey { fn partial_cmp(&self, other: &Self) -> Option { let mut cmp = self.0 .0.partial_cmp(&other.0 .0); @@ -250,7 +248,7 @@ impl SingleFormatCollection { format.season_number, format.season_id.clone(), ))) - .or_insert(BTreeMap::new()) + .or_default() .insert( SingleFormatCollectionEpisodeKey(format.sequence_number), single_formats, @@ -340,6 +338,7 @@ pub struct Format { } impl Format { + #[allow(clippy::type_complexity)] pub fn from_single_formats( mut single_formats: Vec<(SingleFormat, VariantData, Vec<(Subtitle, bool)>)>, ) -> Self { @@ -349,7 +348,7 @@ impl Format { ( single_format.audio.clone(), subtitles - .into_iter() + .iter() .map(|(s, _)| s.locale.clone()) .collect::>(), ) @@ -440,7 +439,7 @@ impl Format { info!( "Downloading {} to {}", self.title, - if is_special_file(&dst) || dst.to_str().unwrap() == "-" { + if is_special_file(dst) || dst.to_str().unwrap() == "-" { dst.to_string_lossy().to_string() } else { format!("'{}'", dst.to_str().unwrap()) diff --git a/crunchy-cli-core/src/utils/locale.rs b/crunchy-cli-core/src/utils/locale.rs index d749fcb..8651078 100644 --- a/crunchy-cli-core/src/utils/locale.rs +++ b/crunchy-cli-core/src/utils/locale.rs @@ -19,8 +19,7 @@ pub fn system_locale() -> Locale { pub fn all_locale_in_locales(locales: Vec) -> Vec { if locales .iter() - .find(|l| l.to_string().to_lowercase().trim() == "all") - .is_some() + .any(|l| l.to_string().to_lowercase().trim() == "all") { Locale::all() } else { diff --git a/crunchy-cli-core/src/utils/log.rs b/crunchy-cli-core/src/utils/log.rs index 6650e58..942c652 100644 --- a/crunchy-cli-core/src/utils/log.rs +++ b/crunchy-cli-core/src/utils/log.rs @@ -57,7 +57,6 @@ macro_rules! tab_info { } pub(crate) use tab_info; -#[allow(clippy::type_complexity)] pub struct CliLogger { level: LevelFilter, progress: Mutex>, diff --git a/crunchy-cli-core/src/utils/os.rs b/crunchy-cli-core/src/utils/os.rs index 0596789..977e968 100644 --- a/crunchy-cli-core/src/utils/os.rs +++ b/crunchy-cli-core/src/utils/os.rs @@ -24,7 +24,7 @@ pub fn has_ffmpeg() -> bool { /// Get the temp directory either by the specified `CRUNCHY_CLI_TEMP_DIR` env variable or the dir /// provided by the os. pub fn temp_directory() -> PathBuf { - env::var("CRUNCHY_CLI_TEMP_DIR").map_or(env::temp_dir(), |d| PathBuf::from(d)) + env::var("CRUNCHY_CLI_TEMP_DIR").map_or(env::temp_dir(), PathBuf::from) } /// Any tempfile should be created with this function. The prefix and directory of every file From c08931b6105d3a6756862d2548e5a428c3f93272 Mon Sep 17 00:00:00 2001 From: bytedream Date: Mon, 6 Nov 2023 22:47:09 +0100 Subject: [PATCH 052/204] Add new commands and format option to readme --- README.md | 112 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 92 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 3cbb8c9..2491939 100644 --- a/README.md +++ b/README.md @@ -61,14 +61,6 @@ Check out the [releases](https://github.com/crunchy-labs/crunchy-cli/releases) t $ yay -S crunchy-cli-bin ``` -- [Nix](https://nixos.org/) - - This requires [nix](https://nixos.org) and you'll probably need `--extra-experimental-features "nix-command flakes"`, depending on your configurations. - - ```shell - $ nix github:crunchy-labs/crunchy-cli - ``` - - [Scoop](https://scoop.sh/) For Windows users, we support the [scoop](https://scoop.sh/#/) command-line installer. @@ -88,6 +80,14 @@ Check out the [releases](https://github.com/crunchy-labs/crunchy-cli/releases) t Supported archs: `x86_64_linux`, `arm64_monterey`, `sonoma`, `ventura` +- [Nix](https://nixos.org/) + + This requires [nix](https://nixos.org) and you'll probably need `--extra-experimental-features "nix-command flakes"`, depending on your configurations. + + ```shell + $ nix github:crunchy-labs/crunchy-cli + ``` + ### 🛠 Build it yourself Since we do not support every platform and architecture you may have to build the project yourself. @@ -191,6 +191,17 @@ You can set specific settings which will be Make sure that proxy can either forward TLS requests, which is needed to bypass the (cloudflare) bot protection, or that it is configured so that the proxy can bypass the protection itself. +- User Agent + + There might be cases where a custom user agent is necessary, e.g. to bypass the cloudflare bot protection (#104). + In such cases, the `--user-agent` flag can be used to set a custom user agent. + + ```shell + $ crunchy-cli --user-agent "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)" + ``` + + Default is the user agent, defined in the underlying [library](https://github.com/crunchy-labs/crunchyroll-rs). + ### Login The `login` command can store your session, so you don't have to authenticate every time you execute a command. @@ -254,6 +265,16 @@ The `download` command lets you download episodes with a specific audio language Default is `{title}.mp4`. See the [Template Options section](#output-template-options) below for more options. +- Output template for special episodes + + Define an output template which only gets used when the episode is a special (episode number is 0 or has non-zero decimal places) by using the `--output-special` flag. + + ```shell + $ crunchy-cli download --output-specials -o "Special EP: {title}" https://www.crunchyroll.com/watch/GY8D975JY/veldoras-journal + ``` + + Default is the template, set by the `-o` / `--output` flag. See the [Template Options section](#output-template-options) below for more options. + - Resolution The resolution for videos can be set via the `-r` / `--resolution` flag. @@ -282,6 +303,14 @@ The `download` command lets you download episodes with a specific audio language $ crunchy-cli download --skip-existing https://www.crunchyroll.com/series/GY8VEQ95Y/darling-in-the-franxx ``` +- Skip specials + + If you doesn't want to download special episodes, use the `--skip-specials` flag to skip the download of them. + + ```shell + $ crunchy-cli download --skip-specials https://www.crunchyroll.com/series/GYZJ43JMR/that-time-i-got-reincarnated-as-a-slime[S2] + ``` + - Yes Sometimes different seasons have the same season number (e.g. Sword Art Online Alicization and Alicization War of Underworld are both marked as season 3), in such cases an interactive prompt is shown which needs user further user input to decide which season to download. @@ -301,6 +330,17 @@ The `download` command lets you download episodes with a specific audio language $ crunchy-cli download --force-hardsub -s en-US https://www.crunchyroll.com/watch/GRDQPM1ZY/alone-and-lonesome ``` +- Threads + + To increase the download speed, video segments are downloaded simultaneously by creating multiple threads. + If you want to manually specify how many threads to use when downloading, do this with the `-t` / `--threads` flag. + + ```shell + $ crunchy-cli download -t 1 https://www.crunchyroll.com/series/GY8VEQ95Y/darling-in-the-franxx + ``` + + The default thread count is the count of cpu threads your pc has. + ### Archive The `archive` command lets you download episodes with multiple audios and subtitles and merges it into a `.mkv` file. @@ -341,7 +381,7 @@ The `archive` command lets you download episodes with multiple audios and subtit - Output template Define an output template by using the `-o` / `--output` flag. - crunchy-cli uses the [`.mkv`](https://en.wikipedia.org/wiki/Matroska) container format, because of it's ability to store multiple audio, video and subtitle tracks at once. + _crunchy-cli_ exclusively uses the [`.mkv`](https://en.wikipedia.org/wiki/Matroska) container format, because of its ability to store multiple audio, video and subtitle tracks at once. ```shell $ crunchy-cli archive -o "{title}.mkv" https://www.crunchyroll.com/series/GY8VEQ95Y/darling-in-the-franxx @@ -349,6 +389,17 @@ The `archive` command lets you download episodes with multiple audios and subtit Default is `{title}.mkv`. See the [Template Options section](#output-template-options) below for more options. +- Output template for special episodes + + Define an output template which only gets used when the episode is a special (episode number is 0 or has non-zero decimal places) by using the `--output-special` flag. + _crunchy-cli_ exclusively uses the [`.mkv`](https://en.wikipedia.org/wiki/Matroska) container format, because of its ability to store multiple audio, video and subtitle tracks at once. + + ```shell + $ crunchy-cli archive --output-specials -o "Special EP: {title}" https://www.crunchyroll.com/watch/GY8D975JY/veldoras-journal + ``` + + Default is the template, set by the `-o` / `--output` flag. See the [Template Options section](#output-template-options) below for more options. + - Resolution The resolution for videos can be set via the `-r` / `--resolution` flag. @@ -402,6 +453,14 @@ The `archive` command lets you download episodes with multiple audios and subtit $ crunchy-cli archive --skip-existing https://www.crunchyroll.com/series/GY8VEQ95Y/darling-in-the-franxx ``` +- Skip specials + + If you doesn't want to download special episodes, use the `--skip-specials` flag to skip the download of them. + + ```shell + $ crunchy-cli archive --skip-specials https://www.crunchyroll.com/series/GYZJ43JMR/that-time-i-got-reincarnated-as-a-slime[S2] + ``` + - Yes Sometimes different seasons have the same season number (e.g. Sword Art Online Alicization and Alicization War of Underworld are both marked as season 3), in such cases an interactive prompt is shown which needs user further user input to decide which season to download. @@ -413,6 +472,17 @@ The `archive` command lets you download episodes with multiple audios and subtit If you've passed the `-q` / `--quiet` [global flag](#global-settings), this flag is automatically set. +- Threads + + To increase the download speed, video segments are downloaded simultaneously by creating multiple threads. + If you want to manually specify how many threads to use when downloading, do this with the `-t` / `--threads` flag. + + ```shell + $ crunchy-cli archive -t 1 https://www.crunchyroll.com/series/GY8VEQ95Y/darling-in-the-franxx + ``` + + The default thread count is the count of cpu threads your pc has. + ### Search **Supported urls/input** @@ -479,17 +549,19 @@ The `archive` command lets you download episodes with multiple audios and subtit You can use various template options to change how the filename is processed. The following tags are available: -- `{title}` → Title of the video -- `{series_name}` → Name of the series -- `{season_name}` → Name of the season -- `{audio}` → Audio language of the video -- `{resolution}` → Resolution of the video -- `{season_number}` → Number of the season -- `{episode_number}` → Number of the episode -- `{relative_episode_number}` → Number of the episode relative to its season -- `{series_id}` → ID of the series -- `{season_id}` → ID of the season -- `{episode_id}` → ID of the episode +- `{title}` → Title of the video +- `{series_name}` → Name of the series +- `{season_name}` → Name of the season +- `{audio}` → Audio language of the video +- `{resolution}` → Resolution of the video +- `{season_number}` → Number of the season +- `{episode_number}` → Number of the episode +- `{relative_episode_number}` → Number of the episode relative to its season +- `{sequence_number}` → Like `{episode_number}` but without possible non-number characters +- `{relative_sequence_number}` → Like `{relative_episode_number}` but with support for episode 0's and .5's +- `{series_id}` → ID of the series +- `{season_id}` → ID of the season +- `{episode_id}` → ID of the episode Example: From d52fe7fb923b7b60c0b54b3cda2fe3bf1087bb09 Mon Sep 17 00:00:00 2001 From: bytedream Date: Mon, 6 Nov 2023 22:56:51 +0100 Subject: [PATCH 053/204] Update dependencies and version --- Cargo.lock | 436 ++++++++++++++++++------------------ Cargo.toml | 4 +- crunchy-cli-core/Cargo.toml | 8 +- 3 files changed, 228 insertions(+), 220 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 409a005..8608f0e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -30,9 +30,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea5d730647d4fadd988536d06fecce94b7b4f2a7efdae548f1cf4b63205518ab" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" dependencies = [ "memchr", ] @@ -54,9 +54,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.5.0" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f58811cfac344940f1a400b6e6231ce35171f614f26439e80f8c1465c5cc0c" +checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44" dependencies = [ "anstyle", "anstyle-parse", @@ -68,15 +68,15 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b84bf0a05bbb2a83e5eb6fa36bb6e87baa08193c35ff52bbf6b38d8af2890e46" +checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" [[package]] name = "anstyle-parse" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" +checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140" dependencies = [ "utf8parse", ] @@ -92,9 +92,9 @@ dependencies = [ [[package]] name = "anstyle-wincon" -version = "2.1.0" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58f54d10c6dfa51283a066ceab3ec1ab78d13fae00aa49243a45e4571fb79dfd" +checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" dependencies = [ "anstyle", "windows-sys 0.48.0", @@ -108,9 +108,9 @@ checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" [[package]] name = "async-trait" -version = "0.1.73" +version = "0.1.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" +checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" dependencies = [ "proc-macro2", "quote", @@ -140,9 +140,9 @@ dependencies = [ [[package]] name = "base64" -version = "0.21.4" +version = "0.21.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2" +checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" [[package]] name = "base64-serde" @@ -162,9 +162,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" [[package]] name = "block-padding" @@ -238,9 +238,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.4" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1d7b8d5ec32af0fadc644bf1fd509a688c2103b185644bb1e29d164e0703136" +checksum = "ac495e00dcec98c83465d5ad66c5c4fabd652fd6686e7c6269b117e729a6f17b" dependencies = [ "clap_builder", "clap_derive", @@ -248,9 +248,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.4" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5179bb514e4d7c2051749d8fcefa2ed6d06a9f4e6d69faf3805f5d80b8cf8d56" +checksum = "c77ed9a32a62e6ca27175d00d29d05ca32e396ea1eb5fb01d8256b669cec7663" dependencies = [ "anstream", "anstyle", @@ -260,18 +260,18 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.4.1" +version = "4.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4110a1e6af615a9e6d0a36f805d5c99099f8bab9b8042f5bc1fa220a4a89e36f" +checksum = "bffe91f06a11b4b9420f62103854e90867812cd5d01557f853c5ee8e791b12ae" dependencies = [ "clap", ] [[package]] name = "clap_derive" -version = "4.4.2" +version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0862016ff20d69b84ef8247369fabf5c008a7417002411897d40ee1f4532b873" +checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" dependencies = [ "heck", "proc-macro2", @@ -281,15 +281,15 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd7cc57abe963c6d3b9d8be5b06ba7c8957a930305ca90304f24ef040aa6f961" +checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" [[package]] name = "clap_mangen" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b44f35c514163027542f7147797ff930523eea288e03642727348ef1a9666f6b" +checksum = "d3be86020147691e1d2ef58f75346a3d4d94807bfc473e377d52f09f0f7d77f7" dependencies = [ "clap", "roff", @@ -360,16 +360,16 @@ checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" [[package]] name = "cpufeatures" -version = "0.2.9" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" +checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" dependencies = [ "libc", ] [[package]] name = "crunchy-cli" -version = "3.0.3" +version = "3.1.0" dependencies = [ "chrono", "clap", @@ -382,7 +382,7 @@ dependencies = [ [[package]] name = "crunchy-cli-core" -version = "3.0.3" +version = "3.1.0" dependencies = [ "anyhow", "async-trait", @@ -412,9 +412,9 @@ dependencies = [ [[package]] name = "crunchyroll-rs" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "771cd92c5a4cc050f301674d77bca6c23f8f260ef346bd06c11b4b05ab9e0166" +checksum = "19bdd19b3f1b26e1a45ed32f7b2db68981111a9f5e9551b2d225bf470dca1e11" dependencies = [ "aes", "async-trait", @@ -439,9 +439,9 @@ dependencies = [ [[package]] name = "crunchyroll-rs-internal" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b260191f1125c7ba31e35071524938de5c6b0c2d248e5a35c62c4605e2da427e" +checksum = "f0a12fb14fd65dede6da7dad3e4c434f6aee9c18cf2bae0d2cc5021cd5a29fec" dependencies = [ "darling", "quote", @@ -505,9 +505,9 @@ dependencies = [ [[package]] name = "dash-mpd" -version = "0.13.1" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b18de4d072c5be455129422f6a69eb17c032467750d857820cb0c9a92e86a4ed" +checksum = "ad33027a1ac2f37def4c33a5987a8e047fd34f77ff7cabc14bd437aa6d8d4dd2" dependencies = [ "base64", "base64-serde", @@ -522,15 +522,17 @@ dependencies = [ "serde_with", "thiserror", "tokio", + "url", "xattr", ] [[package]] name = "deranged" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2696e8a945f658fd14dc3b87242e6b80cd0f36ff04ea560fa39082368847946" +checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3" dependencies = [ + "powerfmt", "serde", ] @@ -607,30 +609,19 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.3" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "136526188508e25c6fef639d7927dfb3e0e3084488bf202267829cf7fc23dbdd" +checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860" dependencies = [ - "errno-dragonfly", "libc", "windows-sys 0.48.0", ] -[[package]] -name = "errno-dragonfly" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" -dependencies = [ - "cc", - "libc", -] - [[package]] name = "fastrand" -version = "2.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" [[package]] name = "fnv" @@ -680,50 +671,38 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" dependencies = [ "futures-core", ] [[package]] name = "futures-core" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" - -[[package]] -name = "futures-macro" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] +checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" [[package]] name = "futures-sink" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" +checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" [[package]] name = "futures-task" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" +checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" [[package]] name = "futures-util" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" dependencies = [ "futures-core", - "futures-macro", "futures-task", "pin-project-lite", "pin-utils", @@ -784,9 +763,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "hashbrown" -version = "0.14.0" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" +checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" [[package]] name = "heck" @@ -857,7 +836,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2 0.4.9", + "socket2 0.4.10", "tokio", "tower-service", "tracing", @@ -866,9 +845,9 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.24.1" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d78e1e73ec14cf7375674f74d7dde185c8206fd9dea6fb6295e8a98098aaa97" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", "http", @@ -893,16 +872,16 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.57" +version = "0.1.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" +checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows", + "windows-core", ] [[package]] @@ -964,12 +943,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" dependencies = [ "equivalent", - "hashbrown 0.14.0", + "hashbrown 0.14.2", "serde", ] @@ -1007,9 +986,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.8.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" [[package]] name = "iso8601" @@ -1028,9 +1007,9 @@ checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "js-sys" -version = "0.3.64" +version = "0.3.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +checksum = "54c0c35952f67de54bb584e9fd912b3023117cbafc0a77d8f3dee1fb5f572fe8" dependencies = [ "wasm-bindgen", ] @@ -1043,15 +1022,26 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.148" +version = "0.2.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" +checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" + +[[package]] +name = "libredox" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" +dependencies = [ + "bitflags 2.4.1", + "libc", + "redox_syscall", +] [[package]] name = "linux-raw-sys" -version = "0.4.7" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a9bad9f94746442c783ca431b22403b519cd7fbeed0533fdd6328b2f2212128" +checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" [[package]] name = "log" @@ -1077,9 +1067,9 @@ checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" [[package]] name = "memchr" -version = "2.6.3" +version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" [[package]] name = "mime" @@ -1104,9 +1094,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0" dependencies = [ "libc", "wasi", @@ -1135,7 +1125,7 @@ version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.4.1", "cfg-if", "libc", ] @@ -1152,9 +1142,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" +checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" dependencies = [ "autocfg", ] @@ -1192,11 +1182,11 @@ checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] name = "openssl" -version = "0.10.57" +version = "0.10.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bac25ee399abb46215765b1cb35bc0212377e58a061560d8b29b024fd0430e7c" +checksum = "7a257ad03cd8fb16ad4172fedf8094451e1af1c4b70097636ef2eac9a5f0cc33" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.4.1", "cfg-if", "foreign-types", "libc", @@ -1224,18 +1214,18 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-src" -version = "300.1.5+3.1.3" +version = "300.1.6+3.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "559068e4c12950d7dcaa1857a61725c0d38d4fc03ff8e070ab31a75d6e316491" +checksum = "439fac53e092cd7442a3660c85dde4643ab3b5bd39040912388dcdabf6b88085" dependencies = [ "cc", ] [[package]] name = "openssl-sys" -version = "0.9.93" +version = "0.9.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db4d56a4c0478783083cfafcc42493dd4a981d41669da64b4572a2a089b51b1d" +checksum = "40a4130519a360279579c2053038317e40eff64d13fd3f004f9e1b72b8a6aaf9" dependencies = [ "cc", "libc", @@ -1276,15 +1266,21 @@ checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" [[package]] name = "portable-atomic" -version = "1.4.3" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31114a898e107c51bb1609ffaf55a0e011cf6a4d7f1170d0015a165082c0338b" +checksum = "3bccab0e7fd7cc19f820a1c8c91720af652d0c88dc9664dd72aef2614f04af3b" + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "proc-macro2" -version = "1.0.67" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" +checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" dependencies = [ "unicode-ident", ] @@ -1307,9 +1303,9 @@ dependencies = [ [[package]] name = "quick-xml" -version = "0.30.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eff6510e86862b57b210fd8cbe8ed3f0d7d600b9c2863cd4549a2e033c66e956" +checksum = "1004a344b30a54e2ee58d66a71b32d2db2feb0a31f9a2d302bf0536f15de2a33" dependencies = [ "memchr", "serde", @@ -1326,38 +1322,29 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.16" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_syscall" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ "bitflags 1.3.2", ] [[package]] name = "redox_users" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" dependencies = [ "getrandom", - "redox_syscall 0.2.16", + "libredox", "thiserror", ] [[package]] name = "regex" -version = "1.9.5" +version = "1.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "697061221ea1b4a94a624f67d0ae2bfe4e22b8a17b6a192afb11046542cc8c47" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" dependencies = [ "aho-corasick", "memchr", @@ -1367,9 +1354,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.3.8" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2f401f4955220693b56f8ec66ee9c78abffd8d1c4f23dc41a23839eb88f0795" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" dependencies = [ "aho-corasick", "memchr", @@ -1378,15 +1365,15 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.7.5" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "reqwest" -version = "0.11.20" +version = "0.11.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e9ad3fe7488d7e34558a2033d45a0c90b72d97b4f80705666fea71472e2e6a1" +checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" dependencies = [ "base64", "bytes", @@ -1414,6 +1401,7 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded", + "system-configuration", "tokio", "tokio-native-tls", "tokio-rustls", @@ -1429,17 +1417,16 @@ dependencies = [ [[package]] name = "ring" -version = "0.16.20" +version = "0.17.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +checksum = "fb0205304757e5d899b9c2e448b867ffd03ae7f988002e47cd24954391394d0b" dependencies = [ "cc", + "getrandom", "libc", - "once_cell", "spin", "untrusted", - "web-sys", - "winapi", + "windows-sys 0.48.0", ] [[package]] @@ -1456,11 +1443,11 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustix" -version = "0.38.14" +version = "0.38.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "747c788e9ce8e92b12cd485c49ddf90723550b654b32508f979b71a7b1ecda4f" +checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.4.1", "errno", "libc", "linux-raw-sys", @@ -1469,9 +1456,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.7" +version = "0.21.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd8d6c9f025a446bc4d18ad9632e69aec8f287aa84499ee335599fabd20c3fd8" +checksum = "446e14c5cda4f3f30fe71863c34ec70f5ac79d6087097ad0bb433e1be5edf04c" dependencies = [ "log", "ring", @@ -1502,9 +1489,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.101.6" +version = "0.101.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c7d5dece342910d9ba34d259310cae3e0154b873b35408b787b59bce53d34fe" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" dependencies = [ "ring", "untrusted", @@ -1527,9 +1514,9 @@ dependencies = [ [[package]] name = "sct" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ "ring", "untrusted", @@ -1560,18 +1547,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.188" +version = "1.0.191" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" +checksum = "a834c4821019838224821468552240d4d95d14e751986442c816572d39a080c9" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.188" +version = "1.0.191" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" +checksum = "46fa52d5646bce91b680189fe5b1c049d2ea38dabb4e2e7c8d00ca12cfbfbcfd" dependencies = [ "proc-macro2", "quote", @@ -1580,9 +1567,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.107" +version = "1.0.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" +checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" dependencies = [ "itoa", "ryu", @@ -1612,15 +1599,15 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.3.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ca3b16a3d82c4088f343b7480a93550b3eabe1a358569c2dfe38bbcead07237" +checksum = "64cd236ccc1b7a29e7e2739f27c0b2dd199804abc4290e32f59f3b68d6405c23" dependencies = [ "base64", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.0.0", + "indexmap 2.1.0", "serde", "serde_json", "serde_with_macros", @@ -1629,9 +1616,9 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.3.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e6be15c453eb305019bfa438b1593c731f36a289a7853f7707ee29e870b3b3c" +checksum = "93634eb5f75a2323b16de4748022ac4297f9e76b6dced2be287a099f41b5e788" dependencies = [ "darling", "proc-macro2", @@ -1673,9 +1660,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" dependencies = [ "libc", "winapi", @@ -1683,9 +1670,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e" +checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" dependencies = [ "libc", "windows-sys 0.48.0", @@ -1693,9 +1680,9 @@ dependencies = [ [[package]] name = "spin" -version = "0.5.2" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" [[package]] name = "strsim" @@ -1705,9 +1692,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" -version = "2.0.37" +version = "2.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" +checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" dependencies = [ "proc-macro2", "quote", @@ -1724,32 +1711,53 @@ dependencies = [ ] [[package]] -name = "tempfile" -version = "3.8.0" +name = "system-configuration" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "tempfile" +version = "3.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" dependencies = [ "cfg-if", "fastrand", - "redox_syscall 0.3.5", + "redox_syscall", "rustix", "windows-sys 0.48.0", ] [[package]] name = "thiserror" -version = "1.0.48" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d6d7a740b8a666a7e828dd00da9c0dc290dff53154ea77ac109281de90589b7" +checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.48" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49922ecae66cc8a249b77e68d1d0623c1b2c514f0060c27cdc68bd62a1219d35" +checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" dependencies = [ "proc-macro2", "quote", @@ -1758,12 +1766,13 @@ dependencies = [ [[package]] name = "time" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17f6bb557fd245c28e6411aa56b6403c689ad95061f50e4be16c274e70a17e48" +checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" dependencies = [ "deranged", "itoa", + "powerfmt", "serde", "time-core", "time-macros", @@ -1771,15 +1780,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a942f44339478ef67935ab2bbaec2fb0322496cf3cbe84b261e06ac3814c572" +checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20" dependencies = [ "time-core", ] @@ -1801,9 +1810,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.32.0" +version = "1.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9" +checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653" dependencies = [ "backtrace", "bytes", @@ -1811,7 +1820,7 @@ dependencies = [ "mio", "num_cpus", "pin-project-lite", - "socket2 0.5.4", + "socket2 0.5.5", "tokio-macros", "windows-sys 0.48.0", ] @@ -1861,9 +1870,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d68074620f57a0b21594d9735eb2e98ab38b17f80d3fcb189fca266771ca60d" +checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" dependencies = [ "bytes", "futures-core", @@ -1881,20 +1890,19 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.37" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "cfg-if", "pin-project-lite", "tracing-core", ] [[package]] name = "tracing-core" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", ] @@ -1940,9 +1948,9 @@ checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" [[package]] name = "untrusted" -version = "0.7.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" @@ -1990,9 +1998,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.87" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +checksum = "7daec296f25a1bae309c0cd5c29c4b260e510e6d813c286b19eaadf409d40fce" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -2000,9 +2008,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.87" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +checksum = "e397f4664c0e4e428e8313a469aaa58310d302159845980fd23b0f22a847f217" dependencies = [ "bumpalo", "log", @@ -2015,9 +2023,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.37" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" +checksum = "9afec9963e3d0994cac82455b2b3502b81a7f40f9a0d32181f7528d9f4b43e02" dependencies = [ "cfg-if", "js-sys", @@ -2027,9 +2035,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.87" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +checksum = "5961017b3b08ad5f3fe39f1e79877f8ee7c23c5e5fd5eb80de95abc41f1f16b2" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2037,9 +2045,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.87" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +checksum = "c5353b8dab669f5e10f5bd76df26a9360c748f054f862ff5f3f8aae0c7fb3907" dependencies = [ "proc-macro2", "quote", @@ -2050,15 +2058,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.87" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +checksum = "0d046c5d029ba91a1ed14da14dca44b68bf2f124cfbaf741c54151fdb3e0750b" [[package]] name = "web-sys" -version = "0.3.64" +version = "0.3.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +checksum = "5db499c5f66323272151db0e666cd34f78617522fb0c1604d31a27c50c206a85" dependencies = [ "js-sys", "wasm-bindgen", @@ -2093,10 +2101,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "windows" -version = "0.48.0" +name = "windows-core" +version = "0.51.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" dependencies = [ "windows-targets 0.48.5", ] diff --git a/Cargo.toml b/Cargo.toml index e5882d6..a0c1871 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "crunchy-cli" authors = ["Crunchy Labs Maintainers"] -version = "3.0.3" +version = "3.1.0" edition = "2021" license = "MIT" @@ -18,7 +18,7 @@ openssl = ["openssl-tls"] openssl-static = ["openssl-tls-static"] [dependencies] -tokio = { version = "1.32", features = ["macros", "rt-multi-thread", "time"], default-features = false } +tokio = { version = "1.33", features = ["macros", "rt-multi-thread", "time"], default-features = false } native-tls-crate = { package = "native-tls", version = "0.2.11", optional = true } diff --git a/crunchy-cli-core/Cargo.toml b/crunchy-cli-core/Cargo.toml index e38cb1a..9103831 100644 --- a/crunchy-cli-core/Cargo.toml +++ b/crunchy-cli-core/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "crunchy-cli-core" authors = ["Crunchy Labs Maintainers"] -version = "3.0.3" +version = "3.1.0" edition = "2021" license = "MIT" @@ -16,7 +16,7 @@ anyhow = "1.0" async-trait = "0.1" clap = { version = "4.4", features = ["derive", "string"] } chrono = "0.4" -crunchyroll-rs = { version = "0.6.2", features = ["dash-stream"] } +crunchyroll-rs = { version = "0.6.3", features = ["dash-stream"] } ctrlc = "3.4" dialoguer = { version = "0.11", default-features = false } dirs = "5.0" @@ -26,7 +26,7 @@ indicatif = "0.17" lazy_static = "1.4" log = { version = "0.4", features = ["std"] } num_cpus = "1.16" -regex = "1.9" +regex = "1.10" reqwest = { version = "0.11", default-features = false, features = ["socks"] } serde = "1.0" serde_json = "1.0" @@ -34,7 +34,7 @@ serde_plain = "1.0" shlex = "1.2" sys-locale = "0.3" tempfile = "3.8" -tokio = { version = "1.32", features = ["macros", "rt-multi-thread", "time"] } +tokio = { version = "1.33", features = ["macros", "rt-multi-thread", "time"] } rustls-native-certs = { version = "0.6", optional = true } [build-dependencies] From 14e71c05b84ff7458478443b2de4ee71273c61a3 Mon Sep 17 00:00:00 2001 From: bytedream Date: Thu, 16 Nov 2023 13:51:30 +0100 Subject: [PATCH 054/204] Fix aur binary checksums (#266) --- .github/workflows/publish.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index f777f9e..43ea795 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -43,8 +43,8 @@ jobs: curl -LO https://github.com/crunchy-labs/crunchy-cli/releases/download/${{ github.ref_name }}/crunchy-cli-${{ github.ref_name }}-completions.zip curl -LO https://github.com/crunchy-labs/crunchy-cli/releases/download/${{ github.ref_name }}/crunchy-cli-${{ github.ref_name }}-manpages.zip curl -LO https://raw.githubusercontent.com/crunchy-labs/crunchy-cli/${{ github.ref_name }}/LICENSE - echo "CRUNCHY_CLI_BIN_x86_64_SHA256=$(sha256sum crunchy-cli-${{ github.ref_name }}-x86_64-linux | cut -f 1 -d ' ')" >> $GITHUB_ENV - echo "CRUNCHY_CLI_BIN_aarch64_SHA256=$(sha256sum crunchy-cli-${{ github.ref_name }}-aarch64-linux | cut -f 1 -d ' ')" >> $GITHUB_ENV + echo "CRUNCHY_CLI_BIN_x86_64_SHA256=$(sha256sum crunchy-cli-${{ github.ref_name }}-linux-x86_64 | cut -f 1 -d ' ')" >> $GITHUB_ENV + echo "CRUNCHY_CLI_BIN_aarch64_SHA256=$(sha256sum crunchy-cli-${{ github.ref_name }}-linux-aarch64 | cut -f 1 -d ' ')" >> $GITHUB_ENV echo "CRUNCHY_CLI_BIN_COMPLETIONS_SHA256=$(sha256sum crunchy-cli-${{ github.ref_name }}-completions.zip | cut -f 1 -d ' ')" >> $GITHUB_ENV echo "CRUNCHY_CLI_BIN_MANPAGES_SHA256=$(sha256sum crunchy-cli-${{ github.ref_name }}-manpages.zip | cut -f 1 -d ' ')" >> $GITHUB_ENV echo "CRUNCHY_CLI_BIN_LICENSE_SHA256=$(sha256sum LICENSE | cut -f 1 -d ' ')" >> $GITHUB_ENV From 2c370939595149c20ed6ba2fbde3274134be0aad Mon Sep 17 00:00:00 2001 From: bytedream Date: Sun, 19 Nov 2023 19:24:15 +0100 Subject: [PATCH 055/204] Manually burn-in subtitles only if no pre-burned video is available (#268) --- crunchy-cli-core/src/archive/command.rs | 3 +- crunchy-cli-core/src/download/command.rs | 56 +++++++++++++++++++++--- crunchy-cli-core/src/utils/ffmpeg.rs | 2 + crunchy-cli-core/src/utils/format.rs | 4 ++ crunchy-cli-core/src/utils/video.rs | 37 ++++++++++++---- 5 files changed, 88 insertions(+), 14 deletions(-) diff --git a/crunchy-cli-core/src/archive/command.rs b/crunchy-cli-core/src/archive/command.rs index 3585e9c..006bbfa 100644 --- a/crunchy-cli-core/src/archive/command.rs +++ b/crunchy-cli-core/src/archive/command.rs @@ -248,7 +248,8 @@ async fn get_format( for single_format in single_formats { let stream = single_format.stream().await?; - let Some((video, audio)) = variant_data_from_stream(&stream, &archive.resolution).await? + let Some((video, audio, _)) = + variant_data_from_stream(&stream, &archive.resolution, None).await? else { if single_format.is_episode() { bail!( diff --git a/crunchy-cli-core/src/download/command.rs b/crunchy-cli-core/src/download/command.rs index 82cb8f8..cf1a049 100644 --- a/crunchy-cli-core/src/download/command.rs +++ b/crunchy-cli-core/src/download/command.rs @@ -1,7 +1,7 @@ use crate::download::filter::DownloadFilter; use crate::utils::context::Context; use crate::utils::download::{DownloadBuilder, DownloadFormat}; -use crate::utils::ffmpeg::FFmpegPreset; +use crate::utils::ffmpeg::{FFmpegPreset, SOFTSUB_CONTAINERS}; use crate::utils::filter::Filter; use crate::utils::format::{Format, SingleFormat}; use crate::utils::log::progress; @@ -149,6 +149,25 @@ impl Execute for Download { async fn execute(self, ctx: Context) -> Result<()> { let mut parsed_urls = vec![]; + let output_supports_softsubs = SOFTSUB_CONTAINERS.contains( + &Path::new(&self.output) + .extension() + .unwrap_or_default() + .to_string_lossy() + .as_ref(), + ); + let special_output_supports_softsubs = if let Some(so) = &self.output_specials { + SOFTSUB_CONTAINERS.contains( + &Path::new(so) + .extension() + .unwrap_or_default() + .to_string_lossy() + .as_ref(), + ) + } else { + output_supports_softsubs + }; + for (i, url) in self.urls.clone().into_iter().enumerate() { let progress_handler = progress!("Parsing url {}", i + 1); match parse_url(&ctx.crunchy, url.clone(), true).await { @@ -190,7 +209,18 @@ impl Execute for Download { // the vec contains always only one item let single_format = single_formats.remove(0); - let (download_format, format) = get_format(&self, &single_format).await?; + let (download_format, format) = get_format( + &self, + &single_format, + if self.force_hardsub { + true + } else if single_format.is_special() { + !special_output_supports_softsubs + } else { + !output_supports_softsubs + }, + ) + .await?; let mut downloader = download_builder.clone().build(); downloader.add_format(download_format); @@ -227,9 +257,19 @@ impl Execute for Download { async fn get_format( download: &Download, single_format: &SingleFormat, + try_peer_hardsubs: bool, ) -> Result<(DownloadFormat, Format)> { let stream = single_format.stream().await?; - let Some((video, audio)) = variant_data_from_stream(&stream, &download.resolution).await? + let Some((video, audio, contains_hardsub)) = variant_data_from_stream( + &stream, + &download.resolution, + if try_peer_hardsubs { + download.subtitle.clone() + } else { + None + }, + ) + .await? else { if single_format.is_episode() { bail!( @@ -250,7 +290,9 @@ async fn get_format( } }; - let subtitle = if let Some(subtitle_locale) = &download.subtitle { + let subtitle = if contains_hardsub { + None + } else if let Some(subtitle_locale) = &download.subtitle { stream.subtitles.get(subtitle_locale).cloned() } else { None @@ -266,7 +308,7 @@ async fn get_format( )] }), }; - let format = Format::from_single_formats(vec![( + let mut format = Format::from_single_formats(vec![( single_format.clone(), video, subtitle.map_or(vec![], |s| { @@ -276,6 +318,10 @@ async fn get_format( )] }), )]); + if contains_hardsub { + let (_, subs) = format.locales.get_mut(0).unwrap(); + subs.push(download.subtitle.clone().unwrap()) + } Ok((download_format, format)) } diff --git a/crunchy-cli-core/src/utils/ffmpeg.rs b/crunchy-cli-core/src/utils/ffmpeg.rs index 787c79a..7d77833 100644 --- a/crunchy-cli-core/src/utils/ffmpeg.rs +++ b/crunchy-cli-core/src/utils/ffmpeg.rs @@ -2,6 +2,8 @@ use lazy_static::lazy_static; use regex::Regex; use std::str::FromStr; +pub const SOFTSUB_CONTAINERS: [&str; 3] = ["mkv", "mov", "mp4"]; + #[derive(Clone, Debug, Eq, PartialEq)] pub enum FFmpegPreset { Predefined(FFmpegCodec, Option, FFmpegQuality), diff --git a/crunchy-cli-core/src/utils/format.rs b/crunchy-cli-core/src/utils/format.rs index 4c8d3c8..05ac232 100644 --- a/crunchy-cli-core/src/utils/format.rs +++ b/crunchy-cli-core/src/utils/format.rs @@ -172,6 +172,10 @@ impl SingleFormat { pub fn is_episode(&self) -> bool { matches!(self.source, MediaCollection::Episode(_)) } + + pub fn is_special(&self) -> bool { + self.sequence_number == 0.0 || self.sequence_number.fract() != 0.0 + } } struct SingleFormatCollectionEpisodeKey(f32); diff --git a/crunchy-cli-core/src/utils/video.rs b/crunchy-cli-core/src/utils/video.rs index 5b3eaeb..0ae4ba4 100644 --- a/crunchy-cli-core/src/utils/video.rs +++ b/crunchy-cli-core/src/utils/video.rs @@ -1,32 +1,47 @@ -use anyhow::Result; +use anyhow::{bail, Result}; use crunchyroll_rs::media::{Resolution, Stream, VariantData}; use crunchyroll_rs::Locale; pub async fn variant_data_from_stream( stream: &Stream, resolution: &Resolution, -) -> Result> { + subtitle: Option, +) -> Result> { // sometimes Crunchyroll marks episodes without real subtitles that they have subtitles and // reports that only hardsub episode are existing. the following lines are trying to prevent // potential errors which might get caused by this incorrect reporting // (https://github.com/crunchy-labs/crunchy-cli/issues/231) let mut hardsub_locales = stream.streaming_hardsub_locales(); - let hardsub_locale = if !hardsub_locales.contains(&Locale::Custom("".to_string())) + let (hardsub_locale, mut contains_hardsub) = if !hardsub_locales + .contains(&Locale::Custom("".to_string())) && !hardsub_locales.contains(&Locale::Custom(":".to_string())) { // if only one hardsub locale exists, assume that this stream doesn't really contains hardsubs if hardsub_locales.len() == 1 { - Some(hardsub_locales.remove(0)) + (Some(hardsub_locales.remove(0)), false) } else { // fallback to `None`. this should trigger an error message in `stream.dash_streaming_data` // that the requested stream is not available - None + (None, false) } } else { - None + let hardsubs_requested = subtitle.is_some(); + (subtitle, hardsubs_requested) }; - let mut streaming_data = stream.dash_streaming_data(hardsub_locale).await?; + let mut streaming_data = match stream.dash_streaming_data(hardsub_locale).await { + Ok(data) => data, + Err(e) => { + // the error variant is only `crunchyroll_rs::error::Error::Input` when the requested + // hardsub is not available + if let crunchyroll_rs::error::Error::Input { .. } = e { + contains_hardsub = false; + stream.dash_streaming_data(None).await? + } else { + bail!(e) + } + } + }; streaming_data .0 .sort_by(|a, b| a.bandwidth.cmp(&b.bandwidth).reverse()); @@ -42,5 +57,11 @@ pub async fn variant_data_from_stream( .into_iter() .find(|v| resolution.height == v.resolution.height), }; - Ok(video_variant.map(|v| (v, streaming_data.1.first().unwrap().clone()))) + Ok(video_variant.map(|v| { + ( + v, + streaming_data.1.first().unwrap().clone(), + contains_hardsub, + ) + })) } From 440ccd99b5482af43b0cec222d49a45ddd5b43e1 Mon Sep 17 00:00:00 2001 From: bytedream Date: Mon, 20 Nov 2023 22:05:06 +0100 Subject: [PATCH 056/204] Update dependencies and version --- Cargo.lock | 82 +++++++++++++------------ Cargo.toml | 4 +- crunchy-cli-core/Cargo.toml | 6 +- crunchy-cli-core/src/archive/filter.rs | 8 +-- crunchy-cli-core/src/download/filter.rs | 4 +- crunchy-cli-core/src/search/format.rs | 2 +- 6 files changed, 54 insertions(+), 52 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8608f0e..897731f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -238,9 +238,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.7" +version = "4.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac495e00dcec98c83465d5ad66c5c4fabd652fd6686e7c6269b117e729a6f17b" +checksum = "2275f18819641850fa26c89acc84d465c1bf91ce57bc2748b28c420473352f64" dependencies = [ "clap_builder", "clap_derive", @@ -248,9 +248,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.7" +version = "4.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c77ed9a32a62e6ca27175d00d29d05ca32e396ea1eb5fb01d8256b669cec7663" +checksum = "07cdf1b148b25c1e1f7a42225e30a0d99a615cd4637eae7365548dd4529b95bc" dependencies = [ "anstream", "anstyle", @@ -369,7 +369,7 @@ dependencies = [ [[package]] name = "crunchy-cli" -version = "3.1.0" +version = "3.1.1" dependencies = [ "chrono", "clap", @@ -382,7 +382,7 @@ dependencies = [ [[package]] name = "crunchy-cli-core" -version = "3.1.0" +version = "3.1.1" dependencies = [ "anyhow", "async-trait", @@ -412,9 +412,9 @@ dependencies = [ [[package]] name = "crunchyroll-rs" -version = "0.6.3" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19bdd19b3f1b26e1a45ed32f7b2db68981111a9f5e9551b2d225bf470dca1e11" +checksum = "cc4ce434784eee7892ad8c3d1ecaea0c0858db51bbb295b474db38c256e8d2fb" dependencies = [ "aes", "async-trait", @@ -423,7 +423,6 @@ dependencies = [ "crunchyroll-rs-internal", "dash-mpd", "futures-util", - "http", "lazy_static", "m3u8-rs", "regex", @@ -439,9 +438,9 @@ dependencies = [ [[package]] name = "crunchyroll-rs-internal" -version = "0.6.3" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0a12fb14fd65dede6da7dad3e4c434f6aee9c18cf2bae0d2cc5021cd5a29fec" +checksum = "be840f8cf2ce6afc9a9eae268d41423093141ec88f664a515d5ed2a85a66fb60" dependencies = [ "darling", "quote", @@ -505,9 +504,9 @@ dependencies = [ [[package]] name = "dash-mpd" -version = "0.14.3" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad33027a1ac2f37def4c33a5987a8e047fd34f77ff7cabc14bd437aa6d8d4dd2" +checksum = "5471fc46c0b229c8f2308d83be857c745c9f06cc83a433d7047909722e0453b4" dependencies = [ "base64", "base64-serde", @@ -609,9 +608,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860" +checksum = "f258a7194e7f7c2a7837a8913aeab7fd8c383457034fa20ce4dd3dcb813e8eb8" dependencies = [ "libc", "windows-sys 0.48.0", @@ -655,9 +654,12 @@ dependencies = [ [[package]] name = "fs-err" -version = "2.9.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0845fa252299212f0389d64ba26f34fa32cfe41588355f21ed507c59a0f64541" +checksum = "88a41f105fe1d5b6b34b2055e3dc59bb79b46b48b2040b9e6c7b4b5de097aa41" +dependencies = [ + "autocfg", +] [[package]] name = "fs2" @@ -721,9 +723,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" dependencies = [ "cfg-if", "libc", @@ -738,9 +740,9 @@ checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" [[package]] name = "h2" -version = "0.3.21" +version = "0.3.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91fc23aa11be92976ef4729127f1a74adf36d8436f7816b185d18df956790833" +checksum = "4d6250322ef6e60f93f9a2162799302cd6f68f79f6e5d85c8c16f14d1d958178" dependencies = [ "bytes", "fnv", @@ -748,7 +750,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap 1.9.3", + "indexmap 2.1.0", "slab", "tokio", "tokio-util", @@ -787,9 +789,9 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "http" -version = "0.2.9" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" dependencies = [ "bytes", "fnv", @@ -1039,9 +1041,9 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" +checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829" [[package]] name = "log" @@ -1443,9 +1445,9 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustix" -version = "0.38.21" +version = "0.38.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3" +checksum = "dc99bc2d4f1fed22595588a013687477aedf3cdcfb26558c559edb67b4d9b22e" dependencies = [ "bitflags 2.4.1", "errno", @@ -1456,9 +1458,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.8" +version = "0.21.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "446e14c5cda4f3f30fe71863c34ec70f5ac79d6087097ad0bb433e1be5edf04c" +checksum = "629648aced5775d558af50b2b4c7b02983a04b312126d45eeead26e7caa498b9" dependencies = [ "log", "ring", @@ -1480,9 +1482,9 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" dependencies = [ "base64", ] @@ -1547,18 +1549,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.191" +version = "1.0.192" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a834c4821019838224821468552240d4d95d14e751986442c816572d39a080c9" +checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.191" +version = "1.0.192" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46fa52d5646bce91b680189fe5b1c049d2ea38dabb4e2e7c8d00ca12cfbfbcfd" +checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1" dependencies = [ "proc-macro2", "quote", @@ -1810,9 +1812,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.33.0" +version = "1.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f38200e3ef7995e5ef13baec2f432a6da0aa9ac495b2c0e8f3b7eec2c92d653" +checksum = "d0c014766411e834f7af5b8f4cf46257aab4036ca95e9d2c144a10f59ad6f5b9" dependencies = [ "backtrace", "bytes", @@ -1827,9 +1829,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index a0c1871..098c048 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "crunchy-cli" authors = ["Crunchy Labs Maintainers"] -version = "3.1.0" +version = "3.1.1" edition = "2021" license = "MIT" @@ -18,7 +18,7 @@ openssl = ["openssl-tls"] openssl-static = ["openssl-tls-static"] [dependencies] -tokio = { version = "1.33", features = ["macros", "rt-multi-thread", "time"], default-features = false } +tokio = { version = "1.34", features = ["macros", "rt-multi-thread", "time"], default-features = false } native-tls-crate = { package = "native-tls", version = "0.2.11", optional = true } diff --git a/crunchy-cli-core/Cargo.toml b/crunchy-cli-core/Cargo.toml index 9103831..5771888 100644 --- a/crunchy-cli-core/Cargo.toml +++ b/crunchy-cli-core/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "crunchy-cli-core" authors = ["Crunchy Labs Maintainers"] -version = "3.1.0" +version = "3.1.1" edition = "2021" license = "MIT" @@ -16,7 +16,7 @@ anyhow = "1.0" async-trait = "0.1" clap = { version = "4.4", features = ["derive", "string"] } chrono = "0.4" -crunchyroll-rs = { version = "0.6.3", features = ["dash-stream"] } +crunchyroll-rs = { version = "0.7.0", features = ["dash-stream"] } ctrlc = "3.4" dialoguer = { version = "0.11", default-features = false } dirs = "5.0" @@ -34,7 +34,7 @@ serde_plain = "1.0" shlex = "1.2" sys-locale = "0.3" tempfile = "3.8" -tokio = { version = "1.33", features = ["macros", "rt-multi-thread", "time"] } +tokio = { version = "1.34", features = ["macros", "rt-multi-thread", "time"] } rustls-native-certs = { version = "0.6", optional = true } [build-dependencies] diff --git a/crunchy-cli-core/src/archive/filter.rs b/crunchy-cli-core/src/archive/filter.rs index 01612b9..1777072 100644 --- a/crunchy-cli-core/src/archive/filter.rs +++ b/crunchy-cli-core/src/archive/filter.rs @@ -223,7 +223,7 @@ impl Filter for ArchiveFilter { "Season {} is only available with {} audio until episode {} ({})", season.season_number, season_locale.unwrap_or(Locale::ja_JP), - last_episode.episode_number, + last_episode.sequence_number, last_episode.title ) } @@ -278,7 +278,7 @@ impl Filter for ArchiveFilter { if !missing_audio.is_empty() { warn!( "Episode {} is not available with {} audio", - episode.episode_number, + episode.sequence_number, missing_audio .into_iter() .map(|l| l.to_string()) @@ -298,7 +298,7 @@ impl Filter for ArchiveFilter { { warn!( "Episode {} is not available with {} subtitles", - episode.episode_number, + episode.sequence_number, missing_subtitles .into_iter() .map(|l| l.to_string()) @@ -343,7 +343,7 @@ impl Filter for ArchiveFilter { if relative_episode_number.is_none() || relative_sequence_number.is_none() { warn!( "Failed to get relative episode number for episode {} ({}) of {} season {}", - episode.episode_number, + episode.sequence_number, episode.title, episode.series_title, episode.season_number, diff --git a/crunchy-cli-core/src/download/filter.rs b/crunchy-cli-core/src/download/filter.rs index fb2e563..51f1ad8 100644 --- a/crunchy-cli-core/src/download/filter.rs +++ b/crunchy-cli-core/src/download/filter.rs @@ -158,7 +158,7 @@ impl Filter for DownloadFilter { { let error_message = format!( "Episode {} ({}) of {} season {} is not available with {} audio", - episode.episode_number, + episode.sequence_number, episode.title, episode.series_title, episode.season_number, @@ -234,7 +234,7 @@ impl Filter for DownloadFilter { if relative_episode_number.is_none() || relative_sequence_number.is_none() { warn!( "Failed to get relative episode number for episode {} ({}) of {} season {}", - episode.episode_number, + episode.sequence_number, episode.title, episode.series_title, episode.season_number, diff --git a/crunchy-cli-core/src/search/format.rs b/crunchy-cli-core/src/search/format.rs index f9746b1..156bd95 100644 --- a/crunchy-cli-core/src/search/format.rs +++ b/crunchy-cli-core/src/search/format.rs @@ -70,7 +70,7 @@ impl From<&Episode> for FormatEpisode { title: value.title.clone(), description: value.description.clone(), locale: value.audio_locale.clone(), - number: value.episode_number, + number: value.episode_number.unwrap_or_default(), sequence_number: value.sequence_number, duration: value.duration.num_milliseconds(), air_date: value.episode_air_date.timestamp(), From d5df3df95f5972495c8c317f0fb243c32ede0b37 Mon Sep 17 00:00:00 2001 From: bytedream Date: Fri, 1 Dec 2023 01:02:53 +0100 Subject: [PATCH 057/204] Fix fixed subtitle formatting and sorting (#272) --- crunchy-cli-core/src/utils/download.rs | 33 +++++++++++++++++++------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/crunchy-cli-core/src/utils/download.rs b/crunchy-cli-core/src/utils/download.rs index 945cc14..c65b4d2 100644 --- a/crunchy-cli-core/src/utils/download.rs +++ b/crunchy-cli-core/src/utils/download.rs @@ -17,6 +17,7 @@ use std::env; use std::io::Write; use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; +use std::str::FromStr; use std::sync::Arc; use std::time::Duration; use tempfile::TempPath; @@ -788,8 +789,10 @@ pub fn get_video_length(path: &Path) -> Result { /// [crunchy-labs/crunchy-cli#208](https://github.com/crunchy-labs/crunchy-cli/issues/208) for more /// information. fn fix_subtitles(raw: &mut Vec, max_length: NaiveTime) { - let re = Regex::new(r"^Dialogue:\s\d+,(?P\d+:\d+:\d+\.\d+),(?P\d+:\d+:\d+\.\d+),") - .unwrap(); + let re = Regex::new( + r"^Dialogue:\s(?P\d+),(?P\d+:\d+:\d+\.\d+),(?P\d+:\d+:\d+\.\d+),", + ) + .unwrap(); // chrono panics if we try to format NaiveTime with `%2f` and the nano seconds has more than 2 // digits so them have to be reduced manually to avoid the panic @@ -804,9 +807,9 @@ fn fix_subtitles(raw: &mut Vec, max_length: NaiveTime) { formatted_time.split_at(2).0.parse().unwrap() } ) + .split_off(1) // <- in the ASS spec, the hour has only one digit } - let length_as_string = format_naive_time(max_length); let mut entries = (vec![], vec![]); let mut as_lines: Vec = String::from_utf8_lossy(raw.as_slice()) @@ -818,21 +821,33 @@ fn fix_subtitles(raw: &mut Vec, max_length: NaiveTime) { if line.trim() == "[Script Info]" { line.push_str("\nScaledBorderAndShadow: yes") } else if let Some(capture) = re.captures(line) { - let start = capture.name("start").map_or(NaiveTime::default(), |s| { + let mut start = capture.name("start").map_or(NaiveTime::default(), |s| { NaiveTime::parse_from_str(s.as_str(), "%H:%M:%S.%f").unwrap() }); - let end = capture.name("end").map_or(NaiveTime::default(), |s| { - NaiveTime::parse_from_str(s.as_str(), "%H:%M:%S.%f").unwrap() + let mut end = capture.name("end").map_or(NaiveTime::default(), |e| { + NaiveTime::parse_from_str(e.as_str(), "%H:%M:%S.%f").unwrap() }); - if end > max_length { + if start > max_length || end > max_length { + let layer = capture + .name("layer") + .map_or(0, |l| i32::from_str(l.as_str()).unwrap()); + + if start > max_length { + start = max_length; + } + if start > max_length || end > max_length { + end = max_length; + } + *line = re .replace( line, format!( - "Dialogue: {},{},", + "Dialogue: {},{},{},", + layer, format_naive_time(start), - &length_as_string + format_naive_time(end) ), ) .to_string() From 8f77028fcb933137d66c4f4fb2e0d3b7f4454843 Mon Sep 17 00:00:00 2001 From: bytedream Date: Fri, 1 Dec 2023 01:17:49 +0100 Subject: [PATCH 058/204] Show error message instead of panicking when capturing video length of invalid file (#258) --- crunchy-cli-core/src/utils/download.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/crunchy-cli-core/src/utils/download.rs b/crunchy-cli-core/src/utils/download.rs index c65b4d2..de1aed0 100644 --- a/crunchy-cli-core/src/utils/download.rs +++ b/crunchy-cli-core/src/utils/download.rs @@ -768,7 +768,13 @@ pub fn get_video_length(path: &Path) -> Result { .args(["-i", path.to_str().unwrap()]) .output()?; let ffmpeg_output = String::from_utf8(ffmpeg.stderr)?; - let caps = video_length.captures(ffmpeg_output.as_str()).unwrap(); + let caps = video_length.captures(ffmpeg_output.as_str()).map_or( + Err(anyhow::anyhow!( + "failed to get video length: {}", + ffmpeg_output + )), + Ok, + )?; Ok(NaiveTime::parse_from_str(caps.name("time").unwrap().as_str(), "%H:%M:%S%.f").unwrap()) } From 9ca3b79291da1d4d4f3f6abb4c0728f641f75ae7 Mon Sep 17 00:00:00 2001 From: bytedream Date: Sun, 3 Dec 2023 00:15:57 +0100 Subject: [PATCH 059/204] Fix spelling --- crunchy-cli-core/src/utils/ffmpeg.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/crunchy-cli-core/src/utils/ffmpeg.rs b/crunchy-cli-core/src/utils/ffmpeg.rs index 7d77833..39678dc 100644 --- a/crunchy-cli-core/src/utils/ffmpeg.rs +++ b/crunchy-cli-core/src/utils/ffmpeg.rs @@ -229,7 +229,7 @@ impl FFmpegPreset { quality = Some(q) } else { return Err(format!( - "'{}' is not a valid ffmpeg preset (unknown token '{}'", + "'{}' is not a valid ffmpeg preset (unknown token '{}')", s, token )); } @@ -286,12 +286,10 @@ impl FFmpegPreset { output.extend(["-c:v", "h264_nvenc", "-c:a", "copy"]) } FFmpegHwAccel::Apple => { - // Apple's Video Toolbox encoders ignore `-crf`, - // use `-q:v` instead. It's on a scale of 1-100, - // 100 being lossless. Just did some math - // ((-a/51+1)*99+1 where `a` is the old crf value) - // so these settings very likely need some more - // tweeking. + // Apple's Video Toolbox encoders ignore `-crf`, use `-q:v` + // instead. It's on a scale of 1-100, 100 being lossless. Just + // did some math ((-a/51+1)*99+1 where `a` is the old crf value) + // so these settings very likely need some more tweaking match quality { FFmpegQuality::Lossless => output.extend(["-q:v", "65"]), FFmpegQuality::Normal => (), From 9487dd3dbffd4646713ce4e0ec1d6210fc1a1f14 Mon Sep 17 00:00:00 2001 From: bytedream Date: Fri, 8 Dec 2023 22:27:12 +0100 Subject: [PATCH 060/204] Show ffmpeg progress (#270) --- Cargo.lock | 1 + crunchy-cli-core/Cargo.toml | 5 +- crunchy-cli-core/src/utils/download.rs | 142 +++++++++++++++++++------ crunchy-cli-core/src/utils/os.rs | 60 +++++++++++ 4 files changed, 176 insertions(+), 32 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 897731f..fa5723f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -397,6 +397,7 @@ dependencies = [ "indicatif", "lazy_static", "log", + "nix", "num_cpus", "regex", "reqwest", diff --git a/crunchy-cli-core/Cargo.toml b/crunchy-cli-core/Cargo.toml index 5771888..4f0912f 100644 --- a/crunchy-cli-core/Cargo.toml +++ b/crunchy-cli-core/Cargo.toml @@ -34,8 +34,11 @@ serde_plain = "1.0" shlex = "1.2" sys-locale = "0.3" tempfile = "3.8" -tokio = { version = "1.34", features = ["macros", "rt-multi-thread", "time"] } +tokio = { version = "1.34", features = ["io-util", "macros", "net", "rt-multi-thread", "time"] } rustls-native-certs = { version = "0.6", optional = true } +[target.'cfg(not(target_os = "windows"))'.dependencies] +nix = { version = "0.27", features = ["fs"] } + [build-dependencies] chrono = "0.4" diff --git a/crunchy-cli-core/src/utils/download.rs b/crunchy-cli-core/src/utils/download.rs index de1aed0..c154103 100644 --- a/crunchy-cli-core/src/utils/download.rs +++ b/crunchy-cli-core/src/utils/download.rs @@ -1,16 +1,14 @@ use crate::utils::context::Context; use crate::utils::ffmpeg::FFmpegPreset; -use crate::utils::log::progress; -use crate::utils::os::{is_special_file, temp_directory, tempfile}; +use crate::utils::os::{is_special_file, temp_directory, temp_named_pipe, tempfile}; use anyhow::{bail, Result}; use chrono::NaiveTime; use crunchyroll_rs::media::{Subtitle, VariantData, VariantSegment}; use crunchyroll_rs::Locale; -use indicatif::{ProgressBar, ProgressFinish, ProgressStyle}; +use indicatif::{ProgressBar, ProgressDrawTarget, ProgressFinish, ProgressStyle}; use log::{debug, warn, LevelFilter}; use regex::Regex; -use std::borrow::Borrow; -use std::borrow::BorrowMut; +use std::borrow::{Borrow, BorrowMut}; use std::cmp::Ordering; use std::collections::BTreeMap; use std::env; @@ -21,6 +19,7 @@ use std::str::FromStr; use std::sync::Arc; use std::time::Duration; use tempfile::TempPath; +use tokio::io::{AsyncBufReadExt, AsyncReadExt, BufReader}; use tokio::sync::mpsc::unbounded_channel; use tokio::sync::Mutex; use tokio::task::JoinSet; @@ -177,15 +176,19 @@ impl Downloader { let mut videos = vec![]; let mut audios = vec![]; let mut subtitles = vec![]; + let mut max_frames = 0f64; + let fmt_space = self + .formats + .iter() + .flat_map(|f| { + f.audios + .iter() + .map(|(_, locale)| format!("Downloading {} audio", locale).len()) + }) + .max() + .unwrap(); for (i, format) in self.formats.iter().enumerate() { - let fmt_space = format - .audios - .iter() - .map(|(_, locale)| format!("Downloading {} audio", locale).len()) - .max() - .unwrap(); - let video_path = self .download_video( ctx, @@ -232,7 +235,11 @@ impl Downloader { None }; - let len = get_video_length(&video_path)?; + let (len, fps) = get_video_stats(&video_path)?; + let frames = len.signed_duration_since(NaiveTime::MIN).num_seconds() as f64 * fps; + if frames > max_frames { + max_frames = frames; + } for (subtitle, not_cc) in format.subtitles.iter() { if let Some(pb) = &progress_spinner { let mut progress_message = pb.message(); @@ -337,8 +344,14 @@ impl Downloader { } let (input_presets, mut output_presets) = self.ffmpeg_preset.into_input_output_args(); + let fifo = temp_named_pipe()?; - let mut command_args = vec!["-y".to_string(), "-hide_banner".to_string()]; + let mut command_args = vec![ + "-y".to_string(), + "-hide_banner".to_string(), + "-vstats_file".to_string(), + fifo.name(), + ]; command_args.extend(input_presets); command_args.extend(input); command_args.extend(maps); @@ -433,8 +446,6 @@ impl Downloader { } } - let progress_handler = progress!("Generating output file"); - let ffmpeg = Command::new("ffmpeg") // pass ffmpeg stdout to real stdout only if output file is stdout .stdout(if dst.to_str().unwrap() == "-" { @@ -444,14 +455,26 @@ impl Downloader { }) .stderr(Stdio::piped()) .args(command_args) - .output()?; - if !ffmpeg.status.success() { - bail!("{}", String::from_utf8_lossy(ffmpeg.stderr.as_slice())) + .spawn()?; + let ffmpeg_progress = tokio::spawn(async move { + ffmpeg_progress( + max_frames as u64, + fifo, + format!("{:<1$}", "Generating output file", fmt_space + 1), + ) + .await + }); + + let result = ffmpeg.wait_with_output()?; + if !result.status.success() { + bail!("{}", String::from_utf8_lossy(result.stderr.as_slice())) + } + ffmpeg_progress.abort(); + match ffmpeg_progress.await { + Ok(r) => Ok(r?), + Err(e) if e.is_cancelled() => Ok(()), + Err(e) => Err(anyhow::Error::from(e)), } - - progress_handler.stop("Output file generated"); - - Ok(()) } async fn check_free_space( @@ -752,13 +775,10 @@ fn estimate_variant_file_size(variant_data: &VariantData, segments: &[VariantSeg (variant_data.bandwidth / 8) * segments.iter().map(|s| s.length.as_secs()).sum::() } -/// Get the length of a video. This is required because sometimes subtitles have an unnecessary entry -/// long after the actual video ends with artificially extends the video length on some video players. -/// To prevent this, the video length must be hard set. See -/// [crunchy-labs/crunchy-cli#32](https://github.com/crunchy-labs/crunchy-cli/issues/32) for more -/// information. -pub fn get_video_length(path: &Path) -> Result { +/// Get the length and fps of a video. +pub fn get_video_stats(path: &Path) -> Result<(NaiveTime, f64)> { let video_length = Regex::new(r"Duration:\s(?P Discord - - CI + + Build

From ab63dcd2e010cccd4b5a99c48d6576fa6c22d664 Mon Sep 17 00:00:00 2001 From: bytedream Date: Mon, 6 May 2024 20:29:22 +0200 Subject: [PATCH 180/204] Update dependencies and version --- Cargo.lock | 30 +++++++++++++++--------------- Cargo.toml | 2 +- crunchy-cli-core/Cargo.toml | 4 ++-- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b9dce7b..44a47cd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -92,9 +92,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.82" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" +checksum = "25bdb32cbbdce2b519a9cd7df3a678443100e265d5e25ca763b7572a5104f5f3" [[package]] name = "async-speed-limit" @@ -188,9 +188,9 @@ checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" [[package]] name = "cc" -version = "1.0.96" +version = "1.0.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "065a29261d53ba54260972629f9ca6bffa69bac13cd1fed61420f7fa68b9f8bd" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" [[package]] name = "cfg-if" @@ -343,7 +343,7 @@ checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "crunchy-cli" -version = "3.6.0" +version = "3.6.1" dependencies = [ "chrono", "clap", @@ -356,7 +356,7 @@ dependencies = [ [[package]] name = "crunchy-cli-core" -version = "3.6.0" +version = "3.6.1" dependencies = [ "anyhow", "async-speed-limit", @@ -712,9 +712,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "js-sys", @@ -1511,9 +1511,9 @@ checksum = "b833d8d034ea094b1ea68aa6d5c740e0d04bad9d16568d08ba6f76823a114316" [[package]] name = "rsubs-lib" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0df7559a05635a4132b737c736ee286af83f3969cb98d9028d17d333e6b41cc5" +checksum = "9dcca2a9560fca05de8f95bc3767e46673d4b4c1f2c7a11092e10efd95bbdf62" dependencies = [ "regex", "serde", @@ -1646,11 +1646,11 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.10.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "770452e37cad93e0a50d5abc3990d2bc351c36d0328f86cefec2f2fb206eaef6" +checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.5.0", "core-foundation", "core-foundation-sys", "libc", @@ -1659,9 +1659,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.10.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f3cc463c0ef97e11c3461a9d3787412d30e8e7eb907c79180c4a57bf7c04ef" +checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7" dependencies = [ "core-foundation-sys", "libc", diff --git a/Cargo.toml b/Cargo.toml index fe7b301..26f71f3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "crunchy-cli" authors = ["Crunchy Labs Maintainers"] -version = "3.6.0" +version = "3.6.1" edition = "2021" license = "MIT" diff --git a/crunchy-cli-core/Cargo.toml b/crunchy-cli-core/Cargo.toml index 896b68f..8e1ba3a 100644 --- a/crunchy-cli-core/Cargo.toml +++ b/crunchy-cli-core/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "crunchy-cli-core" authors = ["Crunchy Labs Maintainers"] -version = "3.6.0" +version = "3.6.1" edition = "2021" license = "MIT" @@ -30,7 +30,7 @@ log = { version = "0.4", features = ["std"] } num_cpus = "1.16" regex = "1.10" reqwest = { version = "0.12", features = ["socks", "stream"] } -rsubs-lib = "0.2" +rsubs-lib = ">=0.2.1" rusty-chromaprint = "0.2" serde = "1.0" serde_json = "1.0" From 53a710a3732047a1e08d475f6f112b440b8bde8e Mon Sep 17 00:00:00 2001 From: Simon <47527944+Frooastside@users.noreply.github.com> Date: Tue, 7 May 2024 16:13:10 +0200 Subject: [PATCH 181/204] Fix audio syncing using wrong internal index (#407) --- crunchy-cli-core/src/utils/download.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/crunchy-cli-core/src/utils/download.rs b/crunchy-cli-core/src/utils/download.rs index 565ed7d..8a8ad57 100644 --- a/crunchy-cli-core/src/utils/download.rs +++ b/crunchy-cli-core/src/utils/download.rs @@ -321,8 +321,6 @@ impl Downloader { if let Some(offsets) = offsets { let mut root_format_idx = 0; let mut root_format_length = 0; - let mut audio_count: usize = 0; - let mut subtitle_count: usize = 0; for (i, format) in self.formats.iter().enumerate() { let offset = offsets.get(&i).copied().unwrap_or_default(); let format_len = format @@ -340,15 +338,13 @@ impl Downloader { for _ in &format.audios { if let Some(offset) = &offsets.get(&i) { - audio_offsets.insert(audio_count, **offset); + audio_offsets.insert(i, **offset); } - audio_count += 1 } for _ in &format.subtitles { if let Some(offset) = &offsets.get(&i) { - subtitle_offsets.insert(subtitle_count, **offset); + subtitle_offsets.insert(i, **offset); } - subtitle_count += 1 } } From 48bb7a5ef669d3d89ccecfbf02929adeea99a6bd Mon Sep 17 00:00:00 2001 From: bytedream Date: Tue, 14 May 2024 16:11:55 +0200 Subject: [PATCH 182/204] Fix crashes when converting subtitles (#408) --- Cargo.lock | 6 ++-- crunchy-cli-core/Cargo.toml | 3 +- crunchy-cli-core/src/utils/download.rs | 39 ++++++++++++++++---------- 3 files changed, 30 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 44a47cd..cd1f282 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -386,6 +386,7 @@ dependencies = [ "shlex", "sys-locale", "tempfile", + "time", "tokio", "tokio-util", "tower-service", @@ -1511,12 +1512,13 @@ checksum = "b833d8d034ea094b1ea68aa6d5c740e0d04bad9d16568d08ba6f76823a114316" [[package]] name = "rsubs-lib" -version = "0.2.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dcca2a9560fca05de8f95bc3767e46673d4b4c1f2c7a11092e10efd95bbdf62" +checksum = "f43e1a7f184bc76407dbaa67bd2aeea8a15430d7e1e498070963336d03ebedee" dependencies = [ "regex", "serde", + "time", ] [[package]] diff --git a/crunchy-cli-core/Cargo.toml b/crunchy-cli-core/Cargo.toml index 8e1ba3a..49f7a5e 100644 --- a/crunchy-cli-core/Cargo.toml +++ b/crunchy-cli-core/Cargo.toml @@ -30,7 +30,7 @@ log = { version = "0.4", features = ["std"] } num_cpus = "1.16" regex = "1.10" reqwest = { version = "0.12", features = ["socks", "stream"] } -rsubs-lib = ">=0.2.1" +rsubs-lib = "0.3" rusty-chromaprint = "0.2" serde = "1.0" serde_json = "1.0" @@ -38,6 +38,7 @@ serde_plain = "1.0" shlex = "1.3" sys-locale = "0.3" tempfile = "3.10" +time = "0.3" tokio = { version = "1.37", features = ["io-util", "macros", "net", "rt-multi-thread", "time"] } tokio-util = "0.7" tower-service = "0.3" diff --git a/crunchy-cli-core/src/utils/download.rs b/crunchy-cli-core/src/utils/download.rs index 8a8ad57..43d165b 100644 --- a/crunchy-cli-core/src/utils/download.rs +++ b/crunchy-cli-core/src/utils/download.rs @@ -13,17 +13,19 @@ use indicatif::{ProgressBar, ProgressDrawTarget, ProgressFinish, ProgressStyle}; use log::{debug, warn, LevelFilter}; use regex::Regex; use reqwest::Client; -use rsubs_lib::{ssa, vtt}; +use rsubs_lib::{SSA, VTT}; use std::borrow::Borrow; use std::cmp::Ordering; use std::collections::{BTreeMap, HashMap}; use std::io::Write; +use std::ops::Add; use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; use std::sync::Arc; use std::time::Duration; use std::{env, fs}; use tempfile::TempPath; +use time::Time; use tokio::io::{AsyncBufReadExt, AsyncReadExt, BufReader}; use tokio::select; use tokio::sync::mpsc::unbounded_channel; @@ -929,36 +931,43 @@ impl Downloader { ) -> Result { let buf = subtitle.data().await?; let mut ass = match subtitle.format.as_str() { - "ass" => ssa::parse(String::from_utf8_lossy(&buf).to_string()), - "vtt" => vtt::parse(String::from_utf8_lossy(&buf).to_string()).to_ass(), + "ass" => SSA::parse(String::from_utf8_lossy(&buf))?, + "vtt" => VTT::parse(String::from_utf8_lossy(&buf))?.to_ssa(), _ => bail!("unknown subtitle format: {}", subtitle.format), }; // subtitles aren't always correct sorted and video players may have issues with that. to // prevent issues, the subtitles are sorted - ass.events - .sort_by(|a, b| a.line_start.total_ms().cmp(&b.line_start.total_ms())); + // (https://github.com/crunchy-labs/crunchy-cli/issues/208) + ass.events.sort_by(|a, b| a.start.cmp(&b.start)); // it might be the case that the start and/or end time are greater than the actual video // length. this might also result in issues with video players, thus the times are stripped - // to be maxim + // to be at most as long as `max_length` + // (https://github.com/crunchy-labs/crunchy-cli/issues/32) for i in (0..ass.events.len()).rev() { - if ass.events[i].line_end.total_ms() > max_length.num_milliseconds() as u32 { - if ass.events[i].line_start.total_ms() > max_length.num_milliseconds() as u32 { - ass.events[i] - .line_start - .set_ms(max_length.num_milliseconds() as u32); + let max_len = Time::from_hms(0, 0, 0) + .unwrap() + .add(Duration::from_millis(max_length.num_milliseconds() as u64)); + + if ass.events[i].start > max_len { + if ass.events[i].end > max_len { + ass.events[i].start = max_len } - ass.events[i] - .line_end - .set_ms(max_length.num_milliseconds() as u32); + ass.events[i].end = max_len } else { break; } } + // without this additional info, subtitle look very messy in some video player + // (https://github.com/crunchy-labs/crunchy-cli/issues/66) + ass.info + .additional_fields + .insert("ScaledBorderAndShadows".to_string(), "yes".to_string()); + let tempfile = tempfile(".ass")?; let path = tempfile.into_temp_path(); - ass.to_file(path.to_string_lossy().to_string().as_str())?; + fs::write(&path, ass.to_string())?; Ok(path) } From 817963af4fbf0eef1fde26a02f0771e343ce35d9 Mon Sep 17 00:00:00 2001 From: bytedream Date: Tue, 14 May 2024 21:22:23 +0200 Subject: [PATCH 183/204] Fix video containing hardsub if not requested (#415) --- crunchy-cli-core/src/download/command.rs | 20 ++++++++++++++------ crunchy-cli-core/src/utils/video.rs | 24 ++++-------------------- 2 files changed, 18 insertions(+), 26 deletions(-) diff --git a/crunchy-cli-core/src/download/command.rs b/crunchy-cli-core/src/download/command.rs index bb0c1fd..a9c3acf 100644 --- a/crunchy-cli-core/src/download/command.rs +++ b/crunchy-cli-core/src/download/command.rs @@ -384,12 +384,20 @@ async fn get_format( let subtitle = if contains_hardsub { None } else if let Some(subtitle_locale) = &download.subtitle { - stream - .subtitles - .get(subtitle_locale) - .cloned() - // use closed captions as fallback if no actual subtitles are found - .or_else(|| stream.captions.get(subtitle_locale).cloned()) + if download.audio == Locale::ja_JP { + stream + .subtitles + .get(subtitle_locale) + // use closed captions as fallback if no actual subtitles are found + .or_else(|| stream.captions.get(subtitle_locale)) + .cloned() + } else { + stream + .captions + .get(subtitle_locale) + .or_else(|| stream.subtitles.get(subtitle_locale)) + .cloned() + } } else { None }; diff --git a/crunchy-cli-core/src/utils/video.rs b/crunchy-cli-core/src/utils/video.rs index 07f6e76..8b25791 100644 --- a/crunchy-cli-core/src/utils/video.rs +++ b/crunchy-cli-core/src/utils/video.rs @@ -5,28 +5,12 @@ use crunchyroll_rs::Locale; pub async fn stream_data_from_stream( stream: &Stream, resolution: &Resolution, - subtitle: Option, + hardsub_subtitle: Option, ) -> Result> { - // sometimes Crunchyroll marks episodes without real subtitles that they have subtitles and - // reports that only hardsub episode are existing. the following lines are trying to prevent - // potential errors which might get caused by this incorrect reporting - // (https://github.com/crunchy-labs/crunchy-cli/issues/231) - let mut hardsub_locales: Vec = stream.hard_subs.keys().cloned().collect(); - let (hardsub_locale, mut contains_hardsub) = if !hardsub_locales - .contains(&Locale::Custom("".to_string())) - && !hardsub_locales.contains(&Locale::Custom(":".to_string())) - { - // if only one hardsub locale exists, assume that this stream doesn't really contains hardsubs - if hardsub_locales.len() == 1 { - (Some(hardsub_locales.remove(0)), false) - } else { - // fallback to `None`. this should trigger an error message in `stream.dash_streaming_data` - // that the requested stream is not available - (None, false) - } + let (hardsub_locale, mut contains_hardsub) = if hardsub_subtitle.is_some() { + (hardsub_subtitle, true) } else { - let hardsubs_requested = subtitle.is_some(); - (subtitle, hardsubs_requested) + (None, false) }; let (mut videos, mut audios) = match stream.stream_data(hardsub_locale).await { From 590242712b00c90c6c4cd49744764a1b04b64789 Mon Sep 17 00:00:00 2001 From: bytedream Date: Tue, 14 May 2024 21:36:12 +0200 Subject: [PATCH 184/204] Add warning message the `--skip-existing-method` has no effect without `--skip-existing` (#418) --- crunchy-cli-core/src/archive/command.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crunchy-cli-core/src/archive/command.rs b/crunchy-cli-core/src/archive/command.rs index 38bddc1..44a30de 100644 --- a/crunchy-cli-core/src/archive/command.rs +++ b/crunchy-cli-core/src/archive/command.rs @@ -234,6 +234,10 @@ impl Execute for Archive { bail!("`--include-chapters` can only be used if `--merge` is set to 'audio' or 'sync'") } + if !self.skip_existing_method.is_empty() && !self.skip_existing { + warn!("`--skip-existing-method` has no effect if `--skip-existing` is not set") + } + self.audio = all_locale_in_locales(self.audio.clone()); self.subtitle = all_locale_in_locales(self.subtitle.clone()); From a98e31f959892fed57a0510356a0c6a47a5c8672 Mon Sep 17 00:00:00 2001 From: bytedream Date: Tue, 14 May 2024 22:36:59 +0200 Subject: [PATCH 185/204] Only include one CC subtitle --- crunchy-cli-core/src/archive/command.rs | 31 +++++++++++-------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/crunchy-cli-core/src/archive/command.rs b/crunchy-cli-core/src/archive/command.rs index 44a30de..113447f 100644 --- a/crunchy-cli-core/src/archive/command.rs +++ b/crunchy-cli-core/src/archive/command.rs @@ -501,24 +501,21 @@ async fn get_format( .subtitle .iter() .flat_map(|s| { - let subtitles = stream - .subtitles - .get(s) - .cloned() - // the subtitle is probably cc if the audio is not japanese or only one - // subtitle exists for this stream - .map(|l| { - ( - l, - single_format.audio != Locale::ja_JP && stream.subtitles.len() == 1, - ) - }); - let cc = stream.captions.get(s).cloned().map(|l| (l, true)); - + let mut subtitles = vec![]; + if let Some(caption) = stream.captions.get(s) { + subtitles.push((caption.clone(), true)) + } + if let Some(subtitle) = stream.subtitles.get(s) { + // the subtitle is probably cc if the audio is not japanese or only one subtitle + // exists for this stream + let cc = single_format.audio != Locale::ja_JP && stream.subtitles.len() == 1; + // only include the subtitles if no cc subtitle is already present or if it's + // not cc + if subtitles.is_empty() || !cc { + subtitles.push((subtitle.clone(), cc)) + } + } subtitles - .into_iter() - .chain(cc.into_iter()) - .collect::>() }) .collect(); From 5279a9b75910992ad1731557ad65ce4302bb9208 Mon Sep 17 00:00:00 2001 From: bytedream Date: Tue, 14 May 2024 23:42:37 +0200 Subject: [PATCH 186/204] Update dependencies and version --- Cargo.lock | 57 +++++++++++++++++++------------------ Cargo.toml | 2 +- crunchy-cli-core/Cargo.toml | 2 +- 3 files changed, 31 insertions(+), 30 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cd1f282..198afc9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -343,7 +343,7 @@ checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "crunchy-cli" -version = "3.6.1" +version = "3.6.2" dependencies = [ "chrono", "clap", @@ -356,7 +356,7 @@ dependencies = [ [[package]] name = "crunchy-cli-core" -version = "3.6.1" +version = "3.6.2" dependencies = [ "anyhow", "async-speed-limit", @@ -476,12 +476,13 @@ dependencies = [ [[package]] name = "dash-mpd" -version = "0.16.1" +version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79b4bdd5f1c0c7493d780c645f0bff5b9361e6408210fa88910adb181efca64c" +checksum = "876a00c22923799ac46365eb528c10134f979bf58ced5e3113de5b98d9835290" dependencies = [ "base64 0.22.1", "base64-serde", + "bytes", "chrono", "fs-err", "iso8601", @@ -581,9 +582,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ "libc", "windows-sys 0.52.0", @@ -1156,9 +1157,9 @@ dependencies = [ [[package]] name = "num-complex" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23c6602fda94a57c990fe0df199a035d83576b496aa29f4e634a8ac6004e68a6" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" dependencies = [ "num-traits", ] @@ -1345,9 +1346,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.81" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" +checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b" dependencies = [ "unicode-ident", ] @@ -1535,9 +1536,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustfft" @@ -1606,9 +1607,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.5.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "beb461507cee2c2ff151784c52762cf4d9ff6a61f3e80968600ed24fa837fa54" +checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" [[package]] name = "rustls-webpki" @@ -1633,9 +1634,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "schannel" @@ -1671,18 +1672,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.200" +version = "1.0.201" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddc6f9cc94d67c0e21aaf7eda3a010fd3af78ebf6e096aa6e2e13c79749cce4f" +checksum = "780f1cebed1629e4753a1a38a3c72d30b97ec044f0aef68cb26650a3c5cf363c" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.200" +version = "1.0.201" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "856f046b9400cee3c8c94ed572ecdb752444c24528c035cd35882aad6f492bcb" +checksum = "c5e405930b9796f1c00bee880d03fc7e0bb4b9a11afc776885ffe84320da2865" dependencies = [ "proc-macro2", "quote", @@ -1691,9 +1692,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.116" +version = "1.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" +checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" dependencies = [ "itoa", "ryu", @@ -1841,9 +1842,9 @@ checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" [[package]] name = "syn" -version = "2.0.60" +version = "2.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" +checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704" dependencies = [ "proc-macro2", "quote", @@ -1900,18 +1901,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.59" +version = "1.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa" +checksum = "579e9083ca58dd9dcf91a9923bb9054071b9ebbd800b342194c9feb0ee89fc18" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.59" +version = "1.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66" +checksum = "e2470041c06ec3ac1ab38d0356a6119054dedaea53e12fbefc0de730a1c08524" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index 26f71f3..1a1c76f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "crunchy-cli" authors = ["Crunchy Labs Maintainers"] -version = "3.6.1" +version = "3.6.2" edition = "2021" license = "MIT" diff --git a/crunchy-cli-core/Cargo.toml b/crunchy-cli-core/Cargo.toml index 49f7a5e..f3388f7 100644 --- a/crunchy-cli-core/Cargo.toml +++ b/crunchy-cli-core/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "crunchy-cli-core" authors = ["Crunchy Labs Maintainers"] -version = "3.6.1" +version = "3.6.2" edition = "2021" license = "MIT" From 9819b622594e3cb2164aedcef71827618b421c41 Mon Sep 17 00:00:00 2001 From: bytedream Date: Fri, 17 May 2024 23:45:41 +0200 Subject: [PATCH 187/204] Fix typo in additional subtitle field (#421) --- crunchy-cli-core/src/utils/download.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crunchy-cli-core/src/utils/download.rs b/crunchy-cli-core/src/utils/download.rs index 43d165b..d54b0bc 100644 --- a/crunchy-cli-core/src/utils/download.rs +++ b/crunchy-cli-core/src/utils/download.rs @@ -962,7 +962,7 @@ impl Downloader { // (https://github.com/crunchy-labs/crunchy-cli/issues/66) ass.info .additional_fields - .insert("ScaledBorderAndShadows".to_string(), "yes".to_string()); + .insert("ScaledBorderAndShadow".to_string(), "yes".to_string()); let tempfile = tempfile(".ass")?; let path = tempfile.into_temp_path(); From 301dac478f177b70723672effa3f2651ff8419d1 Mon Sep 17 00:00:00 2001 From: bytedream Date: Mon, 20 May 2024 15:57:28 +0200 Subject: [PATCH 188/204] Update dependencies and version --- Cargo.lock | 99 ++++++++++++++++++------------------- Cargo.toml | 5 +- crunchy-cli-core/Cargo.toml | 2 +- 3 files changed, 53 insertions(+), 53 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 198afc9..140125d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -92,9 +92,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.83" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25bdb32cbbdce2b519a9cd7df3a678443100e265d5e25ca763b7572a5104f5f3" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "async-speed-limit" @@ -119,6 +119,12 @@ dependencies = [ "syn", ] +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + [[package]] name = "autocfg" version = "1.3.0" @@ -188,9 +194,9 @@ checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" [[package]] name = "cc" -version = "1.0.97" +version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" +checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f" [[package]] name = "cfg-if" @@ -238,7 +244,7 @@ dependencies = [ "anstream", "anstyle", "clap_lex", - "strsim 0.11.1", + "strsim", ] [[package]] @@ -343,7 +349,7 @@ checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "crunchy-cli" -version = "3.6.2" +version = "3.6.3" dependencies = [ "chrono", "clap", @@ -356,7 +362,7 @@ dependencies = [ [[package]] name = "crunchy-cli-core" -version = "3.6.2" +version = "3.6.3" dependencies = [ "anyhow", "async-speed-limit", @@ -441,9 +447,9 @@ dependencies = [ [[package]] name = "darling" -version = "0.20.8" +version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" +checksum = "83b2eb4d90d12bdda5ed17de686c2acb4c57914f8f921b8da7e112b5a36f3fe1" dependencies = [ "darling_core", "darling_macro", @@ -451,23 +457,23 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.8" +version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f" +checksum = "622687fe0bac72a04e5599029151f5796111b90f1baaa9b544d807a5e31cd120" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", - "strsim 0.10.0", + "strsim", "syn", ] [[package]] name = "darling_macro" -version = "0.20.8" +version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" +checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178" dependencies = [ "darling_core", "quote", @@ -555,9 +561,9 @@ dependencies = [ [[package]] name = "either" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" +checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" [[package]] name = "encode_unicode" @@ -733,15 +739,15 @@ checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "h2" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "816ec7294445779408f36fe57bc5b7fc1cf59664059096c65f905c1c61f58069" +checksum = "fa82e28a107a8cc405f0839610bdc9b15f1e25ec7d696aa5cf173edbcb1486ab" dependencies = [ + "atomic-waker", "bytes", "fnv", "futures-core", "futures-sink", - "futures-util", "http", "indexmap 2.2.6", "slab", @@ -979,9 +985,9 @@ dependencies = [ [[package]] name = "instant" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" dependencies = [ "cfg-if", ] @@ -1043,9 +1049,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.154" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "libredox" @@ -1059,9 +1065,9 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "log" @@ -1099,9 +1105,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" dependencies = [ "adler", ] @@ -1120,7 +1126,7 @@ dependencies = [ [[package]] name = "native-tls" version = "0.2.11" -source = "git+https://github.com/crunchy-labs/rust-not-so-native-tls.git?rev=fdba246#fdba246a79986607cbdf573733445498bb6da2a9" +source = "git+https://github.com/crunchy-labs/rust-not-so-native-tls.git?rev=b7969a8#b7969a88210096e0570e29d42fb13533baf62aa6" dependencies = [ "libc", "log", @@ -1346,9 +1352,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.82" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b" +checksum = "0b33eb56c327dec362a9e55b3ad14f9d2f0904fb5a5b03b513ab5465399e9f43" dependencies = [ "unicode-ident", ] @@ -1514,8 +1520,7 @@ checksum = "b833d8d034ea094b1ea68aa6d5c740e0d04bad9d16568d08ba6f76823a114316" [[package]] name = "rsubs-lib" version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43e1a7f184bc76407dbaa67bd2aeea8a15430d7e1e498070963336d03ebedee" +source = "git+https://github.com/crunchy-labs/rsubs-lib.git?rev=1c51f60#1c51f60b8c48f1a8f7b261372b237d89bdc17dd4" dependencies = [ "regex", "serde", @@ -1613,9 +1618,9 @@ checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" [[package]] name = "rustls-webpki" -version = "0.102.3" +version = "0.102.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3bce581c0dd41bce533ce695a1437fa16a7ab5ac3ccfa99fe1a620a7885eabf" +checksum = "ff448f7e92e913c4b7d4c6d8e4540a1724b319b4152b8aef6d4cf8339712b33e" dependencies = [ "ring", "rustls-pki-types", @@ -1672,18 +1677,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.201" +version = "1.0.202" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "780f1cebed1629e4753a1a38a3c72d30b97ec044f0aef68cb26650a3c5cf363c" +checksum = "226b61a0d411b2ba5ff6d7f73a476ac4f8bb900373459cd00fab8512828ba395" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.201" +version = "1.0.202" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5e405930b9796f1c00bee880d03fc7e0bb4b9a11afc776885ffe84320da2865" +checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838" dependencies = [ "proc-macro2", "quote", @@ -1822,12 +1827,6 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe895eb47f22e2ddd4dabc02bce419d2e643c8e3b585c78158b349195bc24d82" -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - [[package]] name = "strsim" version = "0.11.1" @@ -1842,9 +1841,9 @@ checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" [[package]] name = "syn" -version = "2.0.63" +version = "2.0.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704" +checksum = "d2863d96a84c6439701d7a38f9de935ec562c8832cc55d1dde0f513b52fad106" dependencies = [ "proc-macro2", "quote", @@ -1901,18 +1900,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.60" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "579e9083ca58dd9dcf91a9923bb9054071b9ebbd800b342194c9feb0ee89fc18" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.60" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2470041c06ec3ac1ab38d0356a6119054dedaea53e12fbefc0de730a1c08524" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index 1a1c76f..4021ebc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "crunchy-cli" authors = ["Crunchy Labs Maintainers"] -version = "3.6.2" +version = "3.6.3" edition = "2021" license = "MIT" @@ -34,7 +34,8 @@ members = ["crunchy-cli-core"] [patch.crates-io] # fork of the `native-tls` crate which can use openssl as backend on every platform. this is done as `reqwest` only # supports `rustls` and `native-tls` as tls backend -native-tls = { git = "https://github.com/crunchy-labs/rust-not-so-native-tls.git", rev = "fdba246" } +native-tls = { git = "https://github.com/crunchy-labs/rust-not-so-native-tls.git", rev = "b7969a8" } +rsubs-lib = { git = "https://github.com/crunchy-labs/rsubs-lib.git", rev = "1c51f60" } [profile.release] strip = true diff --git a/crunchy-cli-core/Cargo.toml b/crunchy-cli-core/Cargo.toml index f3388f7..4b4416b 100644 --- a/crunchy-cli-core/Cargo.toml +++ b/crunchy-cli-core/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "crunchy-cli-core" authors = ["Crunchy Labs Maintainers"] -version = "3.6.2" +version = "3.6.3" edition = "2021" license = "MIT" From f7ce888329825470a42e13cf6c0dd35826783d6c Mon Sep 17 00:00:00 2001 From: bytedream Date: Tue, 21 May 2024 21:33:08 +0200 Subject: [PATCH 189/204] Bypass stream limits --- crunchy-cli-core/src/archive/command.rs | 4 ++- crunchy-cli-core/src/download/command.rs | 2 ++ crunchy-cli-core/src/utils/format.rs | 32 +++++++++++++++--------- 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/crunchy-cli-core/src/archive/command.rs b/crunchy-cli-core/src/archive/command.rs index 113447f..d34c4b7 100644 --- a/crunchy-cli-core/src/archive/command.rs +++ b/crunchy-cli-core/src/archive/command.rs @@ -520,7 +520,9 @@ async fn get_format( .collect(); format_pairs.push((single_format, video.clone(), audio, subtitles.clone())); - single_format_to_format_pairs.push((single_format.clone(), video, subtitles)) + single_format_to_format_pairs.push((single_format.clone(), video, subtitles)); + + stream.invalidate().await? } let mut download_formats = vec![]; diff --git a/crunchy-cli-core/src/download/command.rs b/crunchy-cli-core/src/download/command.rs index a9c3acf..fcf069b 100644 --- a/crunchy-cli-core/src/download/command.rs +++ b/crunchy-cli-core/src/download/command.rs @@ -434,5 +434,7 @@ async fn get_format( subs.push(download.subtitle.clone().unwrap()) } + stream.invalidate().await?; + Ok((download_format, format)) } diff --git a/crunchy-cli-core/src/utils/format.rs b/crunchy-cli-core/src/utils/format.rs index 0a71838..325c731 100644 --- a/crunchy-cli-core/src/utils/format.rs +++ b/crunchy-cli-core/src/utils/format.rs @@ -2,7 +2,7 @@ use crate::utils::filter::real_dedup_vec; use crate::utils::locale::LanguageTagging; use crate::utils::log::tab_info; use crate::utils::os::{is_special_file, sanitize}; -use anyhow::{bail, Result}; +use anyhow::Result; use chrono::{Datelike, Duration}; use crunchyroll_rs::media::{Resolution, SkipEvents, Stream, StreamData, Subtitle}; use crunchyroll_rs::{Concert, Episode, Locale, MediaCollection, Movie, MusicVideo}; @@ -166,19 +166,27 @@ impl SingleFormat { } pub async fn stream(&self) -> Result { - let stream = match &self.source { - MediaCollection::Episode(e) => e.stream_maybe_without_drm().await?, - MediaCollection::Movie(m) => m.stream_maybe_without_drm().await?, - MediaCollection::MusicVideo(mv) => mv.stream_maybe_without_drm().await?, - MediaCollection::Concert(c) => c.stream_maybe_without_drm().await?, - _ => unreachable!(), - }; + let mut i = 0; + loop { + let stream = match &self.source { + MediaCollection::Episode(e) => e.stream_maybe_without_drm().await, + MediaCollection::Movie(m) => m.stream_maybe_without_drm().await, + MediaCollection::MusicVideo(mv) => mv.stream_maybe_without_drm().await, + MediaCollection::Concert(c) => c.stream_maybe_without_drm().await, + _ => unreachable!(), + }; - if stream.session.uses_stream_limits { - bail!("Found a stream which probably uses DRM. DRM downloads aren't supported") + // sometimes the request to get streams fails with an 403 and the message "JWT error", + // even if the jwt (i guess the auth bearer token is meant by that) is perfectly valid. + // it's retried the request 3 times if this specific error occurs + if let Err(crunchyroll_rs::error::Error::Request { message, .. }) = &stream { + if message == "JWT error" && i < 3 { + i += 1; + continue; + } + }; + return Ok(stream?); } - - Ok(stream) } pub async fn skip_events(&self) -> Result> { From cbe57e2b6e6262c5a94312a9646faea3a9f23ccb Mon Sep 17 00:00:00 2001 From: bytedream Date: Tue, 21 May 2024 21:34:05 +0200 Subject: [PATCH 190/204] Update dependencies and version --- Cargo.lock | 12 ++++++------ Cargo.toml | 2 +- crunchy-cli-core/Cargo.toml | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 140125d..5ea720f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -349,7 +349,7 @@ checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "crunchy-cli" -version = "3.6.3" +version = "3.6.4" dependencies = [ "chrono", "clap", @@ -362,7 +362,7 @@ dependencies = [ [[package]] name = "crunchy-cli-core" -version = "3.6.3" +version = "3.6.4" dependencies = [ "anyhow", "async-speed-limit", @@ -482,9 +482,9 @@ dependencies = [ [[package]] name = "dash-mpd" -version = "0.16.2" +version = "0.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "876a00c22923799ac46365eb528c10134f979bf58ced5e3113de5b98d9835290" +checksum = "4618a5e165bf47b084963611bcf1d568c681f52d8a237e8862a0cd8c546ba255" dependencies = [ "base64 0.22.1", "base64-serde", @@ -1259,9 +1259,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-src" -version = "300.2.3+3.2.1" +version = "300.3.0+3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cff92b6f71555b61bb9315f7c64da3ca43d87531622120fea0195fc761b4843" +checksum = "eba8804a1c5765b18c4b3f907e6897ebabeedebc9830e1a0046c4a4cf44663e1" dependencies = [ "cc", ] diff --git a/Cargo.toml b/Cargo.toml index 4021ebc..98d2269 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "crunchy-cli" authors = ["Crunchy Labs Maintainers"] -version = "3.6.3" +version = "3.6.4" edition = "2021" license = "MIT" diff --git a/crunchy-cli-core/Cargo.toml b/crunchy-cli-core/Cargo.toml index 4b4416b..8370fdc 100644 --- a/crunchy-cli-core/Cargo.toml +++ b/crunchy-cli-core/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "crunchy-cli-core" authors = ["Crunchy Labs Maintainers"] -version = "3.6.3" +version = "3.6.4" edition = "2021" license = "MIT" From f8bd0929872f4c78a6d2b54eee7dacb4c94cfb9d Mon Sep 17 00:00:00 2001 From: bytedream Date: Tue, 21 May 2024 21:51:18 +0200 Subject: [PATCH 191/204] Add custom error message if too many streams are active --- crunchy-cli-core/src/utils/format.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/crunchy-cli-core/src/utils/format.rs b/crunchy-cli-core/src/utils/format.rs index 325c731..436be78 100644 --- a/crunchy-cli-core/src/utils/format.rs +++ b/crunchy-cli-core/src/utils/format.rs @@ -2,7 +2,7 @@ use crate::utils::filter::real_dedup_vec; use crate::utils::locale::LanguageTagging; use crate::utils::log::tab_info; use crate::utils::os::{is_special_file, sanitize}; -use anyhow::Result; +use anyhow::{bail, Result}; use chrono::{Datelike, Duration}; use crunchyroll_rs::media::{Resolution, SkipEvents, Stream, StreamData, Subtitle}; use crunchyroll_rs::{Concert, Episode, Locale, MediaCollection, Movie, MusicVideo}; @@ -176,13 +176,15 @@ impl SingleFormat { _ => unreachable!(), }; - // sometimes the request to get streams fails with an 403 and the message "JWT error", - // even if the jwt (i guess the auth bearer token is meant by that) is perfectly valid. - // it's retried the request 3 times if this specific error occurs if let Err(crunchyroll_rs::error::Error::Request { message, .. }) = &stream { + // sometimes the request to get streams fails with an 403 and the message + // "JWT error", even if the jwt (i guess the auth bearer token is meant by that) is + // perfectly valid. it's retried the request 3 times if this specific error occurs if message == "JWT error" && i < 3 { i += 1; continue; + } else if message.starts_with("TOO_MANY_ACTIVE_STREAMS") { + bail!("Too many active/parallel streams. Please close at least one stream you're watching and try again") } }; return Ok(stream?); From 5593046aae4c399c1f0568c14ff35f3d75d96edc Mon Sep 17 00:00:00 2001 From: bytedream Date: Wed, 22 May 2024 16:52:43 +0200 Subject: [PATCH 192/204] Update dependencies and version --- Cargo.lock | 12 ++++++------ Cargo.toml | 2 +- crunchy-cli-core/Cargo.toml | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5ea720f..b24bc20 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -349,7 +349,7 @@ checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "crunchy-cli" -version = "3.6.4" +version = "3.6.5" dependencies = [ "chrono", "clap", @@ -362,7 +362,7 @@ dependencies = [ [[package]] name = "crunchy-cli-core" -version = "3.6.4" +version = "3.6.5" dependencies = [ "anyhow", "async-speed-limit", @@ -400,9 +400,9 @@ dependencies = [ [[package]] name = "crunchyroll-rs" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58580acc9c0abf96a231ec8b1a4597ea55d9426ea17f684ce3582e2b26437bbb" +checksum = "7a6754d10e1890089eb733b71aee6f4cbc18374040aedb04c4ca76020bcd9818" dependencies = [ "async-trait", "chrono", @@ -426,9 +426,9 @@ dependencies = [ [[package]] name = "crunchyroll-rs-internal" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce3c844dec8a3390f8c9853b5cf1d65c3d38fd0657b8b5d0e008db8945dea326" +checksum = "ca15fa827cca647852b091006f2b592f8727e1082f812b475b3f9ebe3f59d5bf" dependencies = [ "darling", "quote", diff --git a/Cargo.toml b/Cargo.toml index 98d2269..ccf80ec 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "crunchy-cli" authors = ["Crunchy Labs Maintainers"] -version = "3.6.4" +version = "3.6.5" edition = "2021" license = "MIT" diff --git a/crunchy-cli-core/Cargo.toml b/crunchy-cli-core/Cargo.toml index 8370fdc..98ff9d7 100644 --- a/crunchy-cli-core/Cargo.toml +++ b/crunchy-cli-core/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "crunchy-cli-core" authors = ["Crunchy Labs Maintainers"] -version = "3.6.4" +version = "3.6.5" edition = "2021" license = "MIT" @@ -16,7 +16,7 @@ anyhow = "1.0" async-speed-limit = "0.4" clap = { version = "4.5", features = ["derive", "string"] } chrono = "0.4" -crunchyroll-rs = { version = "0.11.1", features = ["experimental-stabilizations", "tower"] } +crunchyroll-rs = { version = "0.11.2", features = ["experimental-stabilizations", "tower"] } ctrlc = "3.4" dialoguer = { version = "0.11", default-features = false } dirs = "5.0" From 7d2ae719c8fee83f2ba5041f214b87eb53d3c33c Mon Sep 17 00:00:00 2001 From: bytedream Date: Wed, 22 May 2024 16:54:58 +0200 Subject: [PATCH 193/204] Remove internal jwt error retry --- crunchy-cli-core/src/utils/format.rs | 35 +++++++++++----------------- 1 file changed, 13 insertions(+), 22 deletions(-) diff --git a/crunchy-cli-core/src/utils/format.rs b/crunchy-cli-core/src/utils/format.rs index 436be78..c5e8f3d 100644 --- a/crunchy-cli-core/src/utils/format.rs +++ b/crunchy-cli-core/src/utils/format.rs @@ -166,29 +166,20 @@ impl SingleFormat { } pub async fn stream(&self) -> Result { - let mut i = 0; - loop { - let stream = match &self.source { - MediaCollection::Episode(e) => e.stream_maybe_without_drm().await, - MediaCollection::Movie(m) => m.stream_maybe_without_drm().await, - MediaCollection::MusicVideo(mv) => mv.stream_maybe_without_drm().await, - MediaCollection::Concert(c) => c.stream_maybe_without_drm().await, - _ => unreachable!(), - }; + let stream = match &self.source { + MediaCollection::Episode(e) => e.stream_maybe_without_drm().await, + MediaCollection::Movie(m) => m.stream_maybe_without_drm().await, + MediaCollection::MusicVideo(mv) => mv.stream_maybe_without_drm().await, + MediaCollection::Concert(c) => c.stream_maybe_without_drm().await, + _ => unreachable!(), + }; - if let Err(crunchyroll_rs::error::Error::Request { message, .. }) = &stream { - // sometimes the request to get streams fails with an 403 and the message - // "JWT error", even if the jwt (i guess the auth bearer token is meant by that) is - // perfectly valid. it's retried the request 3 times if this specific error occurs - if message == "JWT error" && i < 3 { - i += 1; - continue; - } else if message.starts_with("TOO_MANY_ACTIVE_STREAMS") { - bail!("Too many active/parallel streams. Please close at least one stream you're watching and try again") - } - }; - return Ok(stream?); - } + if let Err(crunchyroll_rs::error::Error::Request { message, .. }) = &stream { + if message.starts_with("TOO_MANY_ACTIVE_STREAMS") { + bail!("Too many active/parallel streams. Please close at least one stream you're watching and try again") + } + }; + Ok(stream?) } pub async fn skip_events(&self) -> Result> { From 74e5e05b0f8b4cb83cd5708747fe81a0183b56f0 Mon Sep 17 00:00:00 2001 From: bytedream Date: Wed, 22 May 2024 23:59:12 +0200 Subject: [PATCH 194/204] Invalidate stream when using search command (#428) --- crunchy-cli-core/src/search/format.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crunchy-cli-core/src/search/format.rs b/crunchy-cli-core/src/search/format.rs index 7ea84d8..ee855b2 100644 --- a/crunchy-cli-core/src/search/format.rs +++ b/crunchy-cli-core/src/search/format.rs @@ -464,7 +464,9 @@ impl Format { if !stream_empty { for (_, episodes) in tree.iter_mut() { for (episode, streams) in episodes { - streams.push(episode.stream_maybe_without_drm().await?) + let stream = episode.stream_maybe_without_drm().await?; + stream.clone().invalidate().await?; + streams.push(stream) } } } else { From a1c7b2069d79ecc634e3ba216fb86e63135d9501 Mon Sep 17 00:00:00 2001 From: bytedream Date: Thu, 23 May 2024 00:01:42 +0200 Subject: [PATCH 195/204] Update dependencies and version --- Cargo.lock | 17 +++++++++-------- Cargo.toml | 3 +-- crunchy-cli-core/Cargo.toml | 6 +++--- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b24bc20..8400022 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -349,7 +349,7 @@ checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "crunchy-cli" -version = "3.6.5" +version = "3.6.6" dependencies = [ "chrono", "clap", @@ -362,7 +362,7 @@ dependencies = [ [[package]] name = "crunchy-cli-core" -version = "3.6.5" +version = "3.6.6" dependencies = [ "anyhow", "async-speed-limit", @@ -400,9 +400,9 @@ dependencies = [ [[package]] name = "crunchyroll-rs" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6754d10e1890089eb733b71aee6f4cbc18374040aedb04c4ca76020bcd9818" +checksum = "1d33b8d77c80dea79e66993cb67963b2171dcf0b8fbc87591c58f2dadfea8da2" dependencies = [ "async-trait", "chrono", @@ -426,9 +426,9 @@ dependencies = [ [[package]] name = "crunchyroll-rs-internal" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca15fa827cca647852b091006f2b592f8727e1082f812b475b3f9ebe3f59d5bf" +checksum = "fa51945265f25c45f7d53bd70e5263dd023c0be45e38eaba886a971cb645d797" dependencies = [ "darling", "quote", @@ -1519,8 +1519,9 @@ checksum = "b833d8d034ea094b1ea68aa6d5c740e0d04bad9d16568d08ba6f76823a114316" [[package]] name = "rsubs-lib" -version = "0.3.0" -source = "git+https://github.com/crunchy-labs/rsubs-lib.git?rev=1c51f60#1c51f60b8c48f1a8f7b261372b237d89bdc17dd4" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d01f7609f0b1bc4fe24b352e8d1792c7d71cc43aea797e14b87974cd009ab402" dependencies = [ "regex", "serde", diff --git a/Cargo.toml b/Cargo.toml index ccf80ec..f263e59 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "crunchy-cli" authors = ["Crunchy Labs Maintainers"] -version = "3.6.5" +version = "3.6.6" edition = "2021" license = "MIT" @@ -35,7 +35,6 @@ members = ["crunchy-cli-core"] # fork of the `native-tls` crate which can use openssl as backend on every platform. this is done as `reqwest` only # supports `rustls` and `native-tls` as tls backend native-tls = { git = "https://github.com/crunchy-labs/rust-not-so-native-tls.git", rev = "b7969a8" } -rsubs-lib = { git = "https://github.com/crunchy-labs/rsubs-lib.git", rev = "1c51f60" } [profile.release] strip = true diff --git a/crunchy-cli-core/Cargo.toml b/crunchy-cli-core/Cargo.toml index 98ff9d7..56964ec 100644 --- a/crunchy-cli-core/Cargo.toml +++ b/crunchy-cli-core/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "crunchy-cli-core" authors = ["Crunchy Labs Maintainers"] -version = "3.6.5" +version = "3.6.6" edition = "2021" license = "MIT" @@ -16,7 +16,7 @@ anyhow = "1.0" async-speed-limit = "0.4" clap = { version = "4.5", features = ["derive", "string"] } chrono = "0.4" -crunchyroll-rs = { version = "0.11.2", features = ["experimental-stabilizations", "tower"] } +crunchyroll-rs = { version = "0.11.3", features = ["experimental-stabilizations", "tower"] } ctrlc = "3.4" dialoguer = { version = "0.11", default-features = false } dirs = "5.0" @@ -30,7 +30,7 @@ log = { version = "0.4", features = ["std"] } num_cpus = "1.16" regex = "1.10" reqwest = { version = "0.12", features = ["socks", "stream"] } -rsubs-lib = "0.3" +rsubs-lib = "~0.3.1" rusty-chromaprint = "0.2" serde = "1.0" serde_json = "1.0" From 67c267be2005d18d39c814087db905a801d41fc5 Mon Sep 17 00:00:00 2001 From: bytedream Date: Fri, 24 May 2024 22:05:04 +0200 Subject: [PATCH 196/204] Remove unused variable --- crunchy-cli-core/src/utils/format.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/crunchy-cli-core/src/utils/format.rs b/crunchy-cli-core/src/utils/format.rs index c5e8f3d..f0a002c 100644 --- a/crunchy-cli-core/src/utils/format.rs +++ b/crunchy-cli-core/src/utils/format.rs @@ -4,7 +4,7 @@ use crate::utils::log::tab_info; use crate::utils::os::{is_special_file, sanitize}; use anyhow::{bail, Result}; use chrono::{Datelike, Duration}; -use crunchyroll_rs::media::{Resolution, SkipEvents, Stream, StreamData, Subtitle}; +use crunchyroll_rs::media::{SkipEvents, Stream, StreamData, Subtitle}; use crunchyroll_rs::{Concert, Episode, Locale, MediaCollection, Movie, MusicVideo}; use log::{debug, info}; use std::cmp::Ordering; @@ -354,8 +354,6 @@ pub struct Format { pub locales: Vec<(Locale, Vec)>, - // deprecated - pub resolution: Resolution, pub width: u64, pub height: u64, pub fps: f64, @@ -401,7 +399,6 @@ impl Format { title: first_format.title, description: first_format.description, locales, - resolution: first_stream.resolution().unwrap(), width: first_stream.resolution().unwrap().width, height: first_stream.resolution().unwrap().height, fps: first_stream.fps().unwrap(), @@ -449,11 +446,11 @@ impl Format { ) .replace( "{width}", - &sanitize(self.resolution.width.to_string(), true, universal), + &sanitize(self.width.to_string(), true, universal), ) .replace( "{height}", - &sanitize(self.resolution.height.to_string(), true, universal), + &sanitize(self.height.to_string(), true, universal), ) .replace("{series_id}", &sanitize(&self.series_id, true, universal)) .replace( @@ -589,7 +586,7 @@ impl Format { .collect::>() .join(", ") ); - tab_info!("Resolution: {}", self.resolution); + tab_info!("Resolution: {}x{}", self.height, self.width); tab_info!("FPS: {:.2}", self.fps) } From fb8e53564442653bcaa972bf8143066b42cb49d3 Mon Sep 17 00:00:00 2001 From: bytedream Date: Fri, 24 May 2024 22:09:23 +0200 Subject: [PATCH 197/204] Fix subtitle title not being human-readable --- crunchy-cli-core/src/utils/download.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crunchy-cli-core/src/utils/download.rs b/crunchy-cli-core/src/utils/download.rs index d54b0bc..accefce 100644 --- a/crunchy-cli-core/src/utils/download.rs +++ b/crunchy-cli-core/src/utils/download.rs @@ -654,7 +654,7 @@ impl Downloader { metadata.extend([ format!("-metadata:s:s:{}", i), format!("title={}", { - let mut title = meta.locale.to_string(); + let mut title = meta.locale.to_human_readable(); if meta.cc { title += " (CC)" } From e7ac6d8874418c3311d433855f5991ea6f0be187 Mon Sep 17 00:00:00 2001 From: bytedream Date: Fri, 24 May 2024 22:17:25 +0200 Subject: [PATCH 198/204] Deprecate search stream.is_drm option --- crunchy-cli-core/src/search/command.rs | 4 ++++ crunchy-cli-core/src/search/format.rs | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/crunchy-cli-core/src/search/command.rs b/crunchy-cli-core/src/search/command.rs index c29ce34..8032bed 100644 --- a/crunchy-cli-core/src/search/command.rs +++ b/crunchy-cli-core/src/search/command.rs @@ -111,6 +111,10 @@ impl Execute for Search { warn!("Using `search` anonymously or with a non-premium account may return incomplete results") } + if self.output.contains("{{stream.is_drm}}") { + warn!("The `{{{{stream.is_drm}}}}` option is deprecated as it isn't reliable anymore and will be removed soon") + } + let input = if crunchyroll_rs::parse::parse_url(&self.input).is_some() { match parse_url(&ctx.crunchy, self.input.clone(), true).await { Ok(ok) => vec![ok], diff --git a/crunchy-cli-core/src/search/format.rs b/crunchy-cli-core/src/search/format.rs index ee855b2..10f4624 100644 --- a/crunchy-cli-core/src/search/format.rs +++ b/crunchy-cli-core/src/search/format.rs @@ -173,7 +173,7 @@ impl From<&Stream> for FormatStream { Self { locale: value.audio_locale.clone(), dash_url: value.url.clone(), - is_drm: value.session.uses_stream_limits, + is_drm: false, } } } From 287df843828e106d4fef2661c796ffaa69742caf Mon Sep 17 00:00:00 2001 From: bytedream Date: Fri, 14 Jun 2024 00:17:08 +0200 Subject: [PATCH 199/204] Rework episode filtering --- Cargo.lock | 16 +- crunchy-cli-core/Cargo.toml | 2 +- crunchy-cli-core/src/archive/command.rs | 47 ++- crunchy-cli-core/src/archive/filter.rs | 466 ----------------------- crunchy-cli-core/src/archive/mod.rs | 1 - crunchy-cli-core/src/download/command.rs | 53 ++- crunchy-cli-core/src/download/filter.rs | 307 --------------- crunchy-cli-core/src/download/mod.rs | 1 - crunchy-cli-core/src/search/format.rs | 28 +- crunchy-cli-core/src/utils/filter.rs | 425 +++++++++++++++++++-- crunchy-cli-core/src/utils/format.rs | 2 + 11 files changed, 515 insertions(+), 833 deletions(-) delete mode 100644 crunchy-cli-core/src/archive/filter.rs delete mode 100644 crunchy-cli-core/src/download/filter.rs diff --git a/Cargo.lock b/Cargo.lock index 8400022..7fdb3d9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -400,9 +400,9 @@ dependencies = [ [[package]] name = "crunchyroll-rs" -version = "0.11.3" +version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d33b8d77c80dea79e66993cb67963b2171dcf0b8fbc87591c58f2dadfea8da2" +checksum = "d6e38c223aecf65c9c9bec50764beea5dc70b6c97cd7f767bf6860f2fc8e0a07" dependencies = [ "async-trait", "chrono", @@ -426,9 +426,9 @@ dependencies = [ [[package]] name = "crunchyroll-rs-internal" -version = "0.11.3" +version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa51945265f25c45f7d53bd70e5263dd023c0be45e38eaba886a971cb645d797" +checksum = "144a38040a21aaa456741a9f6749354527bb68ad3bb14210e0bbc40fbd95186c" dependencies = [ "darling", "quote", @@ -1967,9 +1967,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.37.0" +version = "1.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" dependencies = [ "backtrace", "bytes", @@ -1984,9 +1984,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" dependencies = [ "proc-macro2", "quote", diff --git a/crunchy-cli-core/Cargo.toml b/crunchy-cli-core/Cargo.toml index 56964ec..5c7b901 100644 --- a/crunchy-cli-core/Cargo.toml +++ b/crunchy-cli-core/Cargo.toml @@ -16,7 +16,7 @@ anyhow = "1.0" async-speed-limit = "0.4" clap = { version = "4.5", features = ["derive", "string"] } chrono = "0.4" -crunchyroll-rs = { version = "0.11.3", features = ["experimental-stabilizations", "tower"] } +crunchyroll-rs = { version = "0.11.4", features = ["experimental-stabilizations", "tower"] } ctrlc = "3.4" dialoguer = { version = "0.11", default-features = false } dirs = "5.0" diff --git a/crunchy-cli-core/src/archive/command.rs b/crunchy-cli-core/src/archive/command.rs index d34c4b7..0d1b3a4 100644 --- a/crunchy-cli-core/src/archive/command.rs +++ b/crunchy-cli-core/src/archive/command.rs @@ -1,10 +1,9 @@ -use crate::archive::filter::ArchiveFilter; use crate::utils::context::Context; use crate::utils::download::{ DownloadBuilder, DownloadFormat, DownloadFormatMetadata, MergeBehavior, }; use crate::utils::ffmpeg::FFmpegPreset; -use crate::utils::filter::Filter; +use crate::utils::filter::{Filter, FilterMediaScope}; use crate::utils::format::{Format, SingleFormat}; use crate::utils::locale::{all_locale_in_locales, resolve_locales, LanguageTagging}; use crate::utils::log::progress; @@ -284,9 +283,49 @@ impl Execute for Archive { for (i, (media_collection, url_filter)) in parsed_urls.into_iter().enumerate() { let progress_handler = progress!("Fetching series details"); - let single_format_collection = ArchiveFilter::new( + let single_format_collection = Filter::new( url_filter, - self.clone(), + self.audio.clone(), + self.subtitle.clone(), + |scope, locales| { + let audios = locales.into_iter().map(|l| l.to_string()).collect::>().join(", "); + match scope { + FilterMediaScope::Series(series) => warn!("Series {} is not available with {} audio", series.title, audios), + FilterMediaScope::Season(season) => warn!("Season {} is not available with {} audio", season.season_number, audios), + FilterMediaScope::Episode(episodes) => { + if episodes.len() == 1 { + warn!("Episode {} is not available with {} audio", episodes[0].sequence_number, audios) + } else if episodes.len() == 2 { + warn!("Season {} is only available with {} audio from episode {} to {}", episodes[0].season_number, audios, episodes[0].sequence_number, episodes[1].sequence_number) + } else { + unimplemented!() + } + } + } + Ok(true) + }, + |scope, locales| { + let subtitles = locales.into_iter().map(|l| l.to_string()).collect::>().join(", "); + match scope { + FilterMediaScope::Series(series) => warn!("Series {} is not available with {} subtitles", series.title, subtitles), + FilterMediaScope::Season(season) => warn!("Season {} is not available with {} subtitles", season.season_number, subtitles), + FilterMediaScope::Episode(episodes) => { + if episodes.len() == 1 { + warn!("Episode {} of season {} is not available with {} subtitles", episodes[0].sequence_number, episodes[0].season_title, subtitles) + } else if episodes.len() == 2 { + warn!("Season {} of season {} is only available with {} subtitles from episode {} to {}", episodes[0].season_number, episodes[0].season_title, subtitles, episodes[0].sequence_number, episodes[1].sequence_number) + } else { + unimplemented!() + } + } + } + Ok(true) + }, + |season| { + warn!("Skipping premium episodes in season {season}"); + Ok(()) + }, + Format::has_relative_fmt(&self.output), !self.yes, self.skip_specials, ctx.crunchy.premium().await, diff --git a/crunchy-cli-core/src/archive/filter.rs b/crunchy-cli-core/src/archive/filter.rs deleted file mode 100644 index b08fb6c..0000000 --- a/crunchy-cli-core/src/archive/filter.rs +++ /dev/null @@ -1,466 +0,0 @@ -use crate::archive::command::Archive; -use crate::utils::filter::{real_dedup_vec, Filter}; -use crate::utils::format::{Format, SingleFormat, SingleFormatCollection}; -use crate::utils::interactive_select::{check_for_duplicated_seasons, get_duplicated_seasons}; -use crate::utils::parse::{fract, UrlFilter}; -use anyhow::Result; -use crunchyroll_rs::{Concert, Episode, Locale, Movie, MovieListing, MusicVideo, Season, Series}; -use log::{info, warn}; -use std::collections::{BTreeMap, HashMap}; -use std::ops::Not; - -enum Visited { - Series, - Season, - None, -} - -pub(crate) struct ArchiveFilter { - url_filter: UrlFilter, - archive: Archive, - interactive_input: bool, - skip_special: bool, - season_episodes: HashMap>, - season_subtitles_missing: Vec, - seasons_with_premium: Option>, - season_sorting: Vec, - visited: Visited, -} - -impl ArchiveFilter { - pub(crate) fn new( - url_filter: UrlFilter, - archive: Archive, - interactive_input: bool, - skip_special: bool, - is_premium: bool, - ) -> Self { - Self { - url_filter, - archive, - interactive_input, - skip_special, - season_episodes: HashMap::new(), - season_subtitles_missing: vec![], - seasons_with_premium: is_premium.not().then_some(vec![]), - season_sorting: vec![], - visited: Visited::None, - } - } -} - -impl Filter for ArchiveFilter { - type T = Vec; - type Output = SingleFormatCollection; - - async fn visit_series(&mut self, series: Series) -> Result> { - // `series.audio_locales` isn't always populated b/c of crunchyrolls api. so check if the - // audio is matching only if the field is populated - if !series.audio_locales.is_empty() { - let missing_audio = missing_locales(&series.audio_locales, &self.archive.audio); - if !missing_audio.is_empty() { - warn!( - "Series {} is not available with {} audio", - series.title, - missing_audio - .into_iter() - .map(|l| l.to_string()) - .collect::>() - .join(", ") - ) - } - let missing_subtitle = - missing_locales(&series.subtitle_locales, &self.archive.subtitle); - if !missing_subtitle.is_empty() { - warn!( - "Series {} is not available with {} subtitles", - series.title, - missing_subtitle - .into_iter() - .map(|l| l.to_string()) - .collect::>() - .join(", ") - ) - } - self.visited = Visited::Series - } - - let mut seasons = series.seasons().await?; - let mut remove_ids = vec![]; - for season in seasons.iter_mut() { - if !self.url_filter.is_season_valid(season.season_number) - || (!season - .audio_locales - .iter() - .any(|l| self.archive.audio.contains(l)) - && !season - .available_versions() - .await? - .iter() - .any(|l| self.archive.audio.contains(l))) - { - remove_ids.push(season.id.clone()); - } - } - - seasons.retain(|s| !remove_ids.contains(&s.id)); - - let duplicated_seasons = get_duplicated_seasons(&seasons); - if !duplicated_seasons.is_empty() { - if self.interactive_input { - check_for_duplicated_seasons(&mut seasons); - } else { - info!( - "Found duplicated seasons: {}", - duplicated_seasons - .iter() - .map(|d| d.to_string()) - .collect::>() - .join(", ") - ) - } - } - - Ok(seasons) - } - - async fn visit_season(&mut self, mut season: Season) -> Result> { - if !self.url_filter.is_season_valid(season.season_number) { - return Ok(vec![]); - } - - let mut seasons = season.version(self.archive.audio.clone()).await?; - if self - .archive - .audio - .iter() - .any(|l| season.audio_locales.contains(l)) - { - seasons.insert(0, season.clone()); - } - - if !matches!(self.visited, Visited::Series) { - let mut audio_locales: Vec = seasons - .iter() - .flat_map(|s| s.audio_locales.clone()) - .collect(); - real_dedup_vec(&mut audio_locales); - let missing_audio = missing_locales(&audio_locales, &self.archive.audio); - if !missing_audio.is_empty() { - warn!( - "Season {} is not available with {} audio", - season.season_number, - missing_audio - .into_iter() - .map(|l| l.to_string()) - .collect::>() - .join(", ") - ) - } - - let subtitle_locales: Vec = seasons - .iter() - .flat_map(|s| s.subtitle_locales.clone()) - .collect(); - let missing_subtitle = missing_locales(&subtitle_locales, &self.archive.subtitle); - if !missing_subtitle.is_empty() { - warn!( - "Season {} is not available with {} subtitles", - season.season_number, - missing_subtitle - .into_iter() - .map(|l| l.to_string()) - .collect::>() - .join(", ") - ) - } - self.visited = Visited::Season - } - - let mut episodes = vec![]; - for season in seasons { - self.season_sorting.push(season.id.clone()); - let season_locale = if season.audio_locales.len() < 2 { - Some( - season - .audio_locales - .first() - .cloned() - .unwrap_or(Locale::ja_JP), - ) - } else { - None - }; - let mut eps = season.episodes().await?; - let before_len = eps.len(); - - for mut ep in eps.clone() { - if let Some(l) = &season_locale { - if &ep.audio_locale == l { - continue; - } - eps.remove(eps.iter().position(|p| p.id == ep.id).unwrap()); - } else { - let mut requested_locales = self.archive.audio.clone(); - if let Some(idx) = requested_locales.iter().position(|p| p == &ep.audio_locale) - { - requested_locales.remove(idx); - } else { - eps.remove(eps.iter().position(|p| p.id == ep.id).unwrap()); - } - eps.extend(ep.version(self.archive.audio.clone()).await?); - } - } - if eps.len() < before_len { - if eps.is_empty() { - if matches!(self.visited, Visited::Series) { - warn!( - "Season {} is not available with {} audio", - season.season_number, - season_locale.unwrap_or(Locale::ja_JP) - ) - } - } else { - let last_episode = eps.last().unwrap(); - warn!( - "Season {} is only available with {} audio until episode {} ({})", - season.season_number, - season_locale.unwrap_or(Locale::ja_JP), - last_episode.sequence_number, - last_episode.title - ) - } - } - episodes.extend(eps) - } - - if Format::has_relative_fmt(&self.archive.output) { - for episode in episodes.iter() { - self.season_episodes - .entry(episode.season_id.clone()) - .or_default() - .push(episode.clone()) - } - } - - Ok(episodes) - } - - async fn visit_episode(&mut self, mut episode: Episode) -> Result> { - if !self - .url_filter - .is_episode_valid(episode.sequence_number, episode.season_number) - { - return Ok(None); - } - - // skip the episode if it's a special - if self.skip_special - && (episode.sequence_number == 0.0 || episode.sequence_number.fract() != 0.0) - { - return Ok(None); - } - - let mut episodes = vec![]; - if !matches!(self.visited, Visited::Series) && !matches!(self.visited, Visited::Season) { - if self.archive.audio.contains(&episode.audio_locale) { - episodes.push((episode.clone(), episode.subtitle_locales.clone())) - } - episodes.extend( - episode - .version(self.archive.audio.clone()) - .await? - .into_iter() - .map(|e| (e.clone(), e.subtitle_locales.clone())), - ); - let audio_locales: Vec = episodes - .iter() - .map(|(e, _)| e.audio_locale.clone()) - .collect(); - let missing_audio = missing_locales(&audio_locales, &self.archive.audio); - if !missing_audio.is_empty() { - warn!( - "Episode {} is not available with {} audio", - episode.sequence_number, - missing_audio - .into_iter() - .map(|l| l.to_string()) - .collect::>() - .join(", ") - ) - } - - let mut subtitle_locales: Vec = - episodes.iter().flat_map(|(_, s)| s.clone()).collect(); - real_dedup_vec(&mut subtitle_locales); - let missing_subtitles = missing_locales(&subtitle_locales, &self.archive.subtitle); - if !missing_subtitles.is_empty() - && !self - .season_subtitles_missing - .contains(&episode.season_number) - { - warn!( - "Episode {} is not available with {} subtitles", - episode.sequence_number, - missing_subtitles - .into_iter() - .map(|l| l.to_string()) - .collect::>() - .join(", ") - ); - self.season_subtitles_missing.push(episode.season_number) - } - } else { - episodes.push((episode.clone(), episode.subtitle_locales.clone())) - } - - if self.seasons_with_premium.is_some() { - let episode_len_before = episodes.len(); - episodes.retain(|(e, _)| !e.is_premium_only); - if episode_len_before < episodes.len() - && !self - .seasons_with_premium - .as_ref() - .unwrap() - .contains(&episode.season_number) - { - warn!( - "Skipping premium episodes in season {}", - episode.season_number - ); - self.seasons_with_premium - .as_mut() - .unwrap() - .push(episode.season_number) - } - - if episodes.is_empty() { - return Ok(None); - } - } - - let mut relative_episode_number = None; - let mut relative_sequence_number = None; - // get the relative episode number. only done if the output string has the pattern to include - // the relative episode number as this requires some extra fetching - if Format::has_relative_fmt(&self.archive.output) { - let season_eps = match self.season_episodes.get(&episode.season_id) { - Some(eps) => eps, - None => { - self.season_episodes.insert( - episode.season_id.clone(), - episode.season().await?.episodes().await?, - ); - self.season_episodes.get(&episode.season_id).unwrap() - } - }; - let mut non_integer_sequence_number_count = 0; - for (i, ep) in season_eps.iter().enumerate() { - if ep.sequence_number.fract() != 0.0 || ep.sequence_number == 0.0 { - non_integer_sequence_number_count += 1; - } - if ep.id == episode.id { - relative_episode_number = Some(i + 1); - relative_sequence_number = Some( - (i + 1 - non_integer_sequence_number_count) as f32 - + fract(ep.sequence_number), - ); - break; - } - } - if relative_episode_number.is_none() || relative_sequence_number.is_none() { - warn!( - "Failed to get relative episode number for episode {} ({}) of {} season {}", - episode.sequence_number, - episode.title, - episode.series_title, - episode.season_number, - ) - } - } - - Ok(Some( - episodes - .into_iter() - .map(|(e, s)| { - SingleFormat::new_from_episode( - e, - s, - relative_episode_number.map(|n| n as u32), - relative_sequence_number, - ) - }) - .collect(), - )) - } - - async fn visit_movie_listing(&mut self, movie_listing: MovieListing) -> Result> { - Ok(movie_listing.movies().await?) - } - - async fn visit_movie(&mut self, movie: Movie) -> Result> { - Ok(Some(vec![SingleFormat::new_from_movie(movie, vec![])])) - } - - async fn visit_music_video(&mut self, music_video: MusicVideo) -> Result> { - Ok(Some(vec![SingleFormat::new_from_music_video(music_video)])) - } - - async fn visit_concert(&mut self, concert: Concert) -> Result> { - Ok(Some(vec![SingleFormat::new_from_concert(concert)])) - } - - async fn finish(self, input: Vec) -> Result { - let flatten_input: Self::T = input.into_iter().flatten().collect(); - - let mut single_format_collection = SingleFormatCollection::new(); - - let mut pre_sorted: BTreeMap = BTreeMap::new(); - for data in flatten_input { - pre_sorted - .entry(data.identifier.clone()) - .or_insert(vec![]) - .push(data) - } - - let mut sorted: Vec<(String, Self::T)> = pre_sorted.into_iter().collect(); - sorted.sort_by(|(_, a), (_, b)| { - self.season_sorting - .iter() - .position(|p| p == &a.first().unwrap().season_id) - .unwrap() - .cmp( - &self - .season_sorting - .iter() - .position(|p| p == &b.first().unwrap().season_id) - .unwrap(), - ) - }); - - for (_, mut data) in sorted { - data.sort_by(|a, b| { - self.archive - .audio - .iter() - .position(|p| p == &a.audio) - .unwrap_or(usize::MAX) - .cmp( - &self - .archive - .audio - .iter() - .position(|p| p == &b.audio) - .unwrap_or(usize::MAX), - ) - }); - single_format_collection.add_single_formats(data) - } - - Ok(single_format_collection) - } -} - -fn missing_locales<'a>(available: &[Locale], searched: &'a [Locale]) -> Vec<&'a Locale> { - searched.iter().filter(|p| !available.contains(p)).collect() -} diff --git a/crunchy-cli-core/src/archive/mod.rs b/crunchy-cli-core/src/archive/mod.rs index c3544a4..670d0c2 100644 --- a/crunchy-cli-core/src/archive/mod.rs +++ b/crunchy-cli-core/src/archive/mod.rs @@ -1,4 +1,3 @@ mod command; -mod filter; pub use command::Archive; diff --git a/crunchy-cli-core/src/download/command.rs b/crunchy-cli-core/src/download/command.rs index fcf069b..8e3794f 100644 --- a/crunchy-cli-core/src/download/command.rs +++ b/crunchy-cli-core/src/download/command.rs @@ -1,8 +1,7 @@ -use crate::download::filter::DownloadFilter; use crate::utils::context::Context; use crate::utils::download::{DownloadBuilder, DownloadFormat, DownloadFormatMetadata}; use crate::utils::ffmpeg::{FFmpegPreset, SOFTSUB_CONTAINERS}; -use crate::utils::filter::Filter; +use crate::utils::filter::{Filter, FilterMediaScope}; use crate::utils::format::{Format, SingleFormat}; use crate::utils::locale::{resolve_locales, LanguageTagging}; use crate::utils::log::progress; @@ -14,7 +13,7 @@ use anyhow::bail; use anyhow::Result; use crunchyroll_rs::media::Resolution; use crunchyroll_rs::Locale; -use log::{debug, warn}; +use log::{debug, error, warn}; use std::collections::HashMap; use std::path::Path; @@ -250,9 +249,53 @@ impl Execute for Download { for (i, (media_collection, url_filter)) in parsed_urls.into_iter().enumerate() { let progress_handler = progress!("Fetching series details"); - let single_format_collection = DownloadFilter::new( + let single_format_collection = Filter::new( url_filter, - self.clone(), + vec![self.audio.clone()], + self.subtitle.as_ref().map_or(vec![], |s| vec![s.clone()]), + |scope, locales| { + match scope { + FilterMediaScope::Series(series) => bail!("Series {} is not available with {} audio", series.title, locales[0]), + FilterMediaScope::Season(season) => { + error!("Season {} is not available with {} audio", season.season_number, locales[0]); + Ok(false) + } + FilterMediaScope::Episode(episodes) => { + if episodes.len() == 1 { + warn!("Episode {} of season {} is not available with {} audio", episodes[0].sequence_number, episodes[0].season_title, locales[0]) + } else if episodes.len() == 2 { + warn!("Season {} is only available with {} audio from episode {} to {}", episodes[0].season_number, locales[0], episodes[0].sequence_number, episodes[1].sequence_number) + } else { + unimplemented!() + } + Ok(false) + } + } + }, + |scope, locales| { + match scope { + FilterMediaScope::Series(series) => bail!("Series {} is not available with {} subtitles", series.title, locales[0]), + FilterMediaScope::Season(season) => { + warn!("Season {} is not available with {} subtitles", season.season_number, locales[0]); + Ok(false) + }, + FilterMediaScope::Episode(episodes) => { + if episodes.len() == 1 { + warn!("Episode {} of season {} is not available with {} subtitles", episodes[0].sequence_number, episodes[0].season_title, locales[0]) + } else if episodes.len() == 2 { + warn!("Season {} is only available with {} subtitles from episode {} to {}", episodes[0].season_number, locales[0], episodes[0].sequence_number, episodes[1].sequence_number) + } else { + unimplemented!() + } + Ok(false) + } + } + }, + |season| { + warn!("Skipping premium episodes in season {season}"); + Ok(()) + }, + Format::has_relative_fmt(&self.output), !self.yes, self.skip_specials, ctx.crunchy.premium().await, diff --git a/crunchy-cli-core/src/download/filter.rs b/crunchy-cli-core/src/download/filter.rs deleted file mode 100644 index 1c62920..0000000 --- a/crunchy-cli-core/src/download/filter.rs +++ /dev/null @@ -1,307 +0,0 @@ -use crate::download::Download; -use crate::utils::filter::Filter; -use crate::utils::format::{Format, SingleFormat, SingleFormatCollection}; -use crate::utils::interactive_select::{check_for_duplicated_seasons, get_duplicated_seasons}; -use crate::utils::parse::{fract, UrlFilter}; -use anyhow::{bail, Result}; -use crunchyroll_rs::{Concert, Episode, Movie, MovieListing, MusicVideo, Season, Series}; -use log::{error, info, warn}; -use std::collections::HashMap; -use std::ops::Not; - -pub(crate) struct DownloadFilter { - url_filter: UrlFilter, - download: Download, - interactive_input: bool, - skip_special: bool, - season_episodes: HashMap>, - season_subtitles_missing: Vec, - seasons_with_premium: Option>, - season_visited: bool, -} - -impl DownloadFilter { - pub(crate) fn new( - url_filter: UrlFilter, - download: Download, - interactive_input: bool, - skip_special: bool, - is_premium: bool, - ) -> Self { - Self { - url_filter, - download, - interactive_input, - skip_special, - season_episodes: HashMap::new(), - season_subtitles_missing: vec![], - seasons_with_premium: is_premium.not().then_some(vec![]), - season_visited: false, - } - } -} - -impl Filter for DownloadFilter { - type T = SingleFormat; - type Output = SingleFormatCollection; - - async fn visit_series(&mut self, series: Series) -> Result> { - // `series.audio_locales` isn't always populated b/c of crunchyrolls api. so check if the - // audio is matching only if the field is populated - if !series.audio_locales.is_empty() && !series.audio_locales.contains(&self.download.audio) - { - error!( - "Series {} is not available with {} audio", - series.title, self.download.audio - ); - return Ok(vec![]); - } - - let mut seasons = vec![]; - for mut season in series.seasons().await? { - if !self.url_filter.is_season_valid(season.season_number) { - continue; - } - - if !season - .audio_locales - .iter() - .any(|l| l == &self.download.audio) - { - if season - .available_versions() - .await? - .iter() - .any(|l| l == &self.download.audio) - { - season = season - .version(vec![self.download.audio.clone()]) - .await? - .remove(0) - } else { - error!( - "Season {} - '{}' is not available with {} audio", - season.season_number, - season.title, - self.download.audio.clone(), - ); - continue; - } - } - - seasons.push(season) - } - - let duplicated_seasons = get_duplicated_seasons(&seasons); - if !duplicated_seasons.is_empty() { - if self.interactive_input { - check_for_duplicated_seasons(&mut seasons); - } else { - info!( - "Found duplicated seasons: {}", - duplicated_seasons - .iter() - .map(|d| d.to_string()) - .collect::>() - .join(", ") - ) - } - } - - Ok(seasons) - } - - async fn visit_season(&mut self, season: Season) -> Result> { - self.season_visited = true; - - let mut episodes = season.episodes().await?; - - if Format::has_relative_fmt(&self.download.output) { - for episode in episodes.iter() { - self.season_episodes - .entry(episode.season_number) - .or_default() - .push(episode.clone()) - } - } - - episodes.retain(|e| { - self.url_filter - .is_episode_valid(e.sequence_number, season.season_number) - }); - - Ok(episodes) - } - - async fn visit_episode(&mut self, mut episode: Episode) -> Result> { - if !self - .url_filter - .is_episode_valid(episode.sequence_number, episode.season_number) - { - return Ok(None); - } - - // skip the episode if it's a special - if self.skip_special - && (episode.sequence_number == 0.0 || episode.sequence_number.fract() != 0.0) - { - return Ok(None); - } - - // check if the audio locale is correct. - // should only be incorrect if the console input was a episode url. otherwise - // `DownloadFilter::visit_season` returns the correct episodes with matching audio - if episode.audio_locale != self.download.audio { - // check if any other version (same episode, other language) of this episode is available - // with the requested audio. if not, return an error - if !episode - .available_versions() - .await? - .contains(&self.download.audio) - { - let error_message = format!( - "Episode {} ({}) of {} season {} is not available with {} audio", - episode.sequence_number, - episode.title, - episode.series_title, - episode.season_number, - self.download.audio - ); - // sometimes a series randomly has episode in an other language. if this is the case, - // only error if the input url was a episode url - if self.season_visited { - warn!("{}", error_message); - return Ok(None); - } else { - bail!("{}", error_message) - } - } - // overwrite the current episode with the other version episode - episode = episode - .version(vec![self.download.audio.clone()]) - .await? - .remove(0) - } - - // check if the subtitles are supported - if let Some(subtitle_locale) = &self.download.subtitle { - if !episode.subtitle_locales.contains(subtitle_locale) { - // if the episode doesn't have the requested subtitles, print a error. to print this - // error only once per season, it's checked if an error got printed before by looking - // up if the season id is present in `self.season_subtitles_missing`. if not, print - // the error and add the season id to `self.season_subtitles_missing`. if it is - // present, skip the error printing - if !self - .season_subtitles_missing - .contains(&episode.season_number) - { - self.season_subtitles_missing.push(episode.season_number); - error!( - "{} season {} is not available with {} subtitles", - episode.series_title, episode.season_number, subtitle_locale - ); - } - return Ok(None); - } - } - - if self.seasons_with_premium.is_some() && episode.is_premium_only { - if !self - .seasons_with_premium - .as_ref() - .unwrap() - .contains(&episode.season_number) - { - warn!( - "Skipping premium episodes in season {}", - episode.season_number - ); - self.seasons_with_premium - .as_mut() - .unwrap() - .push(episode.season_number) - } - - return Ok(None); - } - - let mut relative_episode_number = None; - let mut relative_sequence_number = None; - // get the relative episode number. only done if the output string has the pattern to include - // the relative episode number as this requires some extra fetching - if Format::has_relative_fmt(&self.download.output) { - let season_eps = match self.season_episodes.get(&episode.season_number) { - Some(eps) => eps, - None => { - self.season_episodes.insert( - episode.season_number, - episode.season().await?.episodes().await?, - ); - self.season_episodes.get(&episode.season_number).unwrap() - } - }; - let mut non_integer_sequence_number_count = 0; - for (i, ep) in season_eps.iter().enumerate() { - if ep.sequence_number.fract() != 0.0 || ep.sequence_number == 0.0 { - non_integer_sequence_number_count += 1; - } - if ep.id == episode.id { - relative_episode_number = Some(i + 1); - relative_sequence_number = Some( - (i + 1 - non_integer_sequence_number_count) as f32 - + fract(ep.sequence_number), - ); - break; - } - } - if relative_episode_number.is_none() || relative_sequence_number.is_none() { - warn!( - "Failed to get relative episode number for episode {} ({}) of {} season {}", - episode.sequence_number, - episode.title, - episode.series_title, - episode.season_number, - ) - } - } - - Ok(Some(SingleFormat::new_from_episode( - episode.clone(), - self.download.subtitle.clone().map_or(vec![], |s| { - if episode.subtitle_locales.contains(&s) { - vec![s] - } else { - vec![] - } - }), - relative_episode_number.map(|n| n as u32), - relative_sequence_number, - ))) - } - - async fn visit_movie_listing(&mut self, movie_listing: MovieListing) -> Result> { - Ok(movie_listing.movies().await?) - } - - async fn visit_movie(&mut self, movie: Movie) -> Result> { - Ok(Some(SingleFormat::new_from_movie(movie, vec![]))) - } - - async fn visit_music_video(&mut self, music_video: MusicVideo) -> Result> { - Ok(Some(SingleFormat::new_from_music_video(music_video))) - } - - async fn visit_concert(&mut self, concert: Concert) -> Result> { - Ok(Some(SingleFormat::new_from_concert(concert))) - } - - async fn finish(self, input: Vec) -> Result { - let mut single_format_collection = SingleFormatCollection::new(); - - for data in input { - single_format_collection.add_single_formats(vec![data]) - } - - Ok(single_format_collection) - } -} diff --git a/crunchy-cli-core/src/download/mod.rs b/crunchy-cli-core/src/download/mod.rs index 696872e..47ca304 100644 --- a/crunchy-cli-core/src/download/mod.rs +++ b/crunchy-cli-core/src/download/mod.rs @@ -1,4 +1,3 @@ mod command; -mod filter; pub use command::Download; diff --git a/crunchy-cli-core/src/search/format.rs b/crunchy-cli-core/src/search/format.rs index 10f4624..cf3c5bc 100644 --- a/crunchy-cli-core/src/search/format.rs +++ b/crunchy-cli-core/src/search/format.rs @@ -241,14 +241,6 @@ macro_rules! must_match_if_true { }; } -macro_rules! self_and_versions { - ($var:expr => $audio:expr) => {{ - let mut items = vec![$var.clone()]; - items.extend($var.clone().version($audio).await?); - items - }}; -} - pub struct Format { pattern: Vec<(Range, Scope, String)>, pattern_count: HashMap, @@ -421,7 +413,15 @@ impl Format { }; let mut seasons = vec![]; for season in tmp_seasons { - seasons.extend(self_and_versions!(season => self.filter_options.audio.clone())) + seasons.push(season.clone()); + for version in season.versions { + if season.id == version.id { + continue; + } + if self.filter_options.audio.contains(&version.audio_locale) { + seasons.push(version.season().await?) + } + } } tree.extend( self.filter_options @@ -435,7 +435,15 @@ impl Format { if !episode_empty || !stream_empty { match &media_collection { MediaCollection::Episode(episode) => { - let episodes = self_and_versions!(episode => self.filter_options.audio.clone()); + let mut episodes = vec![episode.clone()]; + for version in &episode.versions { + if episode.id == version.id { + continue; + } + if self.filter_options.audio.contains(&version.audio_locale) { + episodes.push(version.episode().await?) + } + } tree.push(( Season::default(), episodes diff --git a/crunchy-cli-core/src/utils/filter.rs b/crunchy-cli-core/src/utils/filter.rs index 63fac9d..b95596e 100644 --- a/crunchy-cli-core/src/utils/filter.rs +++ b/crunchy-cli-core/src/utils/filter.rs @@ -1,24 +1,397 @@ +use crate::utils::format::{SingleFormat, SingleFormatCollection}; +use crate::utils::interactive_select::{check_for_duplicated_seasons, get_duplicated_seasons}; +use crate::utils::parse::{fract, UrlFilter}; use anyhow::Result; use crunchyroll_rs::{ - Concert, Episode, MediaCollection, Movie, MovieListing, MusicVideo, Season, Series, + Concert, Episode, Locale, MediaCollection, Movie, MovieListing, MusicVideo, Season, Series, }; +use log::{info, warn}; +use std::collections::{BTreeMap, HashMap}; +use std::ops::Not; -pub trait Filter { - type T: Send + Sized; - type Output: Send + Sized; +pub(crate) enum FilterMediaScope<'a> { + Series(&'a Series), + Season(&'a Season), + /// Always contains 1 or 2 episodes. + /// - 1: The episode's audio is completely missing + /// - 2: The requested audio is only available from first entry to last entry + Episode(Vec<&'a Episode>), +} - async fn visit_series(&mut self, series: Series) -> Result>; - async fn visit_season(&mut self, season: Season) -> Result>; - async fn visit_episode(&mut self, episode: Episode) -> Result>; - async fn visit_movie_listing(&mut self, movie_listing: MovieListing) -> Result>; - async fn visit_movie(&mut self, movie: Movie) -> Result>; - async fn visit_music_video(&mut self, music_video: MusicVideo) -> Result>; - async fn visit_concert(&mut self, concert: Concert) -> Result>; +pub(crate) struct Filter { + url_filter: UrlFilter, - async fn visit(mut self, media_collection: MediaCollection) -> Result - where - Self: Send + Sized, - { + skip_specials: bool, + interactive_input: bool, + + relative_episode_number: bool, + + audio_locales: Vec, + subtitle_locales: Vec, + + audios_missing: fn(FilterMediaScope, Vec<&Locale>) -> Result, + subtitles_missing: fn(FilterMediaScope, Vec<&Locale>) -> Result, + no_premium: fn(u32) -> Result<()>, + + is_premium: bool, + + series_visited: bool, + season_episodes: HashMap>, + season_with_premium: Option>, + season_sorting: Vec, +} + +impl Filter { + #[allow(clippy::too_many_arguments)] + pub(crate) fn new( + url_filter: UrlFilter, + audio_locales: Vec, + subtitle_locales: Vec, + audios_missing: fn(FilterMediaScope, Vec<&Locale>) -> Result, + subtitles_missing: fn(FilterMediaScope, Vec<&Locale>) -> Result, + no_premium: fn(u32) -> Result<()>, + relative_episode_number: bool, + interactive_input: bool, + skip_specials: bool, + is_premium: bool, + ) -> Self { + Self { + url_filter, + audio_locales, + subtitle_locales, + relative_episode_number, + interactive_input, + audios_missing, + subtitles_missing, + no_premium, + is_premium, + series_visited: false, + season_episodes: HashMap::new(), + skip_specials, + season_with_premium: is_premium.not().then_some(vec![]), + season_sorting: vec![], + } + } + + async fn visit_series(&mut self, series: Series) -> Result> { + // the audio locales field isn't always populated + if !series.audio_locales.is_empty() { + let missing_audios = missing_locales(&series.audio_locales, &self.audio_locales); + if !missing_audios.is_empty() + && !(self.audios_missing)(FilterMediaScope::Series(&series), missing_audios)? + { + return Ok(vec![]); + } + let missing_subtitles = + missing_locales(&series.subtitle_locales, &self.subtitle_locales); + if !missing_subtitles.is_empty() + && !(self.subtitles_missing)(FilterMediaScope::Series(&series), missing_subtitles)? + { + return Ok(vec![]); + } + } + + let mut seasons = vec![]; + for season in series.seasons().await? { + if !self.url_filter.is_season_valid(season.season_number) { + continue; + } + let missing_audios = missing_locales( + &season + .versions + .iter() + .map(|l| l.audio_locale.clone()) + .collect::>(), + &self.audio_locales, + ); + if !missing_audios.is_empty() + && !(self.audios_missing)(FilterMediaScope::Season(&season), missing_audios)? + { + return Ok(vec![]); + } + seasons.push(season) + } + + let duplicated_seasons = get_duplicated_seasons(&seasons); + if !duplicated_seasons.is_empty() { + if self.interactive_input { + check_for_duplicated_seasons(&mut seasons) + } else { + info!( + "Found duplicated seasons: {}", + duplicated_seasons + .iter() + .map(|d| d.to_string()) + .collect::>() + .join(", ") + ) + } + } + + self.series_visited = true; + + Ok(seasons) + } + + async fn visit_season(&mut self, season: Season) -> Result> { + if !self.url_filter.is_season_valid(season.season_number) { + return Ok(vec![]); + } + + let mut seasons = vec![]; + if self + .audio_locales + .iter() + .any(|l| season.audio_locales.contains(l)) + { + seasons.push(season.clone()) + } + for version in season.versions { + if season.id == version.id { + continue; + } + if self.audio_locales.contains(&version.audio_locale) { + seasons.push(version.season().await?) + } + } + + let mut episodes = vec![]; + for season in seasons { + self.season_sorting.push(season.id.clone()); + let mut eps = season.episodes().await?; + + // removes any episode that does not have the audio locale of the season. yes, this is + // the case sometimes + if season.audio_locales.len() < 2 { + let season_locale = season + .audio_locales + .first() + .cloned() + .unwrap_or(Locale::ja_JP); + eps.retain(|e| e.audio_locale == season_locale) + } + + if eps.len() < season.number_of_episodes as usize + && !(self.audios_missing)( + FilterMediaScope::Episode(vec![eps.first().unwrap(), eps.last().unwrap()]), + vec![&eps.first().unwrap().audio_locale], + )? + { + return Ok(vec![]); + } + + episodes.extend(eps) + } + + if self.relative_episode_number { + for episode in &episodes { + self.season_episodes + .entry(episode.season_id.clone()) + .or_default() + .push(episode.clone()) + } + } + + Ok(episodes) + } + + async fn visit_episode(&mut self, episode: Episode) -> Result> { + if !self + .url_filter + .is_episode_valid(episode.sequence_number, episode.season_number) + { + return Ok(vec![]); + } + + // skip the episode if it's a special + if self.skip_specials + && (episode.sequence_number == 0.0 || episode.sequence_number.fract() != 0.0) + { + return Ok(vec![]); + } + + let mut episodes = vec![]; + if !self.series_visited { + if self.audio_locales.contains(&episode.audio_locale) { + episodes.push(episode.clone()) + } + for version in &episode.versions { + // `episode` is also a version of itself. the if block above already adds the + // episode if it matches the requested audio, so it doesn't need to be requested + // here again + if version.id == episode.id { + continue; + } + if self.audio_locales.contains(&version.audio_locale) { + episodes.push(version.episode().await?) + } + } + + let audio_locales: Vec = + episodes.iter().map(|e| e.audio_locale.clone()).collect(); + let missing_audios = missing_locales(&audio_locales, &self.audio_locales); + if !missing_audios.is_empty() + && !(self.audios_missing)( + FilterMediaScope::Episode(vec![&episode]), + missing_audios, + )? + { + return Ok(vec![]); + } + + let mut subtitle_locales: Vec = episodes + .iter() + .flat_map(|e| e.subtitle_locales.clone()) + .collect(); + subtitle_locales.sort(); + subtitle_locales.dedup(); + let missing_subtitles = missing_locales(&subtitle_locales, &self.subtitle_locales); + if !missing_subtitles.is_empty() + && !(self.subtitles_missing)( + FilterMediaScope::Episode(vec![&episode]), + missing_subtitles, + )? + { + return Ok(vec![]); + } + } else { + episodes.push(episode.clone()) + } + + if let Some(seasons_with_premium) = &mut self.season_with_premium { + let episodes_len_before = episodes.len(); + episodes.retain(|e| !e.is_premium_only && !self.is_premium); + if episodes_len_before < episodes.len() + && !seasons_with_premium.contains(&episode.season_number) + { + (self.no_premium)(episode.season_number)?; + seasons_with_premium.push(episode.season_number) + } + + if episodes.is_empty() { + return Ok(vec![]); + } + } + + let mut relative_episode_number = None; + let mut relative_sequence_number = None; + if self.relative_episode_number { + let season_eps = match self.season_episodes.get(&episode.season_id) { + Some(eps) => eps, + None => { + self.season_episodes.insert( + episode.season_id.clone(), + episode.season().await?.episodes().await?, + ); + self.season_episodes.get(&episode.season_id).unwrap() + } + }; + let mut non_integer_sequence_number_count = 0; + for (i, ep) in season_eps.iter().enumerate() { + if ep.sequence_number != 0.0 || ep.sequence_number.fract() == 0.0 { + non_integer_sequence_number_count += 1 + } + if ep.id == episode.id { + relative_episode_number = Some(i + 1); + relative_sequence_number = Some( + (i + 1 - non_integer_sequence_number_count) as f32 + + fract(ep.sequence_number), + ); + break; + } + } + if relative_episode_number.is_none() || relative_sequence_number.is_none() { + warn!( + "Failed to get relative episode number for episode {} ({}) of {} season {}", + episode.sequence_number, + episode.title, + episode.series_title, + episode.season_number, + ) + } + } + + Ok(episodes + .into_iter() + .map(|e| { + SingleFormat::new_from_episode( + e.clone(), + e.subtitle_locales, + relative_episode_number.map(|n| n as u32), + relative_sequence_number, + ) + }) + .collect()) + } + + async fn visit_movie_listing(&mut self, movie_listing: MovieListing) -> Result> { + Ok(movie_listing.movies().await?) + } + + async fn visit_movie(&mut self, movie: Movie) -> Result> { + Ok(vec![SingleFormat::new_from_movie(movie, vec![])]) + } + + async fn visit_music_video(&mut self, music_video: MusicVideo) -> Result> { + Ok(vec![SingleFormat::new_from_music_video(music_video)]) + } + + async fn visit_concert(&mut self, concert: Concert) -> Result> { + Ok(vec![SingleFormat::new_from_concert(concert)]) + } + + async fn finish(self, input: Vec>) -> Result { + let flatten_input: Vec = input.into_iter().flatten().collect(); + + let mut single_format_collection = SingleFormatCollection::new(); + + let mut pre_sorted: BTreeMap> = BTreeMap::new(); + for data in flatten_input { + pre_sorted + .entry(data.identifier.clone()) + .or_default() + .push(data) + } + + let mut sorted: Vec<(String, Vec)> = pre_sorted.into_iter().collect(); + sorted.sort_by(|(_, a), (_, b)| { + self.season_sorting + .iter() + .position(|p| p == &a.first().unwrap().season_id) + .unwrap() + .cmp( + &self + .season_sorting + .iter() + .position(|p| p == &b.first().unwrap().season_id) + .unwrap(), + ) + }); + + for (_, mut data) in sorted { + data.sort_by(|a, b| { + self.audio_locales + .iter() + .position(|p| p == &a.audio) + .unwrap_or(usize::MAX) + .cmp( + &self + .audio_locales + .iter() + .position(|p| p == &b.audio) + .unwrap_or(usize::MAX), + ) + }); + single_format_collection.add_single_formats(data) + } + + Ok(single_format_collection) + } + + pub(crate) async fn visit( + mut self, + media_collection: MediaCollection, + ) -> Result { let mut items = vec![media_collection]; let mut result = vec![]; @@ -42,9 +415,7 @@ pub trait Filter { .collect::>(), ), MediaCollection::Episode(episode) => { - if let Some(t) = self.visit_episode(episode).await? { - result.push(t) - } + result.push(self.visit_episode(episode).await?) } MediaCollection::MovieListing(movie_listing) => new_items.extend( self.visit_movie_listing(movie_listing) @@ -53,20 +424,12 @@ pub trait Filter { .map(|m| m.into()) .collect::>(), ), - MediaCollection::Movie(movie) => { - if let Some(t) = self.visit_movie(movie).await? { - result.push(t) - } - } + MediaCollection::Movie(movie) => result.push(self.visit_movie(movie).await?), MediaCollection::MusicVideo(music_video) => { - if let Some(t) = self.visit_music_video(music_video).await? { - result.push(t) - } + result.push(self.visit_music_video(music_video).await?) } MediaCollection::Concert(concert) => { - if let Some(t) = self.visit_concert(concert).await? { - result.push(t) - } + result.push(self.visit_concert(concert).await?) } } } @@ -76,8 +439,10 @@ pub trait Filter { self.finish(result).await } +} - async fn finish(self, input: Vec) -> Result; +fn missing_locales<'a>(available: &[Locale], searched: &'a [Locale]) -> Vec<&'a Locale> { + searched.iter().filter(|p| !available.contains(p)).collect() } /// Remove all duplicates from a [`Vec`]. diff --git a/crunchy-cli-core/src/utils/format.rs b/crunchy-cli-core/src/utils/format.rs index f0a002c..33ce261 100644 --- a/crunchy-cli-core/src/utils/format.rs +++ b/crunchy-cli-core/src/utils/format.rs @@ -12,6 +12,7 @@ use std::collections::BTreeMap; use std::env; use std::path::{Path, PathBuf}; +#[allow(dead_code)] #[derive(Clone)] pub struct SingleFormat { pub identifier: String, @@ -347,6 +348,7 @@ impl Iterator for SingleFormatCollectionIterator { } } +#[allow(dead_code)] #[derive(Clone)] pub struct Format { pub title: String, From 8047680799d88521232986e83091b06a5253022b Mon Sep 17 00:00:00 2001 From: bytedream Date: Wed, 19 Jun 2024 23:18:35 +0200 Subject: [PATCH 200/204] Add drm check --- crunchy-cli-core/src/utils/video.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/crunchy-cli-core/src/utils/video.rs b/crunchy-cli-core/src/utils/video.rs index 8b25791..a15296c 100644 --- a/crunchy-cli-core/src/utils/video.rs +++ b/crunchy-cli-core/src/utils/video.rs @@ -27,6 +27,11 @@ pub async fn stream_data_from_stream( } } .unwrap(); + + if videos.iter().any(|v| v.drm.is_some()) || audios.iter().any(|v| v.drm.is_some()) { + bail!("Stream is DRM protected") + } + videos.sort_by(|a, b| a.bandwidth.cmp(&b.bandwidth).reverse()); audios.sort_by(|a, b| a.bandwidth.cmp(&b.bandwidth).reverse()); From 509683d23a5689dc958a79440227585c9d383c30 Mon Sep 17 00:00:00 2001 From: bytedream Date: Wed, 19 Jun 2024 23:38:57 +0200 Subject: [PATCH 201/204] Update dependencies and version --- Cargo.lock | 12 ++++++------ Cargo.toml | 8 ++++---- crunchy-cli-core/Cargo.toml | 6 +++--- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7fdb3d9..d01a80c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -349,7 +349,7 @@ checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "crunchy-cli" -version = "3.6.6" +version = "3.6.7" dependencies = [ "chrono", "clap", @@ -362,7 +362,7 @@ dependencies = [ [[package]] name = "crunchy-cli-core" -version = "3.6.6" +version = "3.6.7" dependencies = [ "anyhow", "async-speed-limit", @@ -1125,8 +1125,8 @@ dependencies = [ [[package]] name = "native-tls" -version = "0.2.11" -source = "git+https://github.com/crunchy-labs/rust-not-so-native-tls.git?rev=b7969a8#b7969a88210096e0570e29d42fb13533baf62aa6" +version = "0.2.12" +source = "git+https://github.com/crunchy-labs/rust-not-so-native-tls.git?rev=c7ac566#c7ac566559d441bbc3e5e5bd04fb7162c38d88b0" dependencies = [ "libc", "log", @@ -1519,9 +1519,9 @@ checksum = "b833d8d034ea094b1ea68aa6d5c740e0d04bad9d16568d08ba6f76823a114316" [[package]] name = "rsubs-lib" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d01f7609f0b1bc4fe24b352e8d1792c7d71cc43aea797e14b87974cd009ab402" +checksum = "8c9f50e3fbcbf1f0bd109954e2dd813d1715c7b4a92a7bf159a85dea49e9d863" dependencies = [ "regex", "serde", diff --git a/Cargo.toml b/Cargo.toml index f263e59..c1e28bb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "crunchy-cli" authors = ["Crunchy Labs Maintainers"] -version = "3.6.6" +version = "3.6.7" edition = "2021" license = "MIT" @@ -14,9 +14,9 @@ openssl-tls = ["dep:native-tls-crate", "native-tls-crate/openssl", "crunchy-cli- openssl-tls-static = ["dep:native-tls-crate", "native-tls-crate/openssl", "crunchy-cli-core/openssl-tls-static"] [dependencies] -tokio = { version = "1.37", features = ["macros", "rt-multi-thread", "time"], default-features = false } +tokio = { version = "1.38", features = ["macros", "rt-multi-thread", "time"], default-features = false } -native-tls-crate = { package = "native-tls", version = "0.2.11", optional = true } +native-tls-crate = { package = "native-tls", version = "0.2.12", optional = true } crunchy-cli-core = { path = "./crunchy-cli-core" } @@ -34,7 +34,7 @@ members = ["crunchy-cli-core"] [patch.crates-io] # fork of the `native-tls` crate which can use openssl as backend on every platform. this is done as `reqwest` only # supports `rustls` and `native-tls` as tls backend -native-tls = { git = "https://github.com/crunchy-labs/rust-not-so-native-tls.git", rev = "b7969a8" } +native-tls = { git = "https://github.com/crunchy-labs/rust-not-so-native-tls.git", rev = "c7ac566" } [profile.release] strip = true diff --git a/crunchy-cli-core/Cargo.toml b/crunchy-cli-core/Cargo.toml index 5c7b901..399053f 100644 --- a/crunchy-cli-core/Cargo.toml +++ b/crunchy-cli-core/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "crunchy-cli-core" authors = ["Crunchy Labs Maintainers"] -version = "3.6.6" +version = "3.6.7" edition = "2021" license = "MIT" @@ -30,7 +30,7 @@ log = { version = "0.4", features = ["std"] } num_cpus = "1.16" regex = "1.10" reqwest = { version = "0.12", features = ["socks", "stream"] } -rsubs-lib = "~0.3.1" +rsubs-lib = "~0.3.2" rusty-chromaprint = "0.2" serde = "1.0" serde_json = "1.0" @@ -39,7 +39,7 @@ shlex = "1.3" sys-locale = "0.3" tempfile = "3.10" time = "0.3" -tokio = { version = "1.37", features = ["io-util", "macros", "net", "rt-multi-thread", "time"] } +tokio = { version = "1.38", features = ["io-util", "macros", "net", "rt-multi-thread", "time"] } tokio-util = "0.7" tower-service = "0.3" rustls-native-certs = { version = "0.7", optional = true } From 756022b955633c73c2920091b3f02d37ab791004 Mon Sep 17 00:00:00 2001 From: bytedream Date: Thu, 20 Jun 2024 00:12:06 +0200 Subject: [PATCH 202/204] Fix panic when in anonymously --- crunchy-cli-core/src/utils/filter.rs | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/crunchy-cli-core/src/utils/filter.rs b/crunchy-cli-core/src/utils/filter.rs index b95596e..3388741 100644 --- a/crunchy-cli-core/src/utils/filter.rs +++ b/crunchy-cli-core/src/utils/filter.rs @@ -171,13 +171,23 @@ impl Filter { eps.retain(|e| e.audio_locale == season_locale) } - if eps.len() < season.number_of_episodes as usize - && !(self.audios_missing)( - FilterMediaScope::Episode(vec![eps.first().unwrap(), eps.last().unwrap()]), - vec![&eps.first().unwrap().audio_locale], - )? - { - return Ok(vec![]); + #[allow(clippy::if_same_then_else)] + if eps.len() < season.number_of_episodes as usize { + if eps.is_empty() + && !(self.audios_missing)( + FilterMediaScope::Season(&season), + season.audio_locales.iter().collect(), + )? + { + return Ok(vec![]); + } else if !eps.is_empty() + && !(self.audios_missing)( + FilterMediaScope::Episode(vec![eps.first().unwrap(), eps.last().unwrap()]), + vec![&eps.first().unwrap().audio_locale], + )? + { + return Ok(vec![]); + } } episodes.extend(eps) From 2cf9125de3f42052d3fb58f5c3f7325876837c75 Mon Sep 17 00:00:00 2001 From: bytedream Date: Mon, 1 Jul 2024 16:37:53 +0200 Subject: [PATCH 203/204] Update README.md --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index 45b8ea7..1ae2645 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,4 @@ -> ~~This project has been sunset as Crunchyroll moved to a DRM-only system. See [#362](https://github.com/crunchy-labs/crunchy-cli/issues/362).~~ -> -> Well there is one endpoint which still has DRM-free streams, I guess I still have a bit time until (finally) everything is DRM-only. +# This project has been sunset as Crunchyroll moved to a DRM-only system. See [#362](https://github.com/crunchy-labs/crunchy-cli/issues/362). # crunchy-cli From 4332b1beef7007129578cc7e253c99c96b5f6e39 Mon Sep 17 00:00:00 2001 From: Simon <47527944+Frooastside@users.noreply.github.com> Date: Mon, 1 Jul 2024 18:43:16 +0200 Subject: [PATCH 204/204] not add start time when syncing (#442) * not add start time when syncing * use itsoffset for all syncing related time shifts --- crunchy-cli-core/src/utils/download.rs | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/crunchy-cli-core/src/utils/download.rs b/crunchy-cli-core/src/utils/download.rs index accefce..2e8f321 100644 --- a/crunchy-cli-core/src/utils/download.rs +++ b/crunchy-cli-core/src/utils/download.rs @@ -322,20 +322,14 @@ impl Downloader { if let Some(offsets) = offsets { let mut root_format_idx = 0; - let mut root_format_length = 0; + let mut root_format_offset = u64::MAX; + for (i, format) in self.formats.iter().enumerate() { let offset = offsets.get(&i).copied().unwrap_or_default(); - let format_len = format - .video - .0 - .segments() - .iter() - .map(|s| s.length.as_millis()) - .sum::() as u64 - - offset.num_milliseconds() as u64; - if format_len > root_format_length { + let format_offset = offset.num_milliseconds() as u64; + if format_offset < root_format_offset { root_format_idx = i; - root_format_length = format_len; + root_format_offset = format_offset; } for _ in &format.audios { @@ -567,7 +561,7 @@ impl Downloader { for (i, meta) in videos.iter().enumerate() { if let Some(start_time) = meta.start_time { - input.extend(["-ss".to_string(), format_time_delta(&start_time)]) + input.extend(["-itsoffset".to_string(), format_time_delta(&start_time)]) } input.extend(["-i".to_string(), meta.path.to_string_lossy().to_string()]); maps.extend(["-map".to_string(), i.to_string()]); @@ -588,7 +582,7 @@ impl Downloader { } for (i, meta) in audios.iter().enumerate() { if let Some(start_time) = meta.start_time { - input.extend(["-ss".to_string(), format_time_delta(&start_time)]) + input.extend(["-itsoffset".to_string(), format_time_delta(&start_time)]) } input.extend(["-i".to_string(), meta.path.to_string_lossy().to_string()]); maps.extend(["-map".to_string(), (i + videos.len()).to_string()]); @@ -635,7 +629,7 @@ impl Downloader { if container_supports_softsubs { for (i, meta) in subtitles.iter().enumerate() { if let Some(start_time) = meta.start_time { - input.extend(["-ss".to_string(), format_time_delta(&start_time)]) + input.extend(["-itsoffset".to_string(), format_time_delta(&start_time)]) } input.extend(["-i".to_string(), meta.path.to_string_lossy().to_string()]); maps.extend([