aboutsummaryrefslogblamecommitdiffstats
path: root/src/font.rs
blob: 64547707f9443af8eb1e12341f434d1a7e4734d6 (plain) (tree)
1
2
3
4
5
6
7
8
                   






                                                                






                                             
                                    

                              
































                                                                                                                                                            
use std::sync::Arc;
use std::time::Duration;

use tokio::sync::RwLock;
use reqwest::StatusCode;

use super::cache::{CacheFuture, CacheGetter, Cache, AsyncCache};
use crate::STATE;

#[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) = 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))
      .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 = 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!")})?;

    Ok(cssreq.text().await.unwrap().into())
  })
}

pub fn font_cache() -> FontCache {
  Arc::new(RwLock::new(AsyncCache::new(Duration::from_secs(86400), font_getter as FontGetter)))
}