about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorBenedikt Peetz <benedikt.peetz@b-peetz.de>2025-07-15 06:53:07 +0200
committerBenedikt Peetz <benedikt.peetz@b-peetz.de>2025-07-15 06:53:07 +0200
commit3c11d068e438da22375a9d0af9abb81c738ebcbb (patch)
treefbcf0814dac311fbd6c33f23315d57b7546e5737
parentrefactor(crates/yt): Use the new storage layer (diff)
downloadyt-3c11d068e438da22375a9d0af9abb81c738ebcbb.zip
refactor(crates/yt/download/progress_hook): Use `json_{get,cast}` and owu-colors
-rw-r--r--crates/yt/src/download/progress_hook.rs141
1 files changed, 49 insertions, 92 deletions
diff --git a/crates/yt/src/download/progress_hook.rs b/crates/yt/src/download/progress_hook.rs
index 99d1a74..e5605fd 100644
--- a/crates/yt/src/download/progress_hook.rs
+++ b/crates/yt/src/download/progress_hook.rs
@@ -23,6 +23,29 @@ use crate::{
     shared::bytes::Bytes,
 };
 
+macro_rules! json_get_default {
+    ($value:expr, $name:literal, $convert:ident, $default:expr) => {
+        $value.get($name).map_or($default, |v| {
+            if v == &serde_json::Value::Null {
+                $default
+            } else {
+                json_cast!(@log_key $name, v, $convert)
+            }
+        })
+    };
+}
+
+fn format_bytes(bytes: u64) -> String {
+    let bytes = Bytes::new(bytes);
+    bytes.to_string()
+}
+
+fn format_speed(speed: f64) -> String {
+    #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
+    let bytes = Bytes::new(speed.floor() as u64);
+    format!("{bytes}/s")
+}
+
 /// # Panics
 /// If expectations fail.
 #[allow(clippy::needless_pass_by_value)]
@@ -35,110 +58,44 @@ pub(crate) fn progress_hook(
         return Ok(());
     }
 
