My personal site cherry.computer
htmx tailwind axum askama

feat: allow media requests to be mocked

cherry.computer d4c5b46a 3f881d6b

verified
+45 -11
+38 -7
server/src/index.rs
··· 5 }; 6 7 use askama::Template; 8 9 #[derive(Template, Debug, Clone)] 10 #[template(path = "index.html")] ··· 13 } 14 15 impl RootTemplate { 16 - pub async fn new(apple_music_client: &AppleMusicClient) -> RootTemplate { 17 - let (game, movie, song) = tokio::join!( 18 - backloggd::cached_fetch(), 19 - letterboxd::cached_fetch(), 20 - apple_music::cached_fetch(apple_music_client) 21 - ); 22 - let media = [game, movie, song].into_iter().flatten().collect(); 23 24 RootTemplate { media } 25 } 26 }
··· 5 }; 6 7 use askama::Template; 8 + use serde::Deserialize; 9 + 10 + #[derive(Deserialize)] 11 + pub struct IndexOptions { 12 + #[serde(default)] 13 + mock: bool, 14 + } 15 16 #[derive(Template, Debug, Clone)] 17 #[template(path = "index.html")] ··· 20 } 21 22 impl RootTemplate { 23 + pub async fn new(apple_music_client: &AppleMusicClient, options: IndexOptions) -> RootTemplate { 24 + let media = if options.mock { 25 + mocked_media() 26 + } else { 27 + let (game, movie, song) = tokio::join!( 28 + backloggd::cached_fetch(), 29 + letterboxd::cached_fetch(), 30 + apple_music::cached_fetch(apple_music_client) 31 + ); 32 + [game, movie, song].into_iter().flatten().collect() 33 + }; 34 35 RootTemplate { media } 36 } 37 } 38 + 39 + fn mocked_media() -> Vec<Media> { 40 + vec![ 41 + Media { 42 + name: "Cyberpunk 2077: Ultimate Edition".to_owned(), 43 + image: "https://images.igdb.com/igdb/image/upload/t_cover_big/co7iy1.jpg".to_owned(), 44 + context: "Nintendo Switch 2".to_owned(), 45 + }, 46 + Media { 47 + name: "The Thursday Murder Club".to_owned(), 48 + image: "https://a.ltrbxd.com/resized/film-poster/6/6/6/2/8/6/666286-the-thursday-murder-club-0-230-0-345-crop.jpg?v=4bfeae38a7".to_owned(), 49 + context: "1 star".to_owned(), 50 + }, 51 + Media { 52 + name: "We Might Feel Unsound".to_owned(), 53 + image: "https://is1-ssl.mzstatic.com/image/thumb/Music124/v4/f4/b2/8e/f4b28ee4-01c6-232c-56a7-b97fd5b0e0ae/00602527857671.rgb.jpg/240x240bb.jpg".to_owned(), 54 + context: "James Blake — James Blake".to_owned(), 55 + }, 56 + ] 57 + }
+7 -4
server/src/main.rs
··· 7 8 #[cfg(debug_assertions)] 9 use crate::am_auth_flow::AuthFlowTemplate; 10 - use crate::index::RootTemplate; 11 use crate::scrapers::apple_music::AppleMusicClient; 12 13 use askama::Template; 14 use axum::{ 15 Router, 16 - extract::State, 17 http::{HeaderName, HeaderValue, StatusCode}, 18 response::{Html, IntoResponse}, 19 routing::{get, get_service}, ··· 59 Ok(()) 60 } 61 62 - async fn render_index_handler(State(state): State<AppState>) -> impl IntoResponse { 63 - let template = RootTemplate::new(&state.apple_music_client).await; 64 template.render().map(Html).map_err(|err| { 65 tracing::error!("failed to render index: {err:?}"); 66 StatusCode::INTERNAL_SERVER_ERROR
··· 7 8 #[cfg(debug_assertions)] 9 use crate::am_auth_flow::AuthFlowTemplate; 10 + use crate::index::{IndexOptions, RootTemplate}; 11 use crate::scrapers::apple_music::AppleMusicClient; 12 13 use askama::Template; 14 use axum::{ 15 Router, 16 + extract::{Query, State}, 17 http::{HeaderName, HeaderValue, StatusCode}, 18 response::{Html, IntoResponse}, 19 routing::{get, get_service}, ··· 59 Ok(()) 60 } 61 62 + async fn render_index_handler( 63 + Query(options): Query<IndexOptions>, 64 + State(state): State<AppState>, 65 + ) -> impl IntoResponse { 66 + let template = RootTemplate::new(&state.apple_music_client, options).await; 67 template.render().map(Html).map_err(|err| { 68 tracing::error!("failed to render index: {err:?}"); 69 StatusCode::INTERNAL_SERVER_ERROR