about summary refs log tree commit diff stats
path: root/src/select/cmds.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/select/cmds.rs')
-rw-r--r--src/select/cmds.rs60
1 files changed, 58 insertions, 2 deletions
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::<Result<_>>()?;
+                            }
+                        } 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?;