/* This file is part of jellything (https://codeberg.org/metamuffin/jellything) which is licensed under the GNU Affero General Public License (version 3); see /COPYING. Copyright (C) 2026 metamuffin */ use super::error::MyResult; use crate::{request_info::RequestInfo, responders::cache::CacheControlImage}; use anyhow::Context; use jellycache::HashKey; use jellycommon::routes::u_image; use jellyimport::generate_person_fallback; use rocket::{get, http::ContentType, response::Redirect}; use std::path::PathBuf; use tokio::task::spawn_blocking; pub const AVIF_QUALITY: u32 = 70; pub const AVIF_SPEED: u8 = 5; #[get("/image/?")] pub async fn r_image( ri: RequestInfo<'_>, path: PathBuf, size: Option, ) -> MyResult<(ContentType, CacheControlImage)> { let size = size.unwrap_or(2048); let path = path.to_string_lossy().to_string(); // fit the resolution into a finite set so the maximum cache is finite too. let width = 2usize.pow(size.clamp(128, 2048).ilog2()); let encoded = spawn_blocking(move || { jellytranscoder::image::transcode(&ri.state.cache, &path, AVIF_QUALITY, AVIF_SPEED, width) .context("transcoding asset") }) .await .unwrap()?; Ok((ContentType::AVIF, CacheControlImage(encoded))) } #[get("/image_fallback/person/?")] pub async fn r_image_fallback_person( ri: RequestInfo<'_>, name: &str, size: Option, ) -> MyResult { let path = ri .state .cache .store(format!("fallback/person/{}.image", HashKey(name)), || { generate_person_fallback(name) })?; Ok(Redirect::found(u_image(&path, size.unwrap_or(2048)))) } // #[get("/n//image/?")] // pub async fn r_item_poster( // session: A, // id: A, // slot: &str, // size: Option, // ) -> MyResult { // let slot = PictureSlot::from_str(slot).map_err(|_| anyhow!("slot invalid"))?; // let node = get_node(&session.0, id.0, false, false, NodeFilterSort::default())?; // let picture = node // .node // .pictures // .get(&slot) // .cloned() // .ok_or(anyhow!("no pic todo"))?; // Ok(Redirect::permanent(rocket::uri!(r_image(picture, size)))) // } // #[get("/n//thumbnail?&")] // pub async fn r_node_thumbnail( // session: A, // id: A, // t: f64, // size: Option, // ) -> MyResult { // let picture = get_node_thumbnail(&session.0, id.0, t).await?; // Ok(Redirect::permanent(rocket::uri!(r_image(picture, size)))) // }