blossom/src/main.rs

153 lines
4.2 KiB
Rust
Raw Normal View History

2023-06-20 14:54:05 +01:00
mod error;
2023-06-20 16:02:12 +01:00
mod live;
2023-05-30 21:48:26 +01:00
mod posts;
mod scrobbles;
mod skweets;
2023-01-15 21:43:21 +00:00
2023-06-20 14:54:05 +01:00
use std::borrow::Cow;
2023-06-22 15:35:18 +01:00
use std::collections::HashSet;
2023-02-19 02:11:17 +00:00
2023-06-22 21:37:10 +01:00
use atom_syndication::Feed;
2023-06-20 14:54:05 +01:00
use rocket::fs::{relative, FileServer};
2023-06-22 21:37:10 +01:00
use rocket::http::{ContentType, Status};
2023-06-20 14:54:05 +01:00
use rocket::{Request, State};
use rocket_dyn_templates::{context, Template};
2023-02-19 02:11:17 +00:00
2023-06-20 14:54:05 +01:00
use error::BlossomError;
type Result<T> = std::result::Result<T, BlossomError>;
2023-02-19 02:11:17 +00:00
struct Clients {
listenbrainz: listenbrainz::raw::Client,
skinnyverse: mastodon_async::Mastodon,
2023-06-20 16:02:12 +01:00
reqwest: reqwest::Client,
2023-01-16 05:18:41 +00:00
}
#[macro_use]
extern crate rocket;
2023-01-16 05:18:41 +00:00
2023-01-15 21:43:21 +00:00
#[get("/")]
2023-06-20 16:02:12 +01:00
async fn home(clients: &State<Clients>) -> Template {
2023-06-21 19:32:30 +01:00
let (live, listenbrainz, skweets, blogposts) = tokio::join!(
2023-06-20 16:02:12 +01:00
live::get_live_status(&clients.reqwest),
2023-06-20 14:54:05 +01:00
scrobbles::get_now_playing(&clients.listenbrainz),
2023-06-21 19:32:30 +01:00
skweets::get_recents(&clients.skinnyverse),
posts::get_blogposts()
2023-06-20 14:54:05 +01:00
);
2023-06-20 16:02:12 +01:00
let is_live = live.unwrap_or_default().online;
2023-06-20 14:54:05 +01:00
let listenbrainz = listenbrainz.unwrap_or_default();
let skweets = skweets.unwrap_or_default();
2023-06-21 19:32:30 +01:00
let blogposts = blogposts.unwrap_or_default();
2023-06-20 16:02:12 +01:00
Template::render(
2023-01-16 05:18:41 +00:00
"home",
2023-02-16 18:02:20 +00:00
context! {
2023-06-21 19:32:30 +01:00
is_live,
listenbrainz,
skweets,
blogposts,
2023-06-20 14:54:05 +01:00
},
2023-06-20 16:02:12 +01:00
)
2023-01-15 21:43:21 +00:00
}
2023-06-21 23:46:20 +01:00
#[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,
},
))
}
2023-06-22 15:35:18 +01:00
#[get("/blog?<filter>")]
async fn blog(filter: Vec<String>) -> Result<Template> {
let mut blogposts = posts::get_blogposts().await?;
let tags: Vec<String> = posts::get_tags(&blogposts)
.into_iter()
.map(|tag| tag.to_owned())
.collect();
let mut filter_hashset: HashSet<String> = HashSet::new();
if !filter.is_empty() {
filter_hashset.extend(filter.into_iter());
blogposts = posts::filter_by_tags(blogposts, &filter_hashset);
}
for blogpost in &mut blogposts {
blogpost.render().await?;
}
let reverse = true;
Ok(Template::render(
"blog",
context! {
reverse,
tags,
filter_hashset,
blogposts,
},
))
}
2023-06-22 21:37:10 +01:00
#[get("/feed")]
async fn feed() -> Result<(Status, (ContentType, String))> {
let posts = posts::get_blogposts().await?;
let feed = posts::syndication::atom(posts).await;
let feed: String = String::from_utf8(feed.write_to(Vec::new())?)?;
Ok((
Status::new(200),
(ContentType::new("application", "atom+xml"), feed),
))
}
2023-01-15 21:43:21 +00:00
#[get("/contact")]
async fn contact() -> Template {
Template::render("contact", context! {})
}
2023-01-17 02:31:48 +00:00
#[get("/plants")]
2023-06-20 14:54:05 +01:00
async fn plants() -> Result<Template> {
2023-02-16 18:02:20 +00:00
Err(BlossomError::Unimplemented(Status::NotImplemented))
2023-01-17 02:31:48 +00:00
}
2023-01-16 05:49:03 +00:00
#[catch(default)]
fn catcher(status: Status, req: &Request) -> Template {
2023-01-16 05:54:09 +00:00
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 {
2023-02-16 18:02:20 +00:00
message = "idk i got bored";
2023-01-16 05:54:09 +00:00
}
2023-01-16 05:49:03 +00:00
let status = format!("{}", status);
Template::render(
"error",
context! { status: status, req: req.uri(), message: message },
)
}
2023-01-15 21:43:21 +00:00
#[tokio::main]
2023-06-20 14:54:05 +01:00
async fn main() -> std::result::Result<(), rocket::Error> {
let mut skinny_data = mastodon_async::Data::default();
skinny_data.base = Cow::from("https://skinnyver.se");
2023-01-15 21:43:21 +00:00
let _rocket = rocket::build()
.manage(Clients {
listenbrainz: listenbrainz::raw::Client::new(),
skinnyverse: mastodon_async::Mastodon::from(skinny_data),
2023-06-20 16:02:12 +01:00
reqwest: reqwest::Client::new(),
})
2023-01-17 02:31:48 +00:00
.attach(Template::custom(|engines| {
engines.tera.autoescape_on(vec![]);
}))
2023-06-22 21:37:10 +01:00
.mount("/", routes![home, contact, blog, blogpost, feed, plants])
.register("/", catchers![catcher])
2023-01-15 21:43:21 +00:00
.mount("/", FileServer::from(relative!("static")))
.launch()
.await?;
Ok(())
}