aboutsummaryrefslogtreecommitdiffstats
path: root/sys/nixpkgs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--sys/nixpkgs/pkgs/default.nix4
-rwxr-xr-xsys/nixpkgs/pkgs/yt/.env3
-rw-r--r--sys/nixpkgs/pkgs/yt/.gitignore (renamed from sys/nixpkgs/pkgs/ytc/.gitignore)0
-rw-r--r--sys/nixpkgs/pkgs/yt/Cargo.lock (renamed from sys/nixpkgs/pkgs/ytc/Cargo.lock)135
-rw-r--r--sys/nixpkgs/pkgs/yt/Cargo.toml35
-rw-r--r--sys/nixpkgs/pkgs/yt/default.nix51
-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
-rw-r--r--sys/nixpkgs/pkgs/yt/src/constants.rs36
-rw-r--r--sys/nixpkgs/pkgs/yt/src/downloader.rs (renamed from sys/nixpkgs/pkgs/ytc/src/downloader.rs)112
-rw-r--r--sys/nixpkgs/pkgs/yt/src/help.str7
-rw-r--r--sys/nixpkgs/pkgs/yt/src/lib.rs140
-rw-r--r--sys/nixpkgs/pkgs/yt/yt.nix27
-rw-r--r--sys/nixpkgs/pkgs/yt/ytc.nix (renamed from sys/nixpkgs/pkgs/ytc/package.nix)5
-rw-r--r--sys/nixpkgs/pkgs/yt/yts.nix25
-rw-r--r--sys/nixpkgs/pkgs/ytc/Cargo.toml15
-rw-r--r--sys/nixpkgs/pkgs/ytc/default.nix19
-rw-r--r--sys/nixpkgs/pkgs/ytc/src/main.rs193
21 files changed, 871 insertions, 297 deletions
diff --git a/sys/nixpkgs/pkgs/default.nix b/sys/nixpkgs/pkgs/default.nix
index 5096f902..6485e53f 100644
--- a/sys/nixpkgs/pkgs/default.nix
+++ b/sys/nixpkgs/pkgs/default.nix
@@ -2,8 +2,8 @@
snap-sync-forked = (import ./snap-sync-forked) {inherit sysLib;};
nvim_plugs = import ./plgs-pkgs;
update_vim_plugins = import ./update_vim_plugins;
- ytc = import ./ytc;
+ yt = import ./yt;
yts-grammar = import ./tree-sitter-yts;
- overlays = snap-sync-forked ++ nvim_plugs ++ update_vim_plugins ++ yts-grammar;
+ overlays = snap-sync-forked ++ nvim_plugs ++ update_vim_plugins ++ yt ++ yts-grammar;
in
overlays
diff --git a/sys/nixpkgs/pkgs/yt/.env b/sys/nixpkgs/pkgs/yt/.env
new file mode 100755
index 00000000..8018a738
--- /dev/null
+++ b/sys/nixpkgs/pkgs/yt/.env
@@ -0,0 +1,3 @@
+#!/usr/bin/env sh
+
+PATH="$(pwd)/target/release/:$(pwd)/target/debug/:$PATH"
diff --git a/sys/nixpkgs/pkgs/ytc/.gitignore b/sys/nixpkgs/pkgs/yt/.gitignore
index c84fa049..c84fa049 100644
--- a/sys/nixpkgs/pkgs/ytc/.gitignore
+++ b/sys/nixpkgs/pkgs/yt/.gitignore
diff --git a/sys/nixpkgs/pkgs/ytc/Cargo.lock b/sys/nixpkgs/pkgs/yt/Cargo.lock
index 630580c1..1f5501d6 100644
--- a/sys/nixpkgs/pkgs/ytc/Cargo.lock
+++ b/sys/nixpkgs/pkgs/yt/Cargo.lock
@@ -19,9 +19,9 @@ dependencies = [
[[package]]
name = "anstream"
-version = "0.6.5"
+version = "0.6.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d664a92ecae85fd0a7392615844904654d1d5f5514837f471ddef4a057aba1b6"
+checksum = "6e2e1ebcb11de5c03c67de28a7df593d32191b44939c482e97702baaaa6ab6a5"
dependencies = [
"anstyle",
"anstyle-parse",
@@ -85,9 +85,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
-version = "2.4.1"
+version = "2.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
+checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf"
[[package]]
name = "bumpalo"
@@ -126,9 +126,9 @@ dependencies = [
[[package]]
name = "clap"
-version = "4.4.13"
+version = "4.4.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "52bdc885e4cacc7f7c9eedc1ef6da641603180c783c41a15c264944deeaab642"
+checksum = "1e578d6ec4194633722ccf9544794b71b1385c3c027efe0c55db226fc880865c"
dependencies = [
"clap_builder",
"clap_derive",
@@ -136,9 +136,9 @@ dependencies = [
[[package]]
name = "clap_builder"
-version = "4.4.12"
+version = "4.4.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fb7fb5e4e979aec3be7791562fcba452f94ad85e954da024396433e0e25a79e9"
+checksum = "4df4df40ec50c46000231c914968278b1eb05098cf8f1b3a518a95030e71d1c7"
dependencies = [
"anstream",
"anstyle",
@@ -211,6 +211,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9544f10105d33957765016b8a9baea7e689bf1f0f2f32c2fa2f568770c38d2b3"
[[package]]
+name = "form_urlencoded"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
+dependencies = [
+ "percent-encoding",
+]
+
+[[package]]
name = "heck"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -240,6 +249,16 @@ dependencies = [
]
[[package]]
+name = "idna"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6"
+dependencies = [
+ "unicode-bidi",
+ "unicode-normalization",
+]
+
+[[package]]
name = "itoa"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -247,24 +266,24 @@ checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
[[package]]
name = "js-sys"
-version = "0.3.66"
+version = "0.3.67"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca"
+checksum = "9a1d36f1235bc969acba30b7f5990b864423a6068a10f7c90ae8f0112e3a59d1"
dependencies = [
"wasm-bindgen",
]
[[package]]
name = "libc"
-version = "0.2.151"
+version = "0.2.152"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4"
+checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7"
[[package]]
name = "linux-raw-sys"
-version = "0.4.12"
+version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456"
+checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c"
[[package]]
name = "log"
@@ -288,10 +307,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
+name = "percent-encoding"
+version = "2.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
+
+[[package]]
name = "proc-macro2"
-version = "1.0.75"
+version = "1.0.76"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "907a61bd0f64c2f29cd1cf1dc34d05176426a3f504a78010f08416ddb7b13708"
+checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c"
dependencies = [
"unicode-ident",
]
@@ -325,11 +350,11 @@ dependencies = [
[[package]]
name = "rustix"
-version = "0.38.28"
+version = "0.38.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316"
+checksum = "322394588aaf33c24007e8bb3238ee3e4c5c09c084ab32bc73890b99ff326bca"
dependencies = [
- "bitflags 2.4.1",
+ "bitflags 2.4.2",
"errno",
"libc",
"linux-raw-sys",
@@ -344,18 +369,18 @@ checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c"
[[package]]
name = "serde"
-version = "1.0.194"
+version = "1.0.195"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b114498256798c94a0689e1a15fec6005dee8ac1f41de56404b67afc2a4b773"
+checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
-version = "1.0.194"
+version = "1.0.195"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a3385e45322e8f9931410f01b3031ec534c3947d0e94c18049af4d9f9907d4e0"
+checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c"
dependencies = [
"proc-macro2",
"quote",
@@ -424,12 +449,53 @@ dependencies = [
]
[[package]]
+name = "tinyvec"
+version = "1.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
+dependencies = [
+ "tinyvec_macros",
+]
+
+[[package]]
+name = "tinyvec_macros"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
+
+[[package]]
+name = "unicode-bidi"
+version = "0.3.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75"
+
+[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
+name = "unicode-normalization"
+version = "0.1.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
+dependencies = [
+ "tinyvec",
+]
+
+[[package]]
+name = "url"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633"
+dependencies = [
+ "form_urlencoded",
+ "idna",
+ "percent-encoding",
+]
+
+[[package]]
name = "utf8parse"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -437,9 +503,9 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
[[package]]
name = "wasm-bindgen"
-version = "0.2.89"
+version = "0.2.90"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e"
+checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
@@ -447,9 +513,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-backend"
-version = "0.2.89"
+version = "0.2.90"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826"
+checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd"
dependencies = [
"bumpalo",
"log",
@@ -462,9 +528,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
-version = "0.2.89"
+version = "0.2.90"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2"
+checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -472,9 +538,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
-version = "0.2.89"
+version = "0.2.90"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283"
+checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7"
dependencies = [
"proc-macro2",
"quote",
@@ -485,9 +551,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
-version = "0.2.89"
+version = "0.2.90"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f"
+checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b"
[[package]]
name = "windows-core"
@@ -622,7 +688,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
[[package]]
-name = "ytc"
+name = "yt"
version = "0.1.0"
dependencies = [
"anyhow",
@@ -632,4 +698,5 @@ dependencies = [
"serde",
"serde_json",
"tempfile",
+ "url",
]
diff --git a/sys/nixpkgs/pkgs/yt/Cargo.toml b/sys/nixpkgs/pkgs/yt/Cargo.toml
new file mode 100644
index 00000000..faad6699
--- /dev/null
+++ b/sys/nixpkgs/pkgs/yt/Cargo.toml
@@ -0,0 +1,35 @@
+[package]
+name = "yt"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+anyhow = "1.0.79"
+clap = { version = "4.4.13", features = ["derive"] }
+cli-log = "2.0.0"
+log = "0.4.20"
+serde = { version = "1.0.195", features = ["derive"] }
+serde_json = "1.0.111"
+tempfile = "3.9.0"
+url = "2.5.0"
+
+# This is here to be able to tell nix which binary to build
+[features]
+yts = []
+ytc = []
+yt = []
+default = ["yt"]
+
+[[bin]]
+name = "yts"
+required-features = ["yts"]
+
+[[bin]]
+name = "ytc"
+required-features = ["ytc"]
+
+[[bin]]
+name = "yt"
+required-features = ["yt"]
diff --git a/sys/nixpkgs/pkgs/yt/default.nix b/sys/nixpkgs/pkgs/yt/default.nix
new file mode 100644
index 00000000..63bce5c3
--- /dev/null
+++ b/sys/nixpkgs/pkgs/yt/default.nix
@@ -0,0 +1,51 @@
+[
+ (
+ final: prev: {
+ yt = import ./yt.nix {
+ inherit
+ (prev)
+ lib
+ makeWrapper
+ rustPlatform
+ # dependencies
+
+ ytcc
+ yt-dlp
+ mpv
+ ;
+ };
+ }
+ )
+ (
+ final: prev: {
+ yts = import ./yts.nix {
+ inherit
+ (prev)
+ lib
+ makeWrapper
+ rustPlatform
+ # dependencies
+
+ ytcc
+ ;
+ };
+ }
+ )
+ (
+ final: prev: {
+ ytc = import ./ytc.nix {
+ inherit
+ (prev)
+ lib
+ makeWrapper
+ rustPlatform
+ # dependencies
+
+ ytcc
+ yt-dlp
+ mpv
+ ;
+ };
+ }
+ )
+]
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(())
+}
diff --git a/sys/nixpkgs/pkgs/yt/src/constants.rs b/sys/nixpkgs/pkgs/yt/src/constants.rs
new file mode 100644
index 00000000..23e1d9b9
--- /dev/null
+++ b/sys/nixpkgs/pkgs/yt/src/constants.rs
@@ -0,0 +1,36 @@
+use std::{env, fs, path::PathBuf};
+
+pub const HELP_STR: &'static str = include_str!("./help.str");
+
+pub const YT_DLP_FLAGS: [&str; 12] = [
+ "--format",
+ "bestvideo[height<=?1080]+bestaudio/best",
+ "--embed-chapters",
+ "--progress",
+ "--write-comments",
+ "--extractor-args",
+ "youtube:max_comments=150,all,100;comment_sort=top",
+ "--write-info-json",
+ "--sponsorblock-mark",
+ "default",
+ "--sponsorblock-remove",
+ "sponsor",
+];
+pub const MPV_FLAGS: [&str; 2] = ["--speed=2.7", "--volume=75"];
+
+pub const CONCURRENT: u32 = 5;
+
+pub const DOWNLOAD_DIR: &str = "/tmp/ytcc";
+
+const STATUS_PATH: &str = "ytcc/running";
+
+pub fn status_path() -> anyhow::Result<PathBuf> {
+ let out: PathBuf = format!(
+ "{}/{}",
+ env::var("XDG_RUNTIME_DIR").expect("This should always exist"),
+ STATUS_PATH
+ )
+ .into();
+ fs::create_dir_all(&out.parent().expect("Parent should exist"))?;
+ Ok(out)
+}
diff --git a/sys/nixpkgs/pkgs/ytc/src/downloader.rs b/sys/nixpkgs/pkgs/yt/src/downloader.rs
index dddebe05..1733500a 100644
--- a/sys/nixpkgs/pkgs/ytc/src/downloader.rs
+++ b/sys/nixpkgs/pkgs/yt/src/downloader.rs
@@ -1,7 +1,8 @@
use std::{
- fs,
+ fs::{self, canonicalize},
io::{stderr, stdout, Read},
mem,
+ os::unix::fs::symlink,
path::PathBuf,
process::Command,
sync::mpsc::{self, Receiver, Sender},
@@ -9,40 +10,28 @@ use std::{
};
use anyhow::{bail, Context, Result};
-use log::debug;
+use log::{debug, warn};
+use url::Url;
-use crate::PlayThing;
+use crate::constants::{status_path, CONCURRENT, DOWNLOAD_DIR, MPV_FLAGS, YT_DLP_FLAGS};
-const YT_DLP_FLAGS: [&str; 12] = [
- "--format",
- "bestvideo[height<=?1080]+bestaudio/best",
- "--embed-chapters",
- "--progress",
- "--write-comments",
- "--extractor-args",
- "youtube:max_comments=150,all,100;comment_sort=top",
- "--write-info-json",
- "--sponsorblock-mark",
- "default",
- "--sponsorblock-remove",
- "sponsor",
-];
-
-const CONCURRENT: u32 = 5;
-
-const DOWNLOAD_DIR: &str = "/tmp/ytcc";
+#[derive(Debug)]
+pub struct Downloadable {
+ pub url: Url,
+ pub id: Option<u32>,
+}
pub struct Downloader {
sent: usize,
download_thread: JoinHandle<Result<()>>,
orx: Receiver<(PathBuf, Option<u32>)>,
- itx: Option<Sender<PlayThing>>,
- playspec: Vec<PlayThing>,
+ itx: Option<Sender<Downloadable>>,
+ playspec: Vec<Downloadable>,
}
impl Downloader {
- pub fn new(mut playspec: Vec<PlayThing>) -> anyhow::Result<Downloader> {
- let (itx, irx): (Sender<PlayThing>, Receiver<PlayThing>) = mpsc::channel();
+ pub fn new(mut playspec: Vec<Downloadable>) -> anyhow::Result<Downloader> {
+ let (itx, irx): (Sender<Downloadable>, Receiver<Downloadable>) = mpsc::channel();
let (otx, orx) = mpsc::channel();
let jh = thread::spawn(move || -> Result<()> {
while let Some(pt) = irx.recv().ok() {
@@ -91,7 +80,10 @@ impl Downloader {
debug!("Will add 1");
self.add(1).ok()?;
} else {
- debug!("Will drop sender");
+ debug!(
+ "Done sending videos to be downloaded, downoladed: {} videos",
+ self.sent
+ );
let itx = mem::take(&mut self.itx);
drop(itx)
}
@@ -99,7 +91,7 @@ impl Downloader {
Some(ok)
}
Err(err) => {
- debug!("Recieved error while listening: {}", err);
+ debug!("Received error while listening: {}", err);
None
}
}
@@ -110,9 +102,63 @@ impl Downloader {
Err(err) => panic!("Can't join thread: '{:#?}'", err),
}
}
+
+ pub fn consume(mut self) -> anyhow::Result<()> {
+ while let Some((path, id)) = self.next() {
+ debug!("Next path to play is: '{}'", path.display());
+ let mut info_json = canonicalize(&path).context("Failed to canoncialize path")?;
+ info_json.set_extension("info.json");
+
+ if status_path()?.is_symlink() {
+ fs::remove_file(status_path()?).context("Failed to delete old status file")?;
+ } else if !status_path()?.exists() {
+ debug!(
+ "The status path at '{}' does not exists",
+ status_path()?.display()
+ );
+ } else {
+ bail!(
+ "The status path ('{}') is not a symlink but exists!",
+ status_path()?.display()
+ );
+ }
+
+ symlink(info_json, status_path()?).context("Failed to symlink")?;
+
+ let mut mpv = Command::new("mpv");
+ mpv.stdout(stdout());
+ mpv.stderr(stderr());
+ mpv.args(MPV_FLAGS);
+ mpv.arg(&path);
+
+ let status = mpv.status().context("Failed to run mpv")?;
+ if status.success() {
+ fs::remove_file(&path)?;
+ if let Some(id) = id {
+ println!("\x1b[32;1mMarking {} as watched!\x1b[0m", id);
+ let mut ytcc = std::process::Command::new("ytcc");
+ ytcc.stdout(stdout());
+ ytcc.stderr(stderr());
+ ytcc.args(["mark"]);
+ ytcc.arg(id.to_string());
+ let status = ytcc.status().context("Failed to run ytcc")?;
+ if let Some(code) = status.code() {
+ if code != 0 {
+ bail!("Ytcc failed with status: {}", code);
+ }
+ }
+ }
+ debug!("mpv exited with: '{}'", status);
+ } else {
+ warn!("mpv exited with: '{}'", status);
+ }
+ }
+ self.drop()?;
+ Ok(())
+ }
}
-fn download_url(url: &str) -> Result<PathBuf> {
+fn download_url(url: &Url) -> Result<PathBuf> {
let output_file = tempfile::NamedTempFile::new().context("Failed to create tempfile")?;
output_file
.as_file()
@@ -130,17 +176,17 @@ fn download_url(url: &str) -> Result<PathBuf> {
yt_dlp.args([
"--output",
"%(channel)s/%(title)s.%(ext)s",
- url,
+ url.as_str(),
"--print-to-file",
"after_move:filepath",
]);
yt_dlp.arg(output_file.path().as_os_str());
+
let status = yt_dlp.status().context("Failed to run yt-dlp")?;
- if let Some(code) = status.code() {
- if code != 0 {
- bail!("yt_dlp execution failed with error: '{}'", status);
- }
+ if !status.success() {
+ bail!("yt_dlp execution failed with error: '{}'", status);
}
+
let mut path = String::new();
output_file
.as_file()
diff --git a/sys/nixpkgs/pkgs/yt/src/help.str b/sys/nixpkgs/pkgs/yt/src/help.str
new file mode 100644
index 00000000..e5b21fce
--- /dev/null
+++ b/sys/nixpkgs/pkgs/yt/src/help.str
@@ -0,0 +1,7 @@
+# Commands:
+# w, watch <id> = watch id
+# d, drop <id> = mark id as watched
+# p, pick <id> = leave id as is; This is a noop
+#
+# These lines can be re-ordered; they are executed from top to bottom.
+# vim: filetype=yts conceallevel=2 concealcursor=nc colorcolumn=
diff --git a/sys/nixpkgs/pkgs/yt/src/lib.rs b/sys/nixpkgs/pkgs/yt/src/lib.rs
new file mode 100644
index 00000000..a08b32db
--- /dev/null
+++ b/sys/nixpkgs/pkgs/yt/src/lib.rs
@@ -0,0 +1,140 @@
+use anyhow::{bail, Context};
+use serde::Deserialize;
+use url::Url;
+
+pub mod constants;
+pub mod downloader;
+
+#[derive(Deserialize)]
+pub struct YtccListData {
+ pub url: String,
+ pub title: String,
+ pub description: String,
+ pub publish_date: String,
+ pub watch_date: Option<String>,
+ pub duration: String,
+ pub thumbnail_url: String,
+ pub extractor_hash: String,
+ pub id: u32,
+ pub playlists: Vec<YtccPlaylistData>,
+}
+#[derive(Deserialize)]
+pub struct YtccPlaylistData {
+ pub name: String,
+ pub url: String,
+ pub reverse: bool,
+}
+
+pub enum LineCommand {
+ Pick,
+ Drop,
+ Watch,
+}
+
+impl std::str::FromStr for LineCommand {
+ type Err = anyhow::Error;
+ fn from_str(v: &str) -> Result<Self, <Self as std::str::FromStr>::Err> {
+ match v {
+ "pick" | "p" => Ok(Self::Pick),
+ "drop" | "d" => Ok(Self::Drop),
+ "watch" | "w" => Ok(Self::Watch),
+ other => bail!("'{}' is not a recognized command!", other),
+ }
+ }
+}
+
+pub struct Line {
+ pub cmd: LineCommand,
+ pub id: u32,
+ pub url: Url,
+}
+
+/// We expect that each line is correctly formatted, and simply use default ones if they are not
+impl From<&str> for Line {
+ fn from(v: &str) -> Self {
+ let buf: Vec<_> = v.split_whitespace().collect();
+ let url: Url = Url::parse(
+ buf.last()
+ .expect("This should always exists")
+ .trim_matches('"'),
+ )
+ .expect("This parsing should work,as the url is generated");
+
+ Line {
+ cmd: buf
+ .get(0)
+ .unwrap_or(&"pick")
+ .parse()
+ .unwrap_or(LineCommand::Pick),
+ id: buf.get(1).unwrap_or(&"0").parse().unwrap_or(0),
+ url,
+ }
+ }
+}
+
+pub struct Duration {
+ time: u32,
+}
+
+impl From<&str> for Duration {
+ fn from(v: &str) -> Self {
+ let buf: Vec<_> = v.split(':').take(2).collect();
+ Self {
+ time: (buf[0]
+ .parse::<u32>()
+ .expect("Should be a number")
+ * 60)
+ + buf[1]
+ .parse::<u32>()
+ .expect("Should be a number"),
+ }
+ }
+}
+
+impl std::fmt::Display for Duration {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
+ const SECOND: u32 = 1;
+ const MINUTE: u32 = 60 * SECOND;
+ const HOUR: u32 = 60 * MINUTE;
+
+ let base_hour = self.time - (self.time % HOUR);
+ let base_min = (self.time % HOUR) - ((self.time % HOUR) % MINUTE);
+ let base_sec = ((self.time % HOUR) % MINUTE) - (((self.time % HOUR) % MINUTE) % SECOND);
+
+ let h = base_hour / HOUR;
+ let m = base_min / MINUTE;
+ let s = base_sec / SECOND;
+
+ if self.time == 0 {
+ write!(f, "[No Duration]")
+ } else if h > 0 {
+ write!(f, "[{h}h {m}m]")
+ } else {
+ write!(f, "[{m}m {s}s]")
+ }
+ }
+}
+#[cfg(test)]
+mod test {
+ use crate::Duration;
+
+ #[test]
+ fn test_display_duration_1h() {
+ let dur = Duration { time: 60 * 60 };
+ assert_eq!("[1h 0m]".to_owned(), dur.to_string());
+ }
+ #[test]
+ fn test_display_duration_30min() {
+ let dur = Duration { time: 60 * 30 };
+ assert_eq!("[30m 0s]".to_owned(), dur.to_string());
+ }
+}
+
+pub fn ytcc_drop(id: u32) -> anyhow::Result<()> {
+ let mut ytcc = std::process::Command::new("ytcc");
+ ytcc.args(["mark", &format!("{}", id)]);
+ if !ytcc.status().context("Failed to run ytcc")?.success() {
+ bail!("`ytcc mark {}` failed to execute", id)
+ }
+ Ok(())
+}
diff --git a/sys/nixpkgs/pkgs/yt/yt.nix b/sys/nixpkgs/pkgs/yt/yt.nix
new file mode 100644
index 00000000..184b7820
--- /dev/null
+++ b/sys/nixpkgs/pkgs/yt/yt.nix
@@ -0,0 +1,27 @@
+{
+ lib,
+ rustPlatform,
+ ytcc,
+ yt-dlp,
+ mpv,
+ makeWrapper,
+}:
+rustPlatform.buildRustPackage {
+ pname = "yt";
+ version = "0.1.0";
+
+ src = ./.;
+ cargoHash = "sha256-AlrixMGbBa+VJZDzplQZwFV9Mp3STjCJUD6zV/JmUyA=";
+
+ buildNoDefaultFeatures = true;
+ buildFeatures = ["yt"];
+
+ nativeBuildInputs = [
+ makeWrapper
+ ];
+
+ postInstall = ''
+ wrapProgram $out/bin/yt \
+ --set PATH ${lib.makeBinPath [mpv yt-dlp ytcc]}
+ '';
+}
diff --git a/sys/nixpkgs/pkgs/ytc/package.nix b/sys/nixpkgs/pkgs/yt/ytc.nix
index 5428ee18..8967ea35 100644
--- a/sys/nixpkgs/pkgs/ytc/package.nix
+++ b/sys/nixpkgs/pkgs/yt/ytc.nix
@@ -11,7 +11,10 @@ rustPlatform.buildRustPackage {
version = "0.1.0";
src = ./.;
- cargoHash = "sha256-KogHeuKKYhhpfSg+ImPCO4RwxWMOhSBXa3OjwCBZxEE=";
+ cargoHash = "sha256-X3bw6p09RttYR/6unu4rGawbmrBuDV8QNzaQlg1cBrs=";
+
+ buildNoDefaultFeatures = true;
+ buildFeatures = ["ytc"];
nativeBuildInputs = [
makeWrapper
diff --git a/sys/nixpkgs/pkgs/yt/yts.nix b/sys/nixpkgs/pkgs/yt/yts.nix
new file mode 100644
index 00000000..fa00dc48
--- /dev/null
+++ b/sys/nixpkgs/pkgs/yt/yts.nix
@@ -0,0 +1,25 @@
+{
+ lib,
+ rustPlatform,
+ ytcc,
+ makeWrapper,
+}:
+rustPlatform.buildRustPackage {
+ pname = "yts";
+ version = "0.1.0";
+
+ src = ./.;
+ cargoHash = "sha256-vtf58M+qTEbgqSMFgaB67mhI4cEXtlQFMTbgmWFoxX4=";
+
+ buildNoDefaultFeatures = true;
+ buildFeatures = ["yts"];
+
+ nativeBuildInputs = [
+ makeWrapper
+ ];
+
+ postInstall = ''
+ wrapProgram $out/bin/yts \
+ --set PATH ${lib.makeBinPath [ytcc]}
+ '';
+}
diff --git a/sys/nixpkgs/pkgs/ytc/Cargo.toml b/sys/nixpkgs/pkgs/ytc/Cargo.toml
deleted file mode 100644
index f958b9c6..00000000
--- a/sys/nixpkgs/pkgs/ytc/Cargo.toml
+++ /dev/null
@@ -1,15 +0,0 @@
-[package]
-name = "ytc"
-version = "0.1.0"
-edition = "2021"
-
-# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
-
-[dependencies]
-anyhow = "1.0.79"
-clap = { version = "4.4.13", features = ["derive"] }
-cli-log = "2.0.0"
-log = "0.4.20"
-serde = { version = "1.0.194", features = ["derive"] }
-serde_json = "1.0.111"
-tempfile = "3.9.0"
diff --git a/sys/nixpkgs/pkgs/ytc/default.nix b/sys/nixpkgs/pkgs/ytc/default.nix
deleted file mode 100644
index d437b84a..00000000
--- a/sys/nixpkgs/pkgs/ytc/default.nix
+++ /dev/null
@@ -1,19 +0,0 @@
-[
- (
- final: prev: {
- ytc = import ./package.nix {
- inherit
- (prev)
- lib
- makeWrapper
- rustPlatform
- # dependencies
-
- ytcc
- yt-dlp
- mpv
- ;
- };
- }
- )
-]
diff --git a/sys/nixpkgs/pkgs/ytc/src/main.rs b/sys/nixpkgs/pkgs/ytc/src/main.rs
deleted file mode 100644
index 75084851..00000000
--- a/sys/nixpkgs/pkgs/ytc/src/main.rs
+++ /dev/null
@@ -1,193 +0,0 @@
-use std::{
- env,
- fs::{self, canonicalize},
- io::{stderr, stdout},
- os::unix::fs::symlink,
- path::PathBuf,
- process::Command as StdCmd,
-};
-
-use anyhow::{bail, Context, Result};
-use clap::{Parser, Subcommand};
-use downloader::Downloader;
-use log::debug;
-use serde::Deserialize;
-
-mod downloader;
-
-const STATUS_PATH: &str = "ytcc/running";
-
-/// 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>,
- },
-}
-
-struct PlayThing {
- url: String,
- id: Option<u32>,
-}
-
-#[derive(Deserialize)]
-struct YtccListData {
- url: String,
- #[allow(unused)]
- title: String,
- #[allow(unused)]
- description: String,
- #[allow(unused)]
- publish_date: String,
- #[allow(unused)]
- watch_date: Option<String>,
- #[allow(unused)]
- duration: String,
- #[allow(unused)]
- thumbnail_url: String,
- #[allow(unused)]
- extractor_hash: String,
- id: u32,
- #[allow(unused)]
- playlists: Vec<YtccPlaylistData>,
-}
-#[derive(Deserialize)]
-struct YtccPlaylistData {
- #[allow(unused)]
- name: String,
- #[allow(unused)]
- url: String,
- #[allow(unused)]
- reverse: bool,
-}
-
-fn main() -> Result<()> {
- let args = Args::parse();
- cli_log::init_cli_log!();
-
- let playspec: Vec<PlayThing> = 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(PlayThing {
- url: json.url.clone(),
- id: Some(json.id),
- })
- }
- output
- }
- Command::Url { urls } => urls
- .into_iter()
- .map(|url| PlayThing { url, id: None })
- .collect(),
- };
-
- debug!("Initializing downloader");
- let mut downloader = Downloader::new(playspec)?;
-
- while let Some((path, id)) = downloader.next() {
- debug!("Next path to play is: '{}'", path.display());
- let mut info_json = canonicalize(&path).context("Failed to canoncialize path")?;
- info_json.set_extension("info.json");
-
- if status_path()?.is_symlink() {
- fs::remove_file(status_path()?).context("Failed to delete old status file")?;
- } else if !status_path()?.exists() {
- debug!(
- "The status path at '{}' does not exists",
- status_path()?.display()
- );
- } else {
- bail!(
- "The status path ('{}') is not a symlink but exists!",
- status_path()?.display()
- );
- }
-
- symlink(info_json, status_path()?).context("Failed to symlink")?;
-
- let mut mpv = StdCmd::new("mpv");
- // mpv.stdout(stdout());
- mpv.stderr(stderr());
- mpv.args(["--speed=2.7", "--volume=75"]);
- mpv.arg(&path);
-
- let status = mpv.status().context("Failed to run mpv")?;
- if let Some(code) = status.code() {
- if code == 0 {
- fs::remove_file(&path)?;
- if let Some(id) = id {
- println!("\x1b[32;1mMarking {} as watched!\x1b[0m", id);
- let mut ytcc = StdCmd::new("ytcc");
- ytcc.stdout(stdout());
- ytcc.stderr(stderr());
- ytcc.args(["mark"]);
- ytcc.arg(id.to_string());
- let status = ytcc.status().context("Failed to run ytcc")?;
- if let Some(code) = status.code() {
- if code != 0 {
- bail!("Ytcc failed with status: {}", code);
- }
- }
- }
- }
- debug!("Mpv exited with: {}", code);
- }
- }
- downloader.drop()?;
-
- Ok(())
-}
-
-fn status_path() -> Result<PathBuf> {
- let out: PathBuf = format!(
- "{}/{}",
- env::var("XDG_RUNTIME_DIR").expect("This should always exist"),
- STATUS_PATH
- )
- .into();
- fs::create_dir_all(&out.parent().expect("Parent should exist"))?;
- Ok(out)
-}