298 lines
8.9 KiB
Rust
298 lines
8.9 KiB
Rust
use std::sync::Arc;
|
|
|
|
use add_command_handler::{SonarrAddCommand, SonarrAddCommandHandler};
|
|
use anyhow::Result;
|
|
use clap::Subcommand;
|
|
use delete_command_handler::{SonarrDeleteCommand, SonarrDeleteCommandHandler};
|
|
use download_command_handler::{SonarrDownloadCommand, SonarrDownloadCommandHandler};
|
|
use edit_command_handler::{SonarrEditCommand, SonarrEditCommandHandler};
|
|
use get_command_handler::{SonarrGetCommand, SonarrGetCommandHandler};
|
|
use list_command_handler::{SonarrListCommand, SonarrListCommandHandler};
|
|
use manual_search_command_handler::{SonarrManualSearchCommand, SonarrManualSearchCommandHandler};
|
|
use refresh_command_handler::{SonarrRefreshCommand, SonarrRefreshCommandHandler};
|
|
use tokio::sync::Mutex;
|
|
use trigger_automatic_search_command_handler::{
|
|
SonarrTriggerAutomaticSearchCommand, SonarrTriggerAutomaticSearchCommandHandler,
|
|
};
|
|
|
|
use crate::{
|
|
app::App,
|
|
models::sonarr_models::SonarrTaskName,
|
|
network::{sonarr_network::SonarrEvent, NetworkTrait},
|
|
};
|
|
|
|
use super::{CliCommandHandler, Command};
|
|
|
|
mod add_command_handler;
|
|
mod delete_command_handler;
|
|
mod download_command_handler;
|
|
mod edit_command_handler;
|
|
mod get_command_handler;
|
|
mod list_command_handler;
|
|
mod manual_search_command_handler;
|
|
mod refresh_command_handler;
|
|
mod trigger_automatic_search_command_handler;
|
|
|
|
#[cfg(test)]
|
|
#[path = "sonarr_command_tests.rs"]
|
|
mod sonarr_command_tests;
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, Subcommand)]
|
|
pub enum SonarrCommand {
|
|
#[command(
|
|
subcommand,
|
|
about = "Commands to add or create new resources within your Sonarr instance"
|
|
)]
|
|
Add(SonarrAddCommand),
|
|
#[command(
|
|
subcommand,
|
|
about = "Commands to delete resources from your Sonarr instance"
|
|
)]
|
|
Delete(SonarrDeleteCommand),
|
|
#[command(
|
|
subcommand,
|
|
about = "Commands to edit resources in your Sonarr instance"
|
|
)]
|
|
Edit(SonarrEditCommand),
|
|
#[command(
|
|
subcommand,
|
|
about = "Commands to fetch details of the resources in your Sonarr instance"
|
|
)]
|
|
Get(SonarrGetCommand),
|
|
#[command(
|
|
subcommand,
|
|
about = "Commands to download releases in your Sonarr instance"
|
|
)]
|
|
Download(SonarrDownloadCommand),
|
|
#[command(
|
|
subcommand,
|
|
about = "Commands to list attributes from your Sonarr instance"
|
|
)]
|
|
List(SonarrListCommand),
|
|
#[command(
|
|
subcommand,
|
|
about = "Commands to refresh the data in your Sonarr instance"
|
|
)]
|
|
Refresh(SonarrRefreshCommand),
|
|
#[command(subcommand, about = "Commands to manually search for releases")]
|
|
ManualSearch(SonarrManualSearchCommand),
|
|
#[command(
|
|
subcommand,
|
|
about = "Commands to trigger automatic searches for releases of different resources in your Sonarr instance"
|
|
)]
|
|
TriggerAutomaticSearch(SonarrTriggerAutomaticSearchCommand),
|
|
#[command(about = "Clear the blocklist")]
|
|
ClearBlocklist,
|
|
#[command(about = "Mark the Sonarr history item with the given ID as 'failed'")]
|
|
MarkHistoryItemAsFailed {
|
|
#[arg(
|
|
long,
|
|
help = "The Sonarr ID of the history item you wish to mark as 'failed'",
|
|
required = true
|
|
)]
|
|
history_item_id: i64,
|
|
},
|
|
#[command(about = "Search for a new series to add to Sonarr")]
|
|
SearchNewSeries {
|
|
#[arg(
|
|
long,
|
|
help = "The title of the series you want to search for",
|
|
required = true
|
|
)]
|
|
query: String,
|
|
},
|
|
#[command(about = "Start the specified Sonarr task")]
|
|
StartTask {
|
|
#[arg(
|
|
long,
|
|
help = "The name of the task to trigger",
|
|
value_enum,
|
|
required = true
|
|
)]
|
|
task_name: SonarrTaskName,
|
|
},
|
|
#[command(
|
|
about = "Test the indexer with the given ID. Note that a successful test returns an empty JSON body; i.e. '{}'"
|
|
)]
|
|
TestIndexer {
|
|
#[arg(long, help = "The ID of the indexer to test", required = true)]
|
|
indexer_id: i64,
|
|
},
|
|
#[command(about = "Test all Sonarr indexers")]
|
|
TestAllIndexers,
|
|
#[command(about = "Toggle monitoring for the specified episode")]
|
|
ToggleEpisodeMonitoring {
|
|
#[arg(
|
|
long,
|
|
help = "The Sonarr ID of the episode to toggle monitoring on",
|
|
required = true
|
|
)]
|
|
episode_id: i64,
|
|
},
|
|
#[command(
|
|
about = "Toggle monitoring for the specified season that corresponds to the specified series ID"
|
|
)]
|
|
ToggleSeasonMonitoring {
|
|
#[arg(
|
|
long,
|
|
help = "The Sonarr ID of the series that the season belongs to",
|
|
required = true
|
|
)]
|
|
series_id: i64,
|
|
#[arg(
|
|
long,
|
|
help = "The season number to toggle monitoring for",
|
|
required = true
|
|
)]
|
|
season_number: i64,
|
|
},
|
|
}
|
|
|
|
impl From<SonarrCommand> for Command {
|
|
fn from(sonarr_command: SonarrCommand) -> Command {
|
|
Command::Sonarr(sonarr_command)
|
|
}
|
|
}
|
|
|
|
pub(super) struct SonarrCliHandler<'a, 'b> {
|
|
app: &'a Arc<Mutex<App<'b>>>,
|
|
command: SonarrCommand,
|
|
network: &'a mut dyn NetworkTrait,
|
|
}
|
|
|
|
impl<'a, 'b> CliCommandHandler<'a, 'b, SonarrCommand> for SonarrCliHandler<'a, 'b> {
|
|
fn with(
|
|
app: &'a Arc<Mutex<App<'b>>>,
|
|
command: SonarrCommand,
|
|
network: &'a mut dyn NetworkTrait,
|
|
) -> Self {
|
|
SonarrCliHandler {
|
|
app,
|
|
command,
|
|
network,
|
|
}
|
|
}
|
|
|
|
async fn handle(self) -> Result<String> {
|
|
let result = match self.command {
|
|
SonarrCommand::Add(add_command) => {
|
|
SonarrAddCommandHandler::with(self.app, add_command, self.network)
|
|
.handle()
|
|
.await?
|
|
}
|
|
SonarrCommand::Delete(delete_command) => {
|
|
SonarrDeleteCommandHandler::with(self.app, delete_command, self.network)
|
|
.handle()
|
|
.await?
|
|
}
|
|
SonarrCommand::Edit(edit_command) => {
|
|
SonarrEditCommandHandler::with(self.app, edit_command, self.network)
|
|
.handle()
|
|
.await?
|
|
}
|
|
SonarrCommand::Download(download_command) => {
|
|
SonarrDownloadCommandHandler::with(self.app, download_command, self.network)
|
|
.handle()
|
|
.await?
|
|
}
|
|
SonarrCommand::Get(get_command) => {
|
|
SonarrGetCommandHandler::with(self.app, get_command, self.network)
|
|
.handle()
|
|
.await?
|
|
}
|
|
SonarrCommand::List(list_command) => {
|
|
SonarrListCommandHandler::with(self.app, list_command, self.network)
|
|
.handle()
|
|
.await?
|
|
}
|
|
SonarrCommand::Refresh(refresh_command) => {
|
|
SonarrRefreshCommandHandler::with(self.app, refresh_command, self.network)
|
|
.handle()
|
|
.await?
|
|
}
|
|
SonarrCommand::ManualSearch(manual_search_command) => {
|
|
SonarrManualSearchCommandHandler::with(self.app, manual_search_command, self.network)
|
|
.handle()
|
|
.await?
|
|
}
|
|
SonarrCommand::TriggerAutomaticSearch(trigger_automatic_search_command) => {
|
|
SonarrTriggerAutomaticSearchCommandHandler::with(
|
|
self.app,
|
|
trigger_automatic_search_command,
|
|
self.network,
|
|
)
|
|
.handle()
|
|
.await?
|
|
}
|
|
SonarrCommand::ClearBlocklist => {
|
|
self
|
|
.network
|
|
.handle_network_event(SonarrEvent::GetBlocklist.into())
|
|
.await?;
|
|
let resp = self
|
|
.network
|
|
.handle_network_event(SonarrEvent::ClearBlocklist.into())
|
|
.await?;
|
|
serde_json::to_string_pretty(&resp)?
|
|
}
|
|
SonarrCommand::MarkHistoryItemAsFailed { history_item_id } => {
|
|
let _ = self
|
|
.network
|
|
.handle_network_event(SonarrEvent::MarkHistoryItemAsFailed(history_item_id).into())
|
|
.await?;
|
|
"Sonarr history item marked as 'failed'".to_owned()
|
|
}
|
|
SonarrCommand::SearchNewSeries { query } => {
|
|
let resp = self
|
|
.network
|
|
.handle_network_event(SonarrEvent::SearchNewSeries(query).into())
|
|
.await?;
|
|
serde_json::to_string_pretty(&resp)?
|
|
}
|
|
SonarrCommand::StartTask { task_name } => {
|
|
let resp = self
|
|
.network
|
|
.handle_network_event(SonarrEvent::StartTask(task_name).into())
|
|
.await?;
|
|
serde_json::to_string_pretty(&resp)?
|
|
}
|
|
SonarrCommand::TestIndexer { indexer_id } => {
|
|
let resp = self
|
|
.network
|
|
.handle_network_event(SonarrEvent::TestIndexer(indexer_id).into())
|
|
.await?;
|
|
serde_json::to_string_pretty(&resp)?
|
|
}
|
|
SonarrCommand::TestAllIndexers => {
|
|
println!("Testing all Sonarr indexers. This may take a minute...");
|
|
let resp = self
|
|
.network
|
|
.handle_network_event(SonarrEvent::TestAllIndexers.into())
|
|
.await?;
|
|
serde_json::to_string_pretty(&resp)?
|
|
}
|
|
SonarrCommand::ToggleEpisodeMonitoring { episode_id } => {
|
|
let resp = self
|
|
.network
|
|
.handle_network_event(SonarrEvent::ToggleEpisodeMonitoring(episode_id).into())
|
|
.await?;
|
|
serde_json::to_string_pretty(&resp)?
|
|
}
|
|
SonarrCommand::ToggleSeasonMonitoring {
|
|
series_id,
|
|
season_number,
|
|
} => {
|
|
let resp = self
|
|
.network
|
|
.handle_network_event(
|
|
SonarrEvent::ToggleSeasonMonitoring((series_id, season_number)).into(),
|
|
)
|
|
.await?;
|
|
serde_json::to_string_pretty(&resp)?
|
|
}
|
|
};
|
|
|
|
Ok(result)
|
|
}
|
|
}
|