aboutsummaryrefslogtreecommitdiffstats
path: root/src/ctx.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/ctx.rs')
-rw-r--r--src/ctx.rs122
1 files changed, 122 insertions, 0 deletions
diff --git a/src/ctx.rs b/src/ctx.rs
new file mode 100644
index 0000000..6beb634
--- /dev/null
+++ b/src/ctx.rs
@@ -0,0 +1,122 @@
+use reqwest::StatusCode;
+use super::deserialize as de;
+use std::sync::Arc;
+
+pub mod model {
+ use std::sync::Arc;
+
+ /// The theme representation of a user.
+ #[derive(serde::Serialize, Debug)]
+ pub struct User {
+ /// Their username.
+ pub name: Arc<str>,
+ /// Their "Display Name".
+ pub realname: Arc<str>,
+
+ /// True if user subscribes to last.fm pro.
+ pub pro_subscriber: bool,
+ /// Total scrobbles.
+ pub scrobble_count: u64,
+ /// Number of artists in library.
+ pub artist_count: u64,
+ /// Number of tracks in library.
+ pub track_count: u64,
+ /// Number of albums in library.
+ pub album_count: u64,
+
+ /// Link to user's profile picture.
+ pub image_url: Arc<str>,
+
+ /// Link to user's profile.
+ pub url: Arc<str>
+ }
+
+ /// The theme representation of an artist
+ #[derive(serde::Serialize, Debug)]
+ pub struct Artist {
+ /// The artist's name.
+ pub name: Arc<str>,
+
+ /// A link to their current image.
+ pub image_url: Arc<str>,
+ /// A link to their last.fm page.
+ pub url: Arc<str>
+ }
+
+ /// The theme representation of a user's most recently scrobbled track.
+ #[derive(serde::Serialize, Debug)]
+ pub struct Scrobble {
+ /// The name of the track.
+ pub name: Arc<str>,
+ /// The name of its album.
+ pub album: Arc<str>,
+ /// The artist who made it.
+ pub artist: Artist,
+
+ /// A link to the track image.
+ pub image_url: Arc<str>,
+ /// True if the user is currently scrobbling it, false if it's just the most recently played track.
+ pub now_playing: bool,
+ /// A link to the track's last.fm page.
+ pub url: Arc<str>,
+
+ /// True if the user has loved the track.
+ pub loved: bool
+ }
+
+ /// The context passed in to all themes.
+ ///
+ /// Serialized as untagged, so themes should check if `error` is set and decide whether to show an error state or try rendering user info.
+ #[derive(serde::Serialize, Debug)]
+ #[serde(untagged)]
+ pub enum Data {
+ /// Contains text explaining a potential error.
+ Error { error: &'static str },
+ /// Contains data about a user and what they're listening to.
+ Data { user: User, scrobble: Scrobble }
+ }
+}
+#[derive(Debug)]
+pub struct ResponseCtx(pub model::Data, pub StatusCode);
+
+impl From<Result<Arc<(de::User, de::Track)>, (StatusCode, &'static str)>> for ResponseCtx {
+ fn from(v: Result<Arc<(de::User, de::Track)>, (StatusCode, &'static str)>) -> ResponseCtx {
+ match v {
+ Ok(a) => {
+ let (user, track) = a.as_ref();
+ ResponseCtx(model::Data::Data {
+ user: model::User {
+ name: user.name.clone(),
+ realname: user.realname.clone(),
+
+ pro_subscriber: user.subscriber,
+ scrobble_count: user.playcount,
+ artist_count: user.artist_count,
+ track_count: user.track_count,
+ album_count: user.track_count,
+
+ image_url: user.images.iter().max_by(|a, b| a.size.cmp(&b.size)).map(|a| a.url.clone()).unwrap_or_else(|| "".into()),
+
+ url: user.url.clone()
+ },
+ scrobble: model::Scrobble {
+ name: track.name.clone(),
+ album: track.album.name.clone(),
+ artist: model::Artist {
+ name: track.artist.name.clone(),
+ image_url: track.artist.images.iter().max_by(|a, b| a.size.cmp(&b.size)).map(|a| a.url.clone()).unwrap_or_else(|| "".into()),
+ url: track.artist.url.clone().unwrap_or_else(|| "".into())
+ },
+ image_url: track.images.iter().max_by(|a, b| a.size.cmp(&b.size)).map(|a| a.url.clone()).unwrap_or_else(|| "".into()),
+ now_playing: track.attr.nowplaying,
+ url: track.url.clone(),
+ loved: track.loved.unwrap_or(false)
+ }
+ }, StatusCode::OK)
+ },
+ Err((status, error)) => {
+ ResponseCtx(model::Data::Error {error}, status)
+ }
+ }
+ }
+}