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;
|
2023-02-15 18:08:23 +00:00
|
|
|
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
|
|
|
|
2023-02-15 18:08:23 +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
|
|
|
}
|
|
|
|
|
2023-02-15 18:08:23 +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)]
|
2023-02-15 18:08:23 +00:00
|
|
|
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> {
|
2023-02-15 18:08:23 +00:00
|
|
|
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()
|
2023-02-15 18:08:23 +00:00
|
|
|
.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-02-15 18:08:23 +00:00
|
|
|
})
|
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])
|
2023-02-15 18:08:23 +00:00
|
|
|
.register("/", catchers![catcher])
|
2023-01-15 21:43:21 +00:00
|
|
|
.mount("/", FileServer::from(relative!("static")))
|
|
|
|
.launch()
|
|
|
|
.await?;
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|