Get cross seed doing what it's actually meant to do: cross seed!

This commit is contained in:
seanomik 2022-06-22 22:06:49 -04:00 committed by SeanOMik
parent 9a7d08cb81
commit 5327c578cd
Signed by: SeanOMik
GPG Key ID: 568F326C7EB33ACB
10 changed files with 831 additions and 97 deletions

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "abstracttorrent"]
path = abstracttorrent
url = https://github.com/SeanOMik/abstracttorrent.git

568
Cargo.lock generated
View File

@ -2,6 +2,14 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "abstracttorrent"
version = "0.1.0"
dependencies = [
"async-trait",
"qbittorrent",
]
[[package]]
name = "adler"
version = "1.0.2"
@ -56,6 +64,17 @@ dependencies = [
"syn",
]
[[package]]
name = "async-trait"
version = "0.1.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96cf8829f67d2eab0b2dfa42c5d0ef737e0724e4a82b01b3e292456202b19716"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "atom_syndication"
version = "0.11.0"
@ -179,6 +198,49 @@ dependencies = [
"custom_derive",
]
[[package]]
name = "cookie"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94d4706de1b0fa5b132270cddffa8585166037822e260a944fe161acd137ca05"
dependencies = [
"percent-encoding",
"time",
"version_check",
]
[[package]]
name = "cookie_store"
version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e4b6aa369f41f5faa04bb80c9b1f4216ea81646ed6124d76ba5c49a7aafd9cd"
dependencies = [
"cookie",
"idna",
"log",
"publicsuffix",
"serde",
"serde_json",
"time",
"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.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
[[package]]
name = "cpufeatures"
version = "0.2.2"
@ -201,6 +263,7 @@ dependencies = [
name = "cross-seed"
version = "0.1.0"
dependencies = [
"abstracttorrent",
"argmap",
"async-recursion",
"bytes 1.1.0",
@ -213,6 +276,7 @@ dependencies = [
"rss",
"serde",
"serde_with",
"stopwatch",
"tokio 1.19.2",
"toml",
"torznab",
@ -421,6 +485,15 @@ dependencies = [
"cfg-if 1.0.0",
]
[[package]]
name = "fastrand"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf"
dependencies = [
"instant",
]
[[package]]
name = "figment"
version = "0.10.6"
@ -451,6 +524,21 @@ 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.0.1"
@ -461,6 +549,12 @@ dependencies = [
"percent-encoding",
]
[[package]]
name = "fuchsia-cprng"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
[[package]]
name = "fuchsia-zircon"
version = "0.3.3"
@ -603,7 +697,7 @@ dependencies = [
"indexmap",
"slab",
"tokio 1.19.2",
"tokio-util 0.7.3",
"tokio-util",
"tracing",
]
@ -613,6 +707,12 @@ version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
[[package]]
name = "hashbrown"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db0d4cf898abf0081f964436dc980e96670a0f36863e4b83aaacdb65c9d7ccc3"
[[package]]
name = "hermit-abi"
version = "0.1.19"
@ -693,6 +793,19 @@ dependencies = [
"tokio-rustls",
]
[[package]]
name = "hyper-tls"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905"
dependencies = [
"bytes 1.1.0",
"hyper",
"native-tls",
"tokio 1.19.2",
"tokio-native-tls",
]
[[package]]
name = "ident_case"
version = "1.0.1"
@ -712,12 +825,12 @@ dependencies = [
[[package]]
name = "indexmap"
version = "1.8.2"
version = "1.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6012d540c5baa3589337a98ce73408de9b5a25ec9fc2c6fd6be8f0d39e0ca5a"
checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e"
dependencies = [
"autocfg",
"hashbrown",
"hashbrown 0.12.1",
]
[[package]]
@ -726,6 +839,15 @@ version = "0.1.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8fae54786f62fb2918dcfae3d568594e50eb9b5c25bf04371af6fe7516452fb"
[[package]]
name = "instant"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
dependencies = [
"cfg-if 1.0.0",
]
[[package]]
name = "iovec"
version = "0.1.4"
@ -758,9 +880,9 @@ checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d"
[[package]]
name = "js-sys"
version = "0.3.57"
version = "0.3.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "671a26f820db17c2a2750743f1dd03bafd15b98c9f30c7c2628c024c05d73397"
checksum = "c3fac17f7123a73ca62df411b1bf727ccc805daa070338fda671c86dac1bdc27"
dependencies = [
"wasm-bindgen",
]
@ -871,6 +993,16 @@ version = "0.3.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
[[package]]
name = "mime_guess"
version = "2.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef"
dependencies = [
"mime",
"unicase",
]
[[package]]
name = "miniz_oxide"
version = "0.5.3"
@ -901,9 +1033,9 @@ dependencies = [
[[package]]
name = "mio"
version = "0.8.3"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "713d550d9b44d89174e066b7a6217ae06234c10cb47819a88290d2b353c31799"
checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf"
dependencies = [
"libc",
"log",
@ -934,6 +1066,24 @@ dependencies = [
"ws2_32-sys",
]
[[package]]
name = "native-tls"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd7e2f3618557f980e0b17e8856252eee3c97fa12c54dff0ca290fb6266ca4a9"
dependencies = [
"lazy_static",
"libc",
"log",
"openssl",
"openssl-probe",
"openssl-sys",
"schannel",
"security-framework",
"security-framework-sys",
"tempfile",
]
[[package]]
name = "net2"
version = "0.2.37"
@ -951,6 +1101,42 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c96aba5aa877601bb3f6dd6a63a969e1f82e60646e81e71b14496995e9853c91"
[[package]]
name = "num"
version = "0.1.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e"
dependencies = [
"num-bigint",
"num-complex",
"num-integer",
"num-iter",
"num-rational",
"num-traits",
]
[[package]]
name = "num-bigint"
version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e63899ad0da84ce718c14936262a41cee2c79c981fc0a0e7c7beb47d5a07e8c1"
dependencies = [
"num-integer",
"num-traits",
"rand",
"rustc-serialize",
]
[[package]]
name = "num-complex"
version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b288631d7878aaf59442cffd36910ea604ecd7745c36054328595114001c9656"
dependencies = [
"num-traits",
"rustc-serialize",
]
[[package]]
name = "num-integer"
version = "0.1.45"
@ -961,6 +1147,29 @@ dependencies = [
"num-traits",
]
[[package]]
name = "num-iter"
version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]]
name = "num-rational"
version = "0.1.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee314c74bd753fc86b4780aa9475da469155f3848473a261d2d18e35245a784e"
dependencies = [
"num-bigint",
"num-integer",
"num-traits",
"rustc-serialize",
]
[[package]]
name = "num-traits"
version = "0.2.15"
@ -980,12 +1189,66 @@ dependencies = [
"libc",
]
[[package]]
name = "num_threads"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44"
dependencies = [
"libc",
]
[[package]]
name = "once_cell"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225"
[[package]]
name = "openssl"
version = "0.10.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb81a6430ac911acb25fe5ac8f1d2af1b4ea8a4fdfda0f1ee4292af2e2d8eb0e"
dependencies = [
"bitflags",
"cfg-if 1.0.0",
"foreign-types",
"libc",
"once_cell",
"openssl-macros",
"openssl-sys",
]
[[package]]
name = "openssl-macros"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c"
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-sys"
version = "0.9.74"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "835363342df5fba8354c5b453325b110ffd54044e588c539cf2f20a8014e4cb1"
dependencies = [
"autocfg",
"cc",
"libc",
"pkg-config",
"vcpkg",
]
[[package]]
name = "parking_lot"
version = "0.9.0"
@ -1097,10 +1360,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "proc-macro2"
version = "1.0.39"
name = "pkg-config"
version = "0.3.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f"
checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae"
[[package]]
name = "proc-macro-hack"
version = "0.5.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
[[package]]
name = "proc-macro2"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7"
dependencies = [
"unicode-ident",
]
@ -1118,6 +1393,35 @@ dependencies = [
"yansi",
]
[[package]]
name = "psl-types"
version = "2.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8eda7c62d9ecaafdf8b62374c006de0adf61666ae96a96ba74a37134aa4e470"
[[package]]
name = "publicsuffix"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "292972edad6bbecc137ab84c5e36421a4a6c979ea31d3cc73540dd04315b33e1"
dependencies = [
"byteorder",
"hashbrown 0.11.2",
"idna",
"psl-types",
]
[[package]]
name = "qbittorrent"
version = "0.1.0"
dependencies = [
"reqwest",
"serde",
"serde_json",
"serde_repr",
"serde_with",
]
[[package]]
name = "quick-xml"
version = "0.22.0"
@ -1140,13 +1444,50 @@ dependencies = [
[[package]]
name = "quote"
version = "1.0.18"
version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1"
checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293"
dependencies = [
"fuchsia-cprng",
"libc",
"rand_core 0.3.1",
"rdrand",
"winapi 0.3.9",
]
[[package]]
name = "rand_core"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
dependencies = [
"rand_core 0.4.2",
]
[[package]]
name = "rand_core"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
[[package]]
name = "rdrand"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "redox_syscall"
version = "0.1.57"
@ -1180,14 +1521,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64"
[[package]]
name = "reqwest"
version = "0.11.10"
name = "remove_dir_all"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46a1f7aa4f35e5e8b4160449f51afc758f0ce6454315a9fa7d0d113e958c41eb"
checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
dependencies = [
"winapi 0.3.9",
]
[[package]]
name = "reqwest"
version = "0.11.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b75aa69a3f06bbcc66ede33af2af253c6f7a86b1ca0033f60c580a27074fbf92"
dependencies = [
"async-compression",
"base64",
"bytes 1.1.0",
"cookie",
"cookie_store",
"encoding_rs",
"futures-core",
"futures-util",
@ -1196,21 +1548,27 @@ dependencies = [
"http-body",
"hyper",
"hyper-rustls",
"hyper-tls",
"ipnet",
"js-sys",
"lazy_static",
"log",
"mime",
"mime_guess",
"native-tls",
"percent-encoding",
"pin-project-lite",
"proc-macro-hack",
"rustls",
"rustls-pemfile",
"serde",
"serde_json",
"serde_urlencoded",
"tokio 1.19.2",
"tokio-native-tls",
"tokio-rustls",
"tokio-util 0.6.10",
"tokio-util",
"tower-service",
"url",
"wasm-bindgen",
"wasm-bindgen-futures",
@ -1246,6 +1604,12 @@ dependencies = [
"quick-xml 0.22.0",
]
[[package]]
name = "rustc-serialize"
version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
[[package]]
name = "rustc_version"
version = "0.2.3"
@ -1269,9 +1633,9 @@ dependencies = [
[[package]]
name = "rustls-pemfile"
version = "0.3.0"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ee86d63972a7c661d1536fefe8c3c8407321c3df668891286de28abcd087360"
checksum = "e7522c9de787ff061458fe9a829dc790a3f5b22dc571694fc5883f448b94d9a9"
dependencies = [
"base64",
]
@ -1282,6 +1646,16 @@ version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695"
[[package]]
name = "schannel"
version = "0.1.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2"
dependencies = [
"lazy_static",
"windows-sys",
]
[[package]]
name = "scopeguard"
version = "1.1.0"
@ -1298,6 +1672,29 @@ dependencies = [
"untrusted",
]
[[package]]
name = "security-framework"
version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dc14f172faf8a0194a3aded622712b0de276821addc574fa54fc0a1167e10dc"
dependencies = [
"bitflags",
"core-foundation",
"core-foundation-sys",
"libc",
"security-framework-sys",
]
[[package]]
name = "security-framework-sys"
version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556"
dependencies = [
"core-foundation-sys",
"libc",
]
[[package]]
name = "semver"
version = "0.9.0"
@ -1344,6 +1741,17 @@ dependencies = [
"serde",
]
[[package]]
name = "serde_repr"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2ad84e47328a31223de7fed7a4f5087f2d6ddfe586cf3ca25b7a165bc0a5aed"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_urlencoded"
version = "0.7.1"
@ -1468,6 +1876,15 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "stopwatch"
version = "0.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d04b5ebc78da44d3a456319d8bc2783e7d8cc7ccbb5cb4dc3f54afbd93bf728"
dependencies = [
"num",
]
[[package]]
name = "strsim"
version = "0.10.0"
@ -1476,15 +1893,29 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "syn"
version = "1.0.96"
version = "1.0.98"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0748dd251e24453cb8717f0354206b91557e4ec8703673a4b30208f2abaf1ebf"
checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "tempfile"
version = "3.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4"
dependencies = [
"cfg-if 1.0.0",
"fastrand",
"libc",
"redox_syscall 0.2.13",
"remove_dir_all",
"winapi 0.3.9",
]
[[package]]
name = "thiserror"
version = "1.0.31"
@ -1514,6 +1945,24 @@ dependencies = [
"once_cell",
]
[[package]]
name = "time"
version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "82501a4c1c0330d640a6e176a3d6a204f5ec5237aca029029d21864a902e27b0"
dependencies = [
"itoa",
"libc",
"num_threads",
"time-macros",
]
[[package]]
name = "time-macros"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42657b1a6f4d817cda8e7a0ace261fe0cc946cf3a80314390b22cc61ae080792"
[[package]]
name = "tinyvec"
version = "1.6.0"
@ -1562,7 +2011,7 @@ dependencies = [
"bytes 1.1.0",
"libc",
"memchr",
"mio 0.8.3",
"mio 0.8.4",
"num_cpus",
"once_cell",
"parking_lot 0.12.1",
@ -1637,6 +2086,16 @@ dependencies = [
"syn",
]
[[package]]
name = "tokio-native-tls"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b"
dependencies = [
"native-tls",
"tokio 1.19.2",
]
[[package]]
name = "tokio-reactor"
version = "0.1.12"
@ -1753,20 +2212,6 @@ dependencies = [
"tokio-reactor",
]
[[package]]
name = "tokio-util"
version = "0.6.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36943ee01a6d67977dd3f84a5a1d2efeb4ada3a1ae771cadfaa535d9d9fc6507"
dependencies = [
"bytes 1.1.0",
"futures-core",
"futures-sink",
"log",
"pin-project-lite",
"tokio 1.19.2",
]
[[package]]
name = "tokio-util"
version = "0.7.3"
@ -1818,9 +2263,9 @@ dependencies = [
[[package]]
name = "tower-service"
version = "0.3.1"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6"
checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
[[package]]
name = "tracing"
@ -1912,6 +2357,15 @@ dependencies = [
"version_check",
]
[[package]]
name = "unicase"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6"
dependencies = [
"version_check",
]
[[package]]
name = "unicode-bidi"
version = "0.3.8"
@ -1920,9 +2374,9 @@ checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992"
[[package]]
name = "unicode-ident"
version = "1.0.0"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee"
checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c"
[[package]]
name = "unicode-normalization"
@ -1969,6 +2423,12 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
[[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"
@ -1993,9 +2453,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.80"
version = "0.2.81"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "27370197c907c55e3f1a9fbe26f44e937fe6451368324e009cba39e139dc08ad"
checksum = "7c53b543413a17a202f4be280a7e5c62a1c69345f5de525ee64f8cfdbc954994"
dependencies = [
"cfg-if 1.0.0",
"wasm-bindgen-macro",
@ -2003,9 +2463,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.80"
version = "0.2.81"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53e04185bfa3a779273da532f5025e33398409573f348985af9a1cbf3774d3f4"
checksum = "5491a68ab4500fa6b4d726bd67408630c3dbe9c4fe7bda16d5c82a1fd8c7340a"
dependencies = [
"bumpalo",
"lazy_static",
@ -2018,9 +2478,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-futures"
version = "0.4.30"
version = "0.4.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f741de44b75e14c35df886aff5f1eb73aa114fa5d4d00dcd37b5e01259bf3b2"
checksum = "de9a9cec1733468a8c657e57fa2413d2ae2c0129b95e87c5b72b8ace4d13f31f"
dependencies = [
"cfg-if 1.0.0",
"js-sys",
@ -2030,9 +2490,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.80"
version = "0.2.81"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17cae7ff784d7e83a2fe7611cfe766ecf034111b49deb850a3dc7699c08251f5"
checksum = "c441e177922bc58f1e12c022624b6216378e5febc2f0533e41ba443d505b80aa"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@ -2040,9 +2500,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.80"
version = "0.2.81"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99ec0dc7a4756fffc231aab1b9f2f578d23cd391390ab27f952ae0c9b3ece20b"
checksum = "7d94ac45fcf608c1f45ef53e748d35660f168490c10b23704c7779ab8f5c3048"
dependencies = [
"proc-macro2",
"quote",
@ -2053,15 +2513,15 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.80"
version = "0.2.81"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d554b7f530dee5964d9a9468d95c1f8b8acae4f282807e7d27d4b03099a46744"
checksum = "6a89911bd99e5f3659ec4acf9c4d93b0a90fe4a2a11f15328472058edc5261be"
[[package]]
name = "web-sys"
version = "0.3.57"
version = "0.3.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b17e741662c70c8bd24ac5c5b18de314a2c26c32bf8346ee1e6f53de919c283"
checksum = "2fed94beee57daf8dd7d51f2b15dc2bcde92d7a72304cdf662a4371008b71b90"
dependencies = [
"js-sys",
"wasm-bindgen",

View File

@ -9,11 +9,18 @@ edition = "2021"
tokio = { version = "1.19.2", features = ["full"] }
tracing = "0.1.35"
tracing-subscriber = "0.3.11"
futures = "0.3.21"
futures = { version = "0.3.21", features= ["executor"] }
toml = "0.5.9"
lava_torrent = "0.7.0" # https://docs.rs/lava_torrent/0.7.0/lava_torrent/
torznab = "0.7.2" # https://docs.rs/torznab/0.7.2/torznab/
stopwatch = "0.0.7"
magnet-url = { git = "https://github.com/SeanOMik/magnet-url-rs.git", branch = "main" }
abstracttorrent = { path = "abstracttorrent" }
#abstracttorrent = { git = "https://github.com/SeanOMik/abstracttorrent.git", branch = "main" }
#qbittorrent = { git = "https://github.com/SeanOMik/qbittorrent-rs.git", branch = "main"}
serde_with = "1.14.0"
serde = { version = "1.0", features = ["derive"] }
figment = { version = "0.10", features = ["toml", "env"] }

1
abstracttorrent Submodule

@ -0,0 +1 @@
Subproject commit 2b4cd84d7faf49d37492c6ff5708454beea7857a

1
src/config/client/mod.rs Normal file
View File

@ -0,0 +1 @@
pub mod qbittorrent;

View File

@ -0,0 +1,8 @@
use serde::{Deserialize, Serialize};
#[derive(Debug, Deserialize, Serialize)]
pub struct QBittorrentConfig {
pub url: String,
pub username: String,
pub password: String,
}

View File

@ -9,7 +9,11 @@ use crate::torznab::TorznabClient;
use super::CliProvider;
#[derive(Deserialize, Serialize)]
fn default_bool_true() -> bool {
true
}
#[derive(Debug, Deserialize, Serialize)]
pub struct Config {
/// The path of the torrents to search.
torrents_path: String,
@ -29,13 +33,12 @@ pub struct Config {
#[serde(default)]
pub use_cache: bool,
/// Whether to keep the original torrent file and create a new one for cross-seed or delete original and upload cross-seed
#[serde(default)]
pub replace_torrents: bool,
/// Whether or not to strip public trackers from cross-seed torrents.
#[serde(default)]
pub strip_public: bool,
pub strip_public_trackers: bool,
/// The category of added cross-seed torrents.
torrent_category: Option<String>,
/// Used for deserializing the indexers into a Vec<Indexer>.
#[serde(rename = "indexers")]
@ -44,11 +47,16 @@ pub struct Config {
/// The indexers to search.
#[serde(skip)]
pub indexers: Vec<Indexer>,
/// Config section for qbittorrent client
pub qbittorrent: Option<super::client::qbittorrent::QBittorrentConfig>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub enum RunMode {
#[serde(alias = "script")]
Script,
#[serde(alias = "daemon")]
Daemon,
}
@ -60,13 +68,25 @@ impl Default for RunMode {
#[derive(Debug, Clone, Deserialize, Serialize)]
pub enum TorrentMode {
Inject,
Search,
/// Inject a found torrent's trackers into the torrent being downloaded
/// by the client.
#[serde(alias = "inject_trackers", alias = "injecttrackers")]
InjectTrackers,
/// Upload the torrent file to the torrent client. This will cause there
/// to be two uploading torrents on the client. One which is found by cross-seed
/// and the other which was imported by the user or another application.
#[serde(alias = "inject_file", alias = "injectfile")]
InjectFile,
/// Cross-seeded torrents will be stored in the filesystem.
#[serde(alias = "search")]
Filesystem,
}
impl Default for TorrentMode {
fn default() -> Self {
TorrentMode::Inject
TorrentMode::InjectTrackers
}
}
@ -145,4 +165,10 @@ impl Config {
pub fn output_path_str(&self) -> Option<&String> {
self.output_path.as_ref()
}
pub fn torrent_category(&self) -> String {
self.torrent_category.as_ref()
.unwrap_or(&String::from("cross-seed-rs"))
.clone()
}
}

View File

@ -1,8 +1,10 @@
pub mod config;
pub use config::Config;
pub use config::*;
pub mod argument_tree;
pub use argument_tree::*;
pub mod cli_provider;
pub use cli_provider::*;
pub mod client;

View File

@ -1,12 +1,18 @@
mod config;
mod torznab;
mod torrent_client;
use config::Config;
use config::{Config, TorrentMode};
use abstracttorrent::common::GetTorrentListParams;
use abstracttorrent::torrent::{TorrentUpload, TorrentState, TorrentInfo};
use lava_torrent::bencode::BencodeElem;
use tracing::{info, Level, debug};
use tracing::{info, Level, debug, warn, error};
use std::ops::Deref;
use std::path::{Path, PathBuf};
use std::error::Error;
use std::vec;
use lava_torrent::torrent::v1::{Torrent, AnnounceList};
@ -39,15 +45,22 @@ fn read_torrents(path: &Path) -> Result<Vec<PathBuf>, Box<dyn Error>> {
#[tokio::main]
async fn main() {
let subscriber = tracing_subscriber::fmt()
.with_max_level(Level::INFO)
.with_max_level(Level::DEBUG)
.finish();
tracing::subscriber::set_global_default(subscriber).expect("Failed to set global default log subscriber");
// Get config and debug the torrents
let config = Config::new();
let config = Arc::new(Config::new());
info!("Searching for torrents in: {}", config.torrents_path_str());
// Get a torrent client from the config.
let mut torrent_client = torrent_client::TorrentClient::from_config(&config);
torrent_client.login(&config).await.unwrap();
// Torrent client no longer needs to mut, so we can just create an `Arc` without a mutex.
let torrent_client = Arc::new(torrent_client);
let mut indexers = config.indexers.clone();
// Create torznab clients for each indexer.
@ -64,24 +77,59 @@ async fn main() {
// Log the amount of torrents.
let torrent_files = read_torrents(config.torrents_path()).unwrap();
info!("Found {} torrents", torrent_files.len());
info!("Found {} torrent files...", torrent_files.len());
// Convert the indexers to be async friendly.
let mut indexers = indexers.iter()
.map(|indexer| Arc::new(RwLock::new(indexer.clone())))
.collect::<Vec<_>>();
// Store async tasks to wait for them to finish
let mut indexer_handles = vec![];
for torrent_path in torrent_files.iter() {
let torrent = Torrent::read_from_file(torrent_path).unwrap();
info!("Parsing all torrent files...");
let mut stop = stopwatch::Stopwatch::start_new();
// Get the torrents and from the paths
let mut torrents: Vec<Result<Torrent, lava_torrent::LavaTorrentError>> = torrent_files.iter()
.map(|path| Torrent::read_from_file(path))
.collect();
stop.stop();
info!("Took {} seconds to parse all torrents", stop.elapsed().as_secs());
drop(stop);
// Remove the torrents that failed to be read from the file, and
// are not in the download client.
// NOTE: It might be better to get all torrents on the client and check that the torrents are on the
// client locally.
torrents.retain(|torrent| {
if let Ok(torrent) = torrent {
let info = futures::executor::block_on(torrent_client.get_torrent_info(&torrent)).unwrap();
info.is_some()
} else {
false
}
});
// Unwrap the results, all errored ones were removed from the `.retain`
let torrents: Vec<Torrent> = torrents.iter()
.map(|res| res.as_ref().unwrap().clone())
.collect();
info!("Found {} torrents that are in the client and on the filesystem", torrents.len());
for torrent in torrents {
let torrent = Arc::new(torrent);
for indexer in indexers.iter() {
info!("Checking for \"{}\"", torrent.name);
// Clone some `Arc`s for the new async task.
let mut indexer = Arc::clone(indexer);
let torrent = Arc::clone(&torrent);
let torrent_client = Arc::clone(&torrent_client);
let config = Arc::clone(&config);
indexer_handles.push(tokio::spawn(async move {
let lock = indexer.read().await;
match &lock.client {
@ -95,39 +143,159 @@ async fn main() {
if let Some(result) = results.first() {
let found_torrent = result.download_torrent().await.unwrap();
// Check if we found the same torrent in its own indexer
if found_torrent.info_hash() == torrent.info_hash() {
debug!("Found same torrent in its own indexer, skipping...");
return;
}
if let Some(found_announces) = &found_torrent.announce_list {
// Some urls can be encoded so we need to decode to compare them.
let found_announces: Vec<Vec<String>> = found_announces.iter()
.map(|a_list| a_list.iter().map(|a| urlencoding::decode(a).unwrap().to_string()).collect::<Vec<String>>())
.map(|a_list|
a_list.iter().map(|a| urlencoding::decode(a)
.unwrap().to_string())
.collect::<Vec<String>>())
.collect();
if let Some(torrent_announces) = &torrent.announce_list {
let mut found_announces_flat: Vec<&String> = Vec::new();
for i in found_announces.iter() {
for j in i.iter() {
found_announces_flat.push(j);
}
}
// Get the trackers of the torrent from the download client.
let request_info = TorrentInfo::from_hash(torrent.info_hash());
let torrent_announces = torrent_client.get_torrent_trackers(&request_info).await.unwrap();
let torrent_announces: Vec<&String> = torrent_announces.iter().map(|t| &t.url).collect();
let mut flat_announces: Vec<&String> = Vec::new();
for i in torrent_announces.iter() {
for j in i.iter() {
flat_announces.push(j);
}
}
// Flatten the announce list to make them easier to search.
let found_announces: Vec<&String> = found_announces.iter()
.flat_map(|array| array.iter())
.collect();
// Check if the announce urls from the found torrent are in the one
// that is on the file system.
let mut in_tracker = true;
for found_url in found_announces_flat.iter() {
in_tracker = in_tracker && flat_announces.contains(found_url);
}
// Check if the client has the trackers of the torrent already.
let mut client_has_trackers = found_announces.iter()
.all(|tracker| torrent_announces.contains(tracker));
if !in_tracker {
info!("Found a cross-seedable torrent for {}", found_torrent.name);
} else {
debug!("Found the torrent in its original indexer, skipping...");
if !client_has_trackers {
info!("Found a cross-seedable torrent for {}", found_torrent.name);
match torrent_client.get_torrent_info(&torrent).await.unwrap() {
Some(info) => {
info!("Got info: {:?}", info);
match info.state {
TorrentState::Uploading | TorrentState::QueuedUploading => {
debug!("The torrent is being uploaded on the client");
//if config.add_trackers {
match config.torrent_mode {
TorrentMode::InjectTrackers => {
debug!("Can add trackers to the torrent");
if found_torrent.is_private() {
debug!("The found torrent is private, so we must remove the torrent and re-add it with the new trackers...");
match torrent_client.remove_torrent(&info, false).await {
Ok(()) => {
debug!("Re-uploading torrent to client...");
info!("Found announces: {:?}", found_announces);
// Combine both announces and deref the Strings by cloning them.
let mut torrent_announces: Vec<String> = torrent_announces.into_iter()
.chain(found_announces)
.cloned()
.collect();
// Remove the [DHT], [PeX] and [LSD] announces from the list.
// The client should handle those.
torrent_announces.retain(|announce| !(announce.starts_with("** [") && announce.ends_with("] **")));
info!("Old torrent: {:?}", torrent.announce_list);
let mut torrent = (*torrent).clone();
torrent.announce_list = Some(vec![torrent_announces]);
if let Some(extra) = torrent.extra_info_fields.as_mut() {
extra.insert(String::from("private"), BencodeElem::Integer(1));
} else {
let mut extra = std::collections::HashMap::new();
extra.insert(String::from("private"), BencodeElem::Integer(1));
torrent.extra_info_fields = Some(extra);
}
/* torrent.extra_info_fields.as_mut()
.unwrap_or(&mut std::collections::HashMap::new())
.insert(String::from("private"), BencodeElem::Integer(1)); */
info!("Torrent that will be uploaded: {:?}, private: {}", torrent.announce_list, torrent.is_private());
// Clone some fields from the torrent due to ownership issues with
// torrent.encode()
let name = torrent.name.clone();
let hash = torrent.info_hash().clone();
match torrent.encode() {
Ok(bytes) => {
let upload = TorrentUpload::builder()
.category(config.torrent_category())
.tags(info.tags)
.torrent_data(format!("{}.torrent", hash), bytes)
//.paused()
.build();
match torrent_client.add_torrent(&upload).await {
Ok(()) => info!("Added cross-seed torrent {}!", name),
Err(err) => error!("Error adding cross-seed torrent: {} (error: {:?}", name, err),
}
},
Err(e) => error!("Error encoding torrent for upload: {}", e),
}
},
Err(err) => error!("Error removing torrent from client: {} (error: {:?})", torrent.name, err),
}
} else {
debug!("Adding trackers to torrent since they aren't private...");
let torrent_announces = torrent_announces.iter()
.map(|u| u.to_owned().to_owned())
.collect();
if let Err(err) = torrent_client.add_torrent_trackers(&info, torrent_announces).await {
error!("Error adding torrent trackers to torrent: {} (err: {:?})", torrent.name, err);
}
}
},
TorrentMode::InjectFile => {
debug!("Cannot add trackers, uploading new torrent...");
// Clone some fields from the torrent due to ownership issues with
// found_torrent.encode()
let name = found_torrent.name.clone();
let hash = found_torrent.info_hash().clone();
match found_torrent.encode() {
Ok(bytes) => {
let upload = TorrentUpload::builder()
.torrent_data(format!("{}.torrent", hash), bytes)
.category(config.torrent_category())
//.paused() // TODO: don't pause new uploads
.build();
match torrent_client.add_torrent(&upload).await {
Ok(()) => info!("Added cross-seed torrent {}!", name),
Err(err) => error!("Failure to add cross-seed torrent: {} (Error {:?})", name, err),
}
},
Err(e) => warn!("Failure to encode ({}) {}", e, name),
}
},
TorrentMode::Filesystem => {
todo!(); // TODO: implement
}
}
},
_ => debug!("Torrent is not done downloading, skipping..."),
}
},
None => info!("Torrent file {} was not found in the client, skipping...", torrent.name),
}
} else {
debug!("Found the torrent in its original indexer, skipping...");
}
}
}

58
src/torrent_client/mod.rs Normal file
View File

@ -0,0 +1,58 @@
use std::ops::{Deref, DerefMut};
use abstracttorrent::{client::qbittorrent, torrent::TorrentInfo, common::GetTorrentListParams};
use crate::config::Config;
pub struct TorrentClient {
client: Box<dyn abstracttorrent::client::TorrentClient + Send + Sync>,
}
impl TorrentClient {
pub fn from_config(config: &Config) -> Self {
// TODO: figure out which client to use if multiple are specified.
if let Some(qbittorrent) = &config.qbittorrent {
TorrentClient {
client: Box::new(qbittorrent::client::QBittorrentClient::new())
}
} else {
panic!("Invalid config!");
}
}
pub async fn login(&mut self, config: &Config) -> abstracttorrent::client::ClientResult<()> {
let (url, username, password) = match &config.qbittorrent {
Some(qb) => {
(&qb.url, &qb.username, &qb.password)
},
None => {
panic!("Invalid config!");
}
};
self.client.login(&url, username, password).await
}
/* pub fn login_with_config(&self, config: &Config) -> abstracttorrent::client::ClientResult<()> {
self.login(url, username, password)
} */
pub async fn get_torrent_info(&self, torrent: &lava_torrent::torrent::v1::Torrent) -> abstracttorrent::client::ClientResult<Option<TorrentInfo>> {
let params = GetTorrentListParams::builder()
.hash(&torrent.info_hash())
.build();
let results = self.client.get_torrent_list(Some(params)).await?;
Ok(results.first().cloned())
}
}
impl Deref for TorrentClient {
type Target = Box<dyn abstracttorrent::client::TorrentClient + Send + Sync>;
fn deref(&self) -> &Self::Target { &self.client }
}
impl DerefMut for TorrentClient {
fn deref_mut(&mut self) -> &mut Box<dyn abstracttorrent::client::TorrentClient + Send + Sync> { &mut self.client }
}