bootstrap-sona 1.0.1

A simple bootstrap 5 .well-known/fursona viewer
#[macro_use] extern crate rocket;
use rocket::http::{Status, ContentType};
use rocket::http::CookieJar;
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
use include_dir::{include_dir, Dir};
mod rende;
mod req;
use rende::types::Sona;

static ASSETS: Dir = include_dir!("$CARGO_MANIFEST_DIR/static");

#[derive(Serialize, Deserialize, Debug)]
struct MainJSON {
    sonas: Vec<Sona>
}

#[get("/")]
async fn index(cookies: &CookieJar<'_>) -> (Status, (ContentType, String)) {
    let cookie = cookies.get("theme").map(|crumb| format!("{}", crumb.value()));
    let theme = cookie.unwrap_or("light".to_string());
    (Status::Ok, (ContentType::HTML, rende::home(theme)))
}

// I think it'll be a very good idea to clean this up a wee bit.

#[get("/search?<url>")]
async fn sonalookup(cookies: &CookieJar<'_>, url: &str) -> (Status, (ContentType, String)) {
    let cookie = cookies.get("theme").map(|crumb| format!("{}", crumb.value()));
    let theme = cookie.unwrap_or("light".to_string());
    let mut success = false;
    let mut res = req::get(url.to_string() + "/.well-known/fursona").await;
    let mut r;
    if let Err(e) = res {
        return (Status::InternalServerError, (ContentType::HTML, rende::error(e.to_string(), theme)))
    } else if let Ok(e) = res {
        r = e
    } else {
        return (Status::ImATeapot, (ContentType::HTML, rende::error("Somewhere, somewhat, somehow", theme)))
    }
    if r.status() != reqwest::StatusCode::OK {
        res = req::get(url.to_string() + "/.well-known/fursona.json").await;
        if let Err(e) = res { 
            return (Status::InternalServerError, (ContentType::HTML, rende::error(e.to_string(), theme)))
        } else if let Ok(e) = res {
            r = e
        } else {
            return (Status::ImATeapot, (ContentType::HTML, rende::error("Somewhere, somewhat, somehow", theme))) 
        }
        if r.status() == reqwest::StatusCode::OK {
            success = true
        }
    } else {
        success = true
    }
    if success {
        let sonasr: Result<MainJSON, reqwest::Error> = r.json().await;
        let mut content = "".to_string();
        let mut i = 1;
        if let Ok(sonas) = sonasr {
            for sona in sonas.sonas {
                content += &rende::card(sona, i);
                i += 1;
            }
            return (Status::Ok, (ContentType::HTML, rende::cardpage(theme, url.to_string(), content)))
        } else if let Err(e) = sonasr {
            return (Status::InternalServerError, (ContentType::HTML, rende::error(e.to_string(), theme)))
        } else {
            return (Status::ImATeapot, (ContentType::HTML, rende::error("Somewhere, somewhat, somehow", theme)))
        }
    } else {
        return (Status::NotFound, (ContentType::HTML, rende::error("Cannot find a fursona file in this domain.", theme)))
    }
}

#[get("/<file..>")]
fn stat(cookies:&CookieJar<'_>, file: PathBuf) -> (Status, (ContentType, Vec<u8>)) {
    let cookie = cookies.get("theme").map(|crumb| format!("{}", crumb.value()));
    let theme = cookie.unwrap_or("light".to_string());
    if let Some(file) = ASSETS.get_file(file) {
        let ctype = ContentType::from_extension(file.path().extension().and_then(|x| x.to_str()).unwrap_or("")).unwrap_or(ContentType::Binary);
        (Status::Ok, (ctype, file.contents().to_vec()))
    } else {
        (Status::NotFound, (ContentType::HTML, rende::error("You seem to be lost.", theme).into_bytes()))
    }
}

#[launch]
fn rocket() -> _ {
    rocket::build().mount("/", routes![index, stat, sonalookup])
}