gamenight/backend/src/schema/gamenight.rs

216 lines
6.0 KiB
Rust

use crate::schema::users::{users, User};
use crate::schema::{DatabaseError, DbConn};
use chrono::{DateTime, Utc};
use diesel::{Connection, ExpressionMethods, QueryDsl, RunQueryDsl};
use serde::{Deserialize, Serialize};
use uuid::Uuid;
table! {
gamenight (id) {
id -> diesel::sql_types::Uuid,
name -> VarChar,
datetime -> Timestamptz,
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, Clone)]
#[table_name = "gamenight"]
pub struct Gamenight {
pub id: Uuid,
pub name: String,
pub datetime: DateTime<Utc>,
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<Vec<Gamenight>, DatabaseError> {
Ok(conn.run(|c| gamenight::table.load::<Gamenight>(c)).await?)
}
pub async fn insert_gamenight(
conn: &DbConn,
new_gamenight: Gamenight,
game_list: Vec<Game>,
) -> Result<Uuid, DatabaseError> {
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<GamenightGameListEntry> = 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, gamenight_id: Uuid) -> Result<Gamenight, DatabaseError> {
Ok(conn
.run(move |c| gamenight::table.find(gamenight_id).first(c))
.await?)
}
pub async fn delete_gamenight(conn: &DbConn, game_id: Uuid) -> Result<usize, DatabaseError> {
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<Vec<Game>, DatabaseError> {
Ok(conn.run(|c| known_games::table.load::<Game>(c)).await?)
}
pub async fn get_games_of_gamenight(
conn: &DbConn,
gamenight_id: Uuid,
) -> Result<Vec<Game>, DatabaseError> {
Ok(conn
.run::<_, Result<Vec<Game>, _>>(move |c| {
let linked_game_ids: Vec<GamenightGameListEntry> = gamenight_gamelist::table
.filter(gamenight_gamelist::gamenight_id.eq(gamenight_id))
.load::<GamenightGameListEntry>(c)?;
linked_game_ids
.iter()
.map(|l| {
known_games::table
.filter(known_games::id.eq(l.game_id))
.first::<Game>(c)
})
.collect()
})
.await?)
}
pub async fn add_game(conn: &DbConn, game: Game) -> Result<usize, DatabaseError> {
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<Game>) -> 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: Uuid,
) -> Result<Vec<User>, DatabaseError> {
Ok(conn
.run::<_, Result<Vec<User>, _>>(move |c| {
let linked_participants = gamenight_participants::table
.filter(gamenight_participants::gamenight_id.eq(gamenight_id))
.load::<GamenightParticipantsEntry>(c)?;
linked_participants
.iter()
.map(|l| {
users::table
.filter(users::id.eq(l.user_id))
.first::<User>(c)
})
.collect()
})
.await?)
}
pub async fn add_participant(
conn: &DbConn,
participant: GamenightParticipantsEntry,
) -> Result<usize, DatabaseError> {
Ok(conn
.run(move |c| {
diesel::insert_into(gamenight_participants::table)
.values(&participant)
.on_conflict_do_nothing()
.execute(c)
})
.await?)
}
pub async fn remove_participant(
conn: &DbConn,
participant: GamenightParticipantsEntry,
) -> Result<usize, DatabaseError> {
Ok(conn
.run(move |c| diesel::delete(&participant).execute(c))
.await?)
}