From 602dbe50f020090182330cf22034a1bece39616c Mon Sep 17 00:00:00 2001 From: Simon Date: Wed, 14 Jan 2026 11:30:32 +0000 Subject: [PATCH] bugfixes --- Cargo.toml | 1 + src/providers/hypnotube.rs | 2 +- src/providers/javtiful.rs | 3 ++- src/util/discord.rs | 39 +++++++++++++++++++++++++++----------- 4 files changed, 32 insertions(+), 13 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 09df2c0..995660f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,6 +28,7 @@ rustc-hash = "2.1.1" async-trait = "0.1" regex = "1.12.2" titlecase = "3.6.0" +dashmap = "6.1.0" [lints.rust] unexpected_cfgs = "allow" diff --git a/src/providers/hypnotube.rs b/src/providers/hypnotube.rs index afcf85c..0e27bea 100644 --- a/src/providers/hypnotube.rs +++ b/src/providers/hypnotube.rs @@ -212,7 +212,7 @@ impl HypnotubeProvider { .await .unwrap(); if text.contains("Sorry, no results were found.") { - eprint!("Hypnotube query returned no results for page {}", page); + eprintln!("Hypnotube query returned no results for page {}", page); return vec![]; } let video_items: Vec = self.get_video_items_from_html(text.clone()).await; diff --git a/src/providers/javtiful.rs b/src/providers/javtiful.rs index 78aa34a..246eb0d 100644 --- a/src/providers/javtiful.rs +++ b/src/providers/javtiful.rs @@ -232,6 +232,7 @@ impl JavtifulProvider { let futures = block .split("card ") .skip(1) + .filter(|seg| !seg.contains("SPONSOR")) .map(|el| self.get_video_item(el.to_string(), requester.clone())); join_all(futures) @@ -278,7 +279,7 @@ impl JavtifulProvider { .split(" alt=\"") .nth(1) .and_then(|s| s.split('"').next()) - .ok_or_else(|| ErrorKind::Parse("video title".into()))? + .ok_or_else(|| ErrorKind::Parse(format!("video title\n\n{seg}").into()))? .trim() .to_string(); diff --git a/src/util/discord.rs b/src/util/discord.rs index 9712681..dd50ed5 100644 --- a/src/util/discord.rs +++ b/src/util/discord.rs @@ -1,11 +1,15 @@ use std::error::Error; use std::fmt::Write as _; use std::time::{SystemTime, UNIX_EPOCH}; - +use dashmap::DashMap; +use once_cell::sync::Lazy; use serde_json::json; - use crate::util::requester; +// Global cache: Map +static ERROR_CACHE: Lazy> = Lazy::new(DashMap::new); +const COOLDOWN_SECONDS: u64 = 3600; // 1 Hour cooldown + pub fn format_error_chain(err: &dyn Error) -> String { let mut chain_str = String::new(); let mut current_err: Option<&dyn Error> = Some(err); @@ -27,10 +31,29 @@ pub async fn send_discord_error_report( line: u32, module: &str, ) { - // 1. Get Webhook from Environment + let now = SystemTime::now() + .duration_since(UNIX_EPOCH) + .map(|d| d.as_secs()) + .unwrap_or(0); + + // --- Deduplication Logic --- + // Create a unique key based on error content and location + let error_signature = format!("{}-{}-{}", error_msg, file, line); + + if let Some(last_sent) = ERROR_CACHE.get(&error_signature) { + if now - *last_sent < COOLDOWN_SECONDS { + // Error is still in cooldown, skip sending + return; + } + } + + // Update the cache with the current timestamp + ERROR_CACHE.insert(error_signature, now); + // --------------------------- + let webhook_url = match std::env::var("DISCORD_WEBHOOK") { Ok(url) => url, - Err(_) => return, // Exit silently if no webhook is configured + Err(_) => return, }; const MAX_FIELD: usize = 1024; @@ -42,11 +65,6 @@ pub async fn send_discord_error_report( } }; - let timestamp = SystemTime::now() - .duration_since(UNIX_EPOCH) - .map(|d| d.as_secs()) - .unwrap_or(0); - let payload = json!({ "embeds": [{ "title": "🚨 Rust Error Report", @@ -79,12 +97,11 @@ pub async fn send_discord_error_report( } ], "footer": { - "text": format!("Unix time: {}", timestamp) + "text": format!("Unix time: {} | Cooldown active", now) } }] }); let mut requester = requester::Requester::new(); let _ = requester.post_json(&webhook_url, &payload, vec![]).await; - println!("Error report sent."); } \ No newline at end of file