aboutsummaryrefslogtreecommitdiffstats
path: root/src/config.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/config.rs')
-rw-r--r--src/config.rs53
1 files changed, 16 insertions, 37 deletions
diff --git a/src/config.rs b/src/config.rs
index e635f4a..3c11bc8 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -6,7 +6,8 @@ use std::pin::Pin;
use std::time::*;
use super::cache::AsyncCache;
-use super::deserialize::{GetRecentTracks, GetUserInfo, Track, User};
+use super::deserialize::{GetRecentTracks, GetUserInfo, GetTrackInfo, Track, TrackStub, User};
+use super::font::{font_cache, FontCache};
use reqwest::{Client, StatusCode};
use dotenv::var;
@@ -18,13 +19,9 @@ type CacheFuture<Output> = Pin<Box<(dyn Future<Output = Result<Output, (StatusCo
type CacheGetter<Output> = fn(&String) -> CacheFuture<Output>;
type Cache<Output> = Arc<RwLock<AsyncCache<String, Output, CacheGetter<Output>>>>;
-type FontFuture = CacheFuture<Arc<str>>;
-type FontGetter = CacheGetter<Arc<str>>;
-type FontCache = Cache<Arc<str>>;
-
-type UserFuture = CacheFuture<Arc<(User, Track)>>;
-type UserGetter = CacheGetter<Arc<(User, Track)>>;
-type UserCache = Cache<Arc<(User, Track)>>;
+type UserFuture = CacheFuture<Arc<(User, Track, TrackStub)>>;
+type UserGetter = CacheGetter<Arc<(User, Track, TrackStub)>>;
+type UserCache = Cache<Arc<(User, Track, TrackStub)>>;
static INTERNAL_THEMES: &[(&str, &str)] = &[("plain", include_str!("themes/plain.hbs"))];
@@ -49,40 +46,22 @@ fn user_getter(username: &String) -> UserFuture {
if tracksreq.status() == StatusCode::NOT_FOUND { return Err((StatusCode::NOT_FOUND, "User does not exist!")); }
if tracksreq.status() == StatusCode::FORBIDDEN { return Err((StatusCode::FORBIDDEN, "You need to unprivate your song history!")); }
- let tracksinfo = tracksreq.json::<GetRecentTracks>().await
+ let trackstub = tracksreq.json::<GetRecentTracks>().await
.map_err(|e| {log::error!("Couldn't parse user.getRecentTracks for `{username}`: {e}"); (StatusCode::INTERNAL_SERVER_ERROR, "Couldn't parse user.getRecentTracks!")})?
.recenttracks.track.into_iter().next().ok_or((StatusCode::UNPROCESSABLE_ENTITY, "You need to listen to some songs first!"))?;
- Ok(Arc::new((userinfo, tracksinfo)))
- })
-}
-
-fn font_getter(fontname: &String) -> FontFuture {
- let fontname = urlencoding::encode(fontname.as_ref()).to_string();
- Box::pin(async move {
- let Some(google_api_key) = STATE.google_api_key.clone()
- else {
- unreachable!();
- };
-
- let fontreq = STATE.http.get(format!("https://www.googleapis.com/webfonts/v1/webfonts?key={}&family={fontname}", google_api_key))
+ let trackreq = STATE.http.get(format!("https://ws.audioscrobbler.com/2.0/?method=track.getInfo&format=json&username={username}&api_key={}&track={}&artist={}", STATE.lastfm_api_key, trackstub.name, trackstub.artist.name))
.send().await
- .map_err(|e| {log::error!("Failed to get info for font `{fontname}`: {e}"); (StatusCode::SERVICE_UNAVAILABLE, "Couldn't connect to Google Fonts!")})?;
- if fontreq.status() == StatusCode::NOT_FOUND { return Err((StatusCode::NOT_FOUND, "Font does not exist!")); }
- if fontreq.status() == StatusCode::FORBIDDEN {
- log::error!("Invalid Google API key in config!");
- return Err((StatusCode::SERVICE_UNAVAILABLE, "This instance is not configured to support Google Fonts properly, please use a different font."));
- }
+ .map_err(|e| {log::error!("Failed to get tracks for user `{username}`: {e}"); (StatusCode::SERVICE_UNAVAILABLE, "Couldn't connect to last.fm!")})?;
+ if trackreq.status() == StatusCode::NOT_FOUND { return Err((StatusCode::NOT_FOUND, "Track does not exist!")); }
- let cssreq = STATE.http.get(format!("https://fonts.googleapis.com/css2?family={fontname}"))
- .send().await
- .map_err(|e| {log::error!("Failed to get CSS for font `{fontname}`: {e}"); (StatusCode::SERVICE_UNAVAILABLE, "Couldn't download font CSS!")})?;
+ let trackinfo = trackreq.json::<GetTrackInfo>().await
+ .map_err(|e| {log::error!("Couldn't parse track.getInfo for `{}` by `{}` on behalf of {username}: {e}", trackstub.name, trackstub.artist.name); (StatusCode::INTERNAL_SERVER_ERROR, "Couldn't parse track.getInfo!")})?.track;
- Ok(cssreq.text().await.unwrap().into())
+ Ok(Arc::new((userinfo, trackinfo, trackstub)))
})
}
-
#[derive(Debug)]
enum Whitelist {
Exclusive{cache: UserCache, whitelist: BTreeSet<String>},
@@ -95,11 +74,11 @@ pub struct State {
default_theme: Arc<str>,
send_refresh_header: bool,
- http: Client,
+ pub(crate) http: Client,
handlebars: Handlebars<'static>,
- google_api_key: Option<Arc<str>>,
+ pub(crate) google_api_key: Option<Arc<str>>,
google_fonts_cache: FontCache,
whitelist: Whitelist,
@@ -146,7 +125,7 @@ impl State {
},
google_api_key: var("LFME_GOOGLE_API_KEY").map(Into::into).ok(),
- google_fonts_cache: Arc::new(RwLock::new(AsyncCache::new(Duration::from_secs(86400), font_getter as FontGetter))),
+ google_fonts_cache: font_cache(),
whitelist: {
let load_whitelist = || -> Option<BTreeSet<String>> {
@@ -178,7 +157,7 @@ impl State {
self.google_fonts_cache.write().await.get_owned(font).await
}
pub fn has_google_api_key(&self) -> bool { self.google_api_key.is_some() }
- pub async fn get_userinfo(&self, user: &String) -> (Result<Arc<(User, Track)>, (StatusCode, &'static str)>, Duration) {
+ pub async fn get_userinfo(&self, user: &String) -> (Result<Arc<(User, Track, TrackStub)>, (StatusCode, &'static str)>, Duration) {
match &self.whitelist {
Whitelist::Open{default_cache, whitelist_cache, whitelist} => {
if whitelist.contains(user) {