about summary refs log tree commit diff stats
path: root/pkgs/by-name/yt
diff options
context:
space:
mode:
authorBenedikt Peetz <benedikt.peetz@b-peetz.de>2024-05-23 13:26:22 +0200
committerBenedikt Peetz <benedikt.peetz@b-peetz.de>2024-05-23 13:26:22 +0200
commit204731c0a69136c9cebcb54f1afecf5145e26bbe (patch)
treefc9132e5dc74e4a8e1327cdd411839a90f9410aa /pkgs/by-name/yt
parentrefactor(sys): Modularize and move to `modules/system` or `pkgs` (diff)
downloadnixos-config-204731c0a69136c9cebcb54f1afecf5145e26bbe.tar.gz
nixos-config-204731c0a69136c9cebcb54f1afecf5145e26bbe.zip
refactor(pkgs): Categorize into `by-name` shards
This might not be the perfect way to organize a package set --
especially if the set is not nearly the size of nixpkgs -- but it is
_at_ least a way of organization.
Diffstat (limited to 'pkgs/by-name/yt')
-rwxr-xr-xpkgs/by-name/yt/yt/.env3
-rw-r--r--pkgs/by-name/yt/yt/.envrc1
-rw-r--r--pkgs/by-name/yt/yt/.gitignore3
-rw-r--r--pkgs/by-name/yt/yt/Cargo.lock640
-rw-r--r--pkgs/by-name/yt/yt/Cargo.toml35
-rw-r--r--pkgs/by-name/yt/yt/flake.lock61
-rw-r--r--pkgs/by-name/yt/yt/flake.nix30
-rw-r--r--pkgs/by-name/yt/yt/package.nix44
-rw-r--r--pkgs/by-name/yt/yt/src/bin/yt/main.rs91
-rw-r--r--pkgs/by-name/yt/yt/src/bin/ytc/args.rs26
-rw-r--r--pkgs/by-name/yt/yt/src/bin/ytc/main.rs77
-rw-r--r--pkgs/by-name/yt/yt/src/bin/yts/args.rs41
-rw-r--r--pkgs/by-name/yt/yt/src/bin/yts/main.rs91
-rw-r--r--pkgs/by-name/yt/yt/src/constants.rs51
-rw-r--r--pkgs/by-name/yt/yt/src/downloader.rs212
-rw-r--r--pkgs/by-name/yt/yt/src/help.str8
-rw-r--r--pkgs/by-name/yt/yt/src/lib.rs185
-rw-r--r--pkgs/by-name/yt/yt/todo1
-rwxr-xr-xpkgs/by-name/yt/yt/update.sh8
-rw-r--r--pkgs/by-name/yt/yt/yt.nix29
-rw-r--r--pkgs/by-name/yt/yt/ytc.nix29
-rw-r--r--pkgs/by-name/yt/yt/yts.nix27
-rw-r--r--pkgs/by-name/yt/yti/package.nix17
-rwxr-xr-xpkgs/by-name/yt/yti/yti.sh33
24 files changed, 1743 insertions, 0 deletions
diff --git a/pkgs/by-name/yt/yt/.env b/pkgs/by-name/yt/yt/.env
new file mode 100755
index 00000000..8018a738
--- /dev/null
+++ b/pkgs/by-name/yt/yt/.env
@@ -0,0 +1,3 @@
+#!/usr/bin/env sh
+
+PATH="$(pwd)/target/release/:$(pwd)/target/debug/:$PATH"
diff --git a/pkgs/by-name/yt/yt/.envrc b/pkgs/by-name/yt/yt/.envrc
new file mode 100644
index 00000000..3550a30f
--- /dev/null
+++ b/pkgs/by-name/yt/yt/.envrc
@@ -0,0 +1 @@
+use flake
diff --git a/pkgs/by-name/yt/yt/.gitignore b/pkgs/by-name/yt/yt/.gitignore
new file mode 100644
index 00000000..c84fa049
--- /dev/null
+++ b/pkgs/by-name/yt/yt/.gitignore
@@ -0,0 +1,3 @@
+# build dirs
+/target
+/result
diff --git a/pkgs/by-name/yt/yt/Cargo.lock b/pkgs/by-name/yt/yt/Cargo.lock
new file mode 100644
index 00000000..ef2a53fd
--- /dev/null
+++ b/pkgs/by-name/yt/yt/Cargo.lock
@@ -0,0 +1,640 @@
+# 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.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b"
+dependencies = [
+ "anstyle",
+ "anstyle-parse",
+ "anstyle-query",
+ "anstyle-wincon",
+ "colorchoice",
+ "is_terminal_polyfill",
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b"
+
+[[package]]
+name = "anstyle-parse"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4"
+dependencies = [
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle-query"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5"
+dependencies = [
+ "windows-sys",
+]
+
+[[package]]
+name = "anstyle-wincon"
+version = "3.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19"
+dependencies = [
+ "anstyle",
+ "windows-sys",
+]
+
+[[package]]
+name = "anyhow"
+version = "1.0.83"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "25bdb32cbbdce2b519a9cd7df3a678443100e265d5e25ca763b7572a5104f5f3"
+
+[[package]]
+name = "autocfg"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
+
+[[package]]
+name = "bitflags"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
+
+[[package]]
+name = "bumpalo"
+version = "3.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
+
+[[package]]
+name = "cc"
+version = "1.0.97"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4"
+
+[[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.38"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401"
+dependencies = [
+ "android-tzdata",
+ "iana-time-zone",
+ "js-sys",
+ "num-traits",
+ "wasm-bindgen",
+ "windows-targets",
+]
+
+[[package]]
+name = "clap"
+version = "4.5.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0"
+dependencies = [
+ "clap_builder",
+ "clap_derive",
+]
+
+[[package]]
+name = "clap_builder"
+version = "4.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4"
+dependencies = [
+ "anstream",
+ "anstyle",
+ "clap_lex",
+ "strsim",
+]
+
+[[package]]
+name = "clap_derive"
+version = "4.5.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "clap_lex"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
+
+[[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.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422"
+
+[[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.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba"
+dependencies = [
+ "libc",
+ "windows-sys",
+]
+
+[[package]]
+name = "fastrand"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a"
+
+[[package]]
+name = "file-size"
+version = "1.0.3"
+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.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
+
+[[package]]
+name = "iana-time-zone"
+version = "0.1.60"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141"
+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 = "idna"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6"
+dependencies = [
+ "unicode-bidi",
+ "unicode-normalization",
+]
+
+[[package]]
+name = "is_terminal_polyfill"
+version = "1.70.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800"
+
+[[package]]
+name = "itoa"
+version = "1.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
+
+[[package]]
+name = "js-sys"
+version = "0.3.69"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d"
+dependencies = [
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "libc"
+version = "0.2.154"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346"
+
+[[package]]
+name = "linux-raw-sys"
+version = "0.4.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c"
+
+[[package]]
+name = "log"
+version = "0.4.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
+
+[[package]]
+name = "num-traits"
+version = "0.2.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.19.0"
+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.82"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b"
+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.36"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "rustix"
+version = "0.38.34"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f"
+dependencies = [
+ "bitflags",
+ "errno",
+ "libc",
+ "linux-raw-sys",
+ "windows-sys",
+]
+
+[[package]]
+name = "ryu"
+version = "1.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
+
+[[package]]
+name = "serde"
+version = "1.0.201"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "780f1cebed1629e4753a1a38a3c72d30b97ec044f0aef68cb26650a3c5cf363c"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.201"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c5e405930b9796f1c00bee880d03fc7e0bb4b9a11afc776885ffe84320da2865"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.117"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3"
+dependencies = [
+ "itoa",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "strsim"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
+
+[[package]]
+name = "syn"
+version = "2.0.61"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c993ed8ccba56ae856363b1845da7266a7cb78e1d146c8a32d54b45a8b831fc9"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "tempfile"
+version = "3.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1"
+dependencies = [
+ "cfg-if",
+ "fastrand",
+ "rustix",
+ "windows-sys",
+]
+
+[[package]]
+name = "thiserror"
+version = "1.0.60"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "579e9083ca58dd9dcf91a9923bb9054071b9ebbd800b342194c9feb0ee89fc18"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.60"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2470041c06ec3ac1ab38d0356a6119054dedaea53e12fbefc0de730a1c08524"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[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.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5"
+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"
+checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
+
+[[package]]
+name = "wasm-bindgen"
+version = "0.2.92"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8"
+dependencies = [
+ "cfg-if",
+ "wasm-bindgen-macro",
+]
+
+[[package]]
+name = "wasm-bindgen-backend"
+version = "0.2.92"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da"
+dependencies = [
+ "bumpalo",
+ "log",
+ "once_cell",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-macro"
+version = "0.2.92"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726"
+dependencies = [
+ "quote",
+ "wasm-bindgen-macro-support",
+]
+
+[[package]]
+name = "wasm-bindgen-macro-support"
+version = "0.2.92"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wasm-bindgen-backend",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-shared"
+version = "0.2.92"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
+
+[[package]]
+name = "windows-core"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_gnullvm",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
+
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.52.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
+
+[[package]]
+name = "yt"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "clap",
+ "cli-log",
+ "log",
+ "serde",
+ "serde_json",
+ "tempfile",
+ "url",
+]
diff --git a/pkgs/by-name/yt/yt/Cargo.toml b/pkgs/by-name/yt/yt/Cargo.toml
new file mode 100644
index 00000000..7c17d20b
--- /dev/null
+++ b/pkgs/by-name/yt/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.83"
+clap = { version = "4.5.4", features = ["derive"] }
+cli-log = "2.0.0"
+log = "0.4.21"
+serde = { version = "1.0.201", features = ["derive"] }
+serde_json = "1.0.117"
+tempfile = "3.10.1"
+url = "2.5.0"
+
+# This is here to be able to tell nix which binary to build
+[features]
+yts = []
+ytc = []
+yt = []
+default = ["yt", "yts", "ytc"]
+
+[[bin]]
+name = "yts"
+required-features = ["yts"]
+
+[[bin]]
+name = "ytc"
+required-features = ["ytc"]
+
+[[bin]]
+name = "yt"
+required-features = ["yt"]
diff --git a/pkgs/by-name/yt/yt/flake.lock b/pkgs/by-name/yt/yt/flake.lock
new file mode 100644
index 00000000..50494465
--- /dev/null
+++ b/pkgs/by-name/yt/yt/flake.lock
@@ -0,0 +1,61 @@
+{
+  "nodes": {
+    "flake-utils": {
+      "inputs": {
+        "systems": "systems"
+      },
+      "locked": {
+        "lastModified": 1710146030,
+        "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
+        "owner": "numtide",
+        "repo": "flake-utils",
+        "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
+        "type": "github"
+      },
+      "original": {
+        "owner": "numtide",
+        "repo": "flake-utils",
+        "type": "github"
+      }
+    },
+    "nixpkgs": {
+      "locked": {
+        "lastModified": 1715087517,
+        "narHash": "sha256-CLU5Tsg24Ke4+7sH8azHWXKd0CFd4mhLWfhYgUiDBpQ=",
+        "owner": "NixOS",
+        "repo": "nixpkgs",
+        "rev": "b211b392b8486ee79df6cdfb1157ad2133427a29",
+        "type": "github"
+      },
+      "original": {
+        "owner": "NixOS",
+        "ref": "nixos-unstable",
+        "repo": "nixpkgs",
+        "type": "github"
+      }
+    },
+    "root": {
+      "inputs": {
+        "flake-utils": "flake-utils",
+        "nixpkgs": "nixpkgs"
+      }
+    },
+    "systems": {
+      "locked": {
+        "lastModified": 1681028828,
+        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
+        "owner": "nix-systems",
+        "repo": "default",
+        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nix-systems",
+        "repo": "default",
+        "type": "github"
+      }
+    }
+  },
+  "root": "root",
+  "version": 7
+}
diff --git a/pkgs/by-name/yt/yt/flake.nix b/pkgs/by-name/yt/yt/flake.nix
new file mode 100644
index 00000000..561b1c0d
--- /dev/null
+++ b/pkgs/by-name/yt/yt/flake.nix
@@ -0,0 +1,30 @@
+{
+  description = "yt";
+
+  inputs = {
+    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
+
+    flake-utils.url = "github:numtide/flake-utils";
+  };
+
+  outputs = {
+    self,
+    nixpkgs,
+    flake-utils,
+  }: (flake-utils.lib.eachDefaultSystem (system: let
+    pkgs = nixpkgs.legacyPackages."${system}";
+  in {
+    devShells.default = pkgs.mkShell {
+      packages = with pkgs; [
+        # rust stuff
+        cargo
+        clippy
+        rustc
+        rustfmt
+
+        cargo-edit
+        cargo-expand
+      ];
+    };
+  }));
+}
diff --git a/pkgs/by-name/yt/yt/package.nix b/pkgs/by-name/yt/yt/package.nix
new file mode 100644
index 00000000..84eda119
--- /dev/null
+++ b/pkgs/by-name/yt/yt/package.nix
@@ -0,0 +1,44 @@
+{
+  lib,
+  makeWrapper,
+  rustPlatform,
+  # dependencies
+  ytcc,
+  yt-dlp,
+  mpv,
+}: {
+  yt = import ./yt.nix {
+    inherit
+      lib
+      makeWrapper
+      rustPlatform
+      # dependencies
+
+      ytcc
+      yt-dlp
+      mpv
+      ;
+  };
+  yts = import ./yts.nix {
+    inherit
+      lib
+      makeWrapper
+      rustPlatform
+      # dependencies
+
+      ytcc
+      ;
+  };
+  ytc = import ./ytc.nix {
+    inherit
+      lib
+      makeWrapper
+      rustPlatform
+      # dependencies
+
+      ytcc
+      yt-dlp
+      mpv
+      ;
+  };
+}
diff --git a/pkgs/by-name/yt/yt/src/bin/yt/main.rs b/pkgs/by-name/yt/yt/src/bin/yt/main.rs
new file mode 100644
index 00000000..37348834
--- /dev/null
+++ b/pkgs/by-name/yt/yt/src/bin/yt/main.rs
@@ -0,0 +1,91 @@
+use anyhow::{bail, Context, Result};
+use std::{
+    env, fs,
+    io::{BufRead, BufReader, BufWriter, Write},
+    process::Command as StdCmd,
+};
+use tempfile::Builder;
+use yt::{
+    constants::{last_select, HELP_STR},
+    downloader::Downloader,
+    filter_line, 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 = Builder::new()
+        .prefix("yt_video_select-")
+        .suffix(".yts")
+        .rand_bytes(6)
+        .tempfile()
+        .context("Failed to get tempfile")?;
+
+    {
+        let mut edit_file = BufWriter::new(&temp_file);
+
+        json_map.iter().for_each(|line| {
+            let line = line.to_string();
+            edit_file
+                .write_all(line.as_bytes())
+                .expect("This write should not fail");
+        });
+
+        edit_file.write_all(HELP_STR.as_bytes())?;
+        edit_file.flush().context("Failed to flush edit file")?;
+
+        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 read_file = temp_file.reopen()?;
+    fs::copy(
+        temp_file.path(),
+        last_select().context("Failed to get the persistent selection file path")?,
+    )
+    .context("Failed to persist selection file")?;
+
+    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 let Some(downloadable) =
+            filter_line(&line).with_context(|| format!("Failed to process line: '{}'", line))?
+        {
+            watching.push(downloadable);
+        }
+    }
+
+    if watching.is_empty() {
+        return Ok(());
+    }
+
+    let downloader = Downloader::new(watching).context("Failed to construct downloader")?;
+    downloader
+        .consume()
+        .context("Failed to consume downloader")?;
+
+    Ok(())
+}
diff --git a/pkgs/by-name/yt/yt/src/bin/ytc/args.rs b/pkgs/by-name/yt/yt/src/bin/ytc/args.rs
new file mode 100644
index 00000000..8b2d6a61
--- /dev/null
+++ b/pkgs/by-name/yt/yt/src/bin/ytc/args.rs
@@ -0,0 +1,26 @@
+use clap::{Parser, Subcommand};
+/// A helper for downloading and playing youtube videos
+#[derive(Parser, Debug)]
+#[clap(author, version, about, long_about = None)]
+pub struct Args {
+    #[command(subcommand)]
+    /// The subcommand to execute
+    pub subcommand: Command,
+}
+#[derive(Subcommand, Debug)]
+pub enum Command {
+    #[clap(value_parser)]
+    /// Work based of ytcc ids
+    Id {
+        #[clap(value_parser)]
+        /// A list of ids to play
+        ids: Vec<u32>,
+    },
+    #[clap(value_parser)]
+    /// Work based of raw youtube urls
+    Url {
+        #[clap(value_parser)]
+        /// A list of urls to play
+        urls: Vec<String>,
+    },
+}
diff --git a/pkgs/by-name/yt/yt/src/bin/ytc/main.rs b/pkgs/by-name/yt/yt/src/bin/ytc/main.rs
new file mode 100644
index 00000000..b38157df
--- /dev/null
+++ b/pkgs/by-name/yt/yt/src/bin/ytc/main.rs
@@ -0,0 +1,77 @@
+use std::{env, process::Command as StdCmd};
+
+use anyhow::{bail, Context, Result};
+use clap::Parser;
+use log::debug;
+use url::Url;
+use yt::{
+    downloader::{Downloadable, Downloader},
+    YtccListData,
+};
+
+use crate::args::{Args, Command};
+
+mod args;
+
+fn main() -> Result<()> {
+    let args = Args::parse();
+    cli_log::init_cli_log!();
+
+    let playspec: Vec<Downloadable> = match args.subcommand {
+        Command::Id { ids } => {
+            let mut output = Vec::with_capacity(ids.len());
+            for id in ids {
+                debug!("Adding {}", id);
+                let mut ytcc = StdCmd::new("ytcc");
+                ytcc.args([
+                    "--output",
+                    "json",
+                    "list",
+                    "--watched",
+                    "--unwatched",
+                    "--attributes",
+                    "url",
+                    "--ids",
+                    id.to_string().as_str(),
+                ]);
+                let json = serde_json::from_slice::<Vec<YtccListData>>(
+                    &ytcc.output().context("Failed to get url from id")?.stdout,
+                )
+                .context("Failed to deserialize json output")?;
+
+                if json.is_empty() {
+                    bail!("Could not find a video with id: {}", id);
+                }
+                assert_eq!(json.len(), 1);
+                let json = json.first().expect("Has only one element");
+
+                debug!("Id resolved to: '{}'", &json.url);
+
+                output.push(Downloadable {
+                    url: Url::parse(&json.url)?,
+                    id: Some(json.id),
+                })
+            }
+            output
+        }
+        Command::Url { urls } => {
+            let mut output = Vec::with_capacity(urls.len());
+            for url in urls {
+                output.push(Downloadable {
+                    url: Url::parse(&url).context("Failed to parse url")?,
+                    id: None,
+                })
+            }
+            output
+        }
+    };
+
+    debug!("Initializing downloader");
+    let downloader = Downloader::new(playspec)?;
+
+    downloader
+        .consume()
+        .context("Failed to consume downloader")?;
+
+    Ok(())
+}
diff --git a/pkgs/by-name/yt/yt/src/bin/yts/args.rs b/pkgs/by-name/yt/yt/src/bin/yts/args.rs
new file mode 100644
index 00000000..56989421
--- /dev/null
+++ b/pkgs/by-name/yt/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/pkgs/by-name/yt/yt/src/bin/yts/main.rs b/pkgs/by-name/yt/yt/src/bin/yts/main.rs
new file mode 100644
index 00000000..7398db61
--- /dev/null
+++ b/pkgs/by-name/yt/yt/src/bin/yts/main.rs
@@ -0,0 +1,91 @@
+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, filter_line, 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")?;
+
+    json_map.iter().for_each(|line| {
+        let line = line.to_string();
+        edit_file
+            .write_all(line.as_bytes())
+            .expect("This write should not fail");
+    });
+
+    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 let Some(downloadable) =
+            filter_line(&line).with_context(|| format!("Failed to process line: '{}'", line))?
+        {
+            watching.push(downloadable);
+        }
+    }
+
+    let watching: String = watching
+        .iter()
+        .map(|d| d.to_string())
+        .collect::<Vec<String>>()
+        .join("\n");
+    println!("{}", &watching);
+    Ok(())
+}
diff --git a/pkgs/by-name/yt/yt/src/constants.rs b/pkgs/by-name/yt/yt/src/constants.rs
new file mode 100644
index 00000000..5e233656
--- /dev/null
+++ b/pkgs/by-name/yt/yt/src/constants.rs
@@ -0,0 +1,51 @@
+use std::{env, fs, path::PathBuf};
+
+pub const HELP_STR: &str = include_str!("./help.str");
+
+pub const YT_DLP_FLAGS: [&str; 13] = [
+    // Ignore errors arising of unavailable sponsor block API
+    "--ignore-errors",
+    "--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; 4] = [
+    "--speed=2.7",
+    "--volume=75",
+    "--keep-open=yes",
+    "--msg-level=osd/libass=fatal",
+];
+
+pub const CONCURRENT: u32 = 5;
+
+pub const DOWNLOAD_DIR: &str = "/tmp/ytcc";
+
+fn get_runtime_path(component: &'static str) -> anyhow::Result<PathBuf> {
+    let out: PathBuf = format!(
+        "{}/{}",
+        env::var("XDG_RUNTIME_DIR").expect("This should always exist"),
+        component
+    )
+    .into();
+    fs::create_dir_all(out.parent().expect("Parent should exist"))?;
+    Ok(out)
+}
+
+const STATUS_PATH: &str = "ytcc/running";
+pub fn status_path() -> anyhow::Result<PathBuf> {
+    get_runtime_path(STATUS_PATH)
+}
+
+const LAST_SELECT: &str = "ytcc/selected.yts";
+pub fn last_select() -> anyhow::Result<PathBuf> {
+    get_runtime_path(LAST_SELECT)
+}
diff --git a/pkgs/by-name/yt/yt/src/downloader.rs b/pkgs/by-name/yt/yt/src/downloader.rs
new file mode 100644
index 00000000..e915700d
--- /dev/null
+++ b/pkgs/by-name/yt/yt/src/downloader.rs
@@ -0,0 +1,212 @@
+use std::{
+    fs::{self, canonicalize},
+    io::{stderr, stdout, Read},
+    mem,
+    os::unix::fs::symlink,
+    path::PathBuf,
+    process::Command,
+    sync::mpsc::{self, Receiver, Sender},
+    thread::{self, JoinHandle},
+};
+
+use anyhow::{bail, Context, Result};
+use log::{debug, error, warn};
+use url::Url;
+
+use crate::constants::{status_path, CONCURRENT, DOWNLOAD_DIR, MPV_FLAGS, YT_DLP_FLAGS};
+
+#[derive(Debug)]
+pub struct Downloadable {
+    pub url: Url,
+    pub id: Option<u32>,
+}
+
+impl std::fmt::Display for Downloadable {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
+        write!(
+            f,
+            "{}|{}",
+            self.url.as_str().replace('|', ";"),
+            self.id.unwrap_or(0),
+        )
+    }
+}
+
+pub struct Downloader {
+    sent: usize,
+    download_thread: JoinHandle<Result<()>>,
+    orx: Receiver<(PathBuf, Option<u32>)>,
+    itx: Option<Sender<Downloadable>>,
+    playspec: Vec<Downloadable>,
+}
+
+impl Downloader {
+    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 Ok(pt) = irx.recv() {
+                debug!("Got '{}' to be downloaded", pt);
+                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().expect("This call should be guarded");
+            self.itx.as_ref().expect("Should still be valid").send(pt)?;
+            self.sent += 1;
+        }
+        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());
+                if !self.playspec.is_empty() {
+                    self.add(1).ok()?;
+                } else {
+                    debug!(
+                        "Done sending videos to be downloaded, downoladed: {} videos",
+                        self.sent
+                    );
+                    let itx = mem::take(&mut self.itx);
+                    drop(itx)
+                }
+                debug!("Returning: {}|{}", ok.0.display(), ok.1.unwrap_or(0));
+                Some(ok)
+            }
+            Err(err) => {
+                debug!("Received error while listening: {}", err);
+                None
+            }
+        }
+    }
+
+    pub fn drop(self) -> anyhow::Result<()> {
+        // Check that we really downloaded everything
+        assert_eq!(self.playspec.len(), 0);
+        match self.download_thread.join() {
+            Ok(ok) => ok,
+            Err(err) => panic!("Failed to join downloader 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);
+            // TODO: Set the title to the name of the video, not the path <2024-02-09>
+            // mpv.arg(format!("--title="))
+            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: &Url) -> 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")?;
+    if !Into::<PathBuf>::into(DOWNLOAD_DIR).exists() {
+        fs::create_dir_all(DOWNLOAD_DIR)
+            .with_context(|| format!("Failed to create download dir at: {}", DOWNLOAD_DIR))?
+    }
+    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.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 !status.success() {
+        error!("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/pkgs/by-name/yt/yt/src/help.str b/pkgs/by-name/yt/yt/src/help.str
new file mode 100644
index 00000000..130fe42a
--- /dev/null
+++ b/pkgs/by-name/yt/yt/src/help.str
@@ -0,0 +1,8 @@
+# Commands:
+# w, watch  = watch id
+# d, drop   = mark id as watched
+# u, url    = open the associated URL in the `timesinks.youtube` Firefox profile
+# p, pick   = 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/pkgs/by-name/yt/yt/src/lib.rs b/pkgs/by-name/yt/yt/src/lib.rs
new file mode 100644
index 00000000..b089c1a2
--- /dev/null
+++ b/pkgs/by-name/yt/yt/src/lib.rs
@@ -0,0 +1,185 @@
+use anyhow::{bail, Context};
+use downloader::Downloadable;
+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<f64>,
+    pub duration: String,
+    pub thumbnail_url: Option<String>,
+    pub extractor_hash: String,
+    pub id: u32,
+    pub playlists: Vec<YtccPlaylistData>,
+}
+
+impl std::fmt::Display for YtccListData {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
+        write!(
+            f,
+            r#"pick {} "{}" "{}" "{}" "{}" "{}"{}"#,
+            self.id,
+            self.title.replace(['"', '„', '”'], "'"),
+            self.publish_date,
+            self.playlists
+                .iter()
+                .map(|p| p.name.replace('"', "'"))
+                .collect::<Vec<String>>()
+                .join(", "),
+            Duration::from(self.duration.trim()),
+            self.url.replace('"', "'"),
+            "\n"
+        )
+    }
+}
+
+#[derive(Deserialize)]
+pub struct YtccPlaylistData {
+    pub name: String,
+    pub url: String,
+    pub reverse: bool,
+}
+
+pub enum LineCommand {
+    Pick,
+    Drop,
+    Watch,
+    Url,
+}
+
+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),
+            "url" | "u" => Ok(Self::Url),
+            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;
+
+        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(())
+}
+
+pub fn filter_line(line: &str) -> anyhow::Result<Option<Downloadable>> {
+    // Filter out comments and empty lines
+    if line.starts_with('#') || line.trim().is_empty() {
+        return Ok(None);
+    }
+
+    let line = Line::from(line);
+    match line.cmd {
+        LineCommand::Pick => Ok(None),
+        LineCommand::Drop => ytcc_drop(line.id)
+            .with_context(|| format!("Failed to drop: {}", line.id))
+            .map(|_| None),
+        LineCommand::Watch => Ok(Some(Downloadable {
+            id: Some(line.id),
+            url: line.url,
+        })),
+        LineCommand::Url => {
+            let mut firefox = std::process::Command::new("firefox");
+            firefox.args(["-P", "timesinks.youtube"]);
+            firefox.arg(line.url.as_str());
+            let _handle = firefox.spawn().context("Failed to run firefox")?;
+            Ok(None)
+        }
+    }
+}
diff --git a/pkgs/by-name/yt/yt/todo b/pkgs/by-name/yt/yt/todo
new file mode 100644
index 00000000..3f22042c
--- /dev/null
+++ b/pkgs/by-name/yt/yt/todo
@@ -0,0 +1 @@
+subtitles
diff --git a/pkgs/by-name/yt/yt/update.sh b/pkgs/by-name/yt/yt/update.sh
new file mode 100755
index 00000000..e500bb23
--- /dev/null
+++ b/pkgs/by-name/yt/yt/update.sh
@@ -0,0 +1,8 @@
+#!/usr/bin/env sh
+
+nix flake update
+
+[ "$1" = "upgrade" ] && cargo upgrade
+cargo update
+
+# vim: ft=sh
diff --git a/pkgs/by-name/yt/yt/yt.nix b/pkgs/by-name/yt/yt/yt.nix
new file mode 100644
index 00000000..aaa971c3
--- /dev/null
+++ b/pkgs/by-name/yt/yt/yt.nix
@@ -0,0 +1,29 @@
+{
+  lib,
+  rustPlatform,
+  ytcc,
+  yt-dlp,
+  mpv,
+  makeWrapper,
+}:
+rustPlatform.buildRustPackage {
+  pname = "yt";
+  version = "0.1.0";
+
+  src = ./.;
+  cargoLock = {
+    lockFile = ./Cargo.lock;
+  };
+
+  buildNoDefaultFeatures = true;
+  buildFeatures = ["yt"];
+
+  nativeBuildInputs = [
+    makeWrapper
+  ];
+
+  postInstall = ''
+    wrapProgram $out/bin/yt \
+      --prefix PATH : ${lib.makeBinPath [mpv yt-dlp ytcc]}
+  '';
+}
diff --git a/pkgs/by-name/yt/yt/ytc.nix b/pkgs/by-name/yt/yt/ytc.nix
new file mode 100644
index 00000000..dff5bcf8
--- /dev/null
+++ b/pkgs/by-name/yt/yt/ytc.nix
@@ -0,0 +1,29 @@
+{
+  lib,
+  rustPlatform,
+  ytcc,
+  yt-dlp,
+  mpv,
+  makeWrapper,
+}:
+rustPlatform.buildRustPackage {
+  pname = "ytc";
+  version = "0.1.0";
+
+  src = ./.;
+  cargoLock = {
+    lockFile = ./Cargo.lock;
+  };
+
+  buildNoDefaultFeatures = true;
+  buildFeatures = ["ytc"];
+
+  nativeBuildInputs = [
+    makeWrapper
+  ];
+
+  postInstall = ''
+    wrapProgram $out/bin/ytc \
+      --set PATH ${lib.makeBinPath [mpv yt-dlp ytcc]}
+  '';
+}
diff --git a/pkgs/by-name/yt/yt/yts.nix b/pkgs/by-name/yt/yt/yts.nix
new file mode 100644
index 00000000..9a8b172e
--- /dev/null
+++ b/pkgs/by-name/yt/yt/yts.nix
@@ -0,0 +1,27 @@
+{
+  lib,
+  rustPlatform,
+  ytcc,
+  makeWrapper,
+}:
+rustPlatform.buildRustPackage {
+  pname = "yts";
+  version = "0.1.0";
+
+  src = ./.;
+  cargoLock = {
+    lockFile = ./Cargo.lock;
+  };
+
+  buildNoDefaultFeatures = true;
+  buildFeatures = ["yts"];
+
+  nativeBuildInputs = [
+    makeWrapper
+  ];
+
+  postInstall = ''
+    wrapProgram $out/bin/yts \
+      --prefix PATH : ${lib.makeBinPath [ytcc]}
+  '';
+}
diff --git a/pkgs/by-name/yt/yti/package.nix b/pkgs/by-name/yt/yti/package.nix
new file mode 100644
index 00000000..5a39512a
--- /dev/null
+++ b/pkgs/by-name/yt/yti/package.nix
@@ -0,0 +1,17 @@
+{
+  sysLib,
+  gawk,
+  expect,
+  yt-dlp,
+}:
+sysLib.writeShellScript {
+  name = "yti";
+  src = ./yti.sh;
+  generateCompletions = false;
+  keepPath = false;
+  dependencies = [
+    gawk
+    expect
+    yt-dlp
+  ];
+}
diff --git a/pkgs/by-name/yt/yti/yti.sh b/pkgs/by-name/yt/yti/yti.sh
new file mode 100755
index 00000000..a69ffa74
--- /dev/null
+++ b/pkgs/by-name/yt/yti/yti.sh
@@ -0,0 +1,33 @@
+#! /usr/bin/env dash
+
+# shellcheck source=/dev/null
+SHELL_LIBRARY_VERSION="2.1.2" . %SHELL_LIBRARY_PATH
+
+DOWN_DIR=/home/soispha/media/music/down/youtube
+
+tmp=$(mktmp)
+config=$(mktmp)
+
+for e in "$DOWN_DIR"/*.opus; do echo "$e" >>"$tmp"; done
+[ "$(wc -l "$tmp" | awk '{print $1}')" -gt 2 ] && die "something is already downloaded"
+
+cat <<EO >"$config"
+--paths home:"$DOWN_DIR"
+#--output %(fulltitle)
+--restrict-filenames
+--no-overwrites
+--no-write-info-json
+--clean-info-json
+--prefer-free-formats
+#--format mp3
+--extract-audio
+--audio-quality 0
+--audio-format best
+EO
+
+rm "$DOWN_DIR/yt-dlp.log"
+cd "$DOWN_DIR" || die "BUG: no $DOWN_DIR"
+
+unbuffer yt-dlp --config-location "$config" "$1" | tee "$DOWN_DIR/yt-dlp.log"
+
+# vim: ft=sh