aboutsummaryrefslogtreecommitdiffstats
path: root/src/main.rs
diff options
context:
space:
mode:
authorLibravatar cel 🌸 <cel@blos.sm>2024-01-30 16:16:05 +0000
committerLibravatar cel 🌸 <cel@blos.sm>2024-01-30 16:16:05 +0000
commitf00159f53b3774601500ec65345791311ff6efa1 (patch)
treecc65a487e71a056126e1935108a494c7851863f9 /src/main.rs
parent8c03d9a53f4bc2f70fb5c1e0487bc74fe0137fcb (diff)
downloadblossom-f00159f53b3774601500ec65345791311ff6efa1.tar.gz
blossom-f00159f53b3774601500ec65345791311ff6efa1.tar.bz2
blossom-f00159f53b3774601500ec65345791311ff6efa1.zip
migrate to poem and askama
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs212
1 files changed, 98 insertions, 114 deletions
diff --git a/src/main.rs b/src/main.rs
index ed768b4..c38b2eb 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,155 +1,139 @@
+mod atom;
+mod blog;
mod error;
mod live;
mod posts;
mod scrobbles;
mod skweets;
-
-use std::borrow::Cow;
-use std::collections::HashSet;
-use std::time::Duration;
-
-use atom_syndication::Feed;
-use rocket::fs::{relative, FileServer};
-use rocket::http::{ContentType, Status};
-use rocket::{Request, State};
-use rocket_dyn_templates::{context, Template};
+mod templates;
+mod utils;
+
+use std::rc::Rc;
+use std::{collections::HashSet, time::Duration};
+
+use poem::http::StatusCode;
+use poem::Response;
+use poem::{
+ endpoint::EmbeddedFilesEndpoint,
+ get, handler,
+ listener::TcpListener,
+ middleware::AddData,
+ web::{Data, Path, Query},
+ EndpointExt, Route, Server,
+};
+use rust_embed::RustEmbed;
use error::BlossomError;
+use serde::Deserialize;
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;
+#[derive(RustEmbed)]
+#[folder = "static/"]
+struct Static;
-#[get("/")]
-async fn home(clients: &State<Clients>) -> Template {
+#[handler]
+async fn home(Data(reqwest): Data<&reqwest::Client>) -> templates::Home {
+ let listenbrainz_client = listenbrainz::raw::Client::new();
let (live, listenbrainz, blogposts) = tokio::join!(
- live::get_live_status(&clients.reqwest),
- scrobbles::get_now_playing(&clients.listenbrainz),
+ live::get_live_status(reqwest),
+ scrobbles::get_now_playing(&listenbrainz_client),
// skweets::get_recents(&clients.skinnyverse),
- posts::get_blogposts()
+ blog::get_blogposts()
);
let is_live = live.unwrap_or_default().online;
let listenbrainz = listenbrainz.unwrap_or_default();
let blogposts = blogposts.unwrap_or_default();
- Template::render(
- "home",
- context! {
- is_live,
- listenbrainz,
- // skweets,
- blogposts,
- },
- )
+ templates::Home {
+ is_live,
+ listenbrainz,
+ blogposts,
+ }
+}
+
+// #[get("/blog/<blogpost>")]
+#[handler]
+async fn blogpost(Path(blogpost): Path<String>) -> Result<templates::Blogpost> {
+ let blogpost = blog::get_blogpost(&blogpost).await?;
+ Ok(templates::Blogpost {
+ blogpost,
+ filter_tags: HashSet::new(),
+ })
}
-#[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,
- },
- ))
+#[derive(Deserialize)]
+struct FilterTags {
+ filter: String,
}
-#[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)
+// #[get("/blog?<filter>")]
+#[handler]
+async fn get_blog(filter_tags: Option<Query<FilterTags>>) -> Result<templates::Blog> {
+ let mut blogposts = blog::get_blogposts().await?;
+ let tags: Vec<String> = posts::Post::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?;
+ if let Some(Query(FilterTags { filter })) = filter_tags {
+ filter_hashset.insert(filter);
+ blogposts = posts::Post::filter_by_tags(blogposts, &filter_hashset);
}
- let reverse = true;
- Ok(Template::render(
- "blog",
- context! {
- reverse,
- tags,
- filter_hashset,
- blogposts,
- },
- ))
+ Ok(templates::Blog {
+ blogposts,
+ tags,
+ filter_tags: filter_hashset,
+ })
}
-#[get("/feed")]
-async fn feed() -> Result<(Status, (ContentType, String))> {
- let posts = posts::get_blogposts().await?;
- let feed = posts::syndication::atom(posts).await;
+#[handler]
+async fn feed() -> Result<Response> {
+ let posts = blog::get_blogposts().await?;
+ // TODO: i18n
+ let context = atom::Context {
+ page_title: "celeste's hard drive".to_owned(),
+ page_url: "https://en.blos.sm".to_owned(),
+ self_url: "https://en.blos.sm/feed".to_owned(),
+ lang: "en".to_owned(),
+ };
+ let feed = atom::atom(context, posts).await;
let feed: String = String::from_utf8(feed.write_to(Vec::new())?)?;
- Ok((
- Status::new(200),
- (ContentType::new("application", "atom+xml"), feed),
- ))
-}
-
-#[get("/contact")]
-async fn contact() -> Template {
- Template::render("contact", context! {})
+ Ok(Response::builder()
+ .status(StatusCode::OK)
+ .content_type("application/atom+xml")
+ .body(feed))
}
-#[get("/plants")]
-async fn plants() -> Result<Template> {
- Err(BlossomError::Unimplemented(Status::NotImplemented))
+#[handler]
+async fn contact() -> templates::Contact {
+ templates::Contact
}
-#[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 },
- )
+#[handler]
+async fn plants() -> Result<()> {
+ Err(BlossomError::Unimplemented)
}
#[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::builder()
+async fn main() -> std::result::Result<(), std::io::Error> {
+ // let mut skinny_data = mastodon_async::Data::default();
+ // skinny_data.base = Cow::from("https://skinnyver.se");
+ let blossom = Route::new()
+ .at("/", get(home))
+ .at("/blog", get(get_blog))
+ .at("/blog/:blogpost", get(blogpost))
+ .at("/feed", get(feed))
+ .at("/contact", get(contact))
+ .at("/plants", get(plants))
+ .nest("/static/", EmbeddedFilesEndpoint::<Static>::new())
+ .with(AddData::new(
+ reqwest::Client::builder()
.connect_timeout(Duration::from_secs(1))
.build()
.unwrap(),
- })
- .attach(Template::custom(|engines| {
- engines.tera.autoescape_on(vec![]);
- }))
- .mount("/", routes![home, contact, blog, blogpost, feed, plants])
- .register("/", catchers![catcher])
- .mount("/", FileServer::from("./static"))
- .launch()
- .await?;
+ ));
- Ok(())
+ Server::new(TcpListener::bind("0.0.0.0:3000"))
+ .run(blossom)
+ .await
}