autopulse_service/settings/targets/
tdarr.rs1use crate::settings::path_filter::PathFilter;
2use crate::settings::rewrite::Rewrite;
3use crate::settings::targets::TargetProcess;
4use autopulse_database::models::ScanEvent;
5use autopulse_utils::get_url;
6use serde::{Deserialize, Serialize};
7
8use super::{Request, RequestBuilderPerform};
9
10#[derive(Serialize, Deserialize, Clone)]
11pub struct Tdarr {
12 pub url: String,
14 pub db_id: String,
16 pub rewrite: Option<Rewrite>,
18 #[serde(default)]
20 pub filter: PathFilter,
21 #[serde(default)]
23 pub request: Request,
24}
25
26#[derive(Serialize)]
27#[serde(rename_all = "camelCase")]
28#[doc(hidden)]
29struct ScanConfig {
30 #[serde(rename = "dbID")]
31 db_id: String,
32 array_or_path: Vec<String>,
33 mode: String,
34}
35
36#[derive(Serialize)]
37#[serde(rename_all = "camelCase")]
38#[doc(hidden)]
39struct Data {
40 scan_config: ScanConfig,
41}
42
43#[derive(Serialize)]
44#[serde(rename_all = "camelCase")]
45#[doc(hidden)]
46struct Payload {
47 data: Data,
48}
49
50impl Tdarr {
51 fn get_client(&self) -> anyhow::Result<reqwest::Client> {
52 self.request
53 .client_builder(reqwest::header::HeaderMap::new())
54 .build()
55 .map_err(Into::into)
56 }
57
58 async fn scan(&self, evs: &[&ScanEvent]) -> anyhow::Result<()> {
59 let client = self.get_client()?;
60
61 let payload = Payload {
62 data: Data {
63 scan_config: ScanConfig {
64 db_id: self.db_id.clone(),
65 array_or_path: evs.iter().map(|ev| ev.get_path(&self.rewrite)).collect(),
66 mode: "scanFolderWatcher".to_string(),
67 },
68 },
69 };
70
71 let url = get_url(&self.url)?.join("/api/v2/scan-files")?;
72
73 client
74 .post(url)
75 .header("content-type", "application/json")
76 .json(&payload)
77 .perform()
78 .await
79 .map(|_| ())
80 }
81}
82
83impl TargetProcess for Tdarr {
84 async fn process(&self, evs: &[&ScanEvent]) -> anyhow::Result<Vec<String>> {
85 let mut succeeded = Vec::new();
86
87 self.scan(evs).await?;
88
89 succeeded.extend(evs.iter().map(|ev| ev.id.clone()));
90
91 Ok(succeeded)
92 }
93}