Skip to main content

autopulse_service/settings/triggers/
readarr.rs

1use crate::settings::path_filter::PathFilter;
2use crate::settings::rewrite::Rewrite;
3use crate::settings::timer::{EventTimers, Timer};
4use crate::settings::triggers::{TriggerConfig, TriggerRequest};
5use serde::{Deserialize, Serialize};
6
7#[derive(Serialize, Deserialize, Clone)]
8pub struct Readarr {
9    /// Rewrite path
10    pub rewrite: Option<Rewrite>,
11    /// Timer settings
12    pub timer: Option<Timer>,
13    /// Targets to ignore
14    #[serde(default)]
15    pub excludes: Vec<String>,
16    /// Path filter matched against the rewritten file path.
17    #[serde(default)]
18    pub filter: PathFilter,
19    /// Event-specific timers
20    pub event_timers: Option<EventTimers>,
21}
22
23impl TriggerConfig for Readarr {
24    fn rewrite(&self) -> Option<&Rewrite> {
25        self.rewrite.as_ref()
26    }
27
28    fn timer(&self) -> Option<&Timer> {
29        self.timer.as_ref()
30    }
31
32    fn excludes(&self) -> &Vec<String> {
33        &self.excludes
34    }
35
36    fn filter(&self) -> &PathFilter {
37        &self.filter
38    }
39
40    fn event_timers(&self) -> Option<&EventTimers> {
41        self.event_timers.as_ref()
42    }
43}
44
45#[derive(Deserialize, Clone)]
46#[serde(rename_all = "camelCase")]
47#[doc(hidden)]
48pub struct BookFile {
49    path: String,
50}
51
52#[derive(Deserialize, Clone)]
53#[serde(rename_all = "camelCase")]
54#[doc(hidden)]
55pub struct RenamedBookFile {
56    path: String,
57    previous_path: String,
58}
59
60#[derive(Deserialize, Clone)]
61#[serde(rename_all = "camelCase")]
62#[doc(hidden)]
63pub struct Author {
64    path: String,
65}
66
67// Based on https://github.com/Readarr/Readarr/blob/develop/src/NzbDrone.Core/Notifications/Webhook/WebhookBase.cs
68#[derive(Deserialize, Clone)]
69#[serde(tag = "eventType")]
70#[doc(hidden)]
71pub enum ReadarrRequest {
72    #[serde(rename = "Download")]
73    #[serde(rename_all = "camelCase")]
74    Download { book_files: Vec<BookFile> },
75    #[serde(rename = "Rename")]
76    #[serde(rename_all = "camelCase")]
77    Rename {
78        renamed_book_files: Vec<RenamedBookFile>,
79    },
80    #[serde(rename = "AuthorDelete")]
81    #[serde(rename_all = "camelCase")]
82    AuthorDelete { author: Author },
83    #[serde(rename = "BookDelete")]
84    #[serde(rename_all = "camelCase")]
85    BookDelete { author: Author },
86    #[serde(rename = "BookFileDelete")]
87    #[serde(rename_all = "camelCase")]
88    BookFileDelete { book_file: BookFile },
89    #[serde(rename = "Test")]
90    Test,
91    #[serde(other)]
92    Other,
93}
94
95impl TriggerRequest for ReadarrRequest {
96    fn from_json(json: serde_json::Value) -> anyhow::Result<Self> {
97        serde_json::from_value(json).map_err(|e| anyhow::anyhow!(e))
98    }
99    fn paths(&self) -> Vec<(String, bool)> {
100        match self {
101            Self::Download { book_files } => book_files
102                .iter()
103                .map(|book_file| (book_file.path.clone(), true))
104                .collect(),
105            Self::Rename { renamed_book_files } => {
106                let mut paths = vec![];
107
108                for file in renamed_book_files {
109                    paths.push((file.previous_path.clone(), false));
110                    paths.push((file.path.clone(), true));
111                }
112
113                paths
114            }
115            Self::AuthorDelete { author } | Self::BookDelete { author } => {
116                vec![(author.path.clone(), false)]
117            }
118            Self::BookFileDelete { book_file } => {
119                vec![(book_file.path.clone(), false)]
120            }
121            Self::Test | Self::Other => vec![],
122        }
123    }
124}