diff --git a/Cargo.lock b/Cargo.lock
index b9dce7b..d01a80c 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -92,9 +92,9 @@ dependencies = [
[[package]]
name = "anyhow"
-version = "1.0.82"
+version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519"
+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.96"
+version = "1.0.98"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "065a29261d53ba54260972629f9ca6bffa69bac13cd1fed61420f7fa68b9f8bd"
+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.0"
+version = "3.6.7"
dependencies = [
"chrono",
"clap",
@@ -356,7 +362,7 @@ dependencies = [
[[package]]
name = "crunchy-cli-core"
-version = "3.6.0"
+version = "3.6.7"
dependencies = [
"anyhow",
"async-speed-limit",
@@ -386,6 +392,7 @@ dependencies = [
"shlex",
"sys-locale",
"tempfile",
+ "time",
"tokio",
"tokio-util",
"tower-service",
@@ -393,9 +400,9 @@ dependencies = [
[[package]]
name = "crunchyroll-rs"
-version = "0.11.1"
+version = "0.11.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "58580acc9c0abf96a231ec8b1a4597ea55d9426ea17f684ce3582e2b26437bbb"
+checksum = "d6e38c223aecf65c9c9bec50764beea5dc70b6c97cd7f767bf6860f2fc8e0a07"
dependencies = [
"async-trait",
"chrono",
@@ -419,9 +426,9 @@ dependencies = [
[[package]]
name = "crunchyroll-rs-internal"
-version = "0.11.1"
+version = "0.11.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce3c844dec8a3390f8c9853b5cf1d65c3d38fd0657b8b5d0e008db8945dea326"
+checksum = "144a38040a21aaa456741a9f6749354527bb68ad3bb14210e0bbc40fbd95186c"
dependencies = [
"darling",
"quote",
@@ -440,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",
@@ -450,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",
@@ -475,12 +482,13 @@ dependencies = [
[[package]]
name = "dash-mpd"
-version = "0.16.1"
+version = "0.16.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "79b4bdd5f1c0c7493d780c645f0bff5b9361e6408210fa88910adb181efca64c"
+checksum = "4618a5e165bf47b084963611bcf1d568c681f52d8a237e8862a0cd8c546ba255"
dependencies = [
"base64 0.22.1",
"base64-serde",
+ "bytes",
"chrono",
"fs-err",
"iso8601",
@@ -553,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"
@@ -580,9 +588,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",
@@ -712,9 +720,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",
@@ -731,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",
@@ -977,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",
]
@@ -1041,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"
@@ -1057,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"
@@ -1097,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",
]
@@ -1117,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=fdba246#fdba246a79986607cbdf573733445498bb6da2a9"
+version = "0.2.12"
+source = "git+https://github.com/crunchy-labs/rust-not-so-native-tls.git?rev=c7ac566#c7ac566559d441bbc3e5e5bd04fb7162c38d88b0"
dependencies = [
"libc",
"log",
@@ -1155,9 +1163,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",
]
@@ -1251,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",
]
@@ -1344,9 +1352,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
-version = "1.0.81"
+version = "1.0.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba"
+checksum = "0b33eb56c327dec362a9e55b3ad14f9d2f0904fb5a5b03b513ab5465399e9f43"
dependencies = [
"unicode-ident",
]
@@ -1511,12 +1519,13 @@ checksum = "b833d8d034ea094b1ea68aa6d5c740e0d04bad9d16568d08ba6f76823a114316"
[[package]]
name = "rsubs-lib"
-version = "0.2.0"
+version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0df7559a05635a4132b737c736ee286af83f3969cb98d9028d17d333e6b41cc5"
+checksum = "8c9f50e3fbcbf1f0bd109954e2dd813d1715c7b4a92a7bf159a85dea49e9d863"
dependencies = [
"regex",
"serde",
+ "time",
]
[[package]]
@@ -1533,9 +1542,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"
@@ -1604,15 +1613,15 @@ 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"
-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",
@@ -1631,9 +1640,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"
@@ -1646,11 +1655,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 +1668,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",
@@ -1669,18 +1678,18 @@ dependencies = [
[[package]]
name = "serde"
-version = "1.0.200"
+version = "1.0.202"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ddc6f9cc94d67c0e21aaf7eda3a010fd3af78ebf6e096aa6e2e13c79749cce4f"
+checksum = "226b61a0d411b2ba5ff6d7f73a476ac4f8bb900373459cd00fab8512828ba395"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
-version = "1.0.200"
+version = "1.0.202"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "856f046b9400cee3c8c94ed572ecdb752444c24528c035cd35882aad6f492bcb"
+checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838"
dependencies = [
"proc-macro2",
"quote",
@@ -1689,9 +1698,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",
@@ -1819,12 +1828,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"
@@ -1839,9 +1842,9 @@ checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
[[package]]
name = "syn"
-version = "2.0.60"
+version = "2.0.65"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3"
+checksum = "d2863d96a84c6439701d7a38f9de935ec562c8832cc55d1dde0f513b52fad106"
dependencies = [
"proc-macro2",
"quote",
@@ -1898,18 +1901,18 @@ dependencies = [
[[package]]
name = "thiserror"
-version = "1.0.59"
+version = "1.0.61"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa"
+checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
-version = "1.0.59"
+version = "1.0.61"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66"
+checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533"
dependencies = [
"proc-macro2",
"quote",
@@ -1964,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",
@@ -1981,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/Cargo.toml b/Cargo.toml
index fe7b301..c1e28bb 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.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 = "fdba246" }
+native-tls = { git = "https://github.com/crunchy-labs/rust-not-so-native-tls.git", rev = "c7ac566" }
[profile.release]
strip = true
diff --git a/README.md b/README.md
index 1735a6e..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
@@ -22,8 +20,8 @@
-
-
+
+
diff --git a/crunchy-cli-core/Cargo.toml b/crunchy-cli-core/Cargo.toml
index 896b68f..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.0"
+version = "3.6.7"
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.4", 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.2"
+rsubs-lib = "~0.3.2"
rusty-chromaprint = "0.2"
serde = "1.0"
serde_json = "1.0"
@@ -38,7 +38,8 @@ serde_plain = "1.0"
shlex = "1.3"
sys-locale = "0.3"
tempfile = "3.10"
-tokio = { version = "1.37", features = ["io-util", "macros", "net", "rt-multi-thread", "time"] }
+time = "0.3"
+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 }
diff --git a/crunchy-cli-core/src/archive/command.rs b/crunchy-cli-core/src/archive/command.rs
index 38bddc1..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;
@@ -234,6 +233,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());
@@ -280,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,
@@ -497,29 +540,28 @@ 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();
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/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