about summary refs log tree commit diff stats
path: root/pkgs/sources/yt/src/bin/ytc
diff options
context:
space:
mode:
Diffstat (limited to 'pkgs/sources/yt/src/bin/ytc')
-rw-r--r--pkgs/sources/yt/src/bin/ytc/args.rs26
-rw-r--r--pkgs/sources/yt/src/bin/ytc/main.rs77
2 files changed, 103 insertions, 0 deletions
diff --git a/pkgs/sources/yt/src/bin/ytc/args.rs b/pkgs/sources/yt/src/bin/ytc/args.rs
new file mode 100644
index 00000000..8b2d6a61
--- /dev/null
+++ b/pkgs/sources/yt/src/bin/ytc/args.rs
@@ -0,0 +1,26 @@
+use clap::{Parser, Subcommand};
+/// A helper for downloading and playing youtube videos
+#[derive(Parser, Debug)]
+#[clap(author, version, about, long_about = None)]
+pub struct Args {
+    #[command(subcommand)]
+    /// The subcommand to execute
+    pub subcommand: Command,
+}
+#[derive(Subcommand, Debug)]
+pub enum Command {
+    #[clap(value_parser)]
+    /// Work based of ytcc ids
+    Id {
+        #[clap(value_parser)]
+        /// A list of ids to play
+        ids: Vec<u32>,
+    },
+    #[clap(value_parser)]
+    /// Work based of raw youtube urls
+    Url {
+        #[clap(value_parser)]
+        /// A list of urls to play
+        urls: Vec<String>,
+    },
+}
diff --git a/pkgs/sources/yt/src/bin/ytc/main.rs b/pkgs/sources/yt/src/bin/ytc/main.rs
new file mode 100644
index 00000000..b38157df
--- /dev/null
+++ b/pkgs/sources/yt/src/bin/ytc/main.rs
@@ -0,0 +1,77 @@
+use std::{env, process::Command as StdCmd};
+
+use anyhow::{bail, Context, Result};
+use clap::Parser;
+use log::debug;
+use url::Url;
+use yt::{
+    downloader::{Downloadable, Downloader},
+    YtccListData,
+};
+
+use crate::args::{Args, Command};
+
+mod args;
+
+fn main() -> Result<()> {
+    let args = Args::parse();
+    cli_log::init_cli_log!();
+
+    let playspec: Vec<Downloadable> = match args.subcommand {
+        Command::Id { ids } => {
+            let mut output = Vec::with_capacity(ids.len());
+            for id in ids {
+                debug!("Adding {}", id);
+                let mut ytcc = StdCmd::new("ytcc");
+                ytcc.args([
+                    "--output",
+                    "json",
+                    "list",
+                    "--watched",
+                    "--unwatched",
+                    "--attributes",
+                    "url",
+                    "--ids",
+                    id.to_string().as_str(),
+                ]);
+                let json = serde_json::from_slice::<Vec<YtccListData>>(
+                    &ytcc.output().context("Failed to get url from id")?.stdout,
+                )
+                .context("Failed to deserialize json output")?;
+
+                if json.is_empty() {
+                    bail!("Could not find a video with id: {}", id);
+                }
+                assert_eq!(json.len(), 1);
+                let json = json.first().expect("Has only one element");
+
+                debug!("Id resolved to: '{}'", &json.url);
+
+                output.push(Downloadable {
+                    url: Url::parse(&json.url)?,
+                    id: Some(json.id),
+                })
+            }
+            output
+        }
+        Command::Url { urls } => {
+            let mut output = Vec::with_capacity(urls.len());
+            for url in urls {
+                output.push(Downloadable {
+                    url: Url::parse(&url).context("Failed to parse url")?,
+                    id: None,
+                })
+            }
+            output
+        }
+    };
+
+    debug!("Initializing downloader");
+    let downloader = Downloader::new(playspec)?;
+
+    downloader
+        .consume()
+        .context("Failed to consume downloader")?;
+
+    Ok(())
+}