Преглед изворни кода

Start route for session creation, creates text

Lee Morgan пре 1 месец
родитељ
комит
3ff400208e

+ 13 - 0
Cargo.lock

@@ -495,6 +495,7 @@ dependencies = [
  "serde_json",
  "sqlx",
  "thiserror 2.0.18",
+ "tokio",
  "uuid 1.23.1",
  "validator",
 ]
@@ -3275,9 +3276,21 @@ dependencies = [
  "pin-project-lite",
  "signal-hook-registry",
  "socket2 0.6.3",
+ "tokio-macros",
  "windows-sys 0.61.2",
 ]
 
+[[package]]
+name = "tokio-macros"
+version = "2.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.117",
+]
+
 [[package]]
 name = "tokio-native-tls"
 version = "0.3.1"

+ 1 - 0
Cargo.toml

@@ -22,5 +22,6 @@ sqlx = { version = "0.8.6", features = [
     "uuid"
 ]}
 thiserror = "2.0.18"
+tokio = { version = "1.52.3", features = ["full"] }
 uuid = { version = "1.23.1", features = ["v4", "v7", "serde"]}
 validator = { version = "0.20.0", features = ["derive"]}

+ 1 - 0
src/controllers/game/mod.rs

@@ -1,2 +1,3 @@
 pub mod create;
 pub mod character;
+pub mod session;

+ 54 - 0
src/controllers/game/session/create.rs

@@ -0,0 +1,54 @@
+use actix_web::{HttpResponse, HttpRequest, web, post};
+use sqlx::PgPool;
+use uuid::Uuid;
+use crate::{
+    http_error::HttpError,
+    auth::user_auth,
+    models::{
+        game::Game,
+        character::Character,
+        session::Session
+    }
+};
+
+#[post("/game/{game_id}/session")]
+pub async fn route(
+    db: web::Data<PgPool>,
+    path: web::Path<String>,
+    req: HttpRequest
+) -> Result<HttpResponse, HttpError> {
+    let user = user_auth(&db, &req, true).await?;
+    let game_id = Uuid::parse_str(&path.into_inner())?;
+    let (game, mut characters, sessions) = Game::get_full_game(&db, game_id, Some(user.id)).await?;
+    let text = new_session_text(game.game_context.clone(), characters.remove(0), sessions);
+
+    Ok(HttpResponse::Ok().json(game))
+}
+
+fn new_session_text(
+    game_context: String,
+    character: Character,
+    sessions: Vec<Session>
+) -> String {
+    let mut text = "".to_string();
+
+    text += "You are acting as a game master for an RPG and running the game.\n";
+    text += &format!("Here is the context for the world: {}\n", game_context);
+    text += &format!(
+        "Character name is {}, here is a description of the character: {}\n",
+        character.name,
+        character.description
+    );
+
+    if sessions.len() == 0 {
+        text += "This is the first session in this game, there have been no previous sessions\n";
+    } else {
+        for (i, session) in sessions.iter().enumerate() {
+            text += &format!("Summary of session {}: {}\n", i, session.summary);
+        }
+    }
+
+    text += "Start off a new session for the player";
+
+    text
+}

+ 1 - 0
src/controllers/game/session/mod.rs

@@ -0,0 +1 @@
+pub mod create;

+ 1 - 0
src/main.rs

@@ -67,6 +67,7 @@ async fn main() -> std::io::Result<()> {
             .configure(routes::webhook::config)
             .configure(routes::game::game::config)
             .configure(routes::game::character::config)
+            .configure(routes::game::session::config)
     })
         .bind(("0.0.0.0", port))
         .expect("Failed to bind to port")

+ 2 - 2
src/models/character.rs

@@ -1,9 +1,9 @@
 use uuid::Uuid;
-use sqlx::PgPool;
+use sqlx::{PgPool, FromRow};
 use serde::Serialize;
 use crate::http_error::HttpError;
 
-#[derive(Serialize)]
+#[derive(Serialize, FromRow)]
 pub struct Character {
     pub id: Uuid,
     pub game_id: Uuid,

+ 47 - 1
src/models/game.rs

@@ -2,7 +2,14 @@ use uuid::Uuid;
 use chrono::{DateTime, Utc};
 use sqlx::{PgPool, FromRow};
 use serde::Serialize;
-use crate::http_error::HttpError;
+use tokio;
+use crate::{
+    http_error::HttpError,
+    models::{
+        character::Character,
+        session::Session
+    }
+};
 
 #[derive(Serialize, FromRow)]
 pub struct Game {
@@ -57,4 +64,43 @@ impl Game {
             None => Err(HttpError::NotFound("Game not found".into()))
         }
     }
+
+    pub async fn get_full_game(
+        db: &PgPool,
+        id: Uuid,
+        user_id: Option<Uuid>
+    ) -> Result<(Game, Vec<Character>, Vec<Session>), HttpError> {
+        let game = sqlx::query_as::<_, Game>(
+            "SELECT *
+            FROM games
+            WHERE id = $1
+                AND ($2::uuid IS NULL OR user_id = $2)"
+        )
+            .bind(id)
+            .bind(user_id)
+            .fetch_optional(db);
+
+        let characters = sqlx::query_as::<_, Character>(
+            "SELECT *
+            FROM characters
+            WHERE game_id = $1"
+        )
+            .bind(id)
+            .fetch_all(db);
+
+        let sessions = sqlx::query_as::<_, Session>(
+            "SELECT *
+            FROM sessions
+            WHERE game_id = $1"
+        )
+            .bind(id)
+            .fetch_all(db);
+
+        let (game, characters, sessions) = tokio::try_join!(game, characters, sessions)?;
+
+        match game {
+            Some(g) => Ok((g, characters, sessions)),
+            None => Err(HttpError::NotFound("Game not found".into()))
+        }
+    }
 }

+ 7 - 5
src/models/session.rs

@@ -1,10 +1,12 @@
 use uuid::Uuid;
 use chrono::{DateTime, Utc};
+use sqlx::FromRow;
 
+#[derive(FromRow)]
 pub struct Session {
-    id: Uuid,
-    game_id: Uuid,
-    summary: String,
-    started_at: DateTime<Utc>,
-    ended_at: DateTime<Utc>
+    pub id: Uuid,
+    pub game_id: Uuid,
+    pub summary: String,
+    pub started_at: DateTime<Utc>,
+    pub ended_at: DateTime<Utc>
 }

+ 1 - 0
src/routes/game/mod.rs

@@ -1,2 +1,3 @@
 pub mod game;
 pub mod character;
+pub mod session;

+ 8 - 0
src/routes/game/session.rs

@@ -0,0 +1,8 @@
+use actix_web::web::ServiceConfig;
+use crate::controllers::game::session::{
+    create
+};
+
+pub fn config(cfg: &mut ServiceConfig) {
+    cfg.service(create::route);
+}