From afd8c906bab23a1967a2f4eed2ca54cc5ad0b5dc Mon Sep 17 00:00:00 2001 From: Paul Makles Date: Wed, 2 Oct 2024 11:31:55 +0100 Subject: [PATCH] fix(services/january): YouTube fallback --- crates/services/january/src/main.rs | 2 + crates/services/january/src/requests.rs | 11 ++++- crates/services/january/src/website_embed.rs | 45 ++++++++++++++------ 3 files changed, 44 insertions(+), 14 deletions(-) diff --git a/crates/services/january/src/main.rs b/crates/services/january/src/main.rs index 2175ca0a..b905b87d 100644 --- a/crates/services/january/src/main.rs +++ b/crates/services/january/src/main.rs @@ -66,6 +66,8 @@ async fn main() -> Result<(), std::io::Error> { .nest("/", api::router().await); // Configure TCP listener and bind + tracing::info!("Listening on 0.0.0.0:14705"); + tracing::info!("Play around with the API: http://localhost:14705/scalar"); let address = SocketAddr::from((Ipv4Addr::UNSPECIFIED, 14705)); let listener = TcpListener::bind(&address).await?; axum::serve(listener, app.into_make_service()).await diff --git a/crates/services/january/src/requests.rs b/crates/services/january/src/requests.rs index c8e540de..44218f1f 100644 --- a/crates/services/january/src/requests.rs +++ b/crates/services/january/src/requests.rs @@ -156,7 +156,7 @@ impl Request { let response = if let Some(Request { response, .. }) = request { response } else { - let Request { response, mime } = Request::new(&url).await?; + let Request { response, mime } = Request::new(url).await?; if matches!(mime.type_(), mime::VIDEO) { response } else { @@ -262,4 +262,13 @@ impl Request { Ok(Request { response, mime }) } + + /// Check if something exists + pub async fn exists(url: &str) -> bool { + if let Ok(response) = CLIENT.head(url).send().await { + response.status().is_success() + } else { + false + } + } } diff --git a/crates/services/january/src/website_embed.rs b/crates/services/january/src/website_embed.rs index 794fe9dc..b52f01c4 100644 --- a/crates/services/january/src/website_embed.rs +++ b/crates/services/january/src/website_embed.rs @@ -207,24 +207,43 @@ pub fn populate_special(original_url: String, metadata: &mut WebsiteMetadata) { id: captures[1].to_string(), }) } else if let Some(captures) = RE_YOUTUBE.captures_iter(url).next() { + let id = captures[1].to_string(); + lazy_static! { static ref RE_TIMESTAMP: Regex = Regex::new("(?:\\?|&)(?:t|start)=([\\w]+)").unwrap(); } - if let Some(video) = &metadata.video { - if let Some(timestamp_captures) = RE_TIMESTAMP.captures_iter(&video.url).next() { - Some(Special::YouTube { - id: captures[1].to_string(), - timestamp: Some(timestamp_captures[1].to_string()), - }) - } else { - Some(Special::YouTube { - id: captures[1].to_string(), - timestamp: None, - }) - } + // YouTube now blocks datacentre IPs from fetching information + // This is a fallback to prevent the embed from looking weird + if metadata.video.is_none() { + metadata.title.replace("YouTube".to_owned()); + metadata.description.take(); + metadata.colour.take(); + metadata.icon_url.take(); + metadata.site_name.take(); + + // Verify the video exists + // TODO: breaks axum :( + // if !crate::requests::Request::exists(&format!( + // "http://img.youtube.com/vi/{}/sddefault.jpg", + // id + // )) + // .await + // { + // return; + // } + } + + if let Some(timestamp_captures) = RE_TIMESTAMP.captures_iter(url).next() { + Some(Special::YouTube { + id, + timestamp: Some(timestamp_captures[1].to_string()), + }) } else { - None + Some(Special::YouTube { + id, + timestamp: None, + }) } } else if let Some(captures) = RE_LIGHTSPEED.captures_iter(url).next() { Some(Special::Lightspeed {