blob: a238a87d509e60fc378fb05ad61d7c50660e86a1 (
plain) (
tree)
|
|
// SPDX-License-Identifier: AGPL-3.0-only
use std::sync::Arc;
use std::time::Duration;
use std::sync::LazyLock;
use tokio::sync::RwLock;
use reqwest::{StatusCode, Client};
use super::{CacheFuture, CacheGetter, Cache, AsyncCache};
use crate::CONFIG;
#[derive(serde::Deserialize, Debug, Default)]
#[serde(default)]
#[serde(rename = "kebab-case")]
pub struct FontQuery {
pub font: Option<Arc<str>>,
pub include_font: Option<Arc<str>>,
pub google_font: Option<Arc<str>>,
// pub small_font: Option<()>
}
pub type FontFuture = CacheFuture<Arc<str>>;
pub type FontGetter = CacheGetter<Arc<str>>;
pub type FontCache = Cache<Arc<str>>;
fn font_getter(fontname: &String) -> FontFuture {
let fontname = urlencoding::encode(fontname.as_ref()).to_string();
Box::pin(async move {
let Some(google_api_key) = CONFIG.google_api_key.clone()
else {
unreachable!();
};
let fontreq = HTTP.get(format!("https://www.googleapis.com/webfonts/v1/webfonts?key={}&family={fontname}", google_api_key))
.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."));
}
let cssreq = 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!")})?;
Ok(cssreq.text().await.unwrap().into())
})
}
static HTTP: LazyLock<Client> = crate::http::lazy();
static FONT_CACHE: LazyLock<FontCache> = LazyLock::new(|| {
Arc::new(RwLock::new(AsyncCache::new(Duration::from_secs(86400), font_getter as FontGetter)))
});
pub async fn get_fontinfo(font: &String) -> Result<Arc<str>, (StatusCode, &'static str)> {
FONT_CACHE.write().await.get_owned(font).await
}
pub fn touch() {
LazyLock::force(&FONT_CACHE);
}
|