refactor rust into separate files and add proper error handling

This commit is contained in:
cel 🌸 2023-02-15 18:08:23 +00:00
parent fce07d2749
commit b8bbceb00b
Signed by: cel
GPG Key ID: 48E29AF13B5F1349
6 changed files with 121 additions and 92 deletions

1
.gitignore vendored
View File

@ -1 +1,2 @@
/target
*~

29
src/error.rs Normal file
View File

@ -0,0 +1,29 @@
use rocket::Responder;
#[derive(Responder, Debug)]
pub enum BlossomError {
#[response(status = 500)]
Reqwest(&'static str, #[response(ignore)] reqwest::Error),
#[response(status = 500)]
ListenBrainz(&'static str, #[response(ignore)] listenbrainz::Error),
#[response(status = 500)]
Skinnyverse(&'static str, #[response(ignore)] mastodon_async::Error),
}
impl From<reqwest::Error> for BlossomError {
fn from(e: reqwest::Error) -> Self {
BlossomError::Reqwest("reqwest error", e)
}
}
impl From<listenbrainz::Error> for BlossomError {
fn from(e: listenbrainz::Error) -> Self {
BlossomError::ListenBrainz("listenbrainz error", e)
}
}
impl From<mastodon_async::Error> for BlossomError {
fn from(e: mastodon_async::Error) -> Self {
BlossomError::Skinnyverse("skinnyverse error", e)
}
}

View File

@ -1,82 +1,27 @@
use std::borrow::Cow;
use listenbrainz::raw::response::UserPlayingNowResponse;
use mastodon_async::{Data, Mastodon};
use rocket::fs::{relative, FileServer};
use rocket::http::Status;
use rocket::response::Responder;
use rocket::Request;
use rocket::State;
use rocket_dyn_templates::{context, Template};
use serde::{Deserialize, Serialize};
use std::borrow::Cow;
mod scrobbles;
mod skweets;
struct Clients {
listenbrainz: listenbrainz::raw::Client,
skinnyverse: mastodon_async::Mastodon,
}
#[macro_use]
extern crate rocket;
#[derive(Serialize, Deserialize)]
struct ScrobbleData {
is_scrobbling: bool,
song: Option<String>,
artist: Option<String>,
}
impl ScrobbleData {
fn new(playingnow: UserPlayingNowResponse) -> Self {
let is_scrobbling = playingnow.payload.count > 0;
if is_scrobbling {
Self {
is_scrobbling,
song: Some(
playingnow
.payload
.listens
.first()
.unwrap()
.track_metadata
.track_name
.clone(),
),
artist: Some(
playingnow
.payload
.listens
.first()
.unwrap()
.track_metadata
.artist_name
.clone(),
),
}
} else {
Self {
is_scrobbling,
song: None,
artist: None,
}
}
}
}
#[get("/")]
async fn home() -> Template {
let listenbrainz = listenbrainz::raw::Client::new();
let playingnow = listenbrainz.user_playing_now("celblossom").unwrap();
let listenbrainz_data = ScrobbleData::new(playingnow);
let mut skinny_data = Data::default();
skinny_data.base = Cow::from("https://skinnyver.se");
let skinny_client = Mastodon::from(skinny_data);
let mut skweets = skinny_client
.statuses("cel", Default::default())
.await
.unwrap()
.initial_items;
skweets.truncate(6);
Template::render(
async fn home(clients: &State<Clients>) -> Result<Template, BlossomError> {
Ok(Template::render(
"home",
context! { is_live: false, listenbrainz: listenbrainz_data, skweets: skweets },
)
context! { is_live: false, listenbrainz: scrobbles::get_now_playing(&clients.listenbrainz).await?, skweets: skweets::get_recents(&clients.skinnyverse).await? },
))
}
#[get("/contact")]
@ -89,16 +34,8 @@ async fn plants() -> Result<Template, BlossomError> {
todo!()
}
// #[get("/test")]
// async fn test() -> Result<Template, BlossomError> {
// let posts = reqwest::get("https://skinnyver.se/api/v1/accounts/cel/statuses")
// .await?
// .json()
// .await?;
// }
#[catch(default)]
fn error(status: Status, req: &Request) -> Template {
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";
@ -118,12 +55,19 @@ fn error(status: Status, req: &Request) -> Template {
#[tokio::main]
async fn main() -> 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),
})
.attach(Template::custom(|engines| {
engines.tera.autoescape_on(vec![]);
}))
.mount("/", routes![home, contact])
.register("/", catchers![error])
.register("/", catchers![catcher])
.mount("/", FileServer::from(relative!("static")))
.launch()
.await?;
@ -131,14 +75,5 @@ async fn main() -> Result<(), rocket::Error> {
Ok(())
}
#[derive(Responder)]
enum BlossomError {
#[response(status = 500)]
Reqwest(&'static str, #[response(ignore)] reqwest::Error),
}
impl From<reqwest::Error> for BlossomError {
fn from(e: reqwest::Error) -> Self {
BlossomError::Reqwest("reqwest error", e)
}
}
mod error;
use error::BlossomError;

55
src/scrobbles.rs Normal file
View File

@ -0,0 +1,55 @@
use listenbrainz::raw::response::UserPlayingNowResponse;
use serde::{Deserialize, Serialize};
use crate::error::BlossomError;
pub async fn get_now_playing(
client: &listenbrainz::raw::Client,
) -> Result<NowPlayingData, BlossomError> {
let playingnow = client.user_playing_now("celblossom")?;
Ok(NowPlayingData::new(playingnow))
}
#[derive(Serialize, Deserialize)]
pub struct NowPlayingData {
pub is_scrobbling: bool,
pub song: Option<String>,
pub artist: Option<String>,
}
impl NowPlayingData {
fn new(playingnow: UserPlayingNowResponse) -> Self {
let is_scrobbling = playingnow.payload.count > 0;
if is_scrobbling {
Self {
is_scrobbling,
song: Some(
playingnow
.payload
.listens
.first()
.unwrap()
.track_metadata
.track_name
.clone(),
),
artist: Some(
playingnow
.payload
.listens
.first()
.unwrap()
.track_metadata
.artist_name
.clone(),
),
}
} else {
Self {
is_scrobbling,
song: None,
artist: None,
}
}
}
}

10
src/skweets.rs Normal file
View File

@ -0,0 +1,10 @@
use crate::error::BlossomError;
use mastodon_async::entities::status::Status;
use mastodon_async::prelude::*;
pub async fn get_recents(client: &Mastodon) -> Result<Vec<Status>, BlossomError> {
Ok(client
.statuses("cel", Default::default())
.await?
.initial_items)
}

View File

@ -74,8 +74,7 @@
<footer class="panel">
<a class="badge" href="https://skinnyver.se"><img src="https://skinnyver.se/instance/skinnyversebadge.png"></a>
<a class="badge" href="https://social.xenofem.me/"><img src="https://s3.eu-west-1.wasabisys.com/skinnyverse/4520d16b-565c-4956-b1f0-dd18afcdf906/xenofemme.png"></a>
<a class="badge" href="https://asbestos.cafe"><img src="https://asbestos.cafe/instance/asbestoscafesisterinstance.png"></a>
<a class="badge" href="https://worm.pink"><img src="https://worm.pink/instance/wormpinksistersite.png"></a>
<a class="badge" href="https://arachnid.town"><img src="https://arachnid.town/media/e900cdf1adcd230b81fb7bb98c4279f5dfaa19ab18a54a0cbc8290a52bcd3ee7.png"></a>
</footer>
</div>