diff --git a/Cargo.lock b/Cargo.lock index 4d02117..1b3e023 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -587,6 +587,40 @@ dependencies = [ "memchr", ] +[[package]] +name = "darling" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" +dependencies = [ + "darling_core", + "quote", + "syn", +] + [[package]] name = "deranged" version = "0.5.5" @@ -1029,6 +1063,12 @@ dependencies = [ "stable_deref_trait", ] +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + [[package]] name = "http" version = "0.2.12" @@ -1323,6 +1363,12 @@ dependencies = [ "zerovec", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "idna" version = "1.1.0" @@ -1376,6 +1422,17 @@ dependencies = [ "hashbrown 0.16.0", ] +[[package]] +name = "inherent" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c727f80bfa4a6c6e2508d2f05b6f4bfce242030bd88ed15ae5331c5b5d30fba7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "ipnet" version = "2.11.0" @@ -1554,6 +1611,7 @@ dependencies = [ "r2d2_sqlite", "reqwest", "rusqlite", + "sea-query", "serde", "serde_json", "tempfile", @@ -2206,6 +2264,31 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "sea-query" +version = "1.0.0-rc.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7e01d76c67146262612a9db50cbc4b4b3236a96a1f04f1744ef2582234187e2" +dependencies = [ + "inherent", + "itoa", + "sea-query-derive", +] + +[[package]] +name = "sea-query-derive" +version = "1.0.0-rc.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d88ad44b6ad9788c8b9476b6b91f94c7461d1e19d39cd8ea37838b1e6ff5aa8" +dependencies = [ + "darling", + "heck", + "proc-macro2", + "quote", + "syn", + "thiserror", +] + [[package]] name = "security-framework" version = "2.11.1" diff --git a/Cargo.toml b/Cargo.toml index 290857c..f270e6e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,7 @@ r2d2 = "0.8.10" r2d2_sqlite = "0.31.0" reqwest = "0.12.24" rusqlite = {version="0.37.0", features=["bundled"]} +sea-query = "1.0.0-rc.34" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0.145" tera = "1.20.1" diff --git a/db/setup_db.sh b/db/setup_db.sh index 2806ba1..439cc18 100755 --- a/db/setup_db.sh +++ b/db/setup_db.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash cd $(dirname "$0") db_file='../storage/mapbattle.db' -sqlite3 "$dbfile" < db.sql -sqlite3 -csv "$dbfile" ".import init_games.csv games" -sqlite3 -csv "$dbfile" ".import init_teams.csv teams" +sqlite3 "$db_file" < db.sql +sqlite3 -csv "$db_file" ".import init_games.csv games" +sqlite3 -csv "$db_file" ".import init_teams.csv teams" diff --git a/src/db.rs b/src/db.rs index 1c3f13c..865edf3 100644 --- a/src/db.rs +++ b/src/db.rs @@ -1,6 +1,7 @@ use crate::data::{Game, Player, Team}; use actix_web::{Error, error, web}; use rusqlite::Row; +use sea_query::{Expr, ExprTrait, Query, SqliteQueryBuilder}; use serde_json::{Map, Value}; use std::collections::HashMap; @@ -54,6 +55,21 @@ pub async fn teams(pool: &Pool) -> Result, Error> { .map_err(error::ErrorInternalServerError) } +pub async fn update_game( + pool: &Pool, + code: String, + start_time: String, + end_time: String, +) -> Result<(), Error> { + let pool = pool.clone(); + let conn = web::block(move || pool.get()) + .await? + .map_err(error::ErrorInternalServerError)?; + web::block(move || update_game_sqlite(conn, code, start_time, end_time)) + .await? + .map_err(error::ErrorInternalServerError) +} + fn get_all_games(conn: Connection, all_teams: HashMap) -> GamesResult { let mut games_stmt = conn.prepare(GAMES_QUERY)?; games_stmt @@ -72,6 +88,30 @@ fn get_all_games(conn: Connection, all_teams: HashMap) -> GamesRes .and_then(Iterator::collect) } +fn update_game_sqlite( + conn: Connection, + code: String, + start_time: String, + end_time: String, +) -> Result<(), rusqlite::Error> { + let update_query = Query::update() + .table("games") + .values([ + ("start_time", start_time.into()), + ("end_time", end_time.into()), + ]) + .and_where(Expr::col("code").eq(code)) + .to_owned(); + let mut update_stmt = conn.prepare(&update_query.to_string(SqliteQueryBuilder))?; + + let result = update_stmt.query([]); + + match result { + Ok(_) => Ok(()), + Err(error) => Err(error), + } +} + fn get_all_teams(conn: Connection) -> TeamsResult { let mut teams_stmt = conn.prepare(TEAMS_QUERY)?; teams_stmt diff --git a/src/main.rs b/src/main.rs index d72edb0..d9ee9fa 100644 --- a/src/main.rs +++ b/src/main.rs @@ -67,6 +67,13 @@ struct QueryForm { query: String, } +#[derive(Deserialize, Debug)] +struct UpdateGameForm { + code: String, + start_time: String, + end_time: String, +} + impl Actor for GamesActor { type Context = actix::Context; } @@ -185,12 +192,32 @@ async fn admin() -> impl Responder { } #[get("/admin/games")] -async fn list_of_games(games: web::Data>>>) -> impl Responder { - let games = games.lock().await; - let games_json = serde_json::to_string(&*games).unwrap(); - HttpResponse::Ok() - .content_type("application/json") - .body(games_json) +async fn list_of_games(pool: web::Data) -> impl Responder { + let games_result = db::games(&pool).await; + match games_result { + Ok(games) => { + let games_json = serde_json::to_string(&*games).unwrap(); + HttpResponse::Ok() + .content_type("application/json") + .body(games_json) + } + Err(err) => HttpResponse::InternalServerError().body(format!("{err}")), + } +} + +#[post("/admin/game/update")] +async fn update_game(pool: web::Data, form: web::Form) -> impl Responder { + match db::update_game( + &pool, + form.code.clone(), + form.start_time.clone(), + form.end_time.clone(), + ) + .await + { + Ok(_) => HttpResponse::Ok().body("{}"), + Err(err) => HttpResponse::InternalServerError().body(format!("{err:?}")), + } } #[post("/admin/query")] @@ -232,6 +259,7 @@ async fn main() -> std::io::Result<()> { .service(admin_query) .service(list_of_games) .service(get_territories) + .service(update_game) }) .bind(("0.0.0.0", 8080))? .run()