ab4f95b166
qBittorrent's add call answers `Ok.` and nothing else — no hash, no name, no duplicate signal — so arr derives the v1 infohash from the magnet or the `.torrent` bytes before the call and looks the torrent up by it. That also drops Transmission's numeric torrent id: the hash is the only identity now. The reaper needs "stopped because a share limit was reached", and qBittorrent's state field cannot tell that apart from a hand-paused torrent. So the ratio and idle counters are checked against the limits arr set, and a torrent stopped by a global limit reads as still seeding rather than being deleted. The WebUI needs a login, so `ARR_QBITTORRENT_USERNAME` and `ARR_QBITTORRENT_PASSWORD` join the env-only secrets; leaving both unset is valid for an instance that whitelists arr's subnet. Verified against qBittorrent 5 (WebAPI 2.15.1) in a container: it rejects `setShareLimits` without `shareLimitAction`, which 4.x ignores, so it is always sent. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
76 lines
2.1 KiB
TOML
76 lines
2.1 KiB
TOML
[workspace]
|
|
resolver = "2"
|
|
members = ["crates/*"]
|
|
|
|
[workspace.package]
|
|
version = "0.1.0"
|
|
edition = "2021"
|
|
license = "MIT"
|
|
repository = "https://git.naps.pt/yolo/arr"
|
|
publish = false
|
|
|
|
[workspace.dependencies]
|
|
# Internal
|
|
arr-api = { path = "crates/arr-api" }
|
|
arr-compat = { path = "crates/arr-compat" }
|
|
arr-core = { path = "crates/arr-core" }
|
|
arr-db = { path = "crates/arr-db" }
|
|
arr-dl = { path = "crates/arr-dl" }
|
|
arr-indexer = { path = "crates/arr-indexer" }
|
|
arr-meta = { path = "crates/arr-meta" }
|
|
arr-parse = { path = "crates/arr-parse" }
|
|
arr-probe = { path = "crates/arr-probe" }
|
|
arr-subs = { path = "crates/arr-subs" }
|
|
|
|
# Runtime and HTTP
|
|
axum = "0.8"
|
|
tokio = { version = "1", features = ["macros", "rt-multi-thread", "sync", "time", "net", "io-util", "fs", "signal", "process"] }
|
|
tower-http = { version = "0.6", features = ["trace"] }
|
|
reqwest = { version = "0.12", default-features = false, features = ["json", "multipart", "rustls-tls"] }
|
|
|
|
# Persistence
|
|
sqlx = { version = "0.9", default-features = false, features = ["runtime-tokio", "sqlite", "macros", "migrate", "chrono", "json"] }
|
|
|
|
# API surface
|
|
utoipa = { version = "5", features = ["axum_extras", "chrono"] }
|
|
utoipa-axum = "0.2"
|
|
utoipa-scalar = { version = "0.3", features = ["axum"] }
|
|
|
|
# Embedded frontend
|
|
include_dir = "0.7"
|
|
mime_guess = "2"
|
|
|
|
# Serialisation
|
|
serde = { version = "1", features = ["derive"] }
|
|
serde_json = "1"
|
|
quick-xml = { version = "0.37", features = ["serialize"] }
|
|
toml = "0.8"
|
|
|
|
# Odds and ends
|
|
chardetng = "1"
|
|
chrono = { version = "0.4", default-features = false, features = ["clock", "serde"] }
|
|
clap = { version = "4.5", features = ["derive", "env"] }
|
|
encoding_rs = "0.8"
|
|
sha1 = "0.10"
|
|
thiserror = "2"
|
|
tracing = "0.1"
|
|
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
|
url = "2"
|
|
uuid = { version = "1", features = ["v4", "serde"] }
|
|
|
|
# Test-only
|
|
tempfile = "3"
|
|
wiremock = "0.6"
|
|
|
|
[workspace.lints.rust]
|
|
unused_crate_dependencies = "warn"
|
|
missing_debug_implementations = "warn"
|
|
|
|
[workspace.lints.clippy]
|
|
pedantic = { level = "warn", priority = -1 }
|
|
unwrap_used = "warn"
|
|
|
|
[profile.release]
|
|
lto = "thin"
|
|
codegen-units = 1
|