mod error;
mod live;
mod posts;
mod scrobbles;
mod skweets;
use std::borrow::Cow;
use rocket::fs::{relative, FileServer};
use rocket::http::Status;
use rocket::{Request, State};
use rocket_dyn_templates::{context, Template};
use error::BlossomError;
type Result<T> = std::result::Result<T, BlossomError>;
struct Clients {
listenbrainz: listenbrainz::raw::Client,
skinnyverse: mastodon_async::Mastodon,
reqwest: reqwest::Client,
}
#[macro_use]
extern crate rocket;
#[get("/")]
async fn home(clients: &State<Clients>) -> Template {
let (live, listenbrainz, skweets, blogposts) = tokio::join!(
live::get_live_status(&clients.reqwest),
scrobbles::get_now_playing(&clients.listenbrainz),
skweets::get_recents(&clients.skinnyverse),
posts::get_blogposts()
);
let is_live = live.unwrap_or_default().online;
let listenbrainz = listenbrainz.unwrap_or_default();
let skweets = skweets.unwrap_or_default();
let blogposts = blogposts.unwrap_or_default();
Template::render(
"home",
context! {
is_live,
listenbrainz,
skweets,
blogposts,
},
)
}
#[get("/blog")]
async fn blog() -> Template {
let mut blogposts = posts::get_blogposts().await.unwrap_or_default();
let tags = posts::get_tags(&blogposts);
for blogpost in &mut blogposts {
blogpost.render().await;
}
let reverse = "reverse".to_owned();
Template::render(
"blog",
context! {
reverse,
blogposts,
tags,
},
)
}
#[get("/blog/<blogpost>")]
async fn blogpost(blogpost: &str) -> Result<Template> {
let mut blogpost = posts::get_blogpost(blogpost).await?;
blogpost.render().await?;
Ok(Template::render(
"blogpost",
context! {
blogpost,
},
))
}
#[get("/contact")]
async fn contact() -> Template {
Template::render("contact", context! {})
}
#[get("/plants")]
async fn plants() -> Result<Template> {
Err(BlossomError::Unimplemented(Status::NotImplemented))
}
#[catch(default)]
fn catcher(status: Status, req: &Request) -> Template {
let message;
if status.code == 404 {
message = "i either haven't built this page yet or it looks like you're a little lost";
} else if status.code == 500 {
message = "omg the server went kaputt!!";
} else if status.code == 501 {
message = "it looks like this is not yet here!!!";
} else {
message = "idk i got bored";
}
let status = format!("{}", status);
Template::render(
"error",
context! { status: status, req: req.uri(), message: message },
)
}
#[tokio::main]
async fn main() -> std::result::Result<(), rocket::Error> {
let mut skinny_data = mastodon_async::Data::default();
skinny_data.base = Cow::from("https://skinnyver.se");
let _rocket = rocket::build()
.manage(Clients {
listenbrainz: listenbrainz::raw::Client::new(),
skinnyverse: mastodon_async::Mastodon::from(skinny_data),
reqwest: reqwest::Client::new(),
})
.attach(Template::custom(|engines| {
engines.tera.autoescape_on(vec![]);
}))
.mount("/", routes![home, contact, blog, blogpost, plants])
.register("/", catchers![catcher])
.mount("/", FileServer::from(relative!("static")))
.launch()
.await?;
Ok(())
}