Fix all cargo clippy warnings across the workspace
Some checks failed
check / check (push) Failing after 53s
Some checks failed
check / check (push) Failing after 53s
Removes genuinely dead code (unused import, no-op cast, an unused PendingGrab accessor, and TmdbClient's TV-search methods now that TVDB fully covers that path), tightens len()>0 checks to is_empty(), swaps two fixed-size test vec!s for arrays, restructures a match to avoid an unnecessary unwrap_err, fixes doc-comment list indentation, and hoists a locked-connection call out of a match scrutinee. Struct fields/enum variants that are still meaningful but not read by current callers (TorrentInfo::save_path, GrabCycleStats::items_seen, X1337 fallback route, BacklogCandidate::path) get #[allow(dead_code)] rather than deletion, same for the two 8-argument functions (too_many_arguments).
This commit is contained in:
parent
471ca884a6
commit
5543485976
9 changed files with 32 additions and 106 deletions
|
|
@ -598,7 +598,7 @@ impl App {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let (media_item_id, season_number, monitored) =
|
let (media_item_id, season_number, monitored) =
|
||||||
(detail.id, episode.season_number as i64, episode.monitored);
|
(detail.id, episode.season_number, episode.monitored);
|
||||||
let result = if monitored {
|
let result = if monitored {
|
||||||
self.client
|
self.client
|
||||||
.unmonitor_season(media_item_id, season_number)
|
.unmonitor_season(media_item_id, season_number)
|
||||||
|
|
|
||||||
|
|
@ -99,14 +99,6 @@ impl PendingGrab {
|
||||||
PendingGrab::Movie { .. } | PendingGrab::SeasonPack { .. } => None,
|
PendingGrab::Movie { .. } | PendingGrab::SeasonPack { .. } => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn root_folder(&self) -> &str {
|
|
||||||
match self {
|
|
||||||
PendingGrab::Episode { root_folder, .. }
|
|
||||||
| PendingGrab::Movie { root_folder, .. }
|
|
||||||
| PendingGrab::SeasonPack { root_folder, .. } => root_folder,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Three separate queries (rather than one `LEFT JOIN episode`) because a
|
/// Three separate queries (rather than one `LEFT JOIN episode`) because a
|
||||||
|
|
@ -1615,7 +1607,7 @@ impl StaleFile {
|
||||||
/// later step (free-space check, the actual move) fails, so a failed
|
/// later step (free-space check, the actual move) fails, so a failed
|
||||||
/// import never leaves neither the old file nor the new one behind.
|
/// import never leaves neither the old file nor the new one behind.
|
||||||
fn restore(&self) {
|
fn restore(&self) {
|
||||||
if self.parked_at.as_os_str().len() > 0 {
|
if !self.parked_at.as_os_str().is_empty() {
|
||||||
std::fs::rename(&self.parked_at, &self.restore_to).ok();
|
std::fs::rename(&self.parked_at, &self.restore_to).ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1909,7 +1901,7 @@ fn import_one(
|
||||||
if let Some(row_id) = stale.row_id {
|
if let Some(row_id) = stale.row_id {
|
||||||
conn.execute("DELETE FROM episode_file WHERE id = ?1", params![row_id])?;
|
conn.execute("DELETE FROM episode_file WHERE id = ?1", params![row_id])?;
|
||||||
}
|
}
|
||||||
if stale.parked_at.as_os_str().len() > 0 {
|
if !stale.parked_at.as_os_str().is_empty() {
|
||||||
std::fs::remove_file(&stale.parked_at).ok();
|
std::fs::remove_file(&stale.parked_at).ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2309,7 +2301,7 @@ fn import_season_pack_file(
|
||||||
if let Some(row_id) = stale.row_id {
|
if let Some(row_id) = stale.row_id {
|
||||||
conn.execute("DELETE FROM episode_file WHERE id = ?1", params![row_id])?;
|
conn.execute("DELETE FROM episode_file WHERE id = ?1", params![row_id])?;
|
||||||
}
|
}
|
||||||
if stale.parked_at.as_os_str().len() > 0 {
|
if !stale.parked_at.as_os_str().is_empty() {
|
||||||
std::fs::remove_file(&stale.parked_at).ok();
|
std::fs::remove_file(&stale.parked_at).ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -633,10 +633,11 @@ async fn background_loop(
|
||||||
// repaired (a rename or an in-place transcode) gets re-probed
|
// repaired (a rename or an in-place transcode) gets re-probed
|
||||||
// immediately rather than waiting for its own turn a full
|
// immediately rather than waiting for its own turn a full
|
||||||
// interval later.
|
// interval later.
|
||||||
match {
|
let probe_result = {
|
||||||
let conn = conn.lock().await;
|
let conn = conn.lock().await;
|
||||||
importer::probe_library(&conn)
|
importer::probe_library(&conn)
|
||||||
} {
|
};
|
||||||
|
match probe_result {
|
||||||
Ok(report) if report.probed > 0 || report.failed > 0 => {
|
Ok(report) if report.probed > 0 || report.failed > 0 => {
|
||||||
info!(?report, "media probe sweep complete");
|
info!(?report, "media probe sweep complete");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ pub struct EpisodeInfo {
|
||||||
/// `MutexGuard` across an `.await` point — this convenience wrapper is only
|
/// `MutexGuard` across an `.await` point — this convenience wrapper is only
|
||||||
/// safe for callers with an owned, unshared `Connection` (e.g. the debug
|
/// safe for callers with an owned, unshared `Connection` (e.g. the debug
|
||||||
/// CLI commands).
|
/// CLI commands).
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub async fn add_series(
|
pub async fn add_series(
|
||||||
conn: &Connection,
|
conn: &Connection,
|
||||||
tvdb: &tvdb::TvdbClient,
|
tvdb: &tvdb::TvdbClient,
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
use super::{EpisodeInfo, MovieSearchResult, SeriesSearchResult};
|
use super::MovieSearchResult;
|
||||||
|
|
||||||
pub struct TmdbClient {
|
pub struct TmdbClient {
|
||||||
bearer_token: String,
|
bearer_token: String,
|
||||||
|
|
@ -22,44 +22,6 @@ impl TmdbClient {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn search_tv(&self, query: &str) -> Result<Vec<SeriesSearchResult>> {
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
struct SearchResponse {
|
|
||||||
results: Vec<TvItem>,
|
|
||||||
}
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
struct TvItem {
|
|
||||||
id: u64,
|
|
||||||
name: String,
|
|
||||||
first_air_date: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
let resp: SearchResponse = self
|
|
||||||
.client
|
|
||||||
.get("https://api.themoviedb.org/3/search/tv")
|
|
||||||
.bearer_auth(&self.bearer_token)
|
|
||||||
.query(&[("query", query)])
|
|
||||||
.send()
|
|
||||||
.await
|
|
||||||
.context("tmdb tv search request failed")?
|
|
||||||
.error_for_status()
|
|
||||||
.context("tmdb tv search returned an error status")?
|
|
||||||
.json()
|
|
||||||
.await
|
|
||||||
.context("tmdb tv search response was not valid JSON")?;
|
|
||||||
|
|
||||||
Ok(resp
|
|
||||||
.results
|
|
||||||
.into_iter()
|
|
||||||
.map(|item| SeriesSearchResult {
|
|
||||||
external_id: item.id.to_string(),
|
|
||||||
name: item.name,
|
|
||||||
year: year_from_date(item.first_air_date.as_deref()),
|
|
||||||
aliases: Vec::new(),
|
|
||||||
})
|
|
||||||
.collect())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn search_movie(&self, query: &str) -> Result<Vec<MovieSearchResult>> {
|
pub async fn search_movie(&self, query: &str) -> Result<Vec<MovieSearchResult>> {
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
struct SearchResponse {
|
struct SearchResponse {
|
||||||
|
|
@ -96,48 +58,6 @@ impl TmdbClient {
|
||||||
})
|
})
|
||||||
.collect())
|
.collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn tv_season_episodes(&self, tv_id: u64, season: u32) -> Result<Vec<EpisodeInfo>> {
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
struct SeasonResponse {
|
|
||||||
#[serde(default)]
|
|
||||||
episodes: Vec<EpisodeItem>,
|
|
||||||
}
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
struct EpisodeItem {
|
|
||||||
season_number: u32,
|
|
||||||
episode_number: u32,
|
|
||||||
name: Option<String>,
|
|
||||||
air_date: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
let resp: SeasonResponse = self
|
|
||||||
.client
|
|
||||||
.get(format!(
|
|
||||||
"https://api.themoviedb.org/3/tv/{tv_id}/season/{season}"
|
|
||||||
))
|
|
||||||
.bearer_auth(&self.bearer_token)
|
|
||||||
.send()
|
|
||||||
.await
|
|
||||||
.context("tmdb season request failed")?
|
|
||||||
.error_for_status()
|
|
||||||
.context("tmdb season returned an error status")?
|
|
||||||
.json()
|
|
||||||
.await
|
|
||||||
.context("tmdb season response was not valid JSON")?;
|
|
||||||
|
|
||||||
Ok(resp
|
|
||||||
.episodes
|
|
||||||
.into_iter()
|
|
||||||
.map(|e| EpisodeInfo {
|
|
||||||
season_number: e.season_number,
|
|
||||||
episode_number: e.episode_number,
|
|
||||||
absolute_number: None,
|
|
||||||
title: e.name,
|
|
||||||
air_date: e.air_date,
|
|
||||||
})
|
|
||||||
.collect())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn year_from_date(date: Option<&str>) -> Option<u32> {
|
fn year_from_date(date: Option<&str>) -> Option<u32> {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
use anyhow::Result;
|
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,9 @@ pub struct TorrentInfo {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub state: String,
|
pub state: String,
|
||||||
pub progress: f64,
|
pub progress: f64,
|
||||||
|
// Not read internally today, but kept to mirror qBittorrent's actual API
|
||||||
|
// shape 1:1 — useful in `{:?}` debug logging and cheap to keep in sync.
|
||||||
|
#[allow(dead_code)]
|
||||||
pub save_path: String,
|
pub save_path: String,
|
||||||
/// Full path to the torrent's content (file or directory root) —
|
/// Full path to the torrent's content (file or directory root) —
|
||||||
/// qBittorrent resolves this for us, so importers don't need to guess
|
/// qBittorrent resolves this for us, so importers don't need to guess
|
||||||
|
|
|
||||||
|
|
@ -752,6 +752,10 @@ async fn grab_and_capture_hash(
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct GrabCycleStats {
|
pub struct GrabCycleStats {
|
||||||
|
// Only read via the derived `Debug` (the debug-grab-cycle CLI command
|
||||||
|
// prints the whole struct), which clippy's dead-code analysis doesn't
|
||||||
|
// credit as a read.
|
||||||
|
#[allow(dead_code)]
|
||||||
pub items_seen: usize,
|
pub items_seen: usize,
|
||||||
pub new_items: usize,
|
pub new_items: usize,
|
||||||
pub grabbed: usize,
|
pub grabbed: usize,
|
||||||
|
|
@ -840,8 +844,8 @@ pub async fn run_grab_cycle(
|
||||||
/// outright (TLS/connection error, not a slow response). Also
|
/// outright (TLS/connection error, not a slow response). Also
|
||||||
/// Cloudflare-fronted, so even if connectivity is restored it carries the
|
/// Cloudflare-fronted, so even if connectivity is restored it carries the
|
||||||
/// same risk profile 1337x does.
|
/// same risk profile 1337x does.
|
||||||
/// If revisiting either, re-verify connectivity first — this isn't a
|
/// If revisiting either, re-verify connectivity first — this isn't a
|
||||||
/// permanent architectural decision, just what was true when checked.
|
/// permanent architectural decision, just what was true when checked.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
enum SearchRoute {
|
enum SearchRoute {
|
||||||
/// Primary general-content (movies + non-anime TV) route — a JSON API,
|
/// Primary general-content (movies + non-anime TV) route — a JSON API,
|
||||||
|
|
@ -851,6 +855,7 @@ enum SearchRoute {
|
||||||
/// (not just "no relevant results") — the mirror-rotation/cooldown
|
/// (not just "no relevant results") — the mirror-rotation/cooldown
|
||||||
/// machinery already built for it is real resilience worth keeping,
|
/// machinery already built for it is real resilience worth keeping,
|
||||||
/// just no longer the first choice given TPB's better precision.
|
/// just no longer the first choice given TPB's better precision.
|
||||||
|
#[allow(dead_code)]
|
||||||
X1337,
|
X1337,
|
||||||
NyaaSearch,
|
NyaaSearch,
|
||||||
}
|
}
|
||||||
|
|
@ -1658,17 +1663,17 @@ pub async fn execute_search_targets(
|
||||||
// with, since dedup (`is_seen`/`mark_seen`) and grab records
|
// with, since dedup (`is_seen`/`mark_seen`) and grab records
|
||||||
// are keyed by source id — attributing a 1337x-sourced guid to
|
// are keyed by source id — attributing a 1337x-sourced guid to
|
||||||
// TPB's source id would silently break dedup between the two.
|
// TPB's source id would silently break dedup between the two.
|
||||||
let (fetch_result, result_source_id) =
|
let (fetch_result, result_source_id) = match primary_result {
|
||||||
if primary_result.is_err() && matches!(target.route, SearchRoute::Tpb) {
|
Err(e) if matches!(target.route, SearchRoute::Tpb) => {
|
||||||
tracing::warn!(
|
tracing::warn!(
|
||||||
query = %target.query,
|
query = %target.query,
|
||||||
error = %primary_result.as_ref().unwrap_err(),
|
error = %e,
|
||||||
"TPB search failed, falling back to 1337x"
|
"TPB search failed, falling back to 1337x"
|
||||||
);
|
);
|
||||||
(scrape.fetch(Some(&target.query)).await, scrape_source_id)
|
(scrape.fetch(Some(&target.query)).await, scrape_source_id)
|
||||||
} else {
|
}
|
||||||
(primary_result, primary_id)
|
other => (other, primary_id),
|
||||||
};
|
};
|
||||||
|
|
||||||
match fetch_result {
|
match fetch_result {
|
||||||
Ok(items) => {
|
Ok(items) => {
|
||||||
|
|
@ -2821,7 +2826,7 @@ mod tests {
|
||||||
seeders: Some(500),
|
seeders: Some(500),
|
||||||
leechers: None,
|
leechers: None,
|
||||||
};
|
};
|
||||||
let mut items = vec![episode.clone(), pack.clone()];
|
let mut items = [episode.clone(), pack.clone()];
|
||||||
items.sort_by_key(release_sort_key);
|
items.sort_by_key(release_sort_key);
|
||||||
assert_eq!(items[0].guid, "pack");
|
assert_eq!(items[0].guid, "pack");
|
||||||
assert_eq!(items[1].guid, "episode");
|
assert_eq!(items[1].guid, "episode");
|
||||||
|
|
@ -2845,7 +2850,7 @@ mod tests {
|
||||||
seeders: Some(50),
|
seeders: Some(50),
|
||||||
leechers: None,
|
leechers: None,
|
||||||
};
|
};
|
||||||
let mut items = vec![low.clone(), high.clone()];
|
let mut items = [low.clone(), high.clone()];
|
||||||
items.sort_by_key(release_sort_key);
|
items.sort_by_key(release_sort_key);
|
||||||
assert_eq!(items[0].guid, "high");
|
assert_eq!(items[0].guid, "high");
|
||||||
assert_eq!(items[1].guid, "low");
|
assert_eq!(items[1].guid, "low");
|
||||||
|
|
|
||||||
|
|
@ -337,6 +337,7 @@ enum EncodeOutcome {
|
||||||
/// original on most of a real backfill — regardless of how well-tuned the
|
/// original on most of a real backfill — regardless of how well-tuned the
|
||||||
/// rate control is, this is what makes "never keep a non-improvement" true
|
/// rate control is, this is what makes "never keep a non-improvement" true
|
||||||
/// unconditionally.
|
/// unconditionally.
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
fn encode_and_verify(
|
fn encode_and_verify(
|
||||||
input: PathBuf,
|
input: PathBuf,
|
||||||
job_id: i64,
|
job_id: i64,
|
||||||
|
|
@ -726,6 +727,10 @@ pub fn find_oversized_av1_candidates(conn: &Connection, cfg: &TranscodeConfig) -
|
||||||
|
|
||||||
pub struct BacklogCandidate {
|
pub struct BacklogCandidate {
|
||||||
pub episode_file_id: i64,
|
pub episode_file_id: i64,
|
||||||
|
// Not read by current callers (they only need episode_file_id to look up
|
||||||
|
// the row again), but cheap to carry along for future logging/debugging
|
||||||
|
// of which file a candidate refers to.
|
||||||
|
#[allow(dead_code)]
|
||||||
pub path: String,
|
pub path: String,
|
||||||
pub size_bytes: i64,
|
pub size_bytes: i64,
|
||||||
pub video_codec: Option<String>,
|
pub video_codec: Option<String>,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue