diff --git a/src/main.rs b/src/main.rs index 5b5dca4..fe72c57 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,14 +5,10 @@ mod user; use std::{collections::HashMap, pin::Pin, sync::Arc}; -use session_rs::{server::SessionServer, session::Session}; -use sqlx::SqlitePool; +use session_rs::server::SessionServer; use tokio::sync::Mutex; -use crate::{ - types::{SessionMap, UUID}, - user::User, -}; +use crate::types::SessionMap; #[tokio::main(flavor = "current_thread")] async fn main() -> session_rs::Result<()> { @@ -71,7 +67,7 @@ async fn main() -> session_rs::Result<()> { let sessions = sessions.clone(); move |_, token| { - authenticate( + methods::auth::authenticate( sessions.clone(), session.clone(), uuid.clone(), @@ -158,25 +154,6 @@ async fn main() -> session_rs::Result<()> { }) .await; - session - .on_request::({ - let uuid = Arc::clone(&uuid); - let pool = Arc::clone(&pool); - - move |_, item_id| { - let pool = Arc::clone(&pool); - let item_id = item_id.clone(); - - cosmetics::equip( - cosmetics::CosmeticKind::Hat, - uuid.clone(), - item_id, - pool, - ) - } - }) - .await; - session .on_request::({ let sessions = Arc::clone(&sessions); @@ -186,18 +163,34 @@ async fn main() -> session_rs::Result<()> { let sessions = Arc::clone(&sessions); let uuid = Arc::clone(&uuid); - send_emote(sessions, uuid, emote) + methods::emote::send_emote(sessions, uuid, emote) } }) .await; session - .on_request::({ + .on_request::({ let sessions = Arc::clone(&sessions); let pool = Arc::clone(&pool); - move |_, uuid: String| { - get_user(sessions.clone(), uuid.clone(), pool.clone()) + move |_, uuid| { + methods::user::get_user( + sessions.clone(), + uuid.clone(), + pool.clone(), + ) + } + }) + .await; + + session + .on_request::({ + let sessions = Arc::clone(&sessions); + let pool = Arc::clone(&pool); + let uuid = Arc::clone(&uuid); + + move |_, targets| { + methods::user::send_user(sessions.clone(), uuid.clone(), targets.clone(), pool.clone()) } }) .await; @@ -208,94 +201,3 @@ async fn main() -> session_rs::Result<()> { }) .await } - -async fn get_user( - sessions: SessionMap, - uuid: String, - pool: Arc, -) -> Result, String> { - if !sessions.lock().await.contains_key(&uuid) { - return Ok(None); - } - - Ok(Some(user::get(&uuid, pool.as_ref()).await?)) -} - -async fn send_emote( - sessions: SessionMap, - uuid: UUID, - emote: types::EmoteRequest, -) -> Result { - let emote_event = types::EventEmote { - from: uuid.lock().await.clone(), - emote: emote.emote, - }; - - for i in emote.targets { - if let Some(sessions) = sessions.lock().await.get_mut(&i) { - let emote_event = emote_event.clone(); - let mut bad_sessions = Vec::new(); - - for s in sessions.iter() { - if s.notify::(emote_event.clone()) - .await - .is_err() - { - bad_sessions.push(s.clone()); - } - } - - for s in bad_sessions { - sessions.remove(&s); - } - } - } - - Ok(format!("Cool")) -} - -async fn authenticate( - sessions: SessionMap, - session: Session, - uuid: UUID, - session_token: String, - pool: Arc, -) -> Result { - if !uuid.lock().await.is_empty() { - return Err(format!("Already authenticated")); - } - - let client = reqwest::Client::new(); - - let response = client - .get("https://api.minecraftservices.com/minecraft/profile") - .bearer_auth(&session_token) - .send() - .await - .map_err(|_| "Failed to validate session".to_string())?; - - if !response.status().is_success() { - return Err(format!( - "Authentication failed with code {}", - response.status() - )); - } - - let auth: types::MinecraftAuthResponse = response - .json() - .await - .map_err(|_| "Unable to parse auth response".to_string())?; - - *uuid.lock().await = auth.id.clone(); - - sessions - .lock() - .await - .entry(auth.id.clone()) - .or_default() - .insert(session); - - println!("Authenticated as {:?}", auth); - - user::get_put(&auth.id, &pool).await -} diff --git a/src/methods/auth.rs b/src/methods/auth.rs new file mode 100644 index 0000000..f58d893 --- /dev/null +++ b/src/methods/auth.rs @@ -0,0 +1,55 @@ +use std::sync::Arc; + +use session_rs::session::Session; +use sqlx::SqlitePool; + +use crate::{ + types::{SessionMap, UUID}, + user::User, +}; + +pub async fn authenticate( + sessions: SessionMap, + session: Session, + uuid: UUID, + session_token: String, + pool: Arc, +) -> Result { + if !uuid.lock().await.is_empty() { + return Err(format!("Already authenticated")); + } + + let client = reqwest::Client::new(); + + let response = client + .get("https://api.minecraftservices.com/minecraft/profile") + .bearer_auth(&session_token) + .send() + .await + .map_err(|_| "Failed to validate session".to_string())?; + + if !response.status().is_success() { + return Err(format!( + "Authentication failed with code {}", + response.status() + )); + } + + let auth: crate::types::MinecraftAuthResponse = response + .json() + .await + .map_err(|_| "Unable to parse auth response".to_string())?; + + *uuid.lock().await = auth.id.clone(); + + sessions + .lock() + .await + .entry(auth.id.clone()) + .or_default() + .insert(session); + + println!("Authenticated as {:?}", auth); + + crate::user::get_put(&auth.id, &pool).await +} diff --git a/src/methods/emote.rs b/src/methods/emote.rs new file mode 100644 index 0000000..006ace0 --- /dev/null +++ b/src/methods/emote.rs @@ -0,0 +1,34 @@ +use crate::types::{SessionMap, UUID}; + +pub async fn send_emote( + sessions: SessionMap, + uuid: UUID, + emote: crate::types::EmoteRequest, +) -> Result<(), String> { + let emote_event = crate::types::EventEmote { + from: uuid.lock().await.clone(), + emote: emote.emote, + }; + + for target in emote.targets { + if let Some(sessions) = sessions.lock().await.get_mut(&target) { + let emote_event = emote_event.clone(); + let mut bad_sessions = Vec::new(); + + for s in sessions.iter() { + if s.notify::(emote_event.clone()) + .await + .is_err() + { + bad_sessions.push(s.clone()); + } + } + + for s in bad_sessions { + sessions.remove(&s); + } + } + } + + Ok(()) +} diff --git a/src/methods.rs b/src/methods/mod.rs similarity index 61% rename from src/methods.rs rename to src/methods/mod.rs index d857866..2ba739a 100644 --- a/src/methods.rs +++ b/src/methods/mod.rs @@ -1,3 +1,7 @@ +pub mod auth; +pub mod emote; +pub mod user; + use serde::{Deserialize, Serialize}; use session_rs::Method; @@ -6,7 +10,7 @@ use crate::{ user::User, }; -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct Auth; impl Method for Auth { @@ -16,7 +20,7 @@ impl Method for Auth { type Error = String; } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct SetCloak; impl Method for SetCloak { @@ -26,7 +30,7 @@ impl Method for SetCloak { type Error = String; } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct SetHat; impl Method for SetHat { @@ -36,7 +40,7 @@ impl Method for SetHat { type Error = String; } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct BuyCloak; impl Method for BuyCloak { @@ -46,7 +50,7 @@ impl Method for BuyCloak { type Error = String; } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct BuyHat; impl Method for BuyHat { @@ -56,32 +60,52 @@ impl Method for BuyHat { type Error = String; } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct Emote; impl Method for Emote { const NAME: &'static str = "emote"; type Request = EmoteRequest; - type Response = String; + type Response = (); type Error = String; } -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct EmoteEvent; impl Method for EmoteEvent { const NAME: &'static str = "emote_event"; type Request = EventEmote; - type Response = String; - type Error = String; + type Response = (); + type Error = (); } -#[derive(Debug, Serialize, Deserialize)] -pub struct Player; +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct GetPlayer; -impl Method for Player { +impl Method for GetPlayer { const NAME: &'static str = "player"; type Request = String; type Response = Option; type Error = String; } + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Player; + +impl Method for Player { + const NAME: &'static str = "player"; + type Request = User; + type Response = (); + type Error = (); +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct SendPlayer; + +impl Method for SendPlayer { + const NAME: &'static str = "send_player"; + type Request = Vec; + type Response = (); + type Error = String; +} diff --git a/src/methods/user.rs b/src/methods/user.rs new file mode 100644 index 0000000..2f859f6 --- /dev/null +++ b/src/methods/user.rs @@ -0,0 +1,48 @@ +use std::sync::Arc; + +use sqlx::SqlitePool; + +use crate::{ + methods, + types::{SessionMap, UUID}, + user::User, +}; + +pub async fn get_user( + sessions: SessionMap, + uuid: String, + pool: Arc, +) -> Result, String> { + if !sessions.lock().await.contains_key(&uuid) { + return Ok(None); + } + + Ok(Some(crate::user::get(&uuid, pool.as_ref()).await?)) +} + +pub async fn send_user( + sessions: SessionMap, + uuid: UUID, + targets: Vec, + pool: Arc, +) -> Result<(), String> { + let user = crate::user::get(&uuid.lock().await, pool.as_ref()).await?; + + for target in targets { + if let Some(sessions) = sessions.lock().await.get_mut(&target) { + let mut bad_sessions = Vec::new(); + + for s in sessions.iter() { + if s.notify::(user.clone()).await.is_err() { + bad_sessions.push(s.clone()); + } + } + + for s in bad_sessions { + sessions.remove(&s); + } + } + } + + Ok(()) +} diff --git a/src/user.rs b/src/user.rs index 00b631e..ecc1bb3 100644 --- a/src/user.rs +++ b/src/user.rs @@ -1,7 +1,7 @@ use serde::{Deserialize, Serialize}; use sqlx::{Row, SqlitePool}; -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct User { pub cloak: String, pub hat: String,