about summary refs log tree commit diff stats
path: root/crates/yt_dlp
diff options
context:
space:
mode:
authorBenedikt Peetz <benedikt.peetz@b-peetz.de>2025-06-17 08:52:28 +0200
committerBenedikt Peetz <benedikt.peetz@b-peetz.de>2025-06-17 08:52:28 +0200
commit0a1700131341c5dac55a395ce5ccdac4f8ec0c9e (patch)
tree1fa1e3322cd19d640a1847d2bf3e27da771fea2b /crates/yt_dlp
parentfix(yt_dlp/): Include the frozen python stdlib (diff)
downloadyt-0a1700131341c5dac55a395ce5ccdac4f8ec0c9e.zip
fix(yt_dlp/post_processors/dearrow): Migrate to curl for api requests
The reqwest crate will panic if it is blockingly run inside another
executor. But we cannot make this function async, as the whole api is
forced to be sync by python ffi.
Diffstat (limited to 'crates/yt_dlp')
-rw-r--r--crates/yt_dlp/Cargo.toml2
-rw-r--r--crates/yt_dlp/src/post_processors/dearrow.rs96
2 files changed, 61 insertions, 37 deletions
diff --git a/crates/yt_dlp/Cargo.toml b/crates/yt_dlp/Cargo.toml
index 3eff9a2..4f62eec 100644
--- a/crates/yt_dlp/Cargo.toml
+++ b/crates/yt_dlp/Cargo.toml
@@ -22,9 +22,9 @@ rust-version.workspace = true
 publish = true
 
 [dependencies]
+curl = "0.4.48"
 indexmap = { version = "2.9.0", default-features = false }
 log.workspace = true
-reqwest = { version = "0.12.20", features = ["blocking", "json"] }
 rustpython = { git = "https://github.com/RustPython/RustPython.git", features = [
   "threading",
   "stdlib",
diff --git a/crates/yt_dlp/src/post_processors/dearrow.rs b/crates/yt_dlp/src/post_processors/dearrow.rs
index bdbea7c..7dc6bbb 100644
--- a/crates/yt_dlp/src/post_processors/dearrow.rs
+++ b/crates/yt_dlp/src/post_processors/dearrow.rs
@@ -8,7 +8,12 @@
 // You should have received a copy of the License along with this program.
 // If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>.
 
-use log::{info, warn};
+use curl::easy::Easy;
+use log::{error, info, warn};
+use rustpython::vm::{
+    PyRef, VirtualMachine,
+    builtins::{PyDict, PyStr},
+};
 use serde::{Deserialize, Serialize};
 
 use crate::{InfoJson, json_get};
@@ -24,44 +29,63 @@ impl PostProcessor for DeArrowPP {
     }
 
     fn process(&self, mut info: InfoJson) -> Result<InfoJson, super::Error> {
-        let mut output: DeArrowApi = reqwest::blocking::get(format!(
-            "https://sponsor.ajay.app/api/branding?videoID={}",
-            json_get!(info, "id", as_str)
-        ))?
-        .json()?;
-
-        output.titles.reverse();
-
-        let title_len = output.titles.len();
-        loop {
-            let Some(title) = output.titles.pop() else {
-                break;
-            };
-
-            if (title.locked || title.votes < 1) && title_len > 1 {
-                info!(
-                    "Skipping title {:#?}, as it is not good enough",
-                    title.value
-                );
-                // Skip titles that are not “good” enough.
-                continue;
-            }
-
-            if let Some(old_title) = info.insert(
-                "title".to_owned(),
-                serde_json::Value::String(title.value.clone()),
-            ) {
-                warn!("Updating title from {:#?} to {:#?}", old_title, title.value);
-                info.insert("original_title".to_owned(), old_title);
-            } else {
-                warn!("Setting title to {:#?}", title.value);
-            }
-
-            break;
+       let mut output: DeArrowApi = {
+           let output_bytes = {
+               let mut dst = Vec::new();
+
+            let mut easy = Easy::new();
+            easy.url(
+                format!(
+                    "https://sponsor.ajay.app/api/branding?videoID={}",
+                    pydict_get!(@vm, info, "id", PyStr).as_str()
+                )
+                .as_str(),
+            )?;
+
+            let mut transfer = easy.transfer();
+            transfer.write_function(|data| {
+                dst.extend_from_slice(data);
+                Ok(data.len())
+            })?;
+            transfer.perform()?;
+            drop(transfer);
+
+            dst
+        };
+
+        serde_json::from_slice(&output_bytes)?
+    };
+
+    // We pop the titles, so we need this vector reversed.
+    output.titles.reverse();
+
+    let title_len = output.titles.len();
+    let selected = loop {
+        let Some(title) = output.titles.pop() else {
+            break false;
+        };
+
+        if (title.locked || title.votes < 1) && title_len > 1 {
+            info!(
+                "DeArrow: Skipping title {:#?}, as it is not good enough",
+                title.value
+            );
+            // Skip titles that are not “good” enough.
+            continue;
         }
 
-        Ok(info)
+        update_title(&info, &title.value, vm);
+
+        break true;
+    };
+
+    if !selected && title_len != 0 {
+        // No title was selected, even though we had some titles.
+        // Just pick the first one in this case.
+        update_title(&info, &output.titles[0].value, vm);
     }
+
+    Ok(info)
 }
 
 #[derive(Serialize, Deserialize)]