use crate::schema::{DatabaseError, DbConn}; use diesel::{Connection, ExpressionMethods, QueryDsl, RunQueryDsl}; use serde::{Deserialize, Serialize}; use uuid::Uuid; table! { gamenight (id) { id -> diesel::sql_types::Uuid, name -> VarChar, datetime -> VarChar, owner_id -> Uuid, } } table! { known_games (id) { id -> diesel::sql_types::Uuid, name -> VarChar, } } table! { gamenight_gamelist(gamenight_id, game_id) { gamenight_id -> diesel::sql_types::Uuid, game_id -> diesel::sql_types::Uuid, } } table! { gamenight_participants(gamenight_id, user_id) { gamenight_id -> diesel::sql_types::Uuid, user_id -> diesel::sql_types::Uuid, } } #[derive(Serialize, Deserialize, Debug, Queryable, Clone, Insertable)] #[table_name = "known_games"] pub struct Game { pub id: Uuid, pub name: String, } #[derive(Serialize, Deserialize, Debug, Queryable, Insertable)] #[table_name = "gamenight"] pub struct GameNight { pub id: Uuid, pub name: String, pub datetime: String, pub owner_id: Uuid, } #[derive(Serialize, Deserialize, Debug, Queryable, Insertable)] #[table_name = "gamenight_gamelist"] pub struct GamenightGameListEntry { pub gamenight_id: Uuid, pub game_id: Uuid, } #[derive(Serialize, Deserialize, Debug, Queryable, Insertable, Identifiable)] #[table_name = "gamenight_participants"] #[primary_key(gamenight_id, user_id)] pub struct GamenightParticipantsEntry { pub gamenight_id: Uuid, pub user_id: Uuid, } #[derive(Serialize, Deserialize, Debug, Queryable)] pub struct DeleteGameNight { pub game_id: Uuid, } #[derive(Serialize, Deserialize, Debug, Queryable)] pub struct GamenightId { pub gamenight_id: Uuid, } pub async fn get_all_gamenights(conn: DbConn) -> Result, DatabaseError> { Ok(conn.run(|c| gamenight::table.load::(c)).await?) } pub async fn insert_gamenight( conn: &DbConn, new_gamenight: GameNight, game_list: Vec, ) -> Result { Ok(conn .run(move |c| { c.transaction::<_, DatabaseError, _>(|| { let id : Uuid = diesel::insert_into(gamenight::table) .values(&new_gamenight) .returning(gamenight::id) .get_result(c)?; let entries: Vec = game_list .iter() .map(|g| GamenightGameListEntry { gamenight_id: new_gamenight.id.clone(), game_id: g.id.clone(), }) .collect(); diesel::insert_into(gamenight_gamelist::table) .values(entries) .execute(c)?; Ok(id) }) }).await? ) } pub async fn get_gamenight(conn: &DbConn, game_id: Uuid) -> Result { Ok(conn .run(move |c| gamenight::table.find(game_id).first(c)) .await?) } pub async fn delete_gamenight(conn: &DbConn, game_id: Uuid) -> Result { Ok(conn .run(move |c| diesel::delete(gamenight::table.filter(gamenight::id.eq(game_id))).execute(c)) .await?) } pub async fn get_all_known_games(conn: &DbConn) -> Result, DatabaseError> { Ok(conn.run(|c| known_games::table.load::(c)).await?) } pub async fn add_game(conn: &DbConn, game: Game) -> Result { Ok(conn .run(|c| { diesel::insert_into(known_games::table) .values(game) .execute(c) }) .await?) } pub async fn add_unknown_games(conn: &DbConn, games: &mut Vec) -> Result<(), DatabaseError> { let all_games = get_all_known_games(conn).await?; for game in games.iter_mut() { if !all_games.iter().any(|g| g.name == game.name) { game.id = Uuid::new_v4(); add_game(conn, game.clone()).await?; } } Ok(()) } pub async fn load_participants(conn: &DbConn, gamenight_id: GamenightId) -> Result, DatabaseError> { Ok(conn .run(move |c| { gamenight_participants::table .filter(gamenight_participants::gamenight_id.eq(gamenight_id.gamenight_id)) .load::(c) }) .await?) } pub async fn insert_participant( conn: &DbConn, participant: GamenightParticipantsEntry, ) -> Result { Ok(conn .run(move |c| { diesel::insert_into(gamenight_participants::table) .values(&participant) .execute(c) }) .await?) } impl From for (Uuid, Uuid) { fn from(entry: GamenightParticipantsEntry) -> Self { (entry.gamenight_id, entry.user_id) } } pub async fn remove_participant( conn: &DbConn, participant: GamenightParticipantsEntry, ) -> Result { Ok(conn .run(move |c| diesel::delete(&participant).execute(c)) .await?) }