breadarr/breadarrd/src/notify.rs
Breadway 5543485976
Some checks failed
check / check (push) Failing after 53s
Fix all cargo clippy warnings across the workspace
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).
2026-08-06 08:51:07 +08:00

69 lines
2.1 KiB
Rust

use serde::Serialize;
#[derive(Serialize)]
struct Payload<'a> {
title: &'a str,
message: &'a str,
}
/// Best-effort push notification — failures are logged, never propagated.
/// The events this fires for (a review-queue item, a run of import
/// failures, the search loop halting) already have a durable home in
/// `event_history`/the TUI; the notification is a convenience nudge on top
/// of that, not the record of truth, so it should never be able to fail an
/// otherwise-successful grab/import/search cycle.
pub struct Notifier {
client: reqwest::Client,
webhook_url: String,
}
impl Notifier {
/// Returns `None` when `webhook_url` is empty — callers hold an
/// `Option<Notifier>` and simply skip notifying rather than every call
/// site needing its own empty-string check.
pub fn new(webhook_url: &str) -> Option<Self> {
if webhook_url.is_empty() {
return None;
}
Some(Self {
client: reqwest::Client::builder()
.timeout(std::time::Duration::from_secs(10))
.build()
.expect("reqwest client build"),
webhook_url: webhook_url.to_string(),
})
}
pub async fn send(&self, title: &str, message: &str) {
let result = self
.client
.post(&self.webhook_url)
.json(&Payload { title, message })
.send()
.await;
match result {
Ok(resp) if !resp.status().is_success() => {
tracing::warn!(status = %resp.status(), "notification webhook returned an error status");
}
Err(e) => {
tracing::warn!(error = %e, "notification webhook request failed");
}
Ok(_) => {}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn new_returns_none_for_an_empty_url() {
assert!(Notifier::new("").is_none());
}
#[test]
fn new_returns_some_for_a_configured_url() {
assert!(Notifier::new("http://localhost:5600/message?token=x").is_some());
}
}