diff options
Diffstat (limited to 'pkgs/sources/yt/src/lib.rs')
-rw-r--r-- | pkgs/sources/yt/src/lib.rs | 185 |
1 files changed, 0 insertions, 185 deletions
diff --git a/pkgs/sources/yt/src/lib.rs b/pkgs/sources/yt/src/lib.rs deleted file mode 100644 index b089c1a2..00000000 --- a/pkgs/sources/yt/src/lib.rs +++ /dev/null @@ -1,185 +0,0 @@ -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) - } - } -} |