-    macro_rules! get {
-        (@interrogate $item:ident, $type_fun:ident, $get_fun:ident, $name:expr) => {{
-            let a = $item.get($name).expect(concat!(
-                "The field '",
-                stringify!($name),
-                "' should exist."
-            ));
-
-            if a.$type_fun() {
-                a.$get_fun().expect(
-                    "The should have been checked in the if guard, so unpacking here is fine",
-                )
-            } else {
-                panic!(
-                    "Value {} => \n{}\n is not of type: {}",
-                    $name,
-                    a,
-                    stringify!($type_fun)
-                );
-            }
-        }};
-
-        ($type_fun:ident, $get_fun:ident, $name1:expr, $name2:expr) => {{
-            let a = get! {@interrogate input, is_object, as_object, $name1};
-            let b = get! {@interrogate a, $type_fun, $get_fun, $name2};
-            b
-        }};
-
-        ($type_fun:ident, $get_fun:ident, $name:expr) => {{
-            get! {@interrogate input, $type_fun, $get_fun, $name}
-        }};
-    }
-
-    macro_rules! default_get {
-        (@interrogate $item:ident, $default:expr, $get_fun:ident, $name:expr) => {{
-            let a = if let Some(field) = $item.get($name) {
-                field.$get_fun().unwrap_or($default)
-            } else {
-                $default
-            };
-            a
-        }};
-
-        ($get_fun:ident, $default:expr, $name1:expr, $name2:expr) => {{
-            let a = get! {@interrogate input, is_object, as_object, $name1};
-            let b = default_get! {@interrogate a, $default, $get_fun, $name2};
-            b
-        }};
-
-        ($get_fun:ident, $default:expr, $name:expr) => {{
-            default_get! {@interrogate input, $default, $get_fun, $name}
-        }};
-    }
-
-    macro_rules! c {
-        ($color:expr, $format:expr) => {
-            format!("\x1b[{}m{}\x1b[0m", $color, $format)
-        };
-    }
-
-    #[allow(clippy::items_after_statements)]
-    fn format_bytes(bytes: u64) -> String {
-        let bytes = Bytes::new(bytes);
-        bytes.to_string()
-    }
-
-    #[allow(clippy::items_after_statements)]
-    fn format_speed(speed: f64) -> String {
-        #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
-        let bytes = Bytes::new(speed.floor() as u64);
-        format!("{bytes}/s")
-    }
+    let info_dict = json_get!(input, "info_dict", as_object);
 
     let get_title = || -> String {
-        match get! {is_string, as_str, "info_dict", "ext"} {
+        match json_get!(info_dict, "ext", as_str) {
             "vtt" => {
                 format!(
                     "Subtitles ({})",
-                    default_get! {as_str, "<No Subtitle Language>", "info_dict", "name"}
+                    json_get_default!(info_dict, "name", as_str, "<No Subtitle Language>")
                 )
             }
             "webm" | "mp4" | "mp3" | "m4a" => {
-                default_get! { as_str, "<No title>", "info_dict", "title"}.to_owned()
+                json_get_default!(info_dict, "title", as_str, "<No title>").to_owned()
             }
             other => panic!("The extension '{other}' is not yet implemented"),
         }
     };
 
-    match get! {is_string, as_str, "status"} {
+    match json_get!(input, "status", as_str) {
         "downloading" => {
-            let elapsed = default_get! {as_f64, 0.0f64, "elapsed"};
-            let eta = default_get! {as_f64, 0.0, "eta"};
-            let speed = default_get! {as_f64, 0.0, "speed"};
+            let elapsed = json_get_default!(input, "elapsed", as_f64, 0.0);
+            let eta = json_get_default!(input, "eta", as_f64, 0.0);
+            let speed = json_get_default!(input, "speed", as_f64, 0.0);
 
-            let downloaded_bytes = get! {is_u64, as_u64, "downloaded_bytes"};
+            let downloaded_bytes = json_get!(input, "downloaded_bytes", as_u64);
             let (total_bytes, bytes_is_estimate): (u64, &'static str) = {
-                let total_bytes = default_get!(as_u64, 0, "total_bytes");
+                let total_bytes = json_get_default!(input, "total_bytes", as_u64, 0);
+
                 if total_bytes == 0 {
-                    let maybe_estimate = default_get!(as_u64, 0, "total_bytes_estimate");
+                    #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
+                    let maybe_estimate =
+                        json_get_default!(input, "total_bytes_estimate", as_f64, 0.0) as u64;
 
                     #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
                     if maybe_estimate == 0 {
-                        // The download speed should be in bytes per second and the eta in seconds.
-                        // Thus multiplying them gets us the raw bytes (which were estimated by `yt_dlp`, from their `info.json`)
+                        // The download speed should be in bytes
+                        // per second and the eta in seconds.
+                        // Thus multiplying them gets us the raw bytes
+                        // (which were estimated by `yt_dlp`, from their `info.json`)
                         let bytes_still_needed = (speed * eta).ceil() as u64;
 
                         (downloaded_bytes + bytes_still_needed, "~")
@@ -170,14 +127,14 @@ pub(crate) fn progress_hook(
 
             eprint!(
                 "{} [{}/{} at {}] -> [{} of {}{} {}] ",
-                c!("34;1", get_title()),
-                c!("33;1", MaybeDuration::from_secs_f64(elapsed)),
-                c!("33;1", MaybeDuration::from_secs_f64(eta)),
-                c!("32;1", format_speed(speed)),
-                c!("31;1", format_bytes(downloaded_bytes)),
-                c!("31;1", bytes_is_estimate),
-                c!("31;1", format_bytes(total_bytes)),
-                c!("36;1", format!("{:.02}%", percent))
+                get_title().bold().blue(),
+                MaybeDuration::from_secs_f64(elapsed).bold().yellow(),
+                MaybeDuration::from_secs_f64(eta).bold().yellow(),
+                format_speed(speed).bold().green(),
+                format_bytes(downloaded_bytes).bold().red(),
+                bytes_is_estimate.bold().red(),
+                format_bytes(total_bytes).bold().red(),
+                format!("{percent:.02}%").bold().cyan(),
             );
             stderr().flush()?;
         }