From 8935c2d4964a18bf83fc305db153843f01e3e1ef Mon Sep 17 00:00:00 2001 From: Radical Date: Sat, 10 May 2025 00:09:59 +0200 Subject: [PATCH] feat: add way to fetch and join invites from /invites/{id} --- src/api/v1/invites/id.rs | 79 +++++++++++++++++++++++++++++++++++++++ src/api/v1/invites/mod.rs | 9 +++++ src/structs.rs | 46 +++++++++++++++++++++-- 3 files changed, 130 insertions(+), 4 deletions(-) create mode 100644 src/api/v1/invites/id.rs create mode 100644 src/api/v1/invites/mod.rs diff --git a/src/api/v1/invites/id.rs b/src/api/v1/invites/id.rs new file mode 100644 index 0000000..7903b26 --- /dev/null +++ b/src/api/v1/invites/id.rs @@ -0,0 +1,79 @@ +use actix_web::{get, post, web, Error, HttpRequest, HttpResponse}; + +use crate::{api::v1::auth::check_access_token, structs::{Guild, Invite, Member}, utils::get_auth_header, Data}; + +#[get("{id}")] +pub async fn get(req: HttpRequest, path: web::Path<(String,)>, data: web::Data) -> Result { + let headers = req.headers(); + + let auth_header = get_auth_header(headers); + + if let Err(error) = auth_header { + return Ok(error) + } + + let invite_id = path.into_inner().0; + + let result = Invite::fetch_one(&data.pool, invite_id).await; + + if let Err(error) = result { + return Ok(error) + } + + let invite = result.unwrap(); + + let guild_result = Guild::fetch_one(&data.pool, invite.guild_uuid).await; + + if let Err(error) = guild_result { + return Ok(error); + } + + let guild = guild_result.unwrap(); + + Ok(HttpResponse::Ok().json(guild)) +} + +#[post("{id}")] +pub async fn join(req: HttpRequest, path: web::Path<(String,)>, data: web::Data) -> Result { + let headers = req.headers(); + + let auth_header = get_auth_header(headers); + + if let Err(error) = auth_header { + return Ok(error) + } + + let invite_id = path.into_inner().0; + + let authorized = check_access_token(auth_header.unwrap(), &data.pool).await; + + if let Err(error) = authorized { + return Ok(error) + } + + let uuid = authorized.unwrap(); + + let result = Invite::fetch_one(&data.pool, invite_id).await; + + if let Err(error) = result { + return Ok(error) + } + + let invite = result.unwrap(); + + let guild_result = Guild::fetch_one(&data.pool, invite.guild_uuid).await; + + if let Err(error) = guild_result { + return Ok(error); + } + + let guild = guild_result.unwrap(); + + let member = Member::new(&data.pool, uuid, guild.uuid).await; + + if let Err(error) = member { + return Ok(error); + } + + Ok(HttpResponse::Ok().json(guild)) +} diff --git a/src/api/v1/invites/mod.rs b/src/api/v1/invites/mod.rs new file mode 100644 index 0000000..89e7466 --- /dev/null +++ b/src/api/v1/invites/mod.rs @@ -0,0 +1,9 @@ +use actix_web::{web, Scope}; + +mod id; + +pub fn web() -> Scope { + web::scope("/invites") + .service(id::get) + .service(id::join) +} diff --git a/src/structs.rs b/src/structs.rs index 1b6ef84..0f72aaf 100644 --- a/src/structs.rs +++ b/src/structs.rs @@ -444,7 +444,7 @@ impl Role { pub struct Member { pub uuid: Uuid, - pub nickname: String, + pub nickname: Option, pub user_uuid: Uuid, pub guild_uuid: Uuid, } @@ -475,15 +475,36 @@ impl Member { return Err(HttpResponse::InternalServerError().finish()) } - let (uuid, nickname): (String, String) = row.unwrap(); + let (uuid, nickname): (String, Option) = row.unwrap(); - Ok(Member { + Ok(Self { uuid: Uuid::from_str(&uuid).unwrap(), nickname, user_uuid, guild_uuid, }) } + + pub async fn new(pool: &Pool, user_uuid: Uuid, guild_uuid: Uuid) -> Result { + let member_uuid = Uuid::now_v7(); + + let row = sqlx::query(&format!("INSERT INTO guild_members uuid, guild_uuid, user_uuid VALUES ('{}', '{}', '{}')", member_uuid, guild_uuid, user_uuid)) + .execute(pool) + .await; + + if let Err(error) = row { + error!("{}", error); + + return Err(HttpResponse::InternalServerError().finish()) + } + + Ok(Self { + uuid: member_uuid, + nickname: None, + user_uuid, + guild_uuid, + }) + } } #[derive(FromRow)] @@ -538,5 +559,22 @@ pub struct Invite { /// User that created the invite user_uuid: Uuid, /// UUID of the guild that the invite belongs to - guild_uuid: Uuid, + pub guild_uuid: Uuid, +} + +impl Invite { + pub async fn fetch_one(pool: &Pool, invite_id: String) -> Result { + let invite: Result = sqlx::query_as("SELECT id, user_uuid, guild_uuid FROM invites WHERE id = $1") + .bind(invite_id) + .fetch_one(pool) + .await; + + if let Err(error) = invite { + error!("{}", error); + + return Err(HttpResponse::InternalServerError().finish()) + } + + Ok(invite.unwrap().build()) + } }