Added the ability to fetch host configs and security configs to the CLI
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
# Adapted from https://github.com/joshka/github-workflows/blob/main/.github/workflows/rust-release-plz.yml
|
# Adapted from https://github.com/joshka/github-workflows/blob/main/.github/workflows/rust-release-plz.yml
|
||||||
# Thanks to joshka for permission to use this template!
|
# Thanks to joshka for permission to use this template!
|
||||||
|
|
||||||
name: Create Release PR and publish to crates.io
|
name: Create Release PR and Publish Release
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
pull-requests: write
|
pull-requests: write
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ You can also clone this repo and run `make docker` to build a docker image local
|
|||||||
- [x] View your library, downloads, collections, and blocklist
|
- [x] View your library, downloads, collections, and blocklist
|
||||||
- [x] View details of a specific movie including description, history, downloaded file info, or the credits
|
- [x] View details of a specific movie including description, history, downloaded file info, or the credits
|
||||||
- [x] View details of any collection and the movies in them
|
- [x] View details of any collection and the movies in them
|
||||||
|
- [x] View your host and security configs from the CLI to programmatically fetch the API token, among other settings
|
||||||
- [x] Search your library or collections
|
- [x] Search your library or collections
|
||||||
- [x] Add movies to your library
|
- [x] Add movies to your library
|
||||||
- [x] Delete movies, downloads, and indexers
|
- [x] Delete movies, downloads, and indexers
|
||||||
@@ -103,7 +104,8 @@ You can also clone this repo and run `make docker` to build a docker image local
|
|||||||
### The Managarr CLI
|
### The Managarr CLI
|
||||||
Managarr can be used in one of two ways: As a TUI, or as a CLI for managing your Servarrs.
|
Managarr can be used in one of two ways: As a TUI, or as a CLI for managing your Servarrs.
|
||||||
|
|
||||||
All management features available in the TUI are also available in the CLI.
|
All management features available in the TUI are also available in the CLI. However, the CLI is
|
||||||
|
equipped with additional features to allow for more advanced usage and automation.
|
||||||
|
|
||||||
The CLI can be helpful for automating tasks or for use in scripts. For example, you can use the CLI to trigger a search for a movie, or to add a movie to your library.
|
The CLI can be helpful for automating tasks or for use in scripts. For example, you can use the CLI to trigger a search for a movie, or to add a movie to your library.
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ mod get_command_handler_tests;
|
|||||||
pub enum RadarrGetCommand {
|
pub enum RadarrGetCommand {
|
||||||
#[command(about = "Get the shared settings for all indexers")]
|
#[command(about = "Get the shared settings for all indexers")]
|
||||||
AllIndexerSettings,
|
AllIndexerSettings,
|
||||||
|
#[command(about = "Fetch the host config for your Radarr instance")]
|
||||||
|
HostConfig,
|
||||||
#[command(about = "Get detailed information for the movie with the given ID")]
|
#[command(about = "Get detailed information for the movie with the given ID")]
|
||||||
MovieDetails {
|
MovieDetails {
|
||||||
#[arg(
|
#[arg(
|
||||||
@@ -39,6 +41,8 @@ pub enum RadarrGetCommand {
|
|||||||
)]
|
)]
|
||||||
movie_id: i64,
|
movie_id: i64,
|
||||||
},
|
},
|
||||||
|
#[command(about = "Fetch the security config for your Radarr instance")]
|
||||||
|
SecurityConfig,
|
||||||
#[command(about = "Get the system status")]
|
#[command(about = "Get the system status")]
|
||||||
SystemStatus,
|
SystemStatus,
|
||||||
}
|
}
|
||||||
@@ -73,12 +77,18 @@ impl<'a, 'b> CliCommandHandler<'a, 'b, RadarrGetCommand> for RadarrGetCommandHan
|
|||||||
RadarrGetCommand::AllIndexerSettings => {
|
RadarrGetCommand::AllIndexerSettings => {
|
||||||
execute_network_event!(self, RadarrEvent::GetAllIndexerSettings);
|
execute_network_event!(self, RadarrEvent::GetAllIndexerSettings);
|
||||||
}
|
}
|
||||||
|
RadarrGetCommand::HostConfig => {
|
||||||
|
execute_network_event!(self, RadarrEvent::GetHostConfig);
|
||||||
|
}
|
||||||
RadarrGetCommand::MovieDetails { movie_id } => {
|
RadarrGetCommand::MovieDetails { movie_id } => {
|
||||||
execute_network_event!(self, RadarrEvent::GetMovieDetails(Some(movie_id)));
|
execute_network_event!(self, RadarrEvent::GetMovieDetails(Some(movie_id)));
|
||||||
}
|
}
|
||||||
RadarrGetCommand::MovieHistory { movie_id } => {
|
RadarrGetCommand::MovieHistory { movie_id } => {
|
||||||
execute_network_event!(self, RadarrEvent::GetMovieHistory(Some(movie_id)));
|
execute_network_event!(self, RadarrEvent::GetMovieHistory(Some(movie_id)));
|
||||||
}
|
}
|
||||||
|
RadarrGetCommand::SecurityConfig => {
|
||||||
|
execute_network_event!(self, RadarrEvent::GetSecurityConfig);
|
||||||
|
}
|
||||||
RadarrGetCommand::SystemStatus => {
|
RadarrGetCommand::SystemStatus => {
|
||||||
execute_network_event!(self, RadarrEvent::GetStatus);
|
execute_network_event!(self, RadarrEvent::GetStatus);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,14 @@ mod test {
|
|||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_get_host_config_has_no_arg_requirements() {
|
||||||
|
let result =
|
||||||
|
Cli::command().try_get_matches_from(["managarr", "radarr", "get", "host-config"]);
|
||||||
|
|
||||||
|
assert!(result.is_ok());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_movie_details_requires_movie_id() {
|
fn test_movie_details_requires_movie_id() {
|
||||||
let result =
|
let result =
|
||||||
@@ -81,6 +89,14 @@ mod test {
|
|||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_get_security_config_has_no_arg_requirements() {
|
||||||
|
let result =
|
||||||
|
Cli::command().try_get_matches_from(["managarr", "radarr", "get", "security-config"]);
|
||||||
|
|
||||||
|
assert!(result.is_ok());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_system_status_has_no_arg_requirements() {
|
fn test_system_status_has_no_arg_requirements() {
|
||||||
let result =
|
let result =
|
||||||
@@ -135,6 +151,29 @@ mod test {
|
|||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_handle_get_host_config_command() {
|
||||||
|
let mut mock_network = MockNetworkTrait::new();
|
||||||
|
mock_network
|
||||||
|
.expect_handle_network_event()
|
||||||
|
.with(eq::<NetworkEvent>(RadarrEvent::GetHostConfig.into()))
|
||||||
|
.times(1)
|
||||||
|
.returning(|_| {
|
||||||
|
Ok(Serdeable::Radarr(RadarrSerdeable::Value(
|
||||||
|
json!({"testResponse": "response"}),
|
||||||
|
)))
|
||||||
|
});
|
||||||
|
let app_arc = Arc::new(Mutex::new(App::default()));
|
||||||
|
let get_host_config_command = RadarrGetCommand::HostConfig;
|
||||||
|
|
||||||
|
let result =
|
||||||
|
RadarrGetCommandHandler::with(&app_arc, get_host_config_command, &mut mock_network)
|
||||||
|
.handle()
|
||||||
|
.await;
|
||||||
|
|
||||||
|
assert!(result.is_ok());
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_handle_get_movie_details_command() {
|
async fn test_handle_get_movie_details_command() {
|
||||||
let expected_movie_id = 1;
|
let expected_movie_id = 1;
|
||||||
@@ -187,6 +226,29 @@ mod test {
|
|||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_handle_get_security_config_command() {
|
||||||
|
let mut mock_network = MockNetworkTrait::new();
|
||||||
|
mock_network
|
||||||
|
.expect_handle_network_event()
|
||||||
|
.with(eq::<NetworkEvent>(RadarrEvent::GetSecurityConfig.into()))
|
||||||
|
.times(1)
|
||||||
|
.returning(|_| {
|
||||||
|
Ok(Serdeable::Radarr(RadarrSerdeable::Value(
|
||||||
|
json!({"testResponse": "response"}),
|
||||||
|
)))
|
||||||
|
});
|
||||||
|
let app_arc = Arc::new(Mutex::new(App::default()));
|
||||||
|
let get_security_config_command = RadarrGetCommand::SecurityConfig;
|
||||||
|
|
||||||
|
let result =
|
||||||
|
RadarrGetCommandHandler::with(&app_arc, get_security_config_command, &mut mock_network)
|
||||||
|
.handle()
|
||||||
|
.await;
|
||||||
|
|
||||||
|
assert!(result.is_ok());
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_handle_get_system_status_command() {
|
async fn test_handle_get_system_status_command() {
|
||||||
let mut mock_network = MockNetworkTrait::new();
|
let mut mock_network = MockNetworkTrait::new();
|
||||||
|
|||||||
@@ -57,6 +57,44 @@ pub struct AddRootFolderBody {
|
|||||||
pub path: String,
|
pub path: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Default, PartialEq, Eq, Clone, Copy, Debug, ValueEnum)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub enum AuthenticationMethod {
|
||||||
|
#[default]
|
||||||
|
Basic,
|
||||||
|
Forms,
|
||||||
|
None,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for AuthenticationMethod {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
let authentication_method = match self {
|
||||||
|
AuthenticationMethod::Basic => "basic",
|
||||||
|
AuthenticationMethod::Forms => "forms",
|
||||||
|
AuthenticationMethod::None => "none",
|
||||||
|
};
|
||||||
|
write!(f, "{authentication_method}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Default, PartialEq, Eq, Clone, Copy, Debug, ValueEnum)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub enum AuthenticationRequired {
|
||||||
|
Enabled,
|
||||||
|
#[default]
|
||||||
|
DisabledForLocalAddresses,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for AuthenticationRequired {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
let authentication_required = match self {
|
||||||
|
AuthenticationRequired::Enabled => "enabled",
|
||||||
|
AuthenticationRequired::DisabledForLocalAddresses => "disabledForLocalAddresses",
|
||||||
|
};
|
||||||
|
write!(f, "{authentication_required}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default, Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
|
#[derive(Default, Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct BlocklistResponse {
|
pub struct BlocklistResponse {
|
||||||
pub records: Vec<BlocklistItem>,
|
pub records: Vec<BlocklistItem>,
|
||||||
@@ -85,6 +123,26 @@ pub struct BlocklistItemMovie {
|
|||||||
pub title: HorizontallyScrollableText,
|
pub title: HorizontallyScrollableText,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Default, PartialEq, Eq, Clone, Copy, Debug, ValueEnum)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub enum CertificateValidation {
|
||||||
|
#[default]
|
||||||
|
Enabled,
|
||||||
|
DisabledForLocalAddresses,
|
||||||
|
Disabled,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for CertificateValidation {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
|
let certificate_validation = match self {
|
||||||
|
CertificateValidation::Enabled => "enabled",
|
||||||
|
CertificateValidation::DisabledForLocalAddresses => "disabledForLocalAddresses",
|
||||||
|
CertificateValidation::Disabled => "disabled",
|
||||||
|
};
|
||||||
|
write!(f, "{certificate_validation}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Derivative, Default, Clone, Debug, PartialEq, Eq)]
|
#[derive(Serialize, Deserialize, Derivative, Default, Clone, Debug, PartialEq, Eq)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct Collection {
|
pub struct Collection {
|
||||||
@@ -223,6 +281,18 @@ pub struct EditMovieParams {
|
|||||||
pub clear_tags: bool,
|
pub clear_tags: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Deserialize, Serialize, Debug, Clone, Eq, PartialEq)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct HostConfig {
|
||||||
|
pub bind_address: HorizontallyScrollableText,
|
||||||
|
#[serde(deserialize_with = "super::from_i64")]
|
||||||
|
pub port: i64,
|
||||||
|
pub url_base: Option<HorizontallyScrollableText>,
|
||||||
|
pub instance_name: Option<HorizontallyScrollableText>,
|
||||||
|
pub application_url: Option<HorizontallyScrollableText>,
|
||||||
|
pub enable_ssl: bool,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default, Deserialize, Serialize, Debug, Clone, Eq, PartialEq)]
|
#[derive(Default, Deserialize, Serialize, Debug, Clone, Eq, PartialEq)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct Indexer {
|
pub struct Indexer {
|
||||||
@@ -560,6 +630,17 @@ pub struct RootFolder {
|
|||||||
pub unmapped_folders: Option<Vec<UnmappedFolder>>,
|
pub unmapped_folders: Option<Vec<UnmappedFolder>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct SecurityConfig {
|
||||||
|
pub authentication_method: AuthenticationMethod,
|
||||||
|
pub authentication_required: AuthenticationRequired,
|
||||||
|
pub username: String,
|
||||||
|
pub password: Option<String>,
|
||||||
|
pub api_key: String,
|
||||||
|
pub certificate_validation: CertificateValidation,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default, Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
|
#[derive(Default, Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct SystemStatus {
|
pub struct SystemStatus {
|
||||||
@@ -647,6 +728,7 @@ pub enum RadarrSerdeable {
|
|||||||
Credits(Vec<Credit>),
|
Credits(Vec<Credit>),
|
||||||
DiskSpaces(Vec<DiskSpace>),
|
DiskSpaces(Vec<DiskSpace>),
|
||||||
DownloadsResponse(DownloadsResponse),
|
DownloadsResponse(DownloadsResponse),
|
||||||
|
HostConfig(HostConfig),
|
||||||
Indexers(Vec<Indexer>),
|
Indexers(Vec<Indexer>),
|
||||||
IndexerSettings(IndexerSettings),
|
IndexerSettings(IndexerSettings),
|
||||||
LogResponse(LogResponse),
|
LogResponse(LogResponse),
|
||||||
@@ -657,6 +739,7 @@ pub enum RadarrSerdeable {
|
|||||||
QueueEvents(Vec<QueueEvent>),
|
QueueEvents(Vec<QueueEvent>),
|
||||||
Releases(Vec<Release>),
|
Releases(Vec<Release>),
|
||||||
RootFolders(Vec<RootFolder>),
|
RootFolders(Vec<RootFolder>),
|
||||||
|
SecurityConfig(SecurityConfig),
|
||||||
SystemStatus(SystemStatus),
|
SystemStatus(SystemStatus),
|
||||||
Tags(Vec<Tag>),
|
Tags(Vec<Tag>),
|
||||||
Tasks(Vec<Task>),
|
Tasks(Vec<Task>),
|
||||||
@@ -686,6 +769,7 @@ serde_enum_from!(
|
|||||||
Credits(Vec<Credit>),
|
Credits(Vec<Credit>),
|
||||||
DiskSpaces(Vec<DiskSpace>),
|
DiskSpaces(Vec<DiskSpace>),
|
||||||
DownloadsResponse(DownloadsResponse),
|
DownloadsResponse(DownloadsResponse),
|
||||||
|
HostConfig(HostConfig),
|
||||||
Indexers(Vec<Indexer>),
|
Indexers(Vec<Indexer>),
|
||||||
IndexerSettings(IndexerSettings),
|
IndexerSettings(IndexerSettings),
|
||||||
LogResponse(LogResponse),
|
LogResponse(LogResponse),
|
||||||
@@ -696,6 +780,7 @@ serde_enum_from!(
|
|||||||
QueueEvents(Vec<QueueEvent>),
|
QueueEvents(Vec<QueueEvent>),
|
||||||
Releases(Vec<Release>),
|
Releases(Vec<Release>),
|
||||||
RootFolders(Vec<RootFolder>),
|
RootFolders(Vec<RootFolder>),
|
||||||
|
SecurityConfig(SecurityConfig),
|
||||||
SystemStatus(SystemStatus),
|
SystemStatus(SystemStatus),
|
||||||
Tags(Vec<Tag>),
|
Tags(Vec<Tag>),
|
||||||
Tasks(Vec<Task>),
|
Tasks(Vec<Task>),
|
||||||
|
|||||||
@@ -5,14 +5,41 @@ mod tests {
|
|||||||
|
|
||||||
use crate::models::{
|
use crate::models::{
|
||||||
radarr_models::{
|
radarr_models::{
|
||||||
AddMovieSearchResult, BlocklistItem, BlocklistResponse, Collection, Credit, DiskSpace,
|
AddMovieSearchResult, AuthenticationMethod, AuthenticationRequired, BlocklistItem,
|
||||||
DownloadRecord, DownloadsResponse, Indexer, IndexerSettings, IndexerTestResult, Log,
|
BlocklistResponse, CertificateValidation, Collection, Credit, DiskSpace, DownloadRecord,
|
||||||
LogResponse, MinimumAvailability, Monitor, Movie, MovieHistoryItem, QualityProfile,
|
DownloadsResponse, Indexer, IndexerSettings, IndexerTestResult, Log, LogResponse,
|
||||||
QueueEvent, RadarrSerdeable, Release, RootFolder, SystemStatus, Tag, Task, TaskName, Update,
|
MinimumAvailability, Monitor, Movie, MovieHistoryItem, QualityProfile, QueueEvent,
|
||||||
|
RadarrSerdeable, Release, RootFolder, SystemStatus, Tag, Task, TaskName, Update,
|
||||||
},
|
},
|
||||||
Serdeable,
|
Serdeable,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_authentication_method_display() {
|
||||||
|
assert_str_eq!(AuthenticationMethod::Basic.to_string(), "basic");
|
||||||
|
assert_str_eq!(AuthenticationMethod::Forms.to_string(), "forms");
|
||||||
|
assert_str_eq!(AuthenticationMethod::None.to_string(), "none");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_authentication_required_display() {
|
||||||
|
assert_str_eq!(AuthenticationRequired::Enabled.to_string(), "enabled");
|
||||||
|
assert_str_eq!(
|
||||||
|
AuthenticationRequired::DisabledForLocalAddresses.to_string(),
|
||||||
|
"disabledForLocalAddresses"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_certificate_validation_display() {
|
||||||
|
assert_str_eq!(CertificateValidation::Enabled.to_string(), "enabled");
|
||||||
|
assert_str_eq!(
|
||||||
|
CertificateValidation::DisabledForLocalAddresses.to_string(),
|
||||||
|
"disabledForLocalAddresses"
|
||||||
|
);
|
||||||
|
assert_str_eq!(CertificateValidation::Disabled.to_string(), "disabled");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_task_name_display() {
|
fn test_task_name_display() {
|
||||||
assert_str_eq!(
|
assert_str_eq!(
|
||||||
|
|||||||
@@ -11,10 +11,10 @@ use crate::app::RadarrConfig;
|
|||||||
use crate::models::radarr_models::{
|
use crate::models::radarr_models::{
|
||||||
AddMovieBody, AddMovieSearchResult, AddOptions, AddRootFolderBody, BlocklistResponse, Collection,
|
AddMovieBody, AddMovieSearchResult, AddOptions, AddRootFolderBody, BlocklistResponse, Collection,
|
||||||
CollectionMovie, CommandBody, Credit, CreditType, DeleteMovieParams, DiskSpace, DownloadRecord,
|
CollectionMovie, CommandBody, Credit, CreditType, DeleteMovieParams, DiskSpace, DownloadRecord,
|
||||||
DownloadsResponse, EditCollectionParams, EditIndexerParams, EditMovieParams, Indexer,
|
DownloadsResponse, EditCollectionParams, EditIndexerParams, EditMovieParams, HostConfig, Indexer,
|
||||||
IndexerSettings, IndexerTestResult, LogResponse, Movie, MovieCommandBody, MovieHistoryItem,
|
IndexerSettings, IndexerTestResult, LogResponse, Movie, MovieCommandBody, MovieHistoryItem,
|
||||||
QualityProfile, QueueEvent, RadarrSerdeable, Release, ReleaseDownloadBody, RootFolder,
|
QualityProfile, QueueEvent, RadarrSerdeable, Release, ReleaseDownloadBody, RootFolder,
|
||||||
SystemStatus, Tag, Task, TaskName, Update,
|
SecurityConfig, SystemStatus, Tag, Task, TaskName, Update,
|
||||||
};
|
};
|
||||||
use crate::models::servarr_data::radarr::modals::{
|
use crate::models::servarr_data::radarr::modals::{
|
||||||
AddMovieModal, EditCollectionModal, EditIndexerModal, EditMovieModal, IndexerTestResultModalItem,
|
AddMovieModal, EditCollectionModal, EditIndexerModal, EditMovieModal, IndexerTestResultModalItem,
|
||||||
@@ -50,6 +50,7 @@ pub enum RadarrEvent {
|
|||||||
GetBlocklist,
|
GetBlocklist,
|
||||||
GetCollections,
|
GetCollections,
|
||||||
GetDownloads,
|
GetDownloads,
|
||||||
|
GetHostConfig,
|
||||||
GetIndexers,
|
GetIndexers,
|
||||||
GetAllIndexerSettings,
|
GetAllIndexerSettings,
|
||||||
GetLogs(Option<u64>),
|
GetLogs(Option<u64>),
|
||||||
@@ -62,6 +63,7 @@ pub enum RadarrEvent {
|
|||||||
GetQueuedEvents,
|
GetQueuedEvents,
|
||||||
GetReleases(Option<i64>),
|
GetReleases(Option<i64>),
|
||||||
GetRootFolders,
|
GetRootFolders,
|
||||||
|
GetSecurityConfig,
|
||||||
GetStatus,
|
GetStatus,
|
||||||
GetTags,
|
GetTags,
|
||||||
GetTasks,
|
GetTasks,
|
||||||
@@ -86,6 +88,7 @@ impl RadarrEvent {
|
|||||||
RadarrEvent::GetBlocklist => "/blocklist?page=1&pageSize=10000",
|
RadarrEvent::GetBlocklist => "/blocklist?page=1&pageSize=10000",
|
||||||
RadarrEvent::GetCollections | RadarrEvent::EditCollection(_) => "/collection",
|
RadarrEvent::GetCollections | RadarrEvent::EditCollection(_) => "/collection",
|
||||||
RadarrEvent::GetDownloads | RadarrEvent::DeleteDownload(_) => "/queue",
|
RadarrEvent::GetDownloads | RadarrEvent::DeleteDownload(_) => "/queue",
|
||||||
|
RadarrEvent::GetHostConfig | RadarrEvent::GetSecurityConfig => "/config/host",
|
||||||
RadarrEvent::GetIndexers | RadarrEvent::EditIndexer(_) | RadarrEvent::DeleteIndexer(_) => {
|
RadarrEvent::GetIndexers | RadarrEvent::EditIndexer(_) | RadarrEvent::DeleteIndexer(_) => {
|
||||||
"/indexer"
|
"/indexer"
|
||||||
}
|
}
|
||||||
@@ -179,14 +182,15 @@ impl<'a, 'b> Network<'a, 'b> {
|
|||||||
self.edit_indexer(params).await.map(RadarrSerdeable::from)
|
self.edit_indexer(params).await.map(RadarrSerdeable::from)
|
||||||
}
|
}
|
||||||
RadarrEvent::EditMovie(params) => self.edit_movie(params).await.map(RadarrSerdeable::from),
|
RadarrEvent::EditMovie(params) => self.edit_movie(params).await.map(RadarrSerdeable::from),
|
||||||
RadarrEvent::GetBlocklist => self.get_blocklist().await.map(RadarrSerdeable::from),
|
|
||||||
RadarrEvent::GetCollections => self.get_collections().await.map(RadarrSerdeable::from),
|
|
||||||
RadarrEvent::GetDownloads => self.get_downloads().await.map(RadarrSerdeable::from),
|
|
||||||
RadarrEvent::GetIndexers => self.get_indexers().await.map(RadarrSerdeable::from),
|
|
||||||
RadarrEvent::GetAllIndexerSettings => self
|
RadarrEvent::GetAllIndexerSettings => self
|
||||||
.get_all_indexer_settings()
|
.get_all_indexer_settings()
|
||||||
.await
|
.await
|
||||||
.map(RadarrSerdeable::from),
|
.map(RadarrSerdeable::from),
|
||||||
|
RadarrEvent::GetBlocklist => self.get_blocklist().await.map(RadarrSerdeable::from),
|
||||||
|
RadarrEvent::GetCollections => self.get_collections().await.map(RadarrSerdeable::from),
|
||||||
|
RadarrEvent::GetDownloads => self.get_downloads().await.map(RadarrSerdeable::from),
|
||||||
|
RadarrEvent::GetHostConfig => self.get_host_config().await.map(RadarrSerdeable::from),
|
||||||
|
RadarrEvent::GetIndexers => self.get_indexers().await.map(RadarrSerdeable::from),
|
||||||
RadarrEvent::GetLogs(events) => self.get_logs(events).await.map(RadarrSerdeable::from),
|
RadarrEvent::GetLogs(events) => self.get_logs(events).await.map(RadarrSerdeable::from),
|
||||||
RadarrEvent::GetMovieCredits(movie_id) => {
|
RadarrEvent::GetMovieCredits(movie_id) => {
|
||||||
self.get_credits(movie_id).await.map(RadarrSerdeable::from)
|
self.get_credits(movie_id).await.map(RadarrSerdeable::from)
|
||||||
@@ -209,6 +213,7 @@ impl<'a, 'b> Network<'a, 'b> {
|
|||||||
self.get_releases(movie_id).await.map(RadarrSerdeable::from)
|
self.get_releases(movie_id).await.map(RadarrSerdeable::from)
|
||||||
}
|
}
|
||||||
RadarrEvent::GetRootFolders => self.get_root_folders().await.map(RadarrSerdeable::from),
|
RadarrEvent::GetRootFolders => self.get_root_folders().await.map(RadarrSerdeable::from),
|
||||||
|
RadarrEvent::GetSecurityConfig => self.get_security_config().await.map(RadarrSerdeable::from),
|
||||||
RadarrEvent::GetStatus => self.get_status().await.map(RadarrSerdeable::from),
|
RadarrEvent::GetStatus => self.get_status().await.map(RadarrSerdeable::from),
|
||||||
RadarrEvent::GetTags => self.get_tags().await.map(RadarrSerdeable::from),
|
RadarrEvent::GetTags => self.get_tags().await.map(RadarrSerdeable::from),
|
||||||
RadarrEvent::GetTasks => self.get_tasks().await.map(RadarrSerdeable::from),
|
RadarrEvent::GetTasks => self.get_tasks().await.map(RadarrSerdeable::from),
|
||||||
@@ -1354,6 +1359,22 @@ impl<'a, 'b> Network<'a, 'b> {
|
|||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn get_host_config(&mut self) -> Result<HostConfig> {
|
||||||
|
info!("Fetching Radarr host config");
|
||||||
|
|
||||||
|
let request_props = self
|
||||||
|
.radarr_request_props_from(
|
||||||
|
RadarrEvent::GetHostConfig.resource(),
|
||||||
|
RequestMethod::Get,
|
||||||
|
None::<()>,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
self
|
||||||
|
.handle_request::<(), HostConfig>(request_props, |_, _| ())
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
async fn get_indexers(&mut self) -> Result<Vec<Indexer>> {
|
async fn get_indexers(&mut self) -> Result<Vec<Indexer>> {
|
||||||
info!("Fetching Radarr indexers");
|
info!("Fetching Radarr indexers");
|
||||||
|
|
||||||
@@ -1765,6 +1786,22 @@ impl<'a, 'b> Network<'a, 'b> {
|
|||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn get_security_config(&mut self) -> Result<SecurityConfig> {
|
||||||
|
info!("Fetching Radarr security config");
|
||||||
|
|
||||||
|
let request_props = self
|
||||||
|
.radarr_request_props_from(
|
||||||
|
RadarrEvent::GetSecurityConfig.resource(),
|
||||||
|
RequestMethod::Get,
|
||||||
|
None::<()>,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
self
|
||||||
|
.handle_request::<(), SecurityConfig>(request_props, |_, _| ())
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
async fn get_status(&mut self) -> Result<SystemStatus> {
|
async fn get_status(&mut self) -> Result<SystemStatus> {
|
||||||
info!("Fetching Radarr system status");
|
info!("Fetching Radarr system status");
|
||||||
|
|
||||||
|
|||||||
@@ -174,6 +174,13 @@ mod test {
|
|||||||
assert_str_eq!(event.resource(), "/queue");
|
assert_str_eq!(event.resource(), "/queue");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_resource_host_config(
|
||||||
|
#[values(RadarrEvent::GetHostConfig, RadarrEvent::GetSecurityConfig)] event: RadarrEvent,
|
||||||
|
) {
|
||||||
|
assert_str_eq!(event.resource(), "/config/host");
|
||||||
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_resource_command(
|
fn test_resource_command(
|
||||||
#[values(
|
#[values(
|
||||||
@@ -2171,6 +2178,37 @@ mod test {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_handle_get_host_config_event() {
|
||||||
|
let host_config_response = json!({
|
||||||
|
"bindAddress": "*",
|
||||||
|
"port": 7878,
|
||||||
|
"urlBase": "some.test.site/radarr",
|
||||||
|
"instanceName": "Radarr",
|
||||||
|
"applicationUrl": "https://some.test.site:7878/radarr",
|
||||||
|
"enableSsl": true
|
||||||
|
});
|
||||||
|
let response: HostConfig = serde_json::from_value(host_config_response.clone()).unwrap();
|
||||||
|
let (async_server, app_arc, _server) = mock_radarr_api(
|
||||||
|
RequestMethod::Get,
|
||||||
|
None,
|
||||||
|
Some(host_config_response),
|
||||||
|
None,
|
||||||
|
RadarrEvent::GetHostConfig.resource(),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
let mut network = Network::new(&app_arc, CancellationToken::new());
|
||||||
|
|
||||||
|
if let RadarrSerdeable::HostConfig(host_config) = network
|
||||||
|
.handle_radarr_event(RadarrEvent::GetHostConfig)
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
{
|
||||||
|
async_server.assert_async().await;
|
||||||
|
assert_eq!(host_config, response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_handle_get_indexers_event() {
|
async fn test_handle_get_indexers_event() {
|
||||||
let indexers_response_json = json!([{
|
let indexers_response_json = json!([{
|
||||||
@@ -2711,7 +2749,7 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_add_tag() {
|
async fn test_handle_add_tag() {
|
||||||
let tag_json = json!({ "id": 3, "label": "testing" });
|
let tag_json = json!({ "id": 3, "label": "testing" });
|
||||||
let response: Tag = serde_json::from_value(tag_json.clone()).unwrap();
|
let response: Tag = serde_json::from_value(tag_json.clone()).unwrap();
|
||||||
let (async_server, app_arc, _server) = mock_radarr_api(
|
let (async_server, app_arc, _server) = mock_radarr_api(
|
||||||
@@ -2792,6 +2830,38 @@ mod test {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_handle_get_security_config_event() {
|
||||||
|
let security_config_response = json!({
|
||||||
|
"authenticationMethod": "forms",
|
||||||
|
"authenticationRequired": "disabledForLocalAddresses",
|
||||||
|
"username": "test",
|
||||||
|
"password": "some password",
|
||||||
|
"apiKey": "someApiKey12345",
|
||||||
|
"certificateValidation": "disabledForLocalAddresses",
|
||||||
|
});
|
||||||
|
let response: SecurityConfig =
|
||||||
|
serde_json::from_value(security_config_response.clone()).unwrap();
|
||||||
|
let (async_server, app_arc, _server) = mock_radarr_api(
|
||||||
|
RequestMethod::Get,
|
||||||
|
None,
|
||||||
|
Some(security_config_response),
|
||||||
|
None,
|
||||||
|
RadarrEvent::GetSecurityConfig.resource(),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
let mut network = Network::new(&app_arc, CancellationToken::new());
|
||||||
|
|
||||||
|
if let RadarrSerdeable::SecurityConfig(security_config) = network
|
||||||
|
.handle_radarr_event(RadarrEvent::GetSecurityConfig)
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
{
|
||||||
|
async_server.assert_async().await;
|
||||||
|
assert_eq!(security_config, response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_handle_get_movie_credits_event() {
|
async fn test_handle_get_movie_credits_event() {
|
||||||
let credits_json = json!([
|
let credits_json = json!([
|
||||||
|
|||||||
Reference in New Issue
Block a user