Added the full Radarr CLI so users can programmatically access all the same management features as in the TUI
This commit is contained in:
+60
-20
@@ -1,11 +1,11 @@
|
||||
use std::cell::RefCell;
|
||||
use std::fmt::{Debug, Display, Formatter};
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock;
|
||||
use radarr_models::RadarrSerdeable;
|
||||
use regex::Regex;
|
||||
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
|
||||
use serde_json::Number;
|
||||
|
||||
pub mod radarr_models;
|
||||
pub mod servarr_data;
|
||||
pub mod stateful_list;
|
||||
@@ -29,6 +29,12 @@ pub enum Route {
|
||||
Tautulli,
|
||||
}
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)]
|
||||
#[serde(untagged)]
|
||||
pub enum Serdeable {
|
||||
Radarr(RadarrSerdeable),
|
||||
}
|
||||
|
||||
pub trait Scrollable {
|
||||
fn scroll_down(&mut self);
|
||||
fn scroll_up(&mut self);
|
||||
@@ -88,19 +94,42 @@ impl Scrollable for ScrollableText {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Deserialize, Debug, Clone, PartialEq, Eq)]
|
||||
#[derive(Default, Deserialize, Debug)]
|
||||
#[serde(from = "String")]
|
||||
pub struct HorizontallyScrollableText {
|
||||
pub text: String,
|
||||
pub offset: RefCell<usize>,
|
||||
pub offset: AtomicUsize,
|
||||
}
|
||||
|
||||
impl Clone for HorizontallyScrollableText {
|
||||
fn clone(&self) -> Self {
|
||||
HorizontallyScrollableText {
|
||||
text: self.text.clone(),
|
||||
offset: AtomicUsize::new(self.offset.load(Ordering::SeqCst)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for HorizontallyScrollableText {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.text == other.text
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for HorizontallyScrollableText {}
|
||||
|
||||
impl From<String> for HorizontallyScrollableText {
|
||||
fn from(text: String) -> HorizontallyScrollableText {
|
||||
HorizontallyScrollableText::new(text)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&String> for HorizontallyScrollableText {
|
||||
fn from(text: &String) -> HorizontallyScrollableText {
|
||||
HorizontallyScrollableText::new(text.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for HorizontallyScrollableText {
|
||||
fn from(text: &str) -> HorizontallyScrollableText {
|
||||
HorizontallyScrollableText::new(text.to_owned())
|
||||
@@ -109,14 +138,14 @@ impl From<&str> for HorizontallyScrollableText {
|
||||
|
||||
impl Display for HorizontallyScrollableText {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
if *self.offset.borrow() == 0 {
|
||||
if self.offset.load(Ordering::SeqCst) == 0 {
|
||||
write!(f, "{}", self.text)
|
||||
} else {
|
||||
let text_vec = self.text.chars().collect::<Vec<_>>();
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
text_vec[*self.offset.borrow()..]
|
||||
text_vec[self.offset.load(Ordering::SeqCst)..]
|
||||
.iter()
|
||||
.cloned()
|
||||
.collect::<String>()
|
||||
@@ -138,7 +167,7 @@ impl HorizontallyScrollableText {
|
||||
pub fn new(text: String) -> HorizontallyScrollableText {
|
||||
HorizontallyScrollableText {
|
||||
text,
|
||||
offset: RefCell::new(0),
|
||||
offset: AtomicUsize::new(0),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,46 +176,44 @@ impl HorizontallyScrollableText {
|
||||
}
|
||||
|
||||
pub fn scroll_left(&self) {
|
||||
if *self.offset.borrow() < self.len() {
|
||||
let new_offset = *self.offset.borrow() + 1;
|
||||
*self.offset.borrow_mut() = new_offset;
|
||||
if self.offset.load(Ordering::SeqCst) < self.len() {
|
||||
self.offset.fetch_add(1, Ordering::SeqCst);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn scroll_right(&self) {
|
||||
if *self.offset.borrow() > 0 {
|
||||
let new_offset = *self.offset.borrow() - 1;
|
||||
*self.offset.borrow_mut() = new_offset;
|
||||
if self.offset.load(Ordering::SeqCst) > 0 {
|
||||
self.offset.fetch_sub(1, Ordering::SeqCst);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn scroll_home(&self) {
|
||||
*self.offset.borrow_mut() = self.len();
|
||||
self.offset.store(self.len(), Ordering::SeqCst);
|
||||
}
|
||||
|
||||
pub fn reset_offset(&self) {
|
||||
*self.offset.borrow_mut() = 0;
|
||||
self.offset.store(0, Ordering::SeqCst);
|
||||
}
|
||||
|
||||
pub fn scroll_left_or_reset(&self, width: usize, is_current_selection: bool, can_scroll: bool) {
|
||||
if can_scroll && is_current_selection && self.len() >= width {
|
||||
if *self.offset.borrow() < self.len() {
|
||||
if self.offset.load(Ordering::SeqCst) < self.len() {
|
||||
self.scroll_left();
|
||||
} else {
|
||||
self.reset_offset();
|
||||
}
|
||||
} else if *self.offset.borrow() != 0 && !is_current_selection {
|
||||
} else if self.offset.load(Ordering::SeqCst) != 0 && !is_current_selection {
|
||||
self.reset_offset();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pop(&mut self) {
|
||||
if *self.offset.borrow() < self.len() {
|
||||
if self.offset.load(Ordering::SeqCst) < self.len() {
|
||||
let (index, _) = self
|
||||
.text
|
||||
.chars()
|
||||
.enumerate()
|
||||
.nth(self.len() - *self.offset.borrow() - 1)
|
||||
.nth(self.len() - self.offset.load(Ordering::SeqCst) - 1)
|
||||
.unwrap();
|
||||
self.text = self
|
||||
.text
|
||||
@@ -202,7 +229,7 @@ impl HorizontallyScrollableText {
|
||||
if self.text.is_empty() {
|
||||
self.text.push(character);
|
||||
} else {
|
||||
let index = self.len() - *self.offset.borrow();
|
||||
let index = self.len() - self.offset.load(Ordering::SeqCst);
|
||||
|
||||
if index == self.len() {
|
||||
self.text.push(character);
|
||||
@@ -338,3 +365,16 @@ pub fn strip_non_search_characters(input: &str) -> String {
|
||||
.replace_all(&input.to_lowercase(), "")
|
||||
.to_string()
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! serde_enum_from {
|
||||
($enum_name:ident { $($variant:ident($ty:ty),)* }) => {
|
||||
$(
|
||||
impl From<$ty> for $enum_name {
|
||||
fn from(value: $ty) -> Self {
|
||||
$enum_name::$variant(value)
|
||||
}
|
||||
}
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
+151
-40
@@ -1,6 +1,7 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::cell::RefCell;
|
||||
use std::sync::atomic::AtomicUsize;
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
use pretty_assertions::{assert_eq, assert_str_eq};
|
||||
use serde::de::value::Error as ValueError;
|
||||
@@ -100,7 +101,22 @@ mod tests {
|
||||
let test_text = "Test string";
|
||||
let horizontally_scrollable_text = HorizontallyScrollableText::from(test_text.to_owned());
|
||||
|
||||
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0);
|
||||
assert_eq!(
|
||||
horizontally_scrollable_text.offset.load(Ordering::SeqCst),
|
||||
0
|
||||
);
|
||||
assert_str_eq!(horizontally_scrollable_text.text, test_text);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_horizontally_scrollable_text_from_string_ref() {
|
||||
let test_text = "Test string".to_owned();
|
||||
let horizontally_scrollable_text = HorizontallyScrollableText::from(&test_text);
|
||||
|
||||
assert_eq!(
|
||||
horizontally_scrollable_text.offset.load(Ordering::SeqCst),
|
||||
0
|
||||
);
|
||||
assert_str_eq!(horizontally_scrollable_text.text, test_text);
|
||||
}
|
||||
|
||||
@@ -109,7 +125,10 @@ mod tests {
|
||||
let test_text = "Test string";
|
||||
let horizontally_scrollable_text = HorizontallyScrollableText::from(test_text);
|
||||
|
||||
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0);
|
||||
assert_eq!(
|
||||
horizontally_scrollable_text.offset.load(Ordering::SeqCst),
|
||||
0
|
||||
);
|
||||
assert_str_eq!(horizontally_scrollable_text.text, test_text);
|
||||
}
|
||||
|
||||
@@ -122,14 +141,14 @@ mod tests {
|
||||
|
||||
let horizontally_scrollable_text = HorizontallyScrollableText {
|
||||
text: test_text.to_owned(),
|
||||
offset: RefCell::new(test_text.len() - 1),
|
||||
offset: AtomicUsize::new(test_text.len() - 1),
|
||||
};
|
||||
|
||||
assert_str_eq!(horizontally_scrollable_text.to_string(), "g");
|
||||
|
||||
let horizontally_scrollable_text = HorizontallyScrollableText {
|
||||
text: test_text.to_owned(),
|
||||
offset: RefCell::new(test_text.len()),
|
||||
offset: AtomicUsize::new(test_text.len()),
|
||||
};
|
||||
|
||||
assert!(horizontally_scrollable_text.to_string().is_empty());
|
||||
@@ -140,7 +159,10 @@ mod tests {
|
||||
let test_text = "Test string";
|
||||
let horizontally_scrollable_text = HorizontallyScrollableText::new(test_text.to_owned());
|
||||
|
||||
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0);
|
||||
assert_eq!(
|
||||
horizontally_scrollable_text.offset.load(Ordering::SeqCst),
|
||||
0
|
||||
);
|
||||
assert_str_eq!(horizontally_scrollable_text.text, test_text);
|
||||
}
|
||||
|
||||
@@ -158,18 +180,24 @@ mod tests {
|
||||
fn test_horizontally_scrollable_text_scroll_text_left() {
|
||||
let horizontally_scrollable_text = HorizontallyScrollableText::from("Test string");
|
||||
|
||||
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0);
|
||||
assert_eq!(
|
||||
horizontally_scrollable_text.offset.load(Ordering::SeqCst),
|
||||
0
|
||||
);
|
||||
|
||||
for i in 1..horizontally_scrollable_text.text.len() - 1 {
|
||||
horizontally_scrollable_text.scroll_left();
|
||||
|
||||
assert_eq!(*horizontally_scrollable_text.offset.borrow(), i);
|
||||
assert_eq!(
|
||||
horizontally_scrollable_text.offset.load(Ordering::SeqCst),
|
||||
i
|
||||
);
|
||||
}
|
||||
|
||||
horizontally_scrollable_text.scroll_left();
|
||||
|
||||
assert_eq!(
|
||||
*horizontally_scrollable_text.offset.borrow(),
|
||||
horizontally_scrollable_text.offset.load(Ordering::SeqCst),
|
||||
horizontally_scrollable_text.text.len() - 1
|
||||
);
|
||||
}
|
||||
@@ -180,37 +208,51 @@ mod tests {
|
||||
|
||||
horizontally_scrollable_text.scroll_left();
|
||||
|
||||
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 1);
|
||||
assert_eq!(
|
||||
horizontally_scrollable_text.offset.load(Ordering::SeqCst),
|
||||
1
|
||||
);
|
||||
assert_str_eq!(horizontally_scrollable_text.to_string(), "리");
|
||||
|
||||
horizontally_scrollable_text.scroll_left();
|
||||
|
||||
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 2);
|
||||
assert_eq!(
|
||||
horizontally_scrollable_text.offset.load(Ordering::SeqCst),
|
||||
2
|
||||
);
|
||||
assert_str_eq!(horizontally_scrollable_text.to_string(), "");
|
||||
|
||||
horizontally_scrollable_text.scroll_left();
|
||||
|
||||
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 2);
|
||||
assert_eq!(
|
||||
horizontally_scrollable_text.offset.load(Ordering::SeqCst),
|
||||
2
|
||||
);
|
||||
assert!(horizontally_scrollable_text.to_string().is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_horizontally_scrollable_text_scroll_text_right() {
|
||||
let horizontally_scrollable_text = HorizontallyScrollableText::from("Test string");
|
||||
*horizontally_scrollable_text.offset.borrow_mut() = horizontally_scrollable_text.text.len();
|
||||
horizontally_scrollable_text
|
||||
.offset
|
||||
.store(horizontally_scrollable_text.len(), Ordering::SeqCst);
|
||||
|
||||
for i in 1..horizontally_scrollable_text.text.len() {
|
||||
horizontally_scrollable_text.scroll_right();
|
||||
|
||||
assert_eq!(
|
||||
*horizontally_scrollable_text.offset.borrow(),
|
||||
horizontally_scrollable_text.offset.load(Ordering::SeqCst),
|
||||
horizontally_scrollable_text.text.len() - i
|
||||
);
|
||||
}
|
||||
|
||||
horizontally_scrollable_text.scroll_right();
|
||||
|
||||
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0);
|
||||
assert_eq!(
|
||||
horizontally_scrollable_text.offset.load(Ordering::SeqCst),
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -220,7 +262,7 @@ mod tests {
|
||||
horizontally_scrollable_text.scroll_home();
|
||||
|
||||
assert_eq!(
|
||||
*horizontally_scrollable_text.offset.borrow(),
|
||||
horizontally_scrollable_text.offset.load(Ordering::SeqCst),
|
||||
horizontally_scrollable_text.text.len()
|
||||
);
|
||||
}
|
||||
@@ -231,19 +273,25 @@ mod tests {
|
||||
|
||||
horizontally_scrollable_text.scroll_home();
|
||||
|
||||
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 2);
|
||||
assert_eq!(
|
||||
horizontally_scrollable_text.offset.load(Ordering::SeqCst),
|
||||
2
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_horizontally_scrollable_text_reset_offset() {
|
||||
let horizontally_scrollable_text = HorizontallyScrollableText {
|
||||
text: "Test string".to_owned(),
|
||||
offset: RefCell::new(1),
|
||||
offset: AtomicUsize::new(1),
|
||||
};
|
||||
|
||||
horizontally_scrollable_text.reset_offset();
|
||||
|
||||
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0);
|
||||
assert_eq!(
|
||||
horizontally_scrollable_text.offset.load(Ordering::SeqCst),
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -254,23 +302,38 @@ mod tests {
|
||||
|
||||
horizontally_scrollable_text.scroll_left_or_reset(width, true, true);
|
||||
|
||||
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 1);
|
||||
assert_eq!(
|
||||
horizontally_scrollable_text.offset.load(Ordering::SeqCst),
|
||||
1
|
||||
);
|
||||
|
||||
horizontally_scrollable_text.scroll_left_or_reset(width, false, true);
|
||||
|
||||
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0);
|
||||
assert_eq!(
|
||||
horizontally_scrollable_text.offset.load(Ordering::SeqCst),
|
||||
0
|
||||
);
|
||||
|
||||
horizontally_scrollable_text.scroll_left_or_reset(width, true, false);
|
||||
|
||||
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0);
|
||||
assert_eq!(
|
||||
horizontally_scrollable_text.offset.load(Ordering::SeqCst),
|
||||
0
|
||||
);
|
||||
|
||||
horizontally_scrollable_text.scroll_left_or_reset(width, true, true);
|
||||
|
||||
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 1);
|
||||
assert_eq!(
|
||||
horizontally_scrollable_text.offset.load(Ordering::SeqCst),
|
||||
1
|
||||
);
|
||||
|
||||
horizontally_scrollable_text.scroll_left_or_reset(test_text.len(), false, true);
|
||||
|
||||
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0);
|
||||
assert_eq!(
|
||||
horizontally_scrollable_text.offset.load(Ordering::SeqCst),
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -278,11 +341,17 @@ mod tests {
|
||||
let horizontally_scrollable_test = HorizontallyScrollableText::from("Test string");
|
||||
horizontally_scrollable_test.scroll_left();
|
||||
|
||||
assert_eq!(*horizontally_scrollable_test.offset.borrow(), 1);
|
||||
assert_eq!(
|
||||
horizontally_scrollable_test.offset.load(Ordering::SeqCst),
|
||||
1
|
||||
);
|
||||
|
||||
horizontally_scrollable_test.scroll_left_or_reset(3, false, false);
|
||||
|
||||
assert_eq!(*horizontally_scrollable_test.offset.borrow(), 0);
|
||||
assert_eq!(
|
||||
horizontally_scrollable_test.offset.load(Ordering::SeqCst),
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -292,15 +361,24 @@ mod tests {
|
||||
|
||||
horizontally_scrollable_text.scroll_left_or_reset(width, true, true);
|
||||
|
||||
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 1);
|
||||
assert_eq!(
|
||||
horizontally_scrollable_text.offset.load(Ordering::SeqCst),
|
||||
1
|
||||
);
|
||||
|
||||
horizontally_scrollable_text.scroll_left_or_reset(width, true, true);
|
||||
|
||||
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 2);
|
||||
assert_eq!(
|
||||
horizontally_scrollable_text.offset.load(Ordering::SeqCst),
|
||||
2
|
||||
);
|
||||
|
||||
horizontally_scrollable_text.scroll_left_or_reset(width, true, true);
|
||||
|
||||
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0);
|
||||
assert_eq!(
|
||||
horizontally_scrollable_text.offset.load(Ordering::SeqCst),
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -310,32 +388,47 @@ mod tests {
|
||||
horizontally_scrollable_text.pop();
|
||||
|
||||
assert_str_eq!(horizontally_scrollable_text.text, "Test sTrin우g");
|
||||
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0);
|
||||
assert_eq!(
|
||||
horizontally_scrollable_text.offset.load(Ordering::SeqCst),
|
||||
0
|
||||
);
|
||||
|
||||
horizontally_scrollable_text.scroll_left();
|
||||
horizontally_scrollable_text.pop();
|
||||
|
||||
assert_str_eq!(horizontally_scrollable_text.text, "Test sTring");
|
||||
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 1);
|
||||
assert_eq!(
|
||||
horizontally_scrollable_text.offset.load(Ordering::SeqCst),
|
||||
1
|
||||
);
|
||||
|
||||
horizontally_scrollable_text.scroll_right();
|
||||
horizontally_scrollable_text.scroll_right();
|
||||
horizontally_scrollable_text.pop();
|
||||
|
||||
assert_str_eq!(horizontally_scrollable_text.text, "Test sTrin");
|
||||
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0);
|
||||
assert_eq!(
|
||||
horizontally_scrollable_text.offset.load(Ordering::SeqCst),
|
||||
0
|
||||
);
|
||||
|
||||
horizontally_scrollable_text.scroll_home();
|
||||
horizontally_scrollable_text.pop();
|
||||
|
||||
assert_str_eq!(horizontally_scrollable_text.text, "Test sTrin");
|
||||
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 10);
|
||||
assert_eq!(
|
||||
horizontally_scrollable_text.offset.load(Ordering::SeqCst),
|
||||
10
|
||||
);
|
||||
|
||||
horizontally_scrollable_text.scroll_right();
|
||||
horizontally_scrollable_text.pop();
|
||||
|
||||
assert_str_eq!(horizontally_scrollable_text.text, "est sTrin");
|
||||
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 9);
|
||||
assert_eq!(
|
||||
horizontally_scrollable_text.offset.load(Ordering::SeqCst),
|
||||
9
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -344,17 +437,26 @@ mod tests {
|
||||
horizontally_scrollable_text.pop();
|
||||
|
||||
assert_str_eq!(horizontally_scrollable_text.text, "우");
|
||||
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0);
|
||||
assert_eq!(
|
||||
horizontally_scrollable_text.offset.load(Ordering::SeqCst),
|
||||
0
|
||||
);
|
||||
|
||||
horizontally_scrollable_text.pop();
|
||||
|
||||
assert!(horizontally_scrollable_text.text.is_empty());
|
||||
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0);
|
||||
assert_eq!(
|
||||
horizontally_scrollable_text.offset.load(Ordering::SeqCst),
|
||||
0
|
||||
);
|
||||
|
||||
horizontally_scrollable_text.pop();
|
||||
|
||||
assert!(horizontally_scrollable_text.text.is_empty());
|
||||
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0);
|
||||
assert_eq!(
|
||||
horizontally_scrollable_text.offset.load(Ordering::SeqCst),
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -364,20 +466,29 @@ mod tests {
|
||||
horizontally_scrollable_text.push('h');
|
||||
|
||||
assert_str_eq!(horizontally_scrollable_text.text, "Test stri우ngh");
|
||||
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0);
|
||||
assert_eq!(
|
||||
horizontally_scrollable_text.offset.load(Ordering::SeqCst),
|
||||
0
|
||||
);
|
||||
|
||||
horizontally_scrollable_text.scroll_left();
|
||||
horizontally_scrollable_text.push('l');
|
||||
|
||||
assert_str_eq!(horizontally_scrollable_text.text, "Test stri우nglh");
|
||||
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 1);
|
||||
assert_eq!(
|
||||
horizontally_scrollable_text.offset.load(Ordering::SeqCst),
|
||||
1
|
||||
);
|
||||
|
||||
horizontally_scrollable_text.scroll_right();
|
||||
horizontally_scrollable_text.scroll_right();
|
||||
horizontally_scrollable_text.push('리');
|
||||
|
||||
assert_str_eq!(horizontally_scrollable_text.text, "Test stri우nglh리");
|
||||
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0);
|
||||
assert_eq!(
|
||||
horizontally_scrollable_text.offset.load(Ordering::SeqCst),
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
+199
-43
@@ -1,18 +1,21 @@
|
||||
use std::fmt::{Display, Formatter};
|
||||
|
||||
use chrono::{DateTime, Utc};
|
||||
use clap::ValueEnum;
|
||||
use derivative::Derivative;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::{Number, Value};
|
||||
use serde_json::{json, Number, Value};
|
||||
use strum_macros::EnumIter;
|
||||
|
||||
use crate::models::HorizontallyScrollableText;
|
||||
use crate::{models::HorizontallyScrollableText, serde_enum_from};
|
||||
|
||||
use super::Serdeable;
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "radarr_models_tests.rs"]
|
||||
mod radarr_models_tests;
|
||||
|
||||
#[derive(Default, Serialize, Debug)]
|
||||
#[derive(Default, Clone, Serialize, Debug, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct AddMovieBody {
|
||||
pub tmdb_id: i64,
|
||||
@@ -25,7 +28,7 @@ pub struct AddMovieBody {
|
||||
pub add_options: AddOptions,
|
||||
}
|
||||
|
||||
#[derive(Derivative, Deserialize, Debug, Default, Clone, PartialEq, Eq)]
|
||||
#[derive(Derivative, Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct AddMovieSearchResult {
|
||||
#[serde(deserialize_with = "super::from_i64")]
|
||||
@@ -42,7 +45,7 @@ pub struct AddMovieSearchResult {
|
||||
pub ratings: RatingsList,
|
||||
}
|
||||
|
||||
#[derive(Default, Serialize, Debug, PartialEq, Eq)]
|
||||
#[derive(Default, Clone, Serialize, Debug, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct AddOptions {
|
||||
pub monitor: String,
|
||||
@@ -54,12 +57,12 @@ pub struct AddRootFolderBody {
|
||||
pub path: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Deserialize, Debug, Clone, PartialEq, Eq)]
|
||||
#[derive(Default, Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
|
||||
pub struct BlocklistResponse {
|
||||
pub records: Vec<BlocklistItem>,
|
||||
}
|
||||
|
||||
#[derive(Default, Deserialize, Debug, Clone, PartialEq, Eq)]
|
||||
#[derive(Default, Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct BlocklistItem {
|
||||
#[serde(deserialize_with = "super::from_i64")]
|
||||
@@ -77,12 +80,12 @@ pub struct BlocklistItem {
|
||||
pub movie: BlocklistItemMovie,
|
||||
}
|
||||
|
||||
#[derive(Default, Deserialize, Debug, Clone, PartialEq, Eq)]
|
||||
#[derive(Default, Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
|
||||
pub struct BlocklistItemMovie {
|
||||
pub title: HorizontallyScrollableText,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Derivative, Default, Clone, Debug, PartialEq, Eq)]
|
||||
#[derive(Serialize, Deserialize, Derivative, Default, Clone, Debug, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Collection {
|
||||
#[serde(deserialize_with = "super::from_i64")]
|
||||
@@ -99,7 +102,7 @@ pub struct Collection {
|
||||
pub movies: Option<Vec<CollectionMovie>>,
|
||||
}
|
||||
|
||||
#[derive(Derivative, Deserialize, Debug, Default, Clone, PartialEq, Eq)]
|
||||
#[derive(Derivative, Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CollectionMovie {
|
||||
pub title: HorizontallyScrollableText,
|
||||
@@ -120,7 +123,7 @@ pub struct CommandBody {
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Default, Clone, Debug, PartialEq, Eq)]
|
||||
#[derive(Serialize, Deserialize, Default, Clone, Debug, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Credit {
|
||||
pub person_name: String,
|
||||
@@ -131,7 +134,7 @@ pub struct Credit {
|
||||
pub credit_type: CreditType,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Default, PartialEq, Eq, Clone, Debug)]
|
||||
#[derive(Serialize, Deserialize, Default, PartialEq, Eq, Clone, Debug)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum CreditType {
|
||||
#[default]
|
||||
@@ -139,7 +142,15 @@ pub enum CreditType {
|
||||
Crew,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone, Eq, PartialEq)]
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub struct DeleteMovieParams {
|
||||
pub id: i64,
|
||||
pub delete_movie_files: bool,
|
||||
pub add_list_exclusion: bool,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct DiskSpace {
|
||||
#[serde(deserialize_with = "super::from_i64")]
|
||||
@@ -148,7 +159,7 @@ pub struct DiskSpace {
|
||||
pub total_space: i64,
|
||||
}
|
||||
|
||||
#[derive(Derivative, Deserialize, Debug, Default, Clone, PartialEq, Eq)]
|
||||
#[derive(Derivative, Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct DownloadRecord {
|
||||
pub title: String,
|
||||
@@ -167,12 +178,51 @@ pub struct DownloadRecord {
|
||||
pub download_client: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Deserialize, Debug)]
|
||||
#[derive(Default, Clone, Serialize, Deserialize, Debug, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct DownloadsResponse {
|
||||
pub records: Vec<DownloadRecord>,
|
||||
}
|
||||
|
||||
#[derive(Default, Clone, Serialize, Debug, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct EditCollectionParams {
|
||||
pub collection_id: i64,
|
||||
pub monitored: Option<bool>,
|
||||
pub minimum_availability: Option<MinimumAvailability>,
|
||||
pub quality_profile_id: Option<i64>,
|
||||
pub root_folder_path: Option<String>,
|
||||
pub search_on_add: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Default, Clone, Serialize, Debug, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct EditIndexerParams {
|
||||
pub indexer_id: i64,
|
||||
pub name: Option<String>,
|
||||
pub enable_rss: Option<bool>,
|
||||
pub enable_automatic_search: Option<bool>,
|
||||
pub enable_interactive_search: Option<bool>,
|
||||
pub url: Option<String>,
|
||||
pub api_key: Option<String>,
|
||||
pub seed_ratio: Option<String>,
|
||||
pub tags: Option<Vec<i64>>,
|
||||
pub priority: Option<i64>,
|
||||
pub clear_tags: bool,
|
||||
}
|
||||
|
||||
#[derive(Default, Clone, Serialize, Debug, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct EditMovieParams {
|
||||
pub movie_id: i64,
|
||||
pub monitored: Option<bool>,
|
||||
pub minimum_availability: Option<MinimumAvailability>,
|
||||
pub quality_profile_id: Option<i64>,
|
||||
pub root_folder_path: Option<String>,
|
||||
pub tags: Option<Vec<i64>>,
|
||||
pub clear_tags: bool,
|
||||
}
|
||||
|
||||
#[derive(Default, Deserialize, Serialize, Debug, Clone, Eq, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Indexer {
|
||||
@@ -223,7 +273,7 @@ pub struct IndexerSettings {
|
||||
pub whitelisted_hardcoded_subs: HorizontallyScrollableText,
|
||||
}
|
||||
|
||||
#[derive(Default, Deserialize, Debug, Clone, PartialEq, Eq)]
|
||||
#[derive(Default, Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct IndexerTestResult {
|
||||
#[serde(deserialize_with = "super::from_i64")]
|
||||
@@ -232,7 +282,7 @@ pub struct IndexerTestResult {
|
||||
pub validation_failures: Vec<IndexerValidationFailure>,
|
||||
}
|
||||
|
||||
#[derive(Default, Deserialize, Debug, Clone, PartialEq, Eq)]
|
||||
#[derive(Default, Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct IndexerValidationFailure {
|
||||
pub property_name: String,
|
||||
@@ -240,12 +290,12 @@ pub struct IndexerValidationFailure {
|
||||
pub severity: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Default, Debug, Clone, PartialEq, Eq, Ord, PartialOrd)]
|
||||
#[derive(Serialize, Deserialize, Default, Debug, Clone, PartialEq, Eq, Ord, PartialOrd)]
|
||||
pub struct Language {
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Deserialize, Clone, Debug, Eq, PartialEq)]
|
||||
#[derive(Default, Serialize, Deserialize, Clone, Debug, Eq, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Log {
|
||||
pub time: DateTime<Utc>,
|
||||
@@ -257,12 +307,12 @@ pub struct Log {
|
||||
pub method: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Default, Deserialize, Debug, Eq, PartialEq)]
|
||||
#[derive(Default, Clone, Serialize, Deserialize, Debug, Eq, PartialEq)]
|
||||
pub struct LogResponse {
|
||||
pub records: Vec<Log>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Derivative, Debug, Clone, PartialEq, Eq)]
|
||||
#[derive(Serialize, Deserialize, Derivative, Debug, Clone, PartialEq, Eq)]
|
||||
#[derivative(Default)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct MediaInfo {
|
||||
@@ -286,7 +336,9 @@ pub struct MediaInfo {
|
||||
pub scan_type: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Default, PartialEq, Eq, Clone, Copy, Debug, EnumIter)]
|
||||
#[derive(
|
||||
Serialize, Deserialize, Default, PartialEq, Eq, Clone, Copy, Debug, EnumIter, ValueEnum,
|
||||
)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub enum MinimumAvailability {
|
||||
#[default]
|
||||
@@ -319,7 +371,7 @@ impl MinimumAvailability {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, PartialEq, Eq, Clone, Copy, Debug, EnumIter)]
|
||||
#[derive(Default, PartialEq, Eq, Clone, Copy, Debug, EnumIter, ValueEnum)]
|
||||
pub enum Monitor {
|
||||
#[default]
|
||||
MovieOnly,
|
||||
@@ -348,7 +400,7 @@ impl Monitor {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Derivative, Deserialize, Debug, Default, Clone, PartialEq, Eq)]
|
||||
#[derive(Derivative, Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Movie {
|
||||
#[serde(deserialize_with = "super::from_i64")]
|
||||
@@ -380,7 +432,7 @@ pub struct Movie {
|
||||
pub collection: Option<MovieCollection>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Default, Debug, Clone, PartialEq, Eq)]
|
||||
#[derive(Serialize, Deserialize, Default, Debug, Clone, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct MovieCollection {
|
||||
pub title: Option<String>,
|
||||
@@ -393,7 +445,7 @@ pub struct MovieCommandBody {
|
||||
pub movie_ids: Vec<i64>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Default, Debug, Clone, PartialEq, Eq)]
|
||||
#[derive(Serialize, Deserialize, Default, Debug, Clone, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct MovieFile {
|
||||
pub relative_path: String,
|
||||
@@ -402,7 +454,7 @@ pub struct MovieFile {
|
||||
pub media_info: Option<MediaInfo>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Default, Debug, Clone, PartialEq, Eq)]
|
||||
#[derive(Serialize, Deserialize, Default, Debug, Clone, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct MovieHistoryItem {
|
||||
pub source_title: HorizontallyScrollableText,
|
||||
@@ -412,24 +464,33 @@ pub struct MovieHistoryItem {
|
||||
pub event_type: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Default, Debug, Clone, PartialEq, Eq, Ord, PartialOrd)]
|
||||
#[derive(Serialize, Deserialize, Default, Debug, Clone, PartialEq, Eq, Ord, PartialOrd)]
|
||||
pub struct Quality {
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Deserialize, Debug)]
|
||||
#[derive(Default, Clone, Serialize, Deserialize, Debug, PartialEq, Eq)]
|
||||
pub struct QualityProfile {
|
||||
#[serde(deserialize_with = "super::from_i64")]
|
||||
pub id: i64,
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Default, Debug, Clone, PartialEq, Eq, Ord, PartialOrd)]
|
||||
impl From<(&i64, &String)> for QualityProfile {
|
||||
fn from(value: (&i64, &String)) -> Self {
|
||||
QualityProfile {
|
||||
id: *value.0,
|
||||
name: value.1.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Default, Debug, Clone, PartialEq, Eq, Ord, PartialOrd)]
|
||||
pub struct QualityWrapper {
|
||||
pub quality: Quality,
|
||||
}
|
||||
|
||||
#[derive(Default, Deserialize, Debug, Clone, PartialEq, Eq)]
|
||||
#[derive(Default, Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct QueueEvent {
|
||||
pub trigger: String,
|
||||
@@ -442,14 +503,14 @@ pub struct QueueEvent {
|
||||
pub duration: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Derivative, Deserialize, Debug, Clone, PartialEq, Eq)]
|
||||
#[derive(Derivative, Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
|
||||
#[derivative(Default)]
|
||||
pub struct Rating {
|
||||
#[derivative(Default(value = "Number::from(0)"))]
|
||||
pub value: Number,
|
||||
}
|
||||
|
||||
#[derive(Default, Deserialize, Debug, Clone, PartialEq, Eq)]
|
||||
#[derive(Default, Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct RatingsList {
|
||||
pub imdb: Option<Rating>,
|
||||
@@ -457,7 +518,7 @@ pub struct RatingsList {
|
||||
pub rotten_tomatoes: Option<Rating>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Default, Clone, Debug, PartialEq, Eq)]
|
||||
#[derive(Serialize, Deserialize, Default, Clone, Debug, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[serde(default)]
|
||||
pub struct Release {
|
||||
@@ -479,7 +540,7 @@ pub struct Release {
|
||||
pub quality: QualityWrapper,
|
||||
}
|
||||
|
||||
#[derive(Default, Serialize, Debug)]
|
||||
#[derive(Default, Serialize, Debug, PartialEq, Eq, Clone)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ReleaseDownloadBody {
|
||||
pub guid: String,
|
||||
@@ -487,7 +548,7 @@ pub struct ReleaseDownloadBody {
|
||||
pub movie_id: i64,
|
||||
}
|
||||
|
||||
#[derive(Default, Deserialize, Debug, Clone, Eq, PartialEq)]
|
||||
#[derive(Default, Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct RootFolder {
|
||||
#[serde(deserialize_with = "super::from_i64")]
|
||||
@@ -499,25 +560,25 @@ pub struct RootFolder {
|
||||
pub unmapped_folders: Option<Vec<UnmappedFolder>>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
#[derive(Default, Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct SystemStatus {
|
||||
pub version: String,
|
||||
pub start_time: DateTime<Utc>,
|
||||
}
|
||||
|
||||
#[derive(Default, Deserialize, Debug)]
|
||||
#[derive(Default, Clone, Serialize, Deserialize, Debug, PartialEq, Eq)]
|
||||
pub struct Tag {
|
||||
#[serde(deserialize_with = "super::from_i64")]
|
||||
pub id: i64,
|
||||
pub label: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Deserialize, Debug, Clone, PartialEq, Eq)]
|
||||
#[derive(Default, Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Task {
|
||||
pub name: String,
|
||||
pub task_name: String,
|
||||
pub task_name: TaskName,
|
||||
#[serde(deserialize_with = "super::from_i64")]
|
||||
pub interval: i64,
|
||||
pub last_execution: DateTime<Utc>,
|
||||
@@ -525,13 +586,39 @@ pub struct Task {
|
||||
pub next_execution: DateTime<Utc>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Default, Debug, Clone, Eq, PartialEq)]
|
||||
#[derive(Default, Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Copy, ValueEnum)]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
pub enum TaskName {
|
||||
#[default]
|
||||
ApplicationCheckUpdate,
|
||||
Backup,
|
||||
CheckHealth,
|
||||
CleanUpRecycleBin,
|
||||
Housekeeping,
|
||||
ImportListSync,
|
||||
MessagingCleanup,
|
||||
RefreshCollections,
|
||||
RefreshMonitoredDownloads,
|
||||
RefreshMovie,
|
||||
RssSync,
|
||||
}
|
||||
|
||||
impl Display for TaskName {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
let task_name = serde_json::to_string(&self)
|
||||
.expect("Unable to serialize task name")
|
||||
.replace('"', "");
|
||||
write!(f, "{task_name}")
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Default, Debug, Clone, Eq, PartialEq)]
|
||||
pub struct UnmappedFolder {
|
||||
pub name: String,
|
||||
pub path: String,
|
||||
}
|
||||
|
||||
#[derive(Default, Deserialize, Debug, Clone, PartialEq, Eq)]
|
||||
#[derive(Default, Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Update {
|
||||
pub version: String,
|
||||
@@ -542,9 +629,78 @@ pub struct Update {
|
||||
pub changes: UpdateChanges,
|
||||
}
|
||||
|
||||
#[derive(Default, Deserialize, Debug, Clone, PartialEq, Eq)]
|
||||
#[derive(Default, Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct UpdateChanges {
|
||||
pub new: Option<Vec<String>>,
|
||||
pub fixed: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)]
|
||||
#[serde(untagged)]
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
pub enum RadarrSerdeable {
|
||||
Value(Value),
|
||||
Tag(Tag),
|
||||
BlocklistResponse(BlocklistResponse),
|
||||
Collections(Vec<Collection>),
|
||||
Credits(Vec<Credit>),
|
||||
DiskSpaces(Vec<DiskSpace>),
|
||||
DownloadsResponse(DownloadsResponse),
|
||||
Indexers(Vec<Indexer>),
|
||||
IndexerSettings(IndexerSettings),
|
||||
LogResponse(LogResponse),
|
||||
Movie(Movie),
|
||||
MovieHistoryItems(Vec<MovieHistoryItem>),
|
||||
Movies(Vec<Movie>),
|
||||
QualityProfiles(Vec<QualityProfile>),
|
||||
QueueEvents(Vec<QueueEvent>),
|
||||
Releases(Vec<Release>),
|
||||
RootFolders(Vec<RootFolder>),
|
||||
SystemStatus(SystemStatus),
|
||||
Tags(Vec<Tag>),
|
||||
Tasks(Vec<Task>),
|
||||
Updates(Vec<Update>),
|
||||
AddMovieSearchResults(Vec<AddMovieSearchResult>),
|
||||
IndexerTestResults(Vec<IndexerTestResult>),
|
||||
}
|
||||
|
||||
impl From<RadarrSerdeable> for Serdeable {
|
||||
fn from(value: RadarrSerdeable) -> Serdeable {
|
||||
Serdeable::Radarr(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<()> for RadarrSerdeable {
|
||||
fn from(_: ()) -> Self {
|
||||
RadarrSerdeable::Value(json!({}))
|
||||
}
|
||||
}
|
||||
|
||||
serde_enum_from!(
|
||||
RadarrSerdeable {
|
||||
Value(Value),
|
||||
Tag(Tag),
|
||||
BlocklistResponse(BlocklistResponse),
|
||||
Collections(Vec<Collection>),
|
||||
Credits(Vec<Credit>),
|
||||
DiskSpaces(Vec<DiskSpace>),
|
||||
DownloadsResponse(DownloadsResponse),
|
||||
Indexers(Vec<Indexer>),
|
||||
IndexerSettings(IndexerSettings),
|
||||
LogResponse(LogResponse),
|
||||
Movie(Movie),
|
||||
MovieHistoryItems(Vec<MovieHistoryItem>),
|
||||
Movies(Vec<Movie>),
|
||||
QualityProfiles(Vec<QualityProfile>),
|
||||
QueueEvents(Vec<QueueEvent>),
|
||||
Releases(Vec<Release>),
|
||||
RootFolders(Vec<RootFolder>),
|
||||
SystemStatus(SystemStatus),
|
||||
Tags(Vec<Tag>),
|
||||
Tasks(Vec<Task>),
|
||||
Updates(Vec<Update>),
|
||||
AddMovieSearchResults(Vec<AddMovieSearchResult>),
|
||||
IndexerTestResults(Vec<IndexerTestResult>),
|
||||
}
|
||||
);
|
||||
|
||||
@@ -1,8 +1,25 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use pretty_assertions::{assert_eq, assert_str_eq};
|
||||
use serde_json::json;
|
||||
|
||||
use crate::models::radarr_models::{DownloadRecord, MinimumAvailability, Monitor};
|
||||
use crate::models::{
|
||||
radarr_models::{
|
||||
AddMovieSearchResult, BlocklistItem, BlocklistResponse, Collection, Credit, DiskSpace,
|
||||
DownloadRecord, DownloadsResponse, Indexer, IndexerSettings, IndexerTestResult, Log,
|
||||
LogResponse, MinimumAvailability, Monitor, Movie, MovieHistoryItem, QualityProfile,
|
||||
QueueEvent, RadarrSerdeable, Release, RootFolder, SystemStatus, Tag, Task, TaskName, Update,
|
||||
},
|
||||
Serdeable,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn test_task_name_display() {
|
||||
assert_str_eq!(
|
||||
TaskName::ApplicationCheckUpdate.to_string(),
|
||||
"ApplicationCheckUpdate"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_minimum_availability_display() {
|
||||
@@ -70,4 +87,323 @@ mod tests {
|
||||
|
||||
assert_eq!(result, expected_record);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_radarr_serdeable_from() {
|
||||
let radarr_serdeable = RadarrSerdeable::Value(json!({}));
|
||||
|
||||
let serdeable: Serdeable = Serdeable::from(radarr_serdeable.clone());
|
||||
|
||||
assert_eq!(serdeable, Serdeable::Radarr(radarr_serdeable));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_radarr_serdeable_from_unit() {
|
||||
let radarr_serdeable = RadarrSerdeable::from(());
|
||||
|
||||
assert_eq!(radarr_serdeable, RadarrSerdeable::Value(json!({})));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_radarr_serdeable_from_value() {
|
||||
let value = json!({"test": "test"});
|
||||
|
||||
let radarr_serdeable: RadarrSerdeable = value.clone().into();
|
||||
|
||||
assert_eq!(radarr_serdeable, RadarrSerdeable::Value(value));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_radarr_serdeable_from_tag() {
|
||||
let tag = Tag {
|
||||
id: 1,
|
||||
..Tag::default()
|
||||
};
|
||||
|
||||
let radarr_serdeable: RadarrSerdeable = tag.clone().into();
|
||||
|
||||
assert_eq!(radarr_serdeable, RadarrSerdeable::Tag(tag));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_radarr_serdeable_from_blocklist_response() {
|
||||
let blocklist_response = BlocklistResponse {
|
||||
records: vec![BlocklistItem {
|
||||
id: 1,
|
||||
..BlocklistItem::default()
|
||||
}],
|
||||
};
|
||||
|
||||
let radarr_serdeable: RadarrSerdeable = blocklist_response.clone().into();
|
||||
|
||||
assert_eq!(
|
||||
radarr_serdeable,
|
||||
RadarrSerdeable::BlocklistResponse(blocklist_response)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_radarr_serdeable_from_collections() {
|
||||
let collections = vec![Collection {
|
||||
id: 1,
|
||||
..Collection::default()
|
||||
}];
|
||||
|
||||
let radarr_serdeable: RadarrSerdeable = collections.clone().into();
|
||||
|
||||
assert_eq!(radarr_serdeable, RadarrSerdeable::Collections(collections));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_radarr_serdeable_from_credits() {
|
||||
let credits = vec![Credit {
|
||||
person_name: "me".to_owned(),
|
||||
..Credit::default()
|
||||
}];
|
||||
|
||||
let radarr_serdeable: RadarrSerdeable = credits.clone().into();
|
||||
|
||||
assert_eq!(radarr_serdeable, RadarrSerdeable::Credits(credits));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_radarr_serdeable_from_disk_spaces() {
|
||||
let disk_spaces = vec![DiskSpace {
|
||||
free_space: 1,
|
||||
total_space: 1,
|
||||
}];
|
||||
|
||||
let radarr_serdeable: RadarrSerdeable = disk_spaces.clone().into();
|
||||
|
||||
assert_eq!(radarr_serdeable, RadarrSerdeable::DiskSpaces(disk_spaces));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_radarr_serdeable_from_downloads_response() {
|
||||
let downloads_response = DownloadsResponse {
|
||||
records: vec![DownloadRecord {
|
||||
id: 1,
|
||||
..DownloadRecord::default()
|
||||
}],
|
||||
};
|
||||
|
||||
let radarr_serdeable: RadarrSerdeable = downloads_response.clone().into();
|
||||
|
||||
assert_eq!(
|
||||
radarr_serdeable,
|
||||
RadarrSerdeable::DownloadsResponse(downloads_response)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_radarr_serdeable_from_indexers() {
|
||||
let indexers = vec![Indexer {
|
||||
id: 1,
|
||||
..Indexer::default()
|
||||
}];
|
||||
|
||||
let radarr_serdeable: RadarrSerdeable = indexers.clone().into();
|
||||
|
||||
assert_eq!(radarr_serdeable, RadarrSerdeable::Indexers(indexers));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_radarr_serdeable_from_indexer_settings() {
|
||||
let indexer_settings = IndexerSettings {
|
||||
id: 1,
|
||||
..IndexerSettings::default()
|
||||
};
|
||||
|
||||
let radarr_serdeable: RadarrSerdeable = indexer_settings.clone().into();
|
||||
|
||||
assert_eq!(
|
||||
radarr_serdeable,
|
||||
RadarrSerdeable::IndexerSettings(indexer_settings)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_radarr_serdeable_from_log_response() {
|
||||
let log_response = LogResponse {
|
||||
records: vec![Log {
|
||||
level: "info".to_owned(),
|
||||
..Log::default()
|
||||
}],
|
||||
};
|
||||
|
||||
let radarr_serdeable: RadarrSerdeable = log_response.clone().into();
|
||||
|
||||
assert_eq!(radarr_serdeable, RadarrSerdeable::LogResponse(log_response));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_radarr_serdeable_from_movie() {
|
||||
let movie = Movie {
|
||||
id: 1,
|
||||
..Movie::default()
|
||||
};
|
||||
|
||||
let radarr_serdeable: RadarrSerdeable = movie.clone().into();
|
||||
|
||||
assert_eq!(radarr_serdeable, RadarrSerdeable::Movie(movie));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_radarr_serdeable_from_movie_history_items() {
|
||||
let movie_history_items = vec![MovieHistoryItem {
|
||||
event_type: "test".to_owned(),
|
||||
..MovieHistoryItem::default()
|
||||
}];
|
||||
|
||||
let radarr_serdeable: RadarrSerdeable = movie_history_items.clone().into();
|
||||
|
||||
assert_eq!(
|
||||
radarr_serdeable,
|
||||
RadarrSerdeable::MovieHistoryItems(movie_history_items)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_radarr_serdeable_from_movies() {
|
||||
let movies = vec![Movie {
|
||||
id: 1,
|
||||
..Movie::default()
|
||||
}];
|
||||
|
||||
let radarr_serdeable: RadarrSerdeable = movies.clone().into();
|
||||
|
||||
assert_eq!(radarr_serdeable, RadarrSerdeable::Movies(movies));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_radarr_serdeable_from_quality_profiles() {
|
||||
let quality_profiles = vec![QualityProfile {
|
||||
id: 1,
|
||||
..QualityProfile::default()
|
||||
}];
|
||||
|
||||
let radarr_serdeable: RadarrSerdeable = quality_profiles.clone().into();
|
||||
|
||||
assert_eq!(
|
||||
radarr_serdeable,
|
||||
RadarrSerdeable::QualityProfiles(quality_profiles)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_radarr_serdeable_from_queue_events() {
|
||||
let queue_events = vec![QueueEvent {
|
||||
trigger: "test".to_owned(),
|
||||
..QueueEvent::default()
|
||||
}];
|
||||
|
||||
let radarr_serdeable: RadarrSerdeable = queue_events.clone().into();
|
||||
|
||||
assert_eq!(radarr_serdeable, RadarrSerdeable::QueueEvents(queue_events));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_radarr_serdeable_from_releases() {
|
||||
let releases = vec![Release {
|
||||
size: 1,
|
||||
..Release::default()
|
||||
}];
|
||||
|
||||
let radarr_serdeable: RadarrSerdeable = releases.clone().into();
|
||||
|
||||
assert_eq!(radarr_serdeable, RadarrSerdeable::Releases(releases));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_radarr_serdeable_from_root_folders() {
|
||||
let root_folders = vec![RootFolder {
|
||||
id: 1,
|
||||
..RootFolder::default()
|
||||
}];
|
||||
|
||||
let radarr_serdeable: RadarrSerdeable = root_folders.clone().into();
|
||||
|
||||
assert_eq!(radarr_serdeable, RadarrSerdeable::RootFolders(root_folders));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_radarr_serdeable_from_system_status() {
|
||||
let system_status = SystemStatus {
|
||||
version: "1".to_owned(),
|
||||
..SystemStatus::default()
|
||||
};
|
||||
|
||||
let radarr_serdeable: RadarrSerdeable = system_status.clone().into();
|
||||
|
||||
assert_eq!(
|
||||
radarr_serdeable,
|
||||
RadarrSerdeable::SystemStatus(system_status)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_radarr_serdeable_from_tags() {
|
||||
let tags = vec![Tag {
|
||||
id: 1,
|
||||
..Tag::default()
|
||||
}];
|
||||
|
||||
let radarr_serdeable: RadarrSerdeable = tags.clone().into();
|
||||
|
||||
assert_eq!(radarr_serdeable, RadarrSerdeable::Tags(tags));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_radarr_serdeable_from_tasks() {
|
||||
let tasks = vec![Task {
|
||||
name: "test".to_owned(),
|
||||
..Task::default()
|
||||
}];
|
||||
|
||||
let radarr_serdeable: RadarrSerdeable = tasks.clone().into();
|
||||
|
||||
assert_eq!(radarr_serdeable, RadarrSerdeable::Tasks(tasks));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_radarr_serdeable_from_updates() {
|
||||
let updates = vec![Update {
|
||||
version: "test".to_owned(),
|
||||
..Update::default()
|
||||
}];
|
||||
|
||||
let radarr_serdeable: RadarrSerdeable = updates.clone().into();
|
||||
|
||||
assert_eq!(radarr_serdeable, RadarrSerdeable::Updates(updates));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_radarr_serdeable_from_add_movie_search_results() {
|
||||
let add_movie_search_results = vec![AddMovieSearchResult {
|
||||
tmdb_id: 1,
|
||||
..AddMovieSearchResult::default()
|
||||
}];
|
||||
|
||||
let radarr_serdeable: RadarrSerdeable = add_movie_search_results.clone().into();
|
||||
|
||||
assert_eq!(
|
||||
radarr_serdeable,
|
||||
RadarrSerdeable::AddMovieSearchResults(add_movie_search_results)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_radarr_serdeable_from_indexer_test_results() {
|
||||
let indexer_test_results = vec![IndexerTestResult {
|
||||
id: 1,
|
||||
..IndexerTestResult::default()
|
||||
}];
|
||||
|
||||
let radarr_serdeable: RadarrSerdeable = indexer_test_results.clone().into();
|
||||
|
||||
assert_eq!(
|
||||
radarr_serdeable,
|
||||
RadarrSerdeable::IndexerTestResults(indexer_test_results)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ impl<'a> Default for RadarrData<'a> {
|
||||
RadarrData {
|
||||
root_folders: StatefulTable::default(),
|
||||
disk_space_vec: Vec::new(),
|
||||
version: String::default(),
|
||||
version: String::new(),
|
||||
start_time: DateTime::default(),
|
||||
movies: StatefulTable::default(),
|
||||
selected_block: BlockSelectionState::default(),
|
||||
@@ -269,7 +269,7 @@ pub enum ActiveRadarrBlock {
|
||||
FilterMovies,
|
||||
FilterMoviesError,
|
||||
Indexers,
|
||||
IndexerSettingsPrompt,
|
||||
AllIndexerSettingsPrompt,
|
||||
IndexerSettingsAvailabilityDelayInput,
|
||||
IndexerSettingsConfirmPrompt,
|
||||
IndexerSettingsMaximumSizeInput,
|
||||
@@ -466,7 +466,7 @@ pub static EDIT_INDEXER_NZB_SELECTION_BLOCKS: [ActiveRadarrBlock; 10] = [
|
||||
ActiveRadarrBlock::EditIndexerConfirmPrompt,
|
||||
];
|
||||
pub static INDEXER_SETTINGS_BLOCKS: [ActiveRadarrBlock; 10] = [
|
||||
ActiveRadarrBlock::IndexerSettingsPrompt,
|
||||
ActiveRadarrBlock::AllIndexerSettingsPrompt,
|
||||
ActiveRadarrBlock::IndexerSettingsAvailabilityDelayInput,
|
||||
ActiveRadarrBlock::IndexerSettingsConfirmPrompt,
|
||||
ActiveRadarrBlock::IndexerSettingsMaximumSizeInput,
|
||||
|
||||
@@ -423,7 +423,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_indexer_settings_blocks_contents() {
|
||||
assert_eq!(INDEXER_SETTINGS_BLOCKS.len(), 10);
|
||||
assert!(INDEXER_SETTINGS_BLOCKS.contains(&ActiveRadarrBlock::IndexerSettingsPrompt));
|
||||
assert!(INDEXER_SETTINGS_BLOCKS.contains(&ActiveRadarrBlock::AllIndexerSettingsPrompt));
|
||||
assert!(
|
||||
INDEXER_SETTINGS_BLOCKS.contains(&ActiveRadarrBlock::IndexerSettingsAvailabilityDelayInput)
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user