aboutsummaryrefslogtreecommitdiffstats
path: root/sys/nixpkgs/pkgs/yt/src/lib.rs
diff options
context:
space:
mode:
authorSoispha <soispha@vhack.eu>2024-01-20 12:03:46 +0100
committerSoispha <soispha@vhack.eu>2024-01-20 12:03:46 +0100
commit089c08af03849fb2883a17726462ca0d8ce8b51f (patch)
treed5d9285c6beab0babd16fe533b621ed56280bdd4 /sys/nixpkgs/pkgs/yt/src/lib.rs
parentfeat(hm/conf/nvim/plgs/treesitter): Add custom parser for `yts` (diff)
downloadnixos-config-089c08af03849fb2883a17726462ca0d8ce8b51f.zip
feat(sys/nixpkgs/pkgs/yt): Merge ytc and the rewritten ytc
Diffstat (limited to '')
-rw-r--r--sys/nixpkgs/pkgs/yt/src/lib.rs140
1 files changed, 140 insertions, 0 deletions
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(())
+}