From 1421720b2bece142c3c861615428525ea1f90ec5 Mon Sep 17 00:00:00 2001 From: Kiana Sheibani Date: Tue, 3 Oct 2023 01:26:25 -0400 Subject: [PATCH] Various improvements --- src/datasets.rs | 37 +++++++++++++++++++++++++------- src/main.rs | 21 ++++++++++++------ src/queries.rs | 6 +++--- src/queries/tournament_events.rs | 4 ++-- src/sync.rs | 4 ++-- 5 files changed, 50 insertions(+), 22 deletions(-) diff --git a/src/datasets.rs b/src/datasets.rs index 5459b76..f414ac4 100644 --- a/src/datasets.rs +++ b/src/datasets.rs @@ -6,7 +6,7 @@ use std::io; use std::path::{Path, PathBuf}; use std::time::SystemTime; -pub struct DatasetConfig { +pub struct DatasetMetadata { pub last_sync: Timestamp, pub game_id: VideogameId, pub game_name: String, @@ -48,13 +48,34 @@ pub fn open_datasets(config_dir: &Path) -> sqlite::Result { // TODO: Sanitize dataset names -pub fn list_datasets(connection: &Connection) -> sqlite::Result> { +pub fn list_dataset_names(connection: &Connection) -> sqlite::Result> { + let query = "SELECT name FROM datasets"; + + connection + .prepare(query)? + .into_iter() + .map(|r| r.map(|x| x.read::<&str, _>("name").to_owned())) + .try_collect() +} + +pub fn list_datasets(connection: &Connection) -> sqlite::Result> { let query = "SELECT * FROM datasets"; connection .prepare(query)? .into_iter() - .map(|x| x.map(|r| r.read::<&str, _>("name").to_owned())) + .map(|r| { + let r_ = r?; + Ok(( + r_.read::<&str, _>("name").to_owned(), + DatasetMetadata { + last_sync: Timestamp(r_.read::("last_sync") as u64), + game_id: VideogameId(r_.read::("game_id") as u64), + game_name: r_.read::<&str, _>("game_name").to_owned(), + state: r_.read::, _>("state").map(String::from), + }, + )) + }) .try_collect() } @@ -71,7 +92,7 @@ pub fn delete_dataset(connection: &Connection, dataset: &str) -> sqlite::Result< pub fn new_dataset( connection: &Connection, dataset: &str, - config: DatasetConfig, + config: DatasetMetadata, ) -> sqlite::Result<()> { let query1 = r#"INSERT INTO datasets (name, game_id, game_name, state) VALUES (?, ?, ?, ?)"#; @@ -97,11 +118,11 @@ pub fn new_dataset( connection.execute(query2) } -pub fn get_dataset_config( +pub fn get_metadata( connection: &Connection, dataset: &str, -) -> sqlite::Result> { - let query = "SELECT last_sync, game_id, state FROM datasets WHERE name = ?"; +) -> sqlite::Result> { + let query = "SELECT last_sync, game_id, game_name, state FROM datasets WHERE name = ?"; Ok(connection .prepare(query)? @@ -110,7 +131,7 @@ pub fn get_dataset_config( .next() .map(|r| { let r_ = r?; - Ok(DatasetConfig { + Ok(DatasetMetadata { last_sync: Timestamp(r_.read::("last_sync") as u64), game_id: VideogameId(r_.read::("game_id") as u64), game_name: r_.read::<&str, _>("game_name").to_owned(), diff --git a/src/main.rs b/src/main.rs index 9501cda..ebf34b7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,7 +3,6 @@ use clap::{Parser, Subcommand}; use std::io::{self, Write}; use std::path::PathBuf; -use std::process::exit; mod queries; use queries::*; @@ -13,11 +12,13 @@ mod sync; use sync::*; pub fn error(msg: &str, code: i32) -> ! { + use std::process::exit; println!("\nERROR: {}", msg); exit(code) } pub fn issue(msg: &str, code: i32) -> ! { + use std::process::exit; println!("\n{}", msg); exit(code) } @@ -119,7 +120,14 @@ fn dataset_list() { open_datasets(&config_dir).unwrap_or_else(|_| error("Could not open datasets file", 1)); let datasets = list_datasets(&connection).expect("Error communicating with SQLite"); - println!("{:?}", datasets); + println!(); + for (name, metadata) in datasets { + if let Some(state) = metadata.state { + println!("{} - {}, {}", name, metadata.game_name, state); + } else { + println!("{} - {}", name, metadata.game_name); + } + } } fn read_string() -> String { @@ -181,7 +189,7 @@ fn dataset_new(name: Option, auth_token: Option) { new_dataset( &connection, &name, - DatasetConfig { + DatasetMetadata { last_sync: Timestamp(1), game_id, game_name, @@ -216,7 +224,7 @@ fn sync(datasets: Vec, all: bool, auth_token: Option) { #[allow(unused_must_use)] let datasets = if all { - list_datasets(&connection).unwrap() + list_dataset_names(&connection).unwrap() } else if datasets.len() == 0 { print!("No datasets provided; create a new one? (y/n) "); if read_string() == "y" { @@ -228,14 +236,13 @@ fn sync(datasets: Vec, all: bool, auth_token: Option) { }; for dataset in datasets { - let dataset_config = get_dataset_config(&connection, &dataset) + let dataset_config = get_metadata(&connection, &dataset) .expect("Error communicating with SQLite") .unwrap_or_else(|| error(&format!("Dataset {} does not exist!", dataset), 1)); sync_dataset(&connection, &dataset, dataset_config, &auth).unwrap_or_else(|err| { connection.execute("ROLLBACK;").unwrap(); - panic!("{:?}", err); - // error("Error communicating with SQLite", 2) + error("Error communicating with SQLite", 2) }); update_last_sync(&connection, &dataset).expect("Error communicating with SQLite"); diff --git a/src/queries.rs b/src/queries.rs index c1ee2d7..c89c649 100644 --- a/src/queries.rs +++ b/src/queries.rs @@ -14,6 +14,7 @@ pub use event_sets::*; pub mod player_info; pub use player_info::*; +use crate::error; use schema::schema; // Auth key @@ -24,7 +25,7 @@ pub fn get_auth_token(config_dir: &Path) -> Option { match var("AUTH_TOKEN") { Ok(key) => Some(key), - Err(VarError::NotUnicode(_)) => panic!("Invalid authorization key"), + Err(VarError::NotUnicode(_)) => error("Invalid authorization key", 2), Err(VarError::NotPresent) => { let mut auth_file = config_dir.to_owned(); auth_file.push("ggelo"); @@ -77,9 +78,8 @@ pub trait QueryUnwrap: 'static + QueryBuilder { // Generic function for running start.gg queries pub fn run_query(vars: Vars, auth_token: &str) -> Option where - Vars: Copy, + Vars: Copy + Serialize, Builder: QueryUnwrap, - Vars: Serialize, for<'de> Builder: Deserialize<'de>, { use cynic::http::ReqwestBlockingExt; diff --git a/src/queries/tournament_events.rs b/src/queries/tournament_events.rs index 9277abd..0c61478 100644 --- a/src/queries/tournament_events.rs +++ b/src/queries/tournament_events.rs @@ -11,10 +11,10 @@ pub struct TournamentEventsVars<'a> { // server-side bug that completely breaks everything when this isn't passed. // We can use a dummy value of 1 when we don't want to filter by time. pub last_sync: Timestamp, - pub game_id: VideogameId, - pub page: i32, + pub game_id: VideogameId, pub state: Option<&'a str>, + pub page: i32, } // Query diff --git a/src/sync.rs b/src/sync.rs index d0bb539..2e19e3d 100644 --- a/src/sync.rs +++ b/src/sync.rs @@ -71,7 +71,7 @@ fn get_event_sets(event: EventId, auth: &str) -> Option> { } } -fn get_tournament_events(dataset_config: &DatasetConfig, auth: &str) -> Option> { +fn get_tournament_events(dataset_config: &DatasetMetadata, auth: &str) -> Option> { println!("Accessing tournaments..."); let tour_response = run_query::( @@ -148,7 +148,7 @@ fn update_from_set(connection: &Connection, dataset: &str, results: SetData) -> pub fn sync_dataset( connection: &Connection, dataset: &str, - dataset_config: DatasetConfig, + dataset_config: DatasetMetadata, auth: &str, ) -> sqlite::Result<()> { let events = get_tournament_events(&dataset_config, auth)