My personal site cherry.computer
htmx tailwind axum askama

refactor: fix pedantic Clippy lints

cherry.computer 45e23b96 5802e018

verified
+56 -52
+10 -8
server/src/index.rs
··· 8 scrobble: Option<ScrobblesTemplate>, 9 } 10 11 - pub async fn get_index(monitor: ScrobbleMonitor) -> RootTemplate { 12 - let scrobbles_template = monitor.try_get_scrobble(); 13 - if scrobbles_template.is_none() { 14 - // start fetching scrobble so we can send a fresh response to the client ASAP 15 - tokio::spawn(async move { monitor.get_scrobble().await }); 16 - } 17 18 - RootTemplate { 19 - scrobble: scrobbles_template, 20 } 21 }
··· 8 scrobble: Option<ScrobblesTemplate>, 9 } 10 11 + impl RootTemplate { 12 + pub fn new(monitor: ScrobbleMonitor) -> RootTemplate { 13 + let scrobbles_template = monitor.try_get_scrobble(); 14 + if scrobbles_template.is_none() { 15 + // start fetching scrobble so we can send a fresh response to the client ASAP 16 + tokio::spawn(async move { monitor.get_scrobble().await }); 17 + } 18 19 + RootTemplate { 20 + scrobble: scrobbles_template, 21 + } 22 } 23 }
+2 -2
server/src/main.rs
··· 4 5 use std::{convert::Infallible, env, net::SocketAddr, time::Duration}; 6 7 - use crate::index::get_index; 8 use crate::scrobble_monitor::ScrobbleMonitor; 9 10 use askama::Template; ··· 55 } 56 57 async fn render_index_handler(State(monitor): State<ScrobbleMonitor>) -> impl IntoResponse { 58 - let template = get_index(monitor).await; 59 template.render().map(Html).map_err(|err| { 60 tracing::error!("failed to render index: {err:?}"); 61 StatusCode::INTERNAL_SERVER_ERROR
··· 4 5 use std::{convert::Infallible, env, net::SocketAddr, time::Duration}; 6 7 + use crate::index::RootTemplate; 8 use crate::scrobble_monitor::ScrobbleMonitor; 9 10 use askama::Template; ··· 55 } 56 57 async fn render_index_handler(State(monitor): State<ScrobbleMonitor>) -> impl IntoResponse { 58 + let template = RootTemplate::new(monitor); 59 template.render().map(Html).map_err(|err| { 60 tracing::error!("failed to render index: {err:?}"); 61 StatusCode::INTERNAL_SERVER_ERROR
+42 -40
server/src/scrobble.rs
··· 2 use serde::Deserialize; 3 4 #[derive(Debug, Clone, Deserialize)] 5 - pub struct ScrobbleArtist { 6 #[serde(rename = "#text")] 7 pub text: String, 8 } 9 10 #[derive(Debug, Clone, Deserialize)] 11 - pub struct ScrobbleImage { 12 #[serde(rename = "#text")] 13 pub text: String, 14 } 15 16 #[derive(Debug, Clone, Deserialize)] 17 - pub struct ScrobbleAttributes { 18 #[serde(rename = "nowplaying")] 19 pub now_playing: String, 20 } 21 22 #[derive(Debug, Clone, Deserialize)] 23 - pub struct ScrobbleTrack { 24 - pub artist: ScrobbleArtist, 25 - pub image: Vec<ScrobbleImage>, 26 pub name: String, 27 #[serde(rename = "@attr")] 28 - pub attributes: Option<ScrobbleAttributes>, 29 } 30 31 #[derive(Debug, Clone, Deserialize)] 32 - pub struct ScrobbleRecentTracks { 33 - pub track: Vec<ScrobbleTrack>, 34 } 35 36 #[derive(Debug, Clone, Deserialize)] 37 pub struct Scrobble { 38 #[serde(rename = "recenttracks")] 39 - pub recent_tracks: ScrobbleRecentTracks, 40 } 41 42 #[derive(Template, Debug, Clone, PartialEq)] ··· 48 pub srcset: Option<String>, 49 } 50 51 - pub fn scrobble_partial(scrobble: Scrobble) -> ScrobblesTemplate { 52 - let latest_track = scrobble 53 - .recent_tracks 54 - .track 55 - .into_iter() 56 - .next() 57 - .expect("no tracks were returned"); 58 - let srcset = latest_track.image.get(0..3).map(|images| { 59 - format!( 60 - "{}, {} 2x, {} 3x", 61 - images[0].text, images[1].text, images[2].text 62 - ) 63 - }); 64 - let text_intro = if latest_track 65 - .attributes 66 - .is_some_and(|attr| attr.now_playing == "true") 67 - { 68 - "Now playing: " 69 - } else { 70 - "Last played: " 71 - }; 72 - let now_playing = format!("{} - {}", latest_track.name, latest_track.artist.text); 73 - 74 - ScrobblesTemplate { 75 - intro: text_intro, 76 - now_playing, 77 - image: latest_track 78 - .image 79 .into_iter() 80 .next() 81 - .map(|image| image.text), 82 - srcset, 83 } 84 }
··· 2 use serde::Deserialize; 3 4 #[derive(Debug, Clone, Deserialize)] 5 + pub struct Artist { 6 #[serde(rename = "#text")] 7 pub text: String, 8 } 9 10 #[derive(Debug, Clone, Deserialize)] 11 + pub struct Image { 12 #[serde(rename = "#text")] 13 pub text: String, 14 } 15 16 #[derive(Debug, Clone, Deserialize)] 17 + pub struct Attributes { 18 #[serde(rename = "nowplaying")] 19 pub now_playing: String, 20 } 21 22 #[derive(Debug, Clone, Deserialize)] 23 + pub struct Track { 24 + pub artist: Artist, 25 + pub image: Vec<Image>, 26 pub name: String, 27 #[serde(rename = "@attr")] 28 + pub attributes: Option<Attributes>, 29 } 30 31 #[derive(Debug, Clone, Deserialize)] 32 + pub struct RecentTracks { 33 + pub track: Vec<Track>, 34 } 35 36 #[derive(Debug, Clone, Deserialize)] 37 pub struct Scrobble { 38 #[serde(rename = "recenttracks")] 39 + pub recent_tracks: RecentTracks, 40 } 41 42 #[derive(Template, Debug, Clone, PartialEq)] ··· 48 pub srcset: Option<String>, 49 } 50 51 + impl ScrobblesTemplate { 52 + pub fn new(scrobble: Scrobble) -> ScrobblesTemplate { 53 + let latest_track = scrobble 54 + .recent_tracks 55 + .track 56 .into_iter() 57 .next() 58 + .expect("no tracks were returned"); 59 + let srcset = latest_track.image.get(0..3).map(|images| { 60 + format!( 61 + "{}, {} 2x, {} 3x", 62 + images[0].text, images[1].text, images[2].text 63 + ) 64 + }); 65 + let text_intro = if latest_track 66 + .attributes 67 + .is_some_and(|attr| attr.now_playing == "true") 68 + { 69 + "Now playing: " 70 + } else { 71 + "Last played: " 72 + }; 73 + let now_playing = format!("{} - {}", latest_track.name, latest_track.artist.text); 74 + 75 + ScrobblesTemplate { 76 + intro: text_intro, 77 + now_playing, 78 + image: latest_track 79 + .image 80 + .into_iter() 81 + .next() 82 + .map(|image| image.text), 83 + srcset, 84 + } 85 } 86 }
+2 -2
server/src/scrobble_monitor.rs
··· 6 use reqwest::Client; 7 use tokio::sync::RwLock; 8 9 - use crate::scrobble::{scrobble_partial, Scrobble, ScrobblesTemplate}; 10 11 #[derive(Debug, Clone)] 12 struct CachedScrobble { ··· 63 _ => { 64 tracing::debug!("fetching new scrobble data"); 65 let scrobble = self.fetch_scrobble().await?; 66 - let scrobble_partial = scrobble_partial(scrobble); 67 *last_scrobble = Some(CachedScrobble { 68 data: scrobble_partial.clone(), 69 fetch_time: Instant::now(),
··· 6 use reqwest::Client; 7 use tokio::sync::RwLock; 8 9 + use crate::scrobble::{Scrobble, ScrobblesTemplate}; 10 11 #[derive(Debug, Clone)] 12 struct CachedScrobble { ··· 63 _ => { 64 tracing::debug!("fetching new scrobble data"); 65 let scrobble = self.fetch_scrobble().await?; 66 + let scrobble_partial = ScrobblesTemplate::new(scrobble); 67 *last_scrobble = Some(CachedScrobble { 68 data: scrobble_partial.clone(), 69 fetch_time: Instant::now(),