Compare commits

..

12 Commits

8 changed files with 596 additions and 346 deletions
+1
View File
@@ -0,0 +1 @@
github: Dark-Alex-17
+22
View File
@@ -0,0 +1,22 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
## [0.1.2](https://github.com/Dark-Alex-17/managarr/compare/v0.1.1...v0.1.2) - 2024-10-30
### Other
- Updated README to a more polished format for the alpha release
## [0.1.1](https://github.com/Dark-Alex-17/managarr/compare/v0.1.0...v0.1.1) - 2024-10-30
### Other
- Final dependency update
- Updated serde version to get minimal_versions job to pass
- Updated strum_macros dependency
Generated
+508 -317
View File
File diff suppressed because it is too large Load Diff
+6 -6
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "managarr" name = "managarr"
version = "0.1.0" version = "0.1.3"
authors = ["Alex Clarke <alex.j.tusa@gmail.com>"] authors = ["Alex Clarke <alex.j.tusa@gmail.com>"]
description = "A TUI and CLI to manage your Servarrs" description = "A TUI and CLI to manage your Servarrs"
keywords = ["managarr", "tui-rs", "dashboard", "servarr", "tui"] keywords = ["managarr", "tui-rs", "dashboard", "servarr", "tui"]
@@ -17,7 +17,7 @@ exclude = [".github", "CONTRIBUTING.md", "*.log", "tags"]
anyhow = "1.0.68" anyhow = "1.0.68"
backtrace = "0.3.67" backtrace = "0.3.67"
bimap = { version = "0.6.3", features = ["serde"] } bimap = { version = "0.6.3", features = ["serde"] }
chrono = { version = "0.4", features = ["serde"] } chrono = { version = "0.4.38", features = ["serde"] }
confy = { version = "0.6.0", default-features = false, features = [ confy = { version = "0.6.0", default-features = false, features = [
"yaml_conf", "yaml_conf",
] } ] }
@@ -27,13 +27,13 @@ human-panic = "1.1.3"
indoc = "2.0.0" indoc = "2.0.0"
log = "0.4.17" log = "0.4.17"
log4rs = { version = "1.2.0", features = ["file_appender"] } log4rs = { version = "1.2.0", features = ["file_appender"] }
regex = "1.7.1" regex = "1.11.1"
reqwest = { version = "0.11.14", features = ["json"] } reqwest = { version = "0.11.14", features = ["json"] }
serde_yaml = "0.9.16" serde_yaml = "0.9.16"
serde_json = "1.0.91" serde_json = "1.0.91"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0.214", features = ["derive"] }
strum = { version = "0.26.1", features = ["derive"] } strum = { version = "0.26.3", features = ["derive"] }
strum_macros = "0.26.1" strum_macros = "0.26.4"
tokio = { version = "1.36.0", features = ["full"] } tokio = { version = "1.36.0", features = ["full"] }
tokio-util = "0.7.8" tokio-util = "0.7.8"
ratatui = { version = "0.28.0", features = ["all-widgets"] } ratatui = { version = "0.28.0", features = ["all-widgets"] }
+1 -1
View File
@@ -23,4 +23,4 @@ FROM debian:stable-slim
# Copy the compiled binary from the builder container # Copy the compiled binary from the builder container
COPY --from=builder --chown=nonroot:nonroot /usr/src/managarr-temp/managarr /usr/local/bin COPY --from=builder --chown=nonroot:nonroot /usr/src/managarr-temp/managarr /usr/local/bin
ENTRYPOINT [ "/usr/local/bin/managarr" ] ENTRYPOINT [ "/usr/local/bin/managarr", "--disable-terminal-size-checks" ]
+3
View File
@@ -32,6 +32,9 @@ lint-fix:
fmt: fmt:
@cargo fmt @cargo fmt
minimal-versions:
@cargo +nightly update -Zdirect-minimal-versions
## Analyze for unsafe usage - `cargo install cargo-geiger` ## Analyze for unsafe usage - `cargo install cargo-geiger`
analyze: analyze:
@cargo geiger @cargo geiger
+17 -10
View File
@@ -45,6 +45,14 @@ cargo install managarr
cargo install --locked managarr cargo install --locked managarr
``` ```
### Docker
Run Managarr as a docker container by mounting your `config.yml` file to `/root/.config/managarr/config.yml`. For example:
```shell
docker run --rm -it -v ~/.config/managarr:/root/.config/managarr darkalex17/managarr
```
You can also clone this repo and run `make docker` to build a docker image locally and run it using the above command.
## Features ## Features
### Radarr ### Radarr
@@ -156,16 +164,6 @@ $ managarr radarr list movies | jq '.[] | select(.title == "Ad Astra") | .id'
277 277
``` ```
## Installation
### Docker
Run Managarr as a docker container by mounting your `config.yml` file to `/root/.config/managarr/config.yml`. For example:
```shell
docker run --rm -it -v ~/.config/managarr:/root/.config/managarr darkalex17/managarr
```
You can also clone this repo and run `make docker` to build a docker image locally and run it using the above command.
# Configuration # Configuration
Managarr assumes reasonable defaults to connect to each service (i.e. Radarr is on localhost:7878), Managarr assumes reasonable defaults to connect to each service (i.e. Radarr is on localhost:7878),
but all servers will require you to input the API token. but all servers will require you to input the API token.
@@ -187,6 +185,15 @@ $HOME/Library/Application Support/managarr/config.yml
%APPDATA%/Roaming/managarr/config.yml %APPDATA%/Roaming/managarr/config.yml
``` ```
## Specify Configuration File
It can sometimes be useful to specify the configuration file you wish to use. This is useful in cases
where you may have more than one instance of a given Servarr running. Thus, you can specify the
config file using the `--config` flag:
```shell
managarr --config /path/to/config.yml
```
### Example Configuration: ### Example Configuration:
```yaml ```yaml
radarr: radarr:
+38 -12
View File
@@ -1,12 +1,16 @@
#![warn(rust_2018_idioms)] #![warn(rust_2018_idioms)]
use std::fs::File;
use std::io::BufReader;
use std::panic::PanicHookInfo; use std::panic::PanicHookInfo;
use std::path::PathBuf;
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc; use std::sync::Arc;
use std::{io, panic, process}; use std::{io, panic, process};
use anyhow::anyhow; use anyhow::anyhow;
use anyhow::Result; use anyhow::Result;
use app::AppConfig;
use clap::{ use clap::{
command, crate_authors, crate_description, crate_name, crate_version, CommandFactory, Parser, command, crate_authors, crate_description, crate_name, crate_version, CommandFactory, Parser,
}; };
@@ -62,6 +66,22 @@ static MIN_TERM_HEIGHT: u16 = 40;
struct Cli { struct Cli {
#[command(subcommand)] #[command(subcommand)]
command: Option<Command>, command: Option<Command>,
#[arg(
long,
global = true,
value_parser,
help = "The Managarr configuration file to use"
)]
config: Option<PathBuf>,
#[arg(long, global = true, help = "Disable the terminal size checks")]
disable_terminal_size_checks: bool,
}
fn load_config(path: &str) -> Result<AppConfig> {
let file = File::open(path).map_err(|e| anyhow!(e))?;
let reader = BufReader::new(file);
let config = serde_yaml::from_reader(reader)?;
Ok(config)
} }
#[tokio::main] #[tokio::main]
@@ -73,7 +93,11 @@ async fn main() -> Result<()> {
let running = Arc::new(AtomicBool::new(true)); let running = Arc::new(AtomicBool::new(true));
let r = running.clone(); let r = running.clone();
let args = Cli::parse(); let args = Cli::parse();
let config = confy::load("managarr", "config")?; let config = if let Some(ref config_file) = args.config {
load_config(config_file.to_str().expect("Invalid config file specified"))?
} else {
confy::load("managarr", "config")?
};
let (sync_network_tx, sync_network_rx) = mpsc::channel(500); let (sync_network_tx, sync_network_rx) = mpsc::channel(500);
let cancellation_token = CancellationToken::new(); let cancellation_token = CancellationToken::new();
let ctrlc_cancellation_token = cancellation_token.clone(); let ctrlc_cancellation_token = cancellation_token.clone();
@@ -110,7 +134,7 @@ async fn main() -> Result<()> {
None => { None => {
let app_nw = Arc::clone(&app); let app_nw = Arc::clone(&app);
std::thread::spawn(move || start_networking(sync_network_rx, &app_nw, cancellation_token)); std::thread::spawn(move || start_networking(sync_network_rx, &app_nw, cancellation_token));
start_ui(&app).await?; start_ui(&app, !args.disable_terminal_size_checks).await?;
} }
} }
@@ -132,16 +156,18 @@ async fn start_networking(
} }
} }
async fn start_ui(app: &Arc<Mutex<App<'_>>>) -> Result<()> { async fn start_ui(app: &Arc<Mutex<App<'_>>>, check_terminal_size: bool) -> Result<()> {
let (width, height) = size()?; if check_terminal_size {
if width < MIN_TERM_WIDTH || height < MIN_TERM_HEIGHT { let (width, height) = size()?;
return Err(anyhow!( if width < MIN_TERM_WIDTH || height < MIN_TERM_HEIGHT {
"Terminal too small. Minimum size required: {}x{}; current terminal size: {}x{}", return Err(anyhow!(
MIN_TERM_WIDTH, "Terminal too small. Minimum size required: {}x{}; current terminal size: {}x{}",
MIN_TERM_HEIGHT, MIN_TERM_WIDTH,
width, MIN_TERM_HEIGHT,
height width,
)); height
));
}
} }
let mut stdout = io::stdout(); let mut stdout = io::stdout();