about summary refs log tree commit diff stats
path: root/sys/nixpkgs/pkgs/yt/src/bin
diff options
context:
space:
mode:
Diffstat (limited to 'sys/nixpkgs/pkgs/yt/src/bin')
-rw-r--r--sys/nixpkgs/pkgs/yt/src/bin/yt/main.rs110
-rw-r--r--sys/nixpkgs/pkgs/yt/src/bin/ytc/args.rs26
-rw-r--r--sys/nixpkgs/pkgs/yt/src/bin/ytc/main.rs75
-rw-r--r--sys/nixpkgs/pkgs/yt/src/bin/yts/args.rs41
-rw-r--r--sys/nixpkgs/pkgs/yt/src/bin/yts/main.rs109
5 files changed, 361 insertions, 0 deletions
diff --git a/sys/nixpkgs/pkgs/yt/src/bin/yt/main.rs b/sys/nixpkgs/pkgs/yt/src/bin/yt/main.rs
new file mode 100644
index 00000000..54d89daa
--- /dev/null
+++ b/sys/nixpkgs/pkgs/yt/src/bin/yt/main.rs
@@ -0,0 +1,110 @@
+use anyhow::{bail, Context, Result};
+use std::{
+    env,
+    io::{BufRead, BufReader, BufWriter, Write},
+    process::Command as StdCmd,
+};
+use tempfile::NamedTempFile;
+use yt::{
+    constants::HELP_STR,
+    downloader::{Downloadable, Downloader},
+    ytcc_drop, Duration, Line, LineCommand, YtccListData,
+};
+
+fn main() -> Result<()> {
+    cli_log::init_cli_log!();
+
+    let json_map = {
+        let mut ytcc = StdCmd::new("ytcc");
+        ytcc.args([
+            "--output",
+            "json",
+            "list",
+            "--order-by",
+            "publish_date",
+            "desc",
+        ]);
+
+        serde_json::from_slice::<Vec<YtccListData>>(
+            &ytcc.output().context("Failed to json from ytcc")?.stdout,
+        )
+        .context("Failed to deserialize json output")?
+    };
+
+    let temp_file = NamedTempFile::new().context("Failed to get tempfile")?;
+    let mut edit_file = BufWriter::new(&temp_file);
+
+    json_map
+        .iter()
+        .map(|line| {
+            format!(
+                r#"pick {} "{}" "{}" "{}" "{}" "{}"{}"#,
+                line.id,
+                line.title.replace('"', "'"),
+                line.publish_date,
+                line.playlists
+                    .iter()
+                    .map(|p| p.name.replace('"', "'"))
+                    .collect::<Vec<String>>()
+                    .join(", "),
+                Duration::from(line.duration.trim()),
+                line.url.replace('"', "'"),
+                "\n"
+            )
+        })
+        .for_each(|line| {
+            edit_file
+                .write(line.as_bytes())
+                .expect("This write should not fail");
+        });
+
+    edit_file.write(HELP_STR.as_bytes())?;
+    edit_file.flush().context("Failed to flush edit file")?;
+
+    let read_file = temp_file.reopen()?;
+
+    let mut nvim = StdCmd::new("nvim");
+    nvim.arg(temp_file.path());
+
+    let status = nvim.status().context("Falied to run nvim")?;
+    if !status.success() {
+        bail!("nvim exited with error status: {}", status)
+    }
+
+    let mut watching = Vec::new();
+    let reader = BufReader::new(&read_file);
+    for line in reader.lines() {
+        let line = line.context("Failed to read line")?;
+
+        if line.starts_with("#") {
+            // comment
+            continue;
+        } else if line.trim().len() == 0 {
+            // empty line
+            continue;
+        }
+
+        let line = Line::from(line.as_str());
+        match line.cmd {
+            LineCommand::Pick => (),
+            LineCommand::Drop => {
+                ytcc_drop(line.id).with_context(|| format!("Failed to drop: {}", line.id))?
+            }
+            LineCommand::Watch => watching.push(Downloadable {
+                id: Some(line.id),
+                url: line.url,
+            }),
+        }
+    }
+
+    if watching.len() == 0 {
+        return Ok(());
+    }
+
+    let downloader = Downloader::new(watching).context("Failed to construct downloader")?;
+    downloader
+        .consume()
+        .context("Failed to consume downloader")?;
+
+    Ok(())
+}
diff --git a/sys/nixpkgs/pkgs/yt/src/bin/ytc/args.rs b/sys/nixpkgs/pkgs/yt/src/bin/ytc/args.rs
new file mode 100644
index 00000000..8b2d6a61
--- /dev/null
+++ b/sys/nixpkgs/pkgs/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/sys/nixpkgs/pkgs/yt/src/bin/ytc/main.rs b/sys/nixpkgs/pkgs/yt/src/bin/ytc/main.rs
new file mode 100644
index 00000000..437df803
--- /dev/null
+++ b/sys/nixpkgs/pkgs/yt/src/bin/ytc/main.rs
@@ -0,0 +1,75 @@
+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",
+                    "--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.len() == 0 {
+                    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(())
+}
diff --git a/sys/nixpkgs/pkgs/yt/src/bin/yts/args.rs b/sys/nixpkgs/pkgs/yt/src/bin/yts/args.rs
new file mode 100644
index 00000000..56989421
--- /dev/null
+++ b/sys/nixpkgs/pkgs/yt/src/bin/yts/args.rs
@@ -0,0 +1,41 @@
+use clap::{Parser, Subcommand};
+/// A helper for selecting which videos to download from ytcc to ytc
+#[derive(Parser, Debug)]
+#[clap(author, version, about, long_about = None)]
+pub struct Args {
+    #[command(subcommand)]
+    /// subcommand to execute
+    pub subcommand: Option<Command>,
+}
+
+#[derive(Subcommand, Debug)]
+pub enum Command {
+    #[clap(value_parser)]
+    /// Which ordering to use
+    Order {
+        #[command(subcommand)]
+        command: OrderCommand,
+    },
+}
+
+#[derive(Subcommand, Debug)]
+pub enum OrderCommand {
+    #[clap(value_parser)]
+    /// Order by date
+    #[group(required = true)]
+    Date {
+        #[arg(value_parser)]
+        /// Order descending
+        desc: bool,
+        #[clap(value_parser)]
+        /// Order ascending
+        asc: bool,
+    },
+    #[clap(value_parser)]
+    /// Pass a raw SQL 'ORDER BY' value
+    Raw {
+        #[clap(value_parser)]
+        /// The raw value(s) to pass
+        value: Vec<String>,
+    },
+}
diff --git a/sys/nixpkgs/pkgs/yt/src/bin/yts/main.rs b/sys/nixpkgs/pkgs/yt/src/bin/yts/main.rs
new file mode 100644
index 00000000..788ecab2
--- /dev/null
+++ b/sys/nixpkgs/pkgs/yt/src/bin/yts/main.rs
@@ -0,0 +1,109 @@
+use anyhow::{bail, Context, Result};
+use clap::Parser;
+use std::{
+    env,
+    io::{BufRead, BufReader, Write},
+    process::Command as StdCmd,
+};
+use tempfile::NamedTempFile;
+use yt::{constants::HELP_STR, ytcc_drop, Line, LineCommand, YtccListData};
+
+use crate::args::{Args, Command, OrderCommand};
+
+mod args;
+
+fn main() -> Result<()> {
+    let args = Args::parse();
+    cli_log::init_cli_log!();
+
+    let ordering = match args.subcommand.unwrap_or(Command::Order {
+        command: OrderCommand::Date {
+            desc: true,
+            asc: false,
+        },
+    }) {
+        Command::Order { command } => match command {
+            OrderCommand::Date { desc, asc } => {
+                if desc {
+                    vec!["--order-by".into(), "publish_date".into(), "desc".into()]
+                } else if asc {
+                    vec!["--order-by".into(), "publish_date".into(), "asc".into()]
+                } else {
+                    vec!["--order-by".into(), "publish_date".into(), "desc".into()]
+                }
+            }
+            OrderCommand::Raw { value } => [vec!["--order-by".into()], value].concat(),
+        },
+    };
+
+    let json_map = {
+        let mut ytcc = StdCmd::new("ytcc");
+        ytcc.args(["--output", "json", "list"]);
+        ytcc.args(ordering);
+
+        serde_json::from_slice::<Vec<YtccListData>>(
+            &ytcc.output().context("Failed to json from ytcc")?.stdout,
+        )
+        .context("Failed to deserialize json output")?
+    };
+
+    let mut edit_file = NamedTempFile::new().context("Failed to get tempfile")?;
+
+    let file: String = json_map
+        .iter()
+        .map(|line| {
+            format!(
+                "pick {} \"{}\" <{}> [{}]\n",
+                line.id,
+                line.title,
+                line.playlists
+                    .iter()
+                    .map(|p| &p.name[..])
+                    .collect::<Vec<&str>>()
+                    .join(", "),
+                line.duration.trim()
+            )
+        })
+        .collect();
+
+    for line in file.lines() {
+        writeln!(&edit_file, "{}", line)?;
+    }
+    write!(&edit_file, "{}", HELP_STR)?;
+    edit_file.flush().context("Failed to flush edit file")?;
+
+    let read_file = edit_file.reopen()?;
+
+    let mut nvim = StdCmd::new("nvim");
+    nvim.arg(edit_file.path());
+
+    let status = nvim.status().context("Falied to run nvim")?;
+    if !status.success() {
+        bail!("Nvim exited with error status: {}", status)
+    }
+
+    let mut watching = Vec::new();
+    let reader = BufReader::new(&read_file);
+    for line in reader.lines() {
+        let line = line.context("Failed to read line")?;
+
+        if line.starts_with("#") {
+            continue;
+        } else if line.trim().len() == 0 {
+            // empty line
+            continue;
+        }
+
+        let line = Line::from(line.as_str());
+        match line.cmd {
+            LineCommand::Pick => (),
+            LineCommand::Drop => {
+                ytcc_drop(line.id).with_context(|| format!("Failed to drop: {}", line.id))?
+            }
+            LineCommand::Watch => watching.push(line.id),
+        }
+    }
+
+    dbg!(&watching);
+    Ok(())
+}