Skip to main content

autopulse_service/settings/
timer.rs

1use serde::{Deserialize, Serialize};
2use std::collections::HashMap;
3
4#[derive(Serialize, Deserialize, Clone, Default)]
5pub struct Timer {
6    /// Time to wait before processing
7    pub wait: Option<u64>,
8}
9
10impl Timer {
11    pub fn chain(&self, link: &Self) -> Self {
12        Self {
13            wait: match (self.wait, link.wait) {
14                (Some(a), Some(b)) => Some(a + b),
15                (Some(a), None) => Some(a),
16                (None, Some(b)) => Some(b),
17                (None, None) => None,
18            },
19        }
20    }
21}
22
23/// Event timers
24///
25/// Define timers that apply to only specific events
26///
27/// Note: Keys are case insensitive
28///
29/// -rr events:
30/// - `Download` - when a download is completed
31/// - `Rename` - when a file is renamed
32///
33/// Lidarr:
34/// - `ArtistDelete` - when an artist is deleted
35///
36/// Radarr:
37/// - `MovieDelete` - when a movie is deleted
38/// - `MovieFileDelete` - when a movie file is deleted
39///
40/// Readarr:
41/// - `AuthorDelete` - when an author is deleted
42/// - `BookDelete` - when a book is deleted
43/// - `BookFileDelete` - when a book file is deleted
44///
45/// Sonarr:
46/// - `SeriesDelete` - when a series is deleted
47/// - `EpisodeFileDelete` - when an episode file is deleted
48///
49/// **Note: These timers apply on top of the original timer**
50///
51/// Example:
52/// ```yaml
53/// event_timers:
54///   download:
55///     wait: 10
56///   
57///   seriesdelete:
58///     wait: 5
59///
60///   EpisodeFileDelete:
61///     wait: 2
62/// ```
63#[derive(Serialize, Clone, Default)]
64pub struct EventTimers {
65    timers: HashMap<String, Timer>,
66}
67
68impl EventTimers {
69    pub fn get(&self, event_name: &str) -> Option<&Timer> {
70        self.timers.get(event_name.to_lowercase().as_str())
71    }
72}
73
74impl<'de> Deserialize<'de> for EventTimers {
75    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
76    where
77        D: serde::Deserializer<'de>,
78    {
79        let map: HashMap<String, Timer> = HashMap::deserialize(deserializer)?;
80
81        Ok(Self {
82            timers: map
83                .into_iter()
84                .map(|(k, v)| (k.to_lowercase(), v))
85                .collect(),
86        })
87    }
88}
89
90#[cfg(test)]
91mod tests {
92    use super::*;
93
94    #[test]
95    fn test_timer_chain() {
96        let timer1 = Timer { wait: Some(10) };
97        let timer2 = Timer { wait: Some(5) };
98        let chained_timer = timer1.chain(&timer2);
99
100        assert_eq!(chained_timer.wait, Some(15));
101    }
102
103    #[test]
104    fn test_timer_chain_none_self() {
105        let timer1 = Timer { wait: None };
106        let timer2 = Timer { wait: Some(5) };
107        let chained = timer1.chain(&timer2);
108        assert_eq!(chained.wait, Some(5));
109    }
110
111    #[test]
112    fn test_timer_chain_none_link() {
113        let timer1 = Timer { wait: Some(10) };
114        let timer2 = Timer { wait: None };
115        let chained = timer1.chain(&timer2);
116        assert_eq!(chained.wait, Some(10));
117    }
118
119    #[test]
120    fn test_timer_chain_both_none() {
121        let timer1 = Timer { wait: None };
122        let timer2 = Timer { wait: None };
123        let chained = timer1.chain(&timer2);
124        assert_eq!(chained.wait, None);
125    }
126
127    #[test]
128    fn test_event_timers_get() {
129        let mut event_timers = EventTimers {
130            timers: HashMap::new(),
131        };
132
133        event_timers
134            .timers
135            .insert("download".to_string(), Timer { wait: Some(10) });
136
137        assert_eq!(event_timers.get("download").unwrap().wait, Some(10));
138        assert!(event_timers.get("unknown").is_none());
139    }
140}