From 1f0445952332d96acadecb936d9eaa7169d52082 Mon Sep 17 00:00:00 2001 From: Benedikt Peetz Date: Mon, 7 Oct 2024 19:43:13 +0200 Subject: feat(cli): Add a `add` command This command allows adding URLs directly. Otherwise, the process would be: `yt subs add ` -> `yt update` -> `yt subs remove ` --- src/select/cmds.rs | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 58 insertions(+), 2 deletions(-) (limited to 'src/select/cmds.rs') diff --git a/src/select/cmds.rs b/src/select/cmds.rs index 3a7a800..b45cc48 100644 --- a/src/select/cmds.rs +++ b/src/select/cmds.rs @@ -11,14 +11,19 @@ use crate::{ app::App, cli::{SelectCommand, SharedSelectionCommandArgs}, + download::download_options::download_opts, storage::video_database::{ + self, getters::get_video_by_hash, - setters::{set_video_options, set_video_status}, + setters::{add_video, set_video_options, set_video_status}, VideoOptions, VideoStatus, }, + update::video_entry_to_video, }; -use anyhow::{Context, Result}; +use anyhow::{bail, Context, Result}; +use futures::future::join_all; +use yt_dlp::wrapper::info_json::InfoType; pub async fn handle_select_cmd( app: &App, @@ -35,6 +40,57 @@ pub async fn handle_select_cmd( SelectCommand::Watched { shared } => { handle_status_change(app, shared, line_number, VideoStatus::Watched).await?; } + SelectCommand::Add { urls } => { + for url in urls { + let opts = download_opts( + &app, + video_database::YtDlpOptions { + subtitle_langs: "".to_owned(), + }, + ); + let entry = yt_dlp::extract_info(&opts, &url, false, true) + .await + .with_context(|| format!("Failed to fetch entry for url: '{}'", url))?; + + async fn add_entry( + app: &App, + entry: yt_dlp::wrapper::info_json::InfoJson, + ) -> Result<()> { + let video = video_entry_to_video(entry, None)?; + println!("{}", video.to_color_display(app).await?); + add_video(app, video).await?; + + Ok(()) + } + + match entry._type { + Some(InfoType::Video) => { + add_entry(&app, entry).await?; + } + Some(InfoType::Playlist) => { + if let Some(mut entries) = entry.entries { + if !entries.is_empty() { + // Pre-warm the cache + add_entry(app, entries.remove(0)).await?; + + let futures: Vec<_> = entries + .into_iter() + .map(|entry| add_entry(&app, entry)) + .collect(); + + join_all(futures).await.into_iter().collect::>()?; + } + } else { + bail!("Your playlist does not seem to have any entries!") + } + } + other => bail!( + "Your URL should point to a video or a playlist, but points to a '{:#?}'", + other + ), + } + } + } SelectCommand::Watch { shared } => { let hash = shared.hash.clone().realize(app).await?; -- cgit 1.4.1