aboutsummaryrefslogtreecommitdiffstats
path: root/sys/nixpkgs/pkgs/yt/src/bin
diff options
context:
space:
mode:
authorSoispha <soispha@vhack.eu>2024-01-20 12:03:46 +0100
committerSoispha <soispha@vhack.eu>2024-01-20 12:03:46 +0100
commit089c08af03849fb2883a17726462ca0d8ce8b51f (patch)
treed5d9285c6beab0babd16fe533b621ed56280bdd4 /sys/nixpkgs/pkgs/yt/src/bin
parentfeat(hm/conf/nvim/plgs/treesitter): Add custom parser for `yts` (diff)
downloadnixos-config-089c08af03849fb2883a17726462ca0d8ce8b51f.zip
feat(sys/nixpkgs/pkgs/yt): Merge ytc and the rewritten ytc
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(())
+}