Skip to content

Commit

Permalink
Added basic sorting options.
Browse files Browse the repository at this point in the history
  • Loading branch information
Supergamer1337 committed Mar 23, 2023
1 parent 3002777 commit b41d3cf
Show file tree
Hide file tree
Showing 5 changed files with 197 additions and 58 deletions.
62 changes: 62 additions & 0 deletions src/arguments.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
use color_eyre::Result;
use itertools::Itertools;
use once_cell::sync::OnceCell;
use std::env;

use crate::{Order, SortingOption};

static INSTANCE: OnceCell<Arguments> = OnceCell::new();

#[derive(Debug)]
pub struct Arguments {
pub sorting: Option<SortingOption>,
}

impl Arguments {
pub fn get_args() -> &'static Arguments {
INSTANCE.get().expect("Arguments have not been initialised")
}

pub fn read_args() -> Result<()> {
if let Some(_) = INSTANCE.get() {
return Ok(());
}

let mut args = env::args().collect_vec();

let args = Arguments {
sorting: Self::read_sort(&mut args),
};

INSTANCE
.set(args)
.expect("Arguments have already been initialized...");
Ok(())
}

fn read_sort(args: &mut Vec<String>) -> Option<SortingOption> {
for (i, arg) in args.iter_mut().enumerate() {
match arg.as_str() {
"-n" => {
args.swap_remove(i);
return Some(SortingOption::Name(Order::Asc));
}
"-nd" => {
args.swap_remove(i);
return Some(SortingOption::Name(Order::Desc));
}
"-s" => {
args.swap_remove(i);
return Some(SortingOption::Size(Order::Desc));
}
"-sa" => {
args.swap_remove(i);
return Some(SortingOption::Size(Order::Asc));
}
_ => continue,
}
}

None
}
}
2 changes: 1 addition & 1 deletion src/arr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ impl Display for TvData {
0 => "unknown".to_string(),
count => count.to_string()
}.yellow(),
&format!("{}%", self.percent_of_episodes_on_disk).blue(),
&format!("{:.2}%", self.percent_of_episodes_on_disk).blue(),
)
}
}
Expand Down
7 changes: 5 additions & 2 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use once_cell::sync::OnceCell;
use serde::Deserialize;
use std::fs;

