feat: CLI support for listing artists

This commit is contained in:
2026-01-05 10:58:48 -07:00
parent 368f7505ff
commit 5d09b2402c
14 changed files with 405 additions and 15 deletions
+84
View File
@@ -0,0 +1,84 @@
use chrono::{DateTime, Utc};
use derivative::Derivative;
use serde::{Deserialize, Serialize};
use serde_json::{Number, Value};
use super::{HorizontallyScrollableText, Serdeable};
use crate::serde_enum_from;
#[derive(Derivative, Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct Artist {
#[serde(deserialize_with = "super::from_i64")]
pub id: i64,
pub mb_id: String,
pub artist_name: HorizontallyScrollableText,
pub foreign_artist_id: String,
pub status: ArtistStatus,
pub overview: Option<String>,
pub artist_type: Option<String>,
pub disambiguation: Option<String>,
pub path: String,
#[serde(deserialize_with = "super::from_i64")]
pub quality_profile_id: i64,
#[serde(deserialize_with = "super::from_i64")]
pub metadata_profile_id: i64,
pub monitored: bool,
pub genres: Vec<String>,
pub tags: Vec<Number>,
pub added: DateTime<Utc>,
pub ratings: Option<Ratings>,
pub statistics: Option<ArtistStatistics>,
}
#[derive(Serialize, Deserialize, Default, PartialEq, Eq, Clone, Copy, Debug)]
#[serde(rename_all = "camelCase")]
pub enum ArtistStatus {
#[default]
Continuing,
Ended,
Deleted,
}
#[derive(Derivative, Serialize, Deserialize, Debug, Default, Clone, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct Ratings {
#[serde(deserialize_with = "super::from_i64")]
pub votes: i64,
#[serde(deserialize_with = "super::from_f64")]
pub value: f64,
}
impl Eq for Ratings {}
#[derive(Derivative, Serialize, Deserialize, Debug, Default, Clone, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct ArtistStatistics {
#[serde(deserialize_with = "super::from_i64")]
pub album_count: i64,
#[serde(deserialize_with = "super::from_i64")]
pub track_file_count: i64,
#[serde(deserialize_with = "super::from_i64")]
pub track_count: i64,
#[serde(deserialize_with = "super::from_i64")]
pub total_track_count: i64,
#[serde(deserialize_with = "super::from_i64")]
pub size_on_disk: i64,
#[serde(deserialize_with = "super::from_f64")]
pub percent_of_tracks: f64,
}
impl Eq for ArtistStatistics {}
impl From<LidarrSerdeable> for Serdeable {
fn from(value: LidarrSerdeable) -> Serdeable {
Serdeable::Lidarr(value)
}
}
serde_enum_from!(
LidarrSerdeable {
Artists(Vec<Artist>),
Value(Value),
}
);
+8 -5
View File
@@ -1,16 +1,19 @@
use std::fmt::{Debug, Display, Formatter};
use std::sync::atomic::{AtomicUsize, Ordering};
use crate::app::ServarrConfig;
use crate::app::context_clues::ContextClue;
use crate::app::ServarrConfig;
use crate::models::servarr_data::lidarr::lidarr_data::ActiveLidarrBlock;
use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock;
use lidarr_models::LidarrSerdeable;
use radarr_models::RadarrSerdeable;
use regex::Regex;
use serde::{Deserialize, Deserializer, Serialize, Serializer, de};
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
use serde_json::Number;
use servarr_data::sonarr::sonarr_data::ActiveSonarrBlock;
use sonarr_models::SonarrSerdeable;
pub mod lidarr_models;
pub mod radarr_models;
pub mod servarr_data;
pub mod servarr_models;
@@ -30,7 +33,7 @@ pub enum Route {
Radarr(ActiveRadarrBlock, Option<ActiveRadarrBlock>),
Sonarr(ActiveSonarrBlock, Option<ActiveSonarrBlock>),
Readarr,
Lidarr,
Lidarr(ActiveLidarrBlock, Option<ActiveLidarrBlock>),
Whisparr,
Bazarr,
Prowlarr,
@@ -43,6 +46,7 @@ pub enum Route {
pub enum Serdeable {
Radarr(RadarrSerdeable),
Sonarr(SonarrSerdeable),
Lidarr(LidarrSerdeable),
}
pub trait Scrollable {
@@ -289,8 +293,7 @@ impl TabState {
TabState { tabs, index: 0 }
}
// Allowing this code for now since we'll eventually be implementing additional Servarr support, and we'll need it then
#[allow(dead_code)]
#[cfg(test)]
pub fn set_index(&mut self, index: usize) -> &TabRoute {
self.index = index;
&self.tabs[self.index]
@@ -0,0 +1,28 @@
use strum::EnumIter;
#[cfg(test)]
use strum::{Display, EnumString};
use crate::models::Route;
#[cfg(test)]
#[path = "lidarr_data_tests.rs"]
mod lidarr_data_tests;
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default, EnumIter)]
#[cfg_attr(test, derive(Display, EnumString))]
pub enum ActiveLidarrBlock {
#[default]
Artists,
}
impl From<ActiveLidarrBlock> for Route {
fn from(active_lidarr_block: ActiveLidarrBlock) -> Route {
Route::Lidarr(active_lidarr_block, None)
}
}
impl From<(ActiveLidarrBlock, Option<ActiveLidarrBlock>)> for Route {
fn from(value: (ActiveLidarrBlock, Option<ActiveLidarrBlock>)) -> Route {
Route::Lidarr(value.0, value.1)
}
}
@@ -0,0 +1,22 @@
#[cfg(test)]
mod tests {
use pretty_assertions::assert_eq;
use crate::models::{servarr_data::lidarr::lidarr_data::ActiveLidarrBlock, Route};
#[test]
fn test_from_active_lidarr_block_to_route() {
assert_eq!(
Route::from(ActiveLidarrBlock::Artists),
Route::Lidarr(ActiveLidarrBlock::Artists, None)
);
}
#[test]
fn test_from_tuple_to_route_with_context() {
assert_eq!(
Route::from((ActiveLidarrBlock::Artists, Some(ActiveLidarrBlock::Artists))),
Route::Lidarr(ActiveLidarrBlock::Artists, Some(ActiveLidarrBlock::Artists),)
);
}
}
+1
View File
@@ -0,0 +1 @@
pub mod lidarr_data;
+1
View File
@@ -1,5 +1,6 @@
use crate::models::Route;
pub mod lidarr;
pub mod modals;
pub mod radarr;
pub mod sonarr;