diff options
Diffstat (limited to 'src/main.rs')
-rw-r--r-- | src/main.rs | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..cfd6adc --- /dev/null +++ b/src/main.rs @@ -0,0 +1,163 @@ +// yt - A fully featured command line YouTube client +// +// Copyright (C) 2024 Benedikt Peetz <benedikt.peetz@b-peetz.de> +// SPDX-License-Identifier: GPL-3.0-or-later +// +// This file is part of Yt. +// +// You should have received a copy of the License along with this program. +// If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>. + +use std::{collections::HashMap, fs}; + +use anyhow::{bail, Context, Result}; +use app::App; +use cache::invalidate; +use clap::Parser; +use cli::{CacheCommand, CheckCommand, SelectCommand, SubscriptionCommand}; +use select::cmds::handle_select_cmd; +use tokio::{ + fs::File, + io::{stdin, BufReader}, +}; +use url::Url; +use yt_dlp::wrapper::info_json::InfoJson; + +use crate::{cli::Command, storage::subscriptions::get_subscriptions}; + +pub mod app; +pub mod cli; + +pub mod cache; +pub mod comments; +pub mod constants; +pub mod download; +pub mod select; +pub mod status; +pub mod storage; +pub mod subscribe; +pub mod update; +pub mod watch; + +#[tokio::main] +async fn main() -> Result<()> { + let args = cli::CliArgs::parse(); + stderrlog::new() + .module(module_path!()) + .modules(&["yt_dlp".to_owned(), "libmpv2".to_owned()]) + .quiet(args.quiet) + .show_module_names(false) + .color(stderrlog::ColorChoice::Auto) + .verbosity(args.verbosity as usize) + .timestamp(stderrlog::Timestamp::Off) + .init() + .expect("Let's just hope that this does not panic"); + + let app = App::new().await?; + + match args.command.unwrap_or(Command::default()) { + Command::Download { force } => { + if force { + invalidate(&app, true).await?; + } + + download::Downloader::new().consume(&app).await?; + } + Command::Select { cmd } => { + let cmd = cmd.unwrap_or(SelectCommand::default()); + + match cmd { + SelectCommand::File { done } => select::select(&app, done).await?, + _ => handle_select_cmd(&app, cmd, None).await?, + } + } + Command::Update { + max_backlog, + subscriptions, + concurrent_processes, + } => { + let all_subs = get_subscriptions(&app).await?; + + for sub in &subscriptions { + if let None = all_subs.0.get(sub) { + bail!( + "Your specified subscription to update '{}' is not a subscription!", + sub + ) + } + } + + update::update(&app, max_backlog, subscriptions, concurrent_processes).await?; + } + + Command::Subscriptions { cmd } => match cmd { + SubscriptionCommand::Add { name, url } => { + subscribe::subscribe(&app, name, url) + .await + .context("Failed to add a subscription")?; + } + SubscriptionCommand::Remove { name } => { + subscribe::unsubscribe(&app, name) + .await + .context("Failed to remove a subscription")?; + } + SubscriptionCommand::List { url } => { + let all_subs = get_subscriptions(&app).await?; + + if url { + for val in all_subs.0.values() { + println!("{}", val.url); + } + } else { + for (key, val) in all_subs.0 { + println!("{}: '{}'", key, val.url); + } + } + } + SubscriptionCommand::Import { file, force } => { + if let Some(file) = file { + let f = File::open(file).await?; + + subscribe::import(&app, BufReader::new(f), force).await? + } else { + subscribe::import(&app, BufReader::new(stdin()), force).await? + }; + } + }, + + Command::Watch {} => watch::watch(&app).await?, + + Command::Status {} => status::show(&app).await?, + + Command::Database { command } => match command { + CacheCommand::Invalidate { hard } => cache::invalidate(&app, hard).await?, + CacheCommand::Maintain { all } => cache::maintain(&app, all).await?, + }, + + Command::Check { command } => match command { + CheckCommand::InfoJson { path } => { + let string = fs::read_to_string(&path) + .with_context(|| format!("Failed to read '{}' to string!", path.display()))?; + + let _: InfoJson = + serde_json::from_str(&string).context("Failed to deserialize value")?; + } + CheckCommand::UpdateInfoJson { path } => { + let string = fs::read_to_string(&path) + .with_context(|| format!("Failed to read '{}' to string!", path.display()))?; + + let _: HashMap<Url, InfoJson> = + serde_json::from_str(&string).context("Failed to deserialize value")?; + } + }, + Command::Comments {} => { + comments::comments(&app).await?; + } + Command::Description {} => { + todo!() + // description::description(&app).await?; + } + } + + Ok(()) +} |