static INSTANCE: OnceCell<Config> = OnceCell::new();
#[derive(Debug, Deserialize)]
pub struct Config {
#[serde(default = "default_items_shown")]
Expand Down Expand Up @@ -44,14 +45,16 @@ pub struct Radarr {
pub url: String,
}

static INSTANCE: OnceCell<Config> = OnceCell::new();

impl Config {
pub fn global() -> &'static Config {
INSTANCE.get().expect("Config has not been initialized.")
}

pub fn read_conf() -> Result<()> {
if let Some(_) = INSTANCE.get() {
return Ok(());
}

let reader = fs::File::open("config.yaml")?;
let mut conf: Config = serde_yaml::from_reader(reader)?;

Expand Down
144 changes: 128 additions & 16 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
mod arguments;
mod arr;
mod config;
mod media_item;
Expand All @@ -8,11 +9,15 @@ mod tautulli;
mod utils;

use color_eyre::{eyre::eyre, Report, Result};
use futures::future;
use itertools::Itertools;
use overseerr::MediaRequest;
use std::{io, process::Command};

use arguments::Arguments;
use config::Config;
use dialoguer::MultiSelect;
use media_item::{gather_requests_data, CompleteMediaItem};
use media_item::{CompleteMediaItem, MediaItem};

use crate::utils::human_file_size;

Expand All @@ -22,13 +27,15 @@ async fn main() -> Result<()> {

read_and_validate_config()?;

let (mut requests, errs) = gather_requests_data().await?;
Arguments::read_args()?;

show_requests_result(&requests, errs)?;
let mut requests = gather_requests_data().await?;

show_requests_result(&requests)?;

clear_screen()?;

let chosen = choose_items_to_delete(&requests)?;
let chosen = choose_items_to_delete(&mut requests)?;

delete_chosen_items(&mut requests, &chosen).await?;

Expand All @@ -48,20 +55,42 @@ fn read_and_validate_config() -> Result<()> {
Ok(())
}

fn show_requests_result(requests: &Vec<CompleteMediaItem>, errs: Vec<Report>) -> Result<()> {
show_potential_request_errors(errs)?;
async fn gather_requests_data() -> Result<Vec<CompleteMediaItem>> {
println!("Gathering all required data from your services.\nDepending on the amount of requests and your connection speed, this could take a while...");

if requests.len() == 0 {
println!("You do not seem to have any valid requests, with data available.");
println!("Are you sure all your requests are available and downloaded? Or some data was unable to be acquired from other services.");
println!("Either try again later, or look over your requests.");
let requests = MediaRequest::get_all().await?;

println!();
wait(None)?;
std::process::exit(0);
}
let futures = requests
.into_iter()
.map(MediaItem::from_request)
.filter(|i| i.is_available() && i.has_manager_active())
.map(|item| {
tokio::spawn(async move {
let item = item.into_complete().await?;

Ok(())
Ok::<CompleteMediaItem, Report>(item)
})
});

let mut errors: Vec<Report> = Vec::new();

let complete_items = future::try_join_all(futures)
.await?
.into_iter()
.filter_map(|f| match f {
Ok(item) => Some(item),
Err(err) => {
errors.push(err);
None
}
})
.unique_by(|item| item.title.clone())
.sorted_by(|item1, item2| item1.title.cmp(&item2.title))
.collect();

show_potential_request_errors(errors)?;

Ok(complete_items)
}

fn show_potential_request_errors(errs: Vec<Report>) -> Result<()> {
Expand Down Expand Up @@ -98,7 +127,23 @@ fn show_potential_request_errors(errs: Vec<Report>) -> Result<()> {
Ok(())
}

fn choose_items_to_delete(requests: &Vec<CompleteMediaItem>) -> Result<Vec<usize>> {
fn show_requests_result(requests: &Vec<CompleteMediaItem>) -> Result<()> {
if requests.len() == 0 {
println!("You do not seem to have any valid requests, with data available.");
println!("Are you sure all your requests are available and downloaded? Or some data was unable to be acquired from other services.");
println!("Either try again later, or look over your requests.");

println!();
wait(None)?;
std::process::exit(0);
}

Ok(())
}

fn choose_items_to_delete(requests: &mut Vec<CompleteMediaItem>) -> Result<Vec<usize>> {
choose_sorting(requests)?;

clear_screen()?;

let items_to_show = Config::global().items_shown;
Expand All @@ -120,6 +165,73 @@ fn choose_items_to_delete(requests: &Vec<CompleteMediaItem>) -> Result<Vec<usize
Ok(chosen)
}

#[derive(Debug, Clone, Copy)]
pub enum Order {
Desc,
Asc,
}

#[derive(Debug, Clone, Copy)]
pub enum SortingOption {
Name(Order),
Size(Order),
}

impl Default for SortingOption {
fn default() -> Self {
Self::Name(Order::Asc)
}
}

fn choose_sorting(requests: &mut Vec<CompleteMediaItem>) -> Result<()> {
clear_screen()?;

let args = Arguments::get_args();

let sort = match args.sorting {
Some(sort) => sort,
None => choose_sorting_dialogue()?,
};

match sort {
SortingOption::Name(Order::Desc) => return Ok(requests.reverse()),
SortingOption::Name(Order::Asc) => return Ok(()),
SortingOption::Size(Order::Asc) => {
return Ok(requests.sort_by_key(|req| req.get_disk_size()))
}
SortingOption::Size(Order::Desc) => {
return Ok(
requests.sort_by(|req1, req2| req2.get_disk_size().cmp(&req1.get_disk_size()))
)
}
}
}

fn choose_sorting_dialogue() -> Result<SortingOption> {
loop {
println!("Choose sorting method:");
println!("Name - Ascending: n (or just enter, it's the default)");
println!("Name - Descending: nd");
println!("Size - Descending: s");
println!("Size - Ascending: sa");

let input = get_user_input()?;

match input
.strip_suffix("\r\n")
.or(input.strip_suffix("\n"))
.unwrap_or(&input)
{
"nd" => return Ok(SortingOption::Name(Order::Desc)),
"n" => return Ok(SortingOption::Name(Order::Asc)),
"sa" => return Ok(SortingOption::Size(Order::Asc)),
"s" => return Ok(SortingOption::Size(Order::Desc)),
"" => return Ok(SortingOption::default()),
_ => (),
};
}
}

fn verify_chosen(requests: &Vec<CompleteMediaItem>, chosen: &Vec<usize>) -> Result<()> {
let total_size: String = human_file_size(
chosen
Expand Down
40 changes: 1 addition & 39 deletions src/media_item.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
use color_eyre::{eyre::eyre, owo_colors::OwoColorize, Report, Result};
use futures::future::{self};
use itertools::Itertools;
use color_eyre::{eyre::eyre, owo_colors::OwoColorize, Result};
use std::fmt::{Debug, Display};
use tokio::try_join;

Expand Down Expand Up @@ -120,42 +118,6 @@ impl CompleteMediaItem {
}
}

pub async fn gather_requests_data() -> Result<(Vec<CompleteMediaItem>, Vec<Report>)> {
println!("Gathering all required data from your services.\nDepending on the amount of requests and your connection speed,this could take a while...");

let requests = MediaRequest::get_all().await?;

let futures = requests
.into_iter()
.map(MediaItem::from_request)
.filter(|i| i.is_available() && i.has_manager_active())
.map(|item| {
tokio::spawn(async move {
let item = item.into_complete().await?;

Ok::<CompleteMediaItem, Report>(item)
})
});

let mut errors: Vec<Report> = Vec::new();

let complete_items = future::try_join_all(futures)
.await?
.into_iter()
.filter_map(|f| match f {
Ok(item) => Some(item),
Err(err) => {
errors.push(err);
None
}
})
.unique_by(|item| item.title.clone())
.sorted_by(|item1, item2| item1.title.cmp(&item2.title))
.collect();

Ok((complete_items, errors))
}

impl Display for CompleteMediaItem {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
Expand Down

0 comments on commit b41d3cf

Please sign in to comment.