aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--hm/soispha/pkgs/default.nix1
-rw-r--r--hm/soispha/pkgs/scripts.nix21
-rwxr-xr-xhm/soispha/pkgs/scripts/specific/ytcc/ytc127
-rw-r--r--sys/nixpkgs/pkgs/default.nix3
-rw-r--r--sys/nixpkgs/pkgs/ytc/.gitignore3
-rw-r--r--sys/nixpkgs/pkgs/ytc/Cargo.lock635
-rw-r--r--sys/nixpkgs/pkgs/ytc/Cargo.toml15
-rw-r--r--sys/nixpkgs/pkgs/ytc/default.nix17
-rw-r--r--sys/nixpkgs/pkgs/ytc/package.nix19
-rw-r--r--sys/nixpkgs/pkgs/ytc/src/downloader.rs146
-rw-r--r--sys/nixpkgs/pkgs/ytc/src/main.rs188
11 files changed, 1027 insertions, 148 deletions
diff --git a/hm/soispha/pkgs/default.nix b/hm/soispha/pkgs/default.nix
index dd4fac1e..ce63341f 100644
--- a/hm/soispha/pkgs/default.nix
+++ b/hm/soispha/pkgs/default.nix
@@ -84,6 +84,7 @@ with pkgs; let
View = [
imv # Image viewer
ytcc # Command line tool to keep track of your favorite playlists on YouTube and many other places.
+ ytc # My tool to download the videos (used in conjunction with the entry above)
];
Listen = [
diff --git a/hm/soispha/pkgs/scripts.nix b/hm/soispha/pkgs/scripts.nix
index dc562c0d..f69bc4cf 100644
--- a/hm/soispha/pkgs/scripts.nix
+++ b/hm/soispha/pkgs/scripts.nix
@@ -230,23 +230,6 @@
path = "wrappers";
dependencies = builtins.attrValues {inherit (pkgs) libvirt;};
};
- ytc-scr = write_shell {
- name = "ytc";
- path = "specific/ytcc";
- dependencies = builtins.attrValues {
- inherit
- (pkgs)
- jq
- yt-dlp
- ytcc
- csvtool
- mpv
- ffmpeg
- gnused
- gawk
- ;
- };
- };
yti-scr = write_shell {
name = "yti";
path = "wrappers";
@@ -257,8 +240,7 @@
path = "specific/ytcc";
keep_path = true; # We need neovim
dependencies = builtins.attrValues {
- inherit (pkgs) ytcc jq gawk;
- inherit ytc-scr;
+ inherit (pkgs) ytcc jq gawk ytc;
};
};
in [
@@ -279,7 +261,6 @@ in [
spodi-scr
update-sys-scr
virsh-del-scr
- ytc-scr
yti-scr
yts-scr
]
diff --git a/hm/soispha/pkgs/scripts/specific/ytcc/ytc b/hm/soispha/pkgs/scripts/specific/ytcc/ytc
deleted file mode 100755
index 5d5da03a..00000000
--- a/hm/soispha/pkgs/scripts/specific/ytcc/ytc
+++ /dev/null
@@ -1,127 +0,0 @@
-#!/usr/bin/env dash
-
-# shellcheck source=/dev/null
-SHELL_LIBRARY_VERSION="1.10.2" . %SHELL_LIBRARY_PATH
-
-# CONSTANTS {{{
-CONCURRENT=4
-OUTPUT_PATH="/tmp/ytcc";
-STATUS_FILE="$XDG_RUNTIME_DIR/ytcc/running";
-STATUS_PATH="$(dirname "$STATUS_FILE")";
-
-col() {
- echo "$1" | csvtool -t ';' -u ';' col "$2" -
-}
-
-play() {
- msg2 "Playing: '$1'"
-
- info_json="$(echo "$1" | sed 's|\(.*\)\.[a-z0-9]\+|\1.info.json|')";
- [ -L "$STATUS_FILE" ] && rm "$STATUS_FILE"
- ln -s "$(readlink -f "$info_json")" "$STATUS_FILE"
-
- mpv "$1" --speed=2.7 --volume=75
- output="$?";
-
- if [ "$output" -eq 0 ]; then
- msg2 "Removing: $1"
- rm "$1"
- msg2 "Marking: " "$2"
- ytcc mark "$2"
- fi
- return "$output"
-}
-
-escape() {
- echo "$1" | awk '{gsub(/;/, ","); print}'
-}
-
-yt_flags="$(mktmp)"
-cat << EOF > "$yt_flags"
---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
-EOF
-# }}}
-
-if [ "$1" = "id" ]; then
- # This is here to keep the sorting in tack
- shift 1
- bases="$(mktmp)";
- for id in "$@"; do
- ytcc --output json list --attributes url --ids "$id" | jq --raw-output 'map("\(.url);\(.id)") | join("\n")' >> "$bases";
- done
-elif [ "$1" = "url" ]; then
- shift 1
- bases="$(mktmp)";
- for url in "$@"; do
- # use 0 as a noop id
- echo "$url;0" >> "$bases";
- done
-else
- die "The first arg must be one of id or url, but it was: '$1'"
-fi
-
-[ -d "$STATUS_PATH" ] || mkdir "$STATUS_PATH";
-[ -d "$OUTPUT_PATH" ] || mkdir "$OUTPUT_PATH";
-cd "$OUTPUT_PATH" || die "(Bug): Was created"
-
-filename_file="$(mktmp)";
-files_to_play="$(mktmp)";
-while read -r base; do
- url="$(col "$base" 1)";
- id="$(col "$base" 2)"
-
- if [ "$old_filename" ]; then
- echo "$(escape "$old_filename");$old_id" >> "$files_to_play"
-
- # Check if the process (pid) exists
- dbg "PID is '$pid'"
- if ! kill -0 "$pid"; then
- saved_base="$(head -n 1 "$files_to_play")";
- sed -i '1d' "$files_to_play";
- saved_name="$(col "$saved_base" 1)";
- saved_id="$(col "$saved_base" 2)"
-
- dbg "Started play for '$saved_name'"
- play "$saved_name" "$saved_id" &
- pid=$!
- else
- dbg "Storing for later '$old_filename'"
- fi
- fi
-
- # The sub shell needs to be unquoted, as the arguments may not be treated as one.
- # shellcheck disable=2046
- yt-dlp $(cat "$yt_flags") --output "%(channel)s/%(title)s.%(ext)s" "$url" --print-to-file after_move:filepath "$filename_file"
-
- filename="$(cat "$filename_file")"
- printf "" > "$filename_file"
-
- if [ "$old_filename" ]; then
- if [ "$(wc -l < "$files_to_play")" -gt "$CONCURRENT" ]; then
- msg2 "Waiting for '$pid' to finish as we already have '$(wc -l < "$files_to_play")' files cached"
- wait "$pid"
- fi
- fi
-
- old_filename="$filename";
- old_id="$id";
-done < "$bases"
-
-wait "$pid"
-echo "$(escape "$old_filename");$old_id" >> "$files_to_play"
-
-while read -r base; do
- name="$(col "$base" 1)";
- id="$(col "$base" 2)"
-
- dbg "Started play for '$name'"
- play "$name" "$id"
-done < "$files_to_play"
-# vim: ft=sh
diff --git a/sys/nixpkgs/pkgs/default.nix b/sys/nixpkgs/pkgs/default.nix
index 8a0898f1..3f9df3ed 100644
--- a/sys/nixpkgs/pkgs/default.nix
+++ b/sys/nixpkgs/pkgs/default.nix
@@ -2,6 +2,7 @@
snap-sync-forked = (import ./snap-sync-forked) {inherit sysLib;};
nvim_plugs = import ./plgs-pkgs;
update_vim_plugins = import ./update_vim_plugins;
- overlays = [] ++ snap-sync-forked ++ nvim_plugs ++ update_vim_plugins;
+ ytc = import ./ytc;
+ overlays = [] ++ snap-sync-forked ++ nvim_plugs ++ update_vim_plugins ++ ytc;
in
overlays
diff --git a/sys/nixpkgs/pkgs/ytc/.gitignore b/sys/nixpkgs/pkgs/ytc/.gitignore
new file mode 100644
index 00000000..c84fa049
--- /dev/null
+++ b/sys/nixpkgs/pkgs/ytc/.gitignore
@@ -0,0 +1,3 @@
+# build dirs
+/target
+/result
diff --git a/sys/nixpkgs/pkgs/ytc/Cargo.lock b/sys/nixpkgs/pkgs/ytc/Cargo.lock
new file mode 100644
index 00000000..630580c1
--- /dev/null
+++ b/sys/nixpkgs/pkgs/ytc/Cargo.lock
@@ -0,0 +1,635 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "android-tzdata"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
+
+[[package]]
+name = "android_system_properties"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "anstream"
+version = "0.6.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d664a92ecae85fd0a7392615844904654d1d5f5514837f471ddef4a057aba1b6"
+dependencies = [
+ "anstyle",
+ "anstyle-parse",
+ "anstyle-query",
+ "anstyle-wincon",
+ "colorchoice",
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87"
+
+[[package]]
+name = "anstyle-parse"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c"
+dependencies = [
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle-query"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648"
+dependencies = [
+ "windows-sys",
+]
+
+[[package]]
+name = "anstyle-wincon"
+version = "3.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7"
+dependencies = [
+ "anstyle",
+ "windows-sys",
+]
+
+[[package]]
+name = "anyhow"
+version = "1.0.79"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca"
+
+[[package]]
+name = "autocfg"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
+
+[[package]]
+name = "bitflags"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
+[[package]]
+name = "bitflags"
+version = "2.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
+
+[[package]]
+name = "bumpalo"
+version = "3.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec"
+
+[[package]]
+name = "cc"
+version = "1.0.83"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "chrono"
+version = "0.4.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38"
+dependencies = [
+ "android-tzdata",
+ "iana-time-zone",
+ "js-sys",
+ "num-traits",
+ "wasm-bindgen",
+ "windows-targets 0.48.5",
+]
+
+[[package]]
+name = "clap"
+version = "4.4.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "52bdc885e4cacc7f7c9eedc1ef6da641603180c783c41a15c264944deeaab642"
+dependencies = [
+ "clap_builder",
+ "clap_derive",
+]
+
+[[package]]
+name = "clap_builder"
+version = "4.4.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fb7fb5e4e979aec3be7791562fcba452f94ad85e954da024396433e0e25a79e9"
+dependencies = [
+ "anstream",
+ "anstyle",
+ "clap_lex",
+ "strsim",
+]
+
+[[package]]
+name = "clap_derive"
+version = "4.4.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "clap_lex"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
+
+[[package]]
+name = "cli-log"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3d2ab00dc4c82ec28af25ac085aecc11ffeabf353755715a3113a7aa044ca5cc"
+dependencies = [
+ "chrono",
+ "file-size",
+ "log",
+ "proc-status",
+]
+
+[[package]]
+name = "colorchoice"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
+
+[[package]]
+name = "core-foundation-sys"
+version = "0.8.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
+
+[[package]]
+name = "errno"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"
+dependencies = [
+ "libc",
+ "windows-sys",
+]
+
+[[package]]
+name = "fastrand"
+version = "2.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
+
+[[package]]
+name = "file-size"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9544f10105d33957765016b8a9baea7e689bf1f0f2f32c2fa2f568770c38d2b3"
+
+[[package]]
+name = "heck"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
+
+[[package]]
+name = "iana-time-zone"
+version = "0.1.59"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6a67363e2aa4443928ce15e57ebae94fd8949958fd1223c4cfc0cd473ad7539"
+dependencies = [
+ "android_system_properties",
+ "core-foundation-sys",
+ "iana-time-zone-haiku",
+ "js-sys",
+ "wasm-bindgen",
+ "windows-core",
+]
+
+[[package]]
+name = "iana-time-zone-haiku"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
+dependencies = [
+ "cc",
+]
+
+[[package]]
+name = "itoa"
+version = "1.0.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
+
+[[package]]
+name = "js-sys"
+version = "0.3.66"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca"
+dependencies = [
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "libc"
+version = "0.2.151"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4"
+
+[[package]]
+name = "linux-raw-sys"
+version = "0.4.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456"
+
+[[package]]
+name = "log"
+version = "0.4.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
+
+[[package]]
+name = "num-traits"
+version = "0.2.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.19.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.75"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "907a61bd0f64c2f29cd1cf1dc34d05176426a3f504a78010f08416ddb7b13708"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "proc-status"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f0e0c0ac915e7b76b47850ba4ffc377abde6c6ff9eeace61d0a89623db449712"
+dependencies = [
+ "thiserror",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
+dependencies = [
+ "bitflags 1.3.2",
+]
+
+[[package]]
+name = "rustix"
+version = "0.38.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316"
+dependencies = [
+ "bitflags 2.4.1",
+ "errno",
+ "libc",
+ "linux-raw-sys",
+ "windows-sys",
+]
+
+[[package]]
+name = "ryu"
+version = "1.0.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c"
+
+[[package]]
+name = "serde"
+version = "1.0.194"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b114498256798c94a0689e1a15fec6005dee8ac1f41de56404b67afc2a4b773"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.194"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a3385e45322e8f9931410f01b3031ec534c3947d0e94c18049af4d9f9907d4e0"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.111"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4"
+dependencies = [
+ "itoa",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "strsim"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
+
+[[package]]
+name = "syn"
+version = "2.0.48"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "tempfile"
+version = "3.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa"
+dependencies = [
+ "cfg-if",
+ "fastrand",
+ "redox_syscall",
+ "rustix",
+ "windows-sys",
+]
+
+[[package]]
+name = "thiserror"
+version = "1.0.56"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.56"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
+
+[[package]]
+name = "utf8parse"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
+
+[[package]]
+name = "wasm-bindgen"
+version = "0.2.89"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e"
+dependencies = [
+ "cfg-if",
+ "wasm-bindgen-macro",
+]
+
+[[package]]
+name = "wasm-bindgen-backend"
+version = "0.2.89"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826"
+dependencies = [
+ "bumpalo",
+ "log",
+ "once_cell",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-macro"
+version = "0.2.89"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2"
+dependencies = [
+ "quote",
+ "wasm-bindgen-macro-support",
+]
+
+[[package]]
+name = "wasm-bindgen-macro-support"
+version = "0.2.89"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wasm-bindgen-backend",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-shared"
+version = "0.2.89"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f"
+
+[[package]]
+name = "windows-core"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
+dependencies = [
+ "windows-targets 0.52.0",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
+dependencies = [
+ "windows-targets 0.52.0",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
+dependencies = [
+ "windows_aarch64_gnullvm 0.48.5",
+ "windows_aarch64_msvc 0.48.5",
+ "windows_i686_gnu 0.48.5",
+ "windows_i686_msvc 0.48.5",
+ "windows_x86_64_gnu 0.48.5",
+ "windows_x86_64_gnullvm 0.48.5",
+ "windows_x86_64_msvc 0.48.5",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
+dependencies = [
+ "windows_aarch64_gnullvm 0.52.0",
+ "windows_aarch64_msvc 0.52.0",
+ "windows_i686_gnu 0.52.0",
+ "windows_i686_msvc 0.52.0",
+ "windows_x86_64_gnu 0.52.0",
+ "windows_x86_64_gnullvm 0.52.0",
+ "windows_x86_64_msvc 0.52.0",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
+
+[[package]]
+name = "ytc"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "clap",
+ "cli-log",
+ "log",
+ "serde",
+ "serde_json",
+ "tempfile",
+]
diff --git a/sys/nixpkgs/pkgs/ytc/Cargo.toml b/sys/nixpkgs/pkgs/ytc/Cargo.toml
new file mode 100644
index 00000000..f958b9c6
--- /dev/null
+++ b/sys/nixpkgs/pkgs/ytc/Cargo.toml
@@ -0,0 +1,15 @@
+[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
new file mode 100644
index 00000000..de247115
--- /dev/null
+++ b/sys/nixpkgs/pkgs/ytc/default.nix
@@ -0,0 +1,17 @@
+[
+ (
+ final: prev: {
+ ytc = import ./package.nix {
+ inherit
+ (prev)
+ rustPlatform
+ # dependencies
+
+ ytcc
+ yt-dlp
+ mpv
+ ;
+ };
+ }
+ )
+]
diff --git a/sys/nixpkgs/pkgs/ytc/package.nix b/sys/nixpkgs/pkgs/ytc/package.nix
new file mode 100644
index 00000000..8c02f073
--- /dev/null
+++ b/sys/nixpkgs/pkgs/ytc/package.nix
@@ -0,0 +1,19 @@
+{
+ rustPlatform,
+ ytcc,
+ yt-dlp,
+ mpv,
+}:
+rustPlatform.buildRustPackage {
+ pname = "ytc";
+ version = "0.1.0";
+
+ src = ./.;
+ cargoHash = "sha256-KogHeuKKYhhpfSg+ImPCO4RwxWMOhSBXa3OjwCBZxEE=";
+
+ buildInputs = [
+ ytcc
+ yt-dlp
+ mpv
+ ];
+}
diff --git a/sys/nixpkgs/pkgs/ytc/src/downloader.rs b/sys/nixpkgs/pkgs/ytc/src/downloader.rs
new file mode 100644
index 00000000..9509278c
--- /dev/null
+++ b/sys/nixpkgs/pkgs/ytc/src/downloader.rs
@@ -0,0 +1,146 @@
+use std::{
+ io::{stderr, stdout, Read},
+ mem,
+ path::PathBuf,
+ process::Command,
+ sync::mpsc::{self, Receiver, Sender},
+ thread::{self, JoinHandle},
+};
+
+use anyhow::{bail, Context, Result};
+use log::debug;
+
+use crate::PlayThing;
+
+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";
+
+pub struct Downloader {
+ sent: usize,
+ download_thread: JoinHandle<Result<()>>,
+ orx: Receiver<(PathBuf, Option<u32>)>,
+ itx: Option<Sender<PlayThing>>,
+ playspec: Vec<PlayThing>,
+}
+
+impl Downloader {
+ pub fn new(mut playspec: Vec<PlayThing>) -> anyhow::Result<Downloader> {
+ let (itx, irx): (Sender<PlayThing>, Receiver<PlayThing>) = mpsc::channel();
+ let (otx, orx) = mpsc::channel();
+ let jh = thread::spawn(move || -> Result<()> {
+ while let Some(pt) = irx.recv().ok() {
+ debug!("Got '{}|{}' to be downloaded", pt.url, pt.id.unwrap_or(0));
+ let path = download_url(&pt.url)
+ .with_context(|| format!("Failed to download url: '{}'", &pt.url))?;
+ otx.send((path, pt.id)).expect("Should not be dropped");
+ }
+ debug!("Finished Downloading everything");
+ Ok(())
+ });
+
+ playspec.reverse();
+ let mut output = Downloader {
+ sent: 0,
+ download_thread: jh,
+ orx,
+ itx: Some(itx),
+ playspec,
+ };
+ if output.playspec.len() <= CONCURRENT as usize {
+ output.add(output.playspec.len() as u32)?;
+ } else {
+ output.add(CONCURRENT)?;
+ }
+ Ok(output)
+ }
+
+ pub fn add(&mut self, number_to_add: u32) -> Result<()> {
+ debug!("Adding {} to be downloaded concurrently", number_to_add);
+ for _ in 0..number_to_add {
+ let pt = self.playspec.pop().context("No more playthings to pop")?;
+ self.itx.as_ref().expect("Should still be valid").send(pt)?;
+ }
+ Ok(())
+ }
+
+ /// Return the next video already downloaded, will block until the download is complete
+ pub fn next(&mut self) -> Option<(PathBuf, Option<u32>)> {
+ debug!("Requesting next output");
+ match self.orx.recv() {
+ Ok(ok) => {
+ debug!("Output downloaded to: {}", ok.0.display());
+ self.sent += 1;
+ if self.sent < self.playspec.len() {
+ debug!("Will add 1");
+ self.add(1).ok()?;
+ } else {
+ debug!("Will drop sender");
+ let itx = mem::take(&mut self.itx);
+ drop(itx)
+ }
+ debug!("Returning: {:#?}", ok);
+ Some(ok)
+ }
+ Err(err) => {
+ debug!("Recieved error while listening: {}", err);
+ None
+ }
+ }
+ }
+ pub fn drop(self) -> anyhow::Result<()> {
+ match self.download_thread.join() {
+ Ok(ok) => ok,
+ Err(err) => panic!("Can't join thread: '{:#?}'", err),
+ }
+ }
+}
+
+fn download_url(url: &str) -> Result<PathBuf> {
+ let output_file = tempfile::NamedTempFile::new().context("Failed to create tempfile")?;
+ output_file
+ .as_file()
+ .set_len(0)
+ .context("Failed to truncate temp-file")?;
+ let mut yt_dlp = Command::new("yt-dlp");
+ yt_dlp.current_dir(DOWNLOAD_DIR);
+ yt_dlp.stdout(stdout());
+ yt_dlp.stderr(stderr());
+ yt_dlp.args(YT_DLP_FLAGS);
+ yt_dlp.args([
+ "--output",
+ "%(channel)s/%(title)s.%(ext)s",
+ url,
+ "--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);
+ }
+ }
+ let mut path = String::new();
+ output_file
+ .as_file()
+ .read_to_string(&mut path)
+ .context("Failed to read output file temp file")?;
+ let path = path.trim();
+ Ok(path.into())
+}
diff --git a/sys/nixpkgs/pkgs/ytc/src/main.rs b/sys/nixpkgs/pkgs/ytc/src/main.rs
new file mode 100644
index 00000000..5c7849b8
--- /dev/null
+++ b/sys/nixpkgs/pkgs/ytc/src/main.rs
@@ -0,0 +1,188 @@
+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 {
+ bail!(
+ "The status path ('{}') is not a symlink!",
+ 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 let Some(id) = id {
+ if code == 0 {
+ println!("\x1b[32;1mMarking {} as watched!\x1b[0m", id);
+ fs::remove_file(&path)?;
+ 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)
+}