feat(services/january): image/video embeds

This commit is contained in:
Paul Makles
2024-10-01 19:13:48 +01:00
parent 21335b3297
commit 66c84e0ad9
4 changed files with 67 additions and 11 deletions

View File

@@ -122,6 +122,17 @@ pub fn image_size(f: &NamedTempFile) -> Option<(usize, usize)> {
} }
} }
/// Determine size of image with buffer
pub fn image_size_vec(v: &[u8]) -> Option<(usize, usize)> {
if let Ok(size) = imagesize::blob_size(v)
.inspect_err(|err| tracing::error!("Failed to generate image size! {err:?}"))
{
Some((size.width, size.height))
} else {
None
}
}
/// Determine size of video at temp file /// Determine size of video at temp file
pub fn video_size(f: &NamedTempFile) -> Option<(i64, i64)> { pub fn video_size(f: &NamedTempFile) -> Option<(i64, i64)> {
if let Ok(data) = ffprobe::ffprobe(f.path()) if let Ok(data) = ffprobe::ffprobe(f.path())

View File

@@ -14,9 +14,9 @@ auto_derived!(
/// URL to the original image /// URL to the original image
pub url: String, pub url: String,
/// Width of the image /// Width of the image
pub width: isize, pub width: usize,
/// Height of the image /// Height of the image
pub height: isize, pub height: usize,
/// Positioning and size /// Positioning and size
pub size: ImageSize, pub size: ImageSize,
} }
@@ -26,9 +26,9 @@ auto_derived!(
/// URL to the original video /// URL to the original video
pub url: String, pub url: String,
/// Width of the video /// Width of the video
pub width: isize, pub width: usize,
/// Height of the video /// Height of the video
pub height: isize, pub height: usize,
} }
/// Type of remote Twitch content /// Type of remote Twitch content

View File

@@ -91,7 +91,7 @@ async fn proxy(Query(UrlQuery { url }): Query<UrlQuery>) -> Result<impl IntoResp
)] )]
async fn embed( async fn embed(
Query(UrlQuery { url }): Query<UrlQuery>, Query(UrlQuery { url }): Query<UrlQuery>,
TypedHeader(Authorization(_bearer)): TypedHeader<Authorization<Bearer>>, // TypedHeader(Authorization(_bearer)): TypedHeader<Authorization<Bearer>>,
) -> Result<Json<Embed>> { ) -> Result<Json<Embed>> {
Request::generate_embed(&url).await.map(Json) Request::generate_embed(&url).await.map(Json)
} }

View File

@@ -7,8 +7,8 @@ use lazy_static::lazy_static;
use mime::Mime; use mime::Mime;
use reqwest::{header::CONTENT_TYPE, redirect, Client, Response}; use reqwest::{header::CONTENT_TYPE, redirect, Client, Response};
use revolt_config::report_internal_error; use revolt_config::report_internal_error;
use revolt_files::{create_thumbnail, decode_image, is_valid_image, video_size}; use revolt_files::{create_thumbnail, decode_image, image_size_vec, is_valid_image, video_size};
use revolt_models::v0::Embed; use revolt_models::v0::{Embed, Image, ImageSize, Video};
use revolt_result::{create_error, Result}; use revolt_result::{create_error, Result};
lazy_static! { lazy_static! {
@@ -79,6 +79,7 @@ impl Request {
} else { } else {
let mut file = report_internal_error!(tempfile::NamedTempFile::new())?; let mut file = report_internal_error!(tempfile::NamedTempFile::new())?;
report_internal_error!(file.write_all(&bytes))?; report_internal_error!(file.write_all(&bytes))?;
if video_size(&file).is_some() { if video_size(&file).is_some() {
Ok((mime.to_string(), bytes.to_vec())) Ok((mime.to_string(), bytes.to_vec()))
} else { } else {
@@ -92,8 +93,7 @@ impl Request {
PROXY_CACHE.insert(url.to_owned(), result.clone()).await; PROXY_CACHE.insert(url.to_owned(), result.clone()).await;
result result
} else { } else {
// Err(create_error!()) Err(create_error!(LabelMe))
todo!() // no proxy
} }
} }
} }
@@ -103,7 +103,52 @@ impl Request {
if let Some(hit) = EMBED_CACHE.get(url).await { if let Some(hit) = EMBED_CACHE.get(url).await {
hit hit
} else { } else {
todo!() let Request { response, mime } = Request::new(url).await?;
match (mime.type_(), mime.subtype()) {
(_, mime::HTML) => {
// let mut metadata = Metadata::from(resp, url).await?;
// metadata.resolve_external().await;
// if metadata.is_none() {
// return Ok(Embed::None);
// }
// Ok(Embed::Website(metadata))
todo!()
}
(mime::IMAGE, _) => {
if let Some((width, height)) =
image_size_vec(&report_internal_error!(response.bytes().await)?)
{
Ok(Embed::Image(Image {
url: url.to_owned(),
width,
height,
size: ImageSize::Large,
}))
} else {
Ok(Embed::None)
}
}
(mime::VIDEO, _) => {
let mut file = report_internal_error!(tempfile::NamedTempFile::new())?;
report_internal_error!(
file.write_all(&report_internal_error!(response.bytes().await)?)
)?;
if let Some((width, height)) = video_size(&file) {
Ok(Embed::Video(Video {
url: url.to_owned(),
width: width as usize,
height: height as usize,
}))
} else {
Ok(Embed::None)
}
}
_ => Ok(Embed::None),
}
} }
} }