Changing to postgres
This commit is contained in:
parent
dbd52f31c6
commit
2dcfb991b4
6
.vscode/settings.json
vendored
Normal file
6
.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"rust-analyzer.linkedProjects": [
|
||||
"./Cargo.toml",
|
||||
"./Cargo.toml"
|
||||
]
|
||||
}
|
|
@ -6,7 +6,10 @@ edition = "2021"
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
rocket = { version = "0.5.0-rc.2", features = ["json"] }
|
||||
mysql = "22.2.0"
|
||||
mysql_common = { version = "0.28.2", features = ["chrono"] }
|
||||
chrono = { version = "0.4.24", features = ["serde"] }
|
||||
dotenv = "0.15.0"
|
||||
rocket = { version = "0.5.0-rc.2", features = ["json"] }
|
||||
tokio = { version = "1.27.0", features = ["full"] }
|
||||
tokio-postgres = { version = "0.7.8", features = ["with-chrono-0_4"] }
|
||||
tokio-test = "0.4.2"
|
||||
serde = "1.0.154"
|
|
@ -1,123 +0,0 @@
|
|||
use mysql_common::{chrono::NaiveDateTime, frunk::HList};
|
||||
use rocket::serde::{Deserialize, Serialize};
|
||||
|
||||
pub type MapRow = HList!(
|
||||
String,
|
||||
String,
|
||||
i8,
|
||||
i8,
|
||||
String,
|
||||
NaiveDateTime,
|
||||
String,
|
||||
i32,
|
||||
i32,
|
||||
bool,
|
||||
bool,
|
||||
bool,
|
||||
bool,
|
||||
bool,
|
||||
bool,
|
||||
bool,
|
||||
bool,
|
||||
bool,
|
||||
bool,
|
||||
bool,
|
||||
bool,
|
||||
bool,
|
||||
bool,
|
||||
bool,
|
||||
bool,
|
||||
bool,
|
||||
bool,
|
||||
bool,
|
||||
bool,
|
||||
bool,
|
||||
bool,
|
||||
bool,
|
||||
bool,
|
||||
bool,
|
||||
bool,
|
||||
bool,
|
||||
bool,
|
||||
bool,
|
||||
bool,
|
||||
bool,
|
||||
bool,
|
||||
bool,
|
||||
bool,
|
||||
bool,
|
||||
bool,
|
||||
bool,
|
||||
bool,
|
||||
bool,
|
||||
bool
|
||||
);
|
||||
|
||||
// Different tile types and whether they appear in the map.
|
||||
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(crate = "rocket::serde")]
|
||||
pub struct MapTileData {
|
||||
pub death: bool,
|
||||
pub through: bool,
|
||||
pub jump: bool,
|
||||
pub dfreeze: bool,
|
||||
pub ehook_start: bool,
|
||||
pub hit_end: bool,
|
||||
pub solo_start: bool,
|
||||
pub tele_gun: bool,
|
||||
pub tele_grenade: bool,
|
||||
pub tele_laser: bool,
|
||||
pub npc_start: bool,
|
||||
pub super_start: bool,
|
||||
pub jetpack_start: bool,
|
||||
pub walljump: bool,
|
||||
pub nph_start: bool,
|
||||
pub weapon_shotgun: bool,
|
||||
pub weapon_grenade: bool,
|
||||
pub powerup_ninja: bool,
|
||||
pub weapon_rifle: bool,
|
||||
pub laser_stop: bool,
|
||||
pub crazy_shotgun: bool,
|
||||
pub dragger: bool,
|
||||
pub door: bool,
|
||||
pub switch_timed: bool,
|
||||
pub switch: bool,
|
||||
pub stop: bool,
|
||||
pub through_all: bool,
|
||||
pub tune: bool,
|
||||
pub oldlaser: bool,
|
||||
pub teleinevil: bool,
|
||||
pub telein: bool,
|
||||
pub telecheck: bool,
|
||||
pub teleinweapon: bool,
|
||||
pub teleinhook: bool,
|
||||
pub checkpoint_first: bool,
|
||||
pub bonus: bool,
|
||||
pub boost: bool,
|
||||
pub plasmaf: bool,
|
||||
pub plasmae: bool,
|
||||
pub plasmau: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(crate = "rocket::serde")]
|
||||
pub struct Map {
|
||||
pub name: String,
|
||||
pub server: String,
|
||||
pub points: i8,
|
||||
pub stars: i8,
|
||||
pub mapper: String,
|
||||
pub timestamp: NaiveDateTime,
|
||||
pub width: i32,
|
||||
pub height: i32,
|
||||
pub tile_data: MapTileData,
|
||||
}
|
||||
|
||||
/*
|
||||
IMPORTANT: For this to work the following SQL query must be executed:
|
||||
```SQL
|
||||
UPDATE record_maps SET Timestamp='1970-01-01 01:01:01' WHERE Timestamp='1990-01-01 00:00:00';
|
||||
```
|
||||
Else the reads on `record_maps` will fail whenever the timestamp is '0000-00-00 00:00:00'!
|
||||
TODO: Fix this server-side.
|
||||
*/
|
|
@ -1,256 +1,148 @@
|
|||
use mysql::prelude::*;
|
||||
use mysql::*;
|
||||
use mysql_common::frunk::hlist_pat;
|
||||
use std::error::Error;
|
||||
use std::result::Result;
|
||||
use std::{env, result};
|
||||
use std::{env, error::Error};
|
||||
|
||||
pub mod map;
|
||||
pub mod race;
|
||||
pub mod teamrace;
|
||||
use dotenv::dotenv;
|
||||
use tokio_postgres::{Client, NoTls};
|
||||
|
||||
pub fn create_pool() -> Pool {
|
||||
let url = match env::var("DB_URI") {
|
||||
Ok(uri) => uri,
|
||||
Err(err) => {
|
||||
println!("You must provide an env var: 'DB_URI'!");
|
||||
panic!("{}", err);
|
||||
}
|
||||
};
|
||||
use self::models::map::Map;
|
||||
|
||||
let pool = match Pool::new(url.as_str()) {
|
||||
Ok(pool) => pool,
|
||||
Err(err) => {
|
||||
println!("Couldn't connect to the database!");
|
||||
panic!("{}", err);
|
||||
}
|
||||
};
|
||||
mod models;
|
||||
|
||||
pool
|
||||
pub struct DatabaseHandler {
|
||||
pub client: Client,
|
||||
}
|
||||
|
||||
pub struct DatabasePoolStore(pub Pool);
|
||||
impl DatabaseHandler {
|
||||
pub async fn create() -> Result<DatabaseHandler, Box<dyn Error>> {
|
||||
// Load the env file
|
||||
dotenv()?;
|
||||
|
||||
pub fn get_maps(pool: &Pool) -> Result<Vec<map::Map>, Box<dyn Error>> {
|
||||
let mut conn = pool.get_conn()?;
|
||||
// Load in the environment variables
|
||||
let connection_host = env::var("DB_HOST")?;
|
||||
let connection_user = env::var("DB_USER")?;
|
||||
let connection_db = env::var("DB_NAME")?;
|
||||
|
||||
let maps = conn.query_map(
|
||||
"SELECT * FROM record_maps AS maps JOIN record_mapinfo AS mapinfo ON maps.Map = mapinfo.Map",
|
||||
|row: map::MapRow| {
|
||||
let hlist_pat![ name, server, points, stars, mapper, timestamp, _name_again, width, height, death, through, jump, dfreeze, hit_end, ehook_start, solo_start, tele_gun, tele_grenade, tele_laser, npc_start, super_start, jetpack_start, walljump, nph_start, weapon_shotgun, weapon_grenade, powerup_ninja, weapon_rifle, laser_stop, crazy_shotgun, dragger, door, switch_timed, switch, stop, through_all, tune, oldlaser, teleinevil, telein, telecheck, teleinweapon, teleinhook, checkpoint_first, bonus, boost, plasmaf, plasmae, plasmau ] = row;
|
||||
map::Map {
|
||||
name,
|
||||
server, points,
|
||||
stars, mapper,
|
||||
timestamp,
|
||||
width,
|
||||
height,
|
||||
tile_data: map::MapTileData { death, through, jump, dfreeze, hit_end, ehook_start, solo_start, tele_gun, tele_grenade, tele_laser, npc_start, super_start, jetpack_start, walljump, nph_start, weapon_shotgun, weapon_grenade, powerup_ninja, weapon_rifle, laser_stop, crazy_shotgun, dragger, door, switch_timed, switch, stop, through_all, tune, oldlaser, teleinevil, telein, telecheck, teleinweapon, teleinhook, checkpoint_first, bonus, boost, plasmaf, plasmae, plasmau }
|
||||
let connection_string = format!(
|
||||
"host={} user={} dbname={}",
|
||||
connection_host, connection_user, connection_db
|
||||
);
|
||||
|
||||
// Connect to the database
|
||||
let (client, connection) = tokio_postgres::connect(&connection_string, NoTls).await?;
|
||||
|
||||
// NOTE: This comes directly from the official documentation (https://docs.rs/tokio-postgres/latest/tokio_postgres/#example)
|
||||
// I hace no idea what in the flying flop it means...
|
||||
tokio::spawn(async move {
|
||||
if let Err(e) = connection.await {
|
||||
eprintln!("Error while connecting to the database: {}", e);
|
||||
}
|
||||
});
|
||||
|
||||
Ok(DatabaseHandler { client })
|
||||
}
|
||||
|
||||
pub async fn get_all_maps(&self) -> Result<Vec<Map>, Box<dyn Error>> {
|
||||
// FIXME: Why does this have to be mutable? Should fix.
|
||||
let mut results = self
|
||||
.client
|
||||
.query(
|
||||
"
|
||||
SELECT record_maps.map, type, points, stars, mapper, release, width, height,
|
||||
CONCAT_WS(',',
|
||||
CASE WHEN DEATH = '1' THEN 'DEATH' END,
|
||||
CASE WHEN THROUGH = '1' THEN 'THROUGH' END,
|
||||
CASE WHEN JUMP = '1' THEN 'JUMP' END,
|
||||
CASE WHEN DFREEZE = '1' THEN 'DFREEZE' END,
|
||||
CASE WHEN EHOOK_START = '1' THEN 'EHOOK_START' END,
|
||||
CASE WHEN HIT_END = '1' THEN 'HIT_END' END,
|
||||
CASE WHEN SOLO_START = '1' THEN 'SOLO_START' END,
|
||||
CASE WHEN TELE_GUN = '1' THEN 'TELE_GUN' END,
|
||||
CASE WHEN TELE_GRENADE = '1' THEN 'TELE_GRENADE' END,
|
||||
CASE WHEN TELE_LASER = '1' THEN 'TELE_LASER' END,
|
||||
CASE WHEN NPC_START = '1' THEN 'NPC_START' END,
|
||||
CASE WHEN SUPER_START = '1' THEN 'SUPER_START' END,
|
||||
CASE WHEN JETPACK_START = '1' THEN 'JETPACK_START' END,
|
||||
CASE WHEN WALLJUMP = '1' THEN 'WALLJUMP' END,
|
||||
CASE WHEN NPH_START = '1' THEN 'NPH_START' END,
|
||||
CASE WHEN WEAPON_SHOTGUN = '1' THEN 'WEAPON_SHOTGUN' END,
|
||||
CASE WHEN WEAPON_GRENADE = '1' THEN 'WEAPON_GRENADE' END,
|
||||
CASE WHEN POWERUP_NINJA = '1' THEN 'POWERUP_NINJA' END,
|
||||
CASE WHEN WEAPON_RIFLE = '1' THEN 'WEAPON_RIFLE' END,
|
||||
CASE WHEN LASER_STOP = '1' THEN 'LASER_STOP' END,
|
||||
CASE WHEN CRAZY_SHOTGUN = '1' THEN 'CRAZY_SHOTGUN' END,
|
||||
CASE WHEN DRAGGER = '1' THEN 'DRAGGER' END,
|
||||
CASE WHEN DOOR = '1' THEN 'DOOR' END,
|
||||
CASE WHEN SWITCH_TIMED = '1' THEN 'SWITCH_TIMED' END,
|
||||
CASE WHEN SWITCH = '1' THEN 'SWITCH' END,
|
||||
CASE WHEN STOP = '1' THEN 'STOP' END,
|
||||
CASE WHEN THROUGH_ALL = '1' THEN 'THROUGH_ALL' END,
|
||||
CASE WHEN TUNE = '1' THEN 'TUNE' END,
|
||||
CASE WHEN OLDLASER = '1' THEN 'OLDLASER' END,
|
||||
CASE WHEN TELEINEVIL = '1' THEN 'TELEINEVIL' END,
|
||||
CASE WHEN TELEIN = '1' THEN 'TELEIN' END,
|
||||
CASE WHEN TELECHECK = '1' THEN 'TELECHECK' END,
|
||||
CASE WHEN TELEINWEAPON = '1' THEN 'TELEINWEAPON' END,
|
||||
CASE WHEN TELEINHOOK = '1' THEN 'TELEINHOOK' END,
|
||||
CASE WHEN CHECKPOINT_FIRST = '1' THEN 'CHECKPOINT_FIRST' END,
|
||||
CASE WHEN BONUS = '1' THEN 'BONUS' END,
|
||||
CASE WHEN BOOST = '1' THEN 'BOOST' END,
|
||||
CASE WHEN PLASMAF = '1' THEN 'PLASMAF' END,
|
||||
CASE WHEN PLASMAE = '1' THEN 'PLASMAE' END,
|
||||
CASE WHEN PLASMAU = '1' THEN 'PLASMAU' END) AS tiles
|
||||
FROM record_maps JOIN record_mapinfo ON record_maps.map = record_mapinfo.map
|
||||
",
|
||||
&[],
|
||||
)
|
||||
.await?
|
||||
.into_iter()
|
||||
.map(|row| Map::from_db_row(&row));
|
||||
|
||||
// If the result has errors, return it. Otherwise, return all the rows.
|
||||
match results.find(|row| row.is_err()) {
|
||||
Some(row) => row.map(|row| vec![row]),
|
||||
None => Ok(results.map(|row| row.unwrap()).collect()),
|
||||
}
|
||||
)?;
|
||||
|
||||
Ok(maps)
|
||||
}
|
||||
|
||||
pub fn get_map_by_name(pool: &Pool, name: &str) -> Result<Option<map::Map>, Box<dyn Error>> {
|
||||
let mut conn = pool.get_conn()?;
|
||||
let stmt = conn.prep("SELECT * FROM record_maps AS maps JOIN record_mapinfo AS mapinfo ON maps.Map = mapinfo.Map WHERE maps.Map = ?")?;
|
||||
|
||||
let map: Option<map::MapRow> = conn.exec_first(&stmt, (name,))?;
|
||||
|
||||
Ok(match map {
|
||||
Some(row) => {
|
||||
let hlist_pat![
|
||||
name,
|
||||
server,
|
||||
points,
|
||||
stars,
|
||||
mapper,
|
||||
timestamp,
|
||||
_name_again,
|
||||
width,
|
||||
height,
|
||||
death,
|
||||
through,
|
||||
jump,
|
||||
dfreeze,
|
||||
hit_end,
|
||||
ehook_start,
|
||||
solo_start,
|
||||
tele_gun,
|
||||
tele_grenade,
|
||||
tele_laser,
|
||||
npc_start,
|
||||
super_start,
|
||||
jetpack_start,
|
||||
walljump,
|
||||
nph_start,
|
||||
weapon_shotgun,
|
||||
weapon_grenade,
|
||||
powerup_ninja,
|
||||
weapon_rifle,
|
||||
laser_stop,
|
||||
crazy_shotgun,
|
||||
dragger,
|
||||
door,
|
||||
switch_timed,
|
||||
switch,
|
||||
stop,
|
||||
through_all,
|
||||
tune,
|
||||
oldlaser,
|
||||
teleinevil,
|
||||
telein,
|
||||
telecheck,
|
||||
teleinweapon,
|
||||
teleinhook,
|
||||
checkpoint_first,
|
||||
bonus,
|
||||
boost,
|
||||
plasmaf,
|
||||
plasmae,
|
||||
plasmau
|
||||
] = row;
|
||||
Some(map::Map {
|
||||
name,
|
||||
server,
|
||||
points,
|
||||
stars,
|
||||
mapper,
|
||||
timestamp,
|
||||
width,
|
||||
height,
|
||||
tile_data: map::MapTileData {
|
||||
death,
|
||||
through,
|
||||
jump,
|
||||
dfreeze,
|
||||
hit_end,
|
||||
ehook_start,
|
||||
solo_start,
|
||||
tele_gun,
|
||||
tele_grenade,
|
||||
tele_laser,
|
||||
npc_start,
|
||||
super_start,
|
||||
jetpack_start,
|
||||
walljump,
|
||||
nph_start,
|
||||
weapon_shotgun,
|
||||
weapon_grenade,
|
||||
powerup_ninja,
|
||||
weapon_rifle,
|
||||
laser_stop,
|
||||
crazy_shotgun,
|
||||
dragger,
|
||||
door,
|
||||
switch_timed,
|
||||
switch,
|
||||
stop,
|
||||
through_all,
|
||||
tune,
|
||||
oldlaser,
|
||||
teleinevil,
|
||||
telein,
|
||||
telecheck,
|
||||
teleinweapon,
|
||||
teleinhook,
|
||||
checkpoint_first,
|
||||
bonus,
|
||||
boost,
|
||||
plasmaf,
|
||||
plasmae,
|
||||
plasmau,
|
||||
},
|
||||
})
|
||||
}
|
||||
None => None,
|
||||
})
|
||||
}
|
||||
|
||||
fn races_result(row: race::RaceRow) -> race::Race {
|
||||
let hlist_pat![
|
||||
map, name, timestamp, time, server, cp1, cp2, cp3, cp4, cp5, cp6, cp7, cp8, cp9, cp10,
|
||||
cp11, cp12, cp13, cp14, cp15, cp16, cp17, cp18, cp19, cp20, cp21, cp22, cp23, cp24, cp25,
|
||||
gameid, ddnet7
|
||||
] = row;
|
||||
race::Race {
|
||||
map,
|
||||
name,
|
||||
timestamp,
|
||||
time,
|
||||
server,
|
||||
cp1,
|
||||
cp2,
|
||||
cp3,
|
||||
cp4,
|
||||
cp5,
|
||||
cp6,
|
||||
cp7,
|
||||
cp8,
|
||||
cp9,
|
||||
cp10,
|
||||
cp11,
|
||||
cp12,
|
||||
cp13,
|
||||
cp14,
|
||||
cp15,
|
||||
cp16,
|
||||
cp17,
|
||||
cp18,
|
||||
cp19,
|
||||
cp20,
|
||||
cp21,
|
||||
cp22,
|
||||
cp23,
|
||||
cp24,
|
||||
cp25,
|
||||
gameid,
|
||||
ddnet7,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_races_by_player(pool: &Pool, player: &str) -> Result<Vec<race::Race>, Box<dyn Error>> {
|
||||
let mut conn = pool.get_conn()?;
|
||||
let stmt = conn.prep("SELECT * FROM record_race WHERE Name = ?")?;
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
let races = conn.exec_map(&stmt, (player,), races_result)?;
|
||||
#[test]
|
||||
fn test_database_connection() {
|
||||
async fn test() {
|
||||
let db = match DatabaseHandler::create().await {
|
||||
Ok(db) => db,
|
||||
Err(err) => panic!("Could not get a client!\n{}", err),
|
||||
};
|
||||
|
||||
Ok(races)
|
||||
}
|
||||
let msg = "Hello World!";
|
||||
let rows = match db.client.query("SELECT $1::TEXT", &[&msg]).await {
|
||||
Ok(rows) => rows,
|
||||
Err(err) => panic!("Could not create query!\n{}", err),
|
||||
};
|
||||
|
||||
pub fn get_races_by_id(pool: &Pool, id: &str) -> Result<Vec<race::Race>, Box<dyn Error>> {
|
||||
let mut conn = pool.get_conn()?;
|
||||
let stmt = conn.prep("SELECT * FROM record_race WHERE GameID = ?")?;
|
||||
let value: &str = rows[0].get(0);
|
||||
assert_eq!(value, msg)
|
||||
}
|
||||
|
||||
let races = conn.exec_map(&stmt, (id,), races_result)?;
|
||||
tokio_test::block_on(test())
|
||||
}
|
||||
|
||||
Ok(races)
|
||||
}
|
||||
#[test]
|
||||
fn test_get_all_maps() {
|
||||
async fn test() {
|
||||
let db = match DatabaseHandler::create().await {
|
||||
Ok(db) => db,
|
||||
Err(err) => panic!("Could not get a client!\n{}", err),
|
||||
};
|
||||
|
||||
pub fn get_races_by_map(pool: &Pool, map: &str) -> Result<Vec<race::Race>, Box<dyn Error>> {
|
||||
let mut conn = pool.get_conn()?;
|
||||
let stmt = conn.prep("SELECT * FROM record_race WHERE Map = ?")?;
|
||||
match db.get_all_maps().await {
|
||||
Ok(maps) => println!("Found maps: {:?}", maps.len()),
|
||||
Err(err) => panic!("Could not get all maps!\n{}", err),
|
||||
};
|
||||
}
|
||||
|
||||
let races = conn.exec_map(&stmt, (map,), races_result)?;
|
||||
|
||||
Ok(races)
|
||||
}
|
||||
|
||||
pub fn get_player_total_playtime(
|
||||
pool: &Pool,
|
||||
player: &str,
|
||||
) -> Result<(Option<f64>, Option<i32>), Box<dyn Error>> {
|
||||
let mut conn = pool.get_conn()?;
|
||||
let stmt = conn.prep(
|
||||
"SELECT COALESCE(SUM(Time),0), COALESCE(COUNT(Time),0) FROM record_race WHERE Name = ?",
|
||||
)?;
|
||||
|
||||
let result = conn.exec_first(&stmt, (player,))?;
|
||||
|
||||
match result {
|
||||
Some((total_playtime, total_games)) => Ok((total_playtime, total_games)),
|
||||
None => Ok((None::<f64>, None::<i32>)),
|
||||
tokio_test::block_on(test())
|
||||
}
|
||||
}
|
||||
|
|
43
src/database/models/map.rs
Normal file
43
src/database/models/map.rs
Normal file
|
@ -0,0 +1,43 @@
|
|||
use std::error::Error;
|
||||
|
||||
use chrono::NaiveDateTime;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tokio_postgres::Row;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Map {
|
||||
map: String,
|
||||
mapper: String,
|
||||
category: String,
|
||||
points: u8,
|
||||
stars: u8,
|
||||
release: Option<NaiveDateTime>,
|
||||
width: u16,
|
||||
height: u16,
|
||||
tiles: Vec<String>,
|
||||
}
|
||||
|
||||
impl Map {
|
||||
pub fn from_db_row(db_row: &Row) -> Result<Self, Box<dyn Error>> {
|
||||
let map: String = db_row.try_get(0)?;
|
||||
let category: String = db_row.try_get(1)?;
|
||||
let points_i16: i16 = db_row.try_get(2)?;
|
||||
let points: u8 = points_i16 as u8;
|
||||
let stars_i16: i16 = db_row.try_get(3)?;
|
||||
let stars: u8 = stars_i16 as u8;
|
||||
let mapper: String = db_row.try_get(4)?;
|
||||
let release: Option<NaiveDateTime> = db_row.try_get(5)?;
|
||||
|
||||
Ok(Map {
|
||||
map,
|
||||
mapper,
|
||||
category,
|
||||
points,
|
||||
stars,
|
||||
release,
|
||||
width: 1,
|
||||
height: 1,
|
||||
tiles: vec![],
|
||||
})
|
||||
}
|
||||
}
|
1
src/database/models/mod.rs
Normal file
1
src/database/models/mod.rs
Normal file
|
@ -0,0 +1 @@
|
|||
pub mod map;
|
|
@ -1,74 +0,0 @@
|
|||
use mysql_common::{chrono::NaiveDateTime, frunk::HList};
|
||||
use rocket::serde::{Deserialize, Serialize};
|
||||
|
||||
pub type RaceRow = HList!(
|
||||
String,
|
||||
String,
|
||||
NaiveDateTime,
|
||||
f64,
|
||||
String,
|
||||
f64,
|
||||
f64,
|
||||
f64,
|
||||
f64,
|
||||
f64,
|
||||
f64,
|
||||
f64,
|
||||
f64,
|
||||
f64,
|
||||
f64,
|
||||
f64,
|
||||
f64,
|
||||
f64,
|
||||
f64,
|
||||
f64,
|
||||
f64,
|
||||
f64,
|
||||
f64,
|
||||
f64,
|
||||
f64,
|
||||
f64,
|
||||
f64,
|
||||
f64,
|
||||
f64,
|
||||
f64,
|
||||
Option<String>,
|
||||
bool
|
||||
);
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(crate = "rocket::serde")]
|
||||
pub struct Race {
|
||||
pub map: String,
|
||||
pub name: String,
|
||||
pub timestamp: NaiveDateTime,
|
||||
pub time: f64,
|
||||
pub server: String,
|
||||
pub cp1: f64,
|
||||
pub cp2: f64,
|
||||
pub cp3: f64,
|
||||
pub cp4: f64,
|
||||
pub cp5: f64,
|
||||
pub cp6: f64,
|
||||
pub cp7: f64,
|
||||
pub cp8: f64,
|
||||
pub cp9: f64,
|
||||
pub cp10: f64,
|
||||
pub cp11: f64,
|
||||
pub cp12: f64,
|
||||
pub cp13: f64,
|
||||
pub cp14: f64,
|
||||
pub cp15: f64,
|
||||
pub cp16: f64,
|
||||
pub cp17: f64,
|
||||
pub cp18: f64,
|
||||
pub cp19: f64,
|
||||
pub cp20: f64,
|
||||
pub cp21: f64,
|
||||
pub cp22: f64,
|
||||
pub cp23: f64,
|
||||
pub cp24: f64,
|
||||
pub cp25: f64,
|
||||
pub gameid: Option<String>,
|
||||
pub ddnet7: bool,
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
use mysql_common::{chrono::NaiveDateTime, frunk::HList};
|
||||
use rocket::serde::{Deserialize, Serialize};
|
||||
|
||||
pub type TeamRaceRow = HList!(String, String, f64, NaiveDateTime, String, String, bool);
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(crate = "rocket::serde")]
|
||||
pub struct TeamRace {
|
||||
pub name: String,
|
||||
pub map: String,
|
||||
pub time: f64,
|
||||
pub timestamp: NaiveDateTime,
|
||||
pub id: String,
|
||||
pub gameid: String,
|
||||
pub ddnet7: bool,
|
||||
}
|
115
src/main.rs
115
src/main.rs
|
@ -1,103 +1,28 @@
|
|||
use database::DatabaseHandler;
|
||||
|
||||
#[macro_use]
|
||||
extern crate rocket;
|
||||
|
||||
use database::create_pool;
|
||||
use rocket::serde::json::Json;
|
||||
use rocket::State;
|
||||
|
||||
extern crate dotenv;
|
||||
use dotenv::dotenv;
|
||||
|
||||
mod database;
|
||||
use database::{map::Map, race::Race, DatabasePoolStore};
|
||||
|
||||
#[get("/maps")]
|
||||
fn get_all_maps(db_pool: &State<DatabasePoolStore>) -> Option<Json<Vec<Map>>> {
|
||||
match database::get_maps(&db_pool.0) {
|
||||
Ok(maps) => Some(Json(maps)),
|
||||
Err(err) => {
|
||||
println!("{err}");
|
||||
None
|
||||
}
|
||||
#[rocket::main]
|
||||
async fn main() {
|
||||
let client = match DatabaseHandler::create().await {
|
||||
Ok(client) => client,
|
||||
Err(err) => panic!(
|
||||
"Encountered an error while connecting to the database!\n{}",
|
||||
err
|
||||
),
|
||||
};
|
||||
|
||||
match rocket::build()
|
||||
.manage(client)
|
||||
.mount("/", routes![])
|
||||
.launch()
|
||||
.await
|
||||
{
|
||||
Ok(_) => (),
|
||||
Err(err) => println!("Encountered an error while starting rocket!\n{}", err),
|
||||
}
|
||||
}
|
||||
|
||||
#[get("/maps/<map>")]
|
||||
fn get_map_by_name(db_pool: &State<DatabasePoolStore>, map: &str) -> Option<Json<Map>> {
|
||||
match database::get_map_by_name(&db_pool.0, map) {
|
||||
Ok(map) => map.map(Json),
|
||||
Err(err) => {
|
||||
println!("{err}");
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[get("/races/by-player/<player>")]
|
||||
fn get_races_by_player(
|
||||
db_pool: &State<DatabasePoolStore>,
|
||||
player: &str,
|
||||
) -> Option<Json<Vec<Race>>> {
|
||||
match database::get_races_by_player(&db_pool.0, player) {
|
||||
Ok(races) => Some(Json(races)),
|
||||
Err(err) => {
|
||||
println!("{err}");
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[get("/races/by-id/<id>")]
|
||||
fn get_races_by_id(db_pool: &State<DatabasePoolStore>, id: &str) -> Option<Json<Vec<Race>>> {
|
||||
match database::get_races_by_id(&db_pool.0, id) {
|
||||
Ok(races) => Some(Json(races)),
|
||||
Err(err) => {
|
||||
println!("{err}");
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[get("/races/by-map/<map>")]
|
||||
fn get_races_by_map(db_pool: &State<DatabasePoolStore>, map: &str) -> Option<Json<Vec<Race>>> {
|
||||
match database::get_races_by_map(&db_pool.0, map) {
|
||||
Ok(races) => Some(Json(races)),
|
||||
Err(err) => {
|
||||
println!("{err}");
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[get("/player/<player>/playtime")]
|
||||
fn get_player_playtime(
|
||||
db_pool: &State<DatabasePoolStore>,
|
||||
player: &str,
|
||||
) -> Option<Json<(Option<f64>, Option<i32>)>> {
|
||||
match database::get_player_total_playtime(&db_pool.0, player) {
|
||||
Ok(playtime) => Some(Json(playtime)),
|
||||
Err(err) => {
|
||||
println!("{err}");
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[launch]
|
||||
fn rocket() -> _ {
|
||||
dotenv().ok();
|
||||
|
||||
let db_pool = create_pool();
|
||||
|
||||
rocket::build().manage(DatabasePoolStore(db_pool)).mount(
|
||||
"/",
|
||||
routes![
|
||||
get_all_maps,
|
||||
get_map_by_name,
|
||||
get_races_by_player,
|
||||
get_races_by_id,
|
||||
get_races_by_map,
|
||||
get_player_playtime
|
||||
],
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user