diff options
| author | salmonik <salmonik@tuta.io> | 2026-11-01 16:17:19 +0100 |
|---|---|---|
| committer | salmonik <salmonik@tuta.io> | 2026-11-01 16:17:19 +0100 |
| commit | f07221b4e1d8aa464a44fe566884ccc0565406e9 (patch) | |
| tree | 48020a68cee1c95521d594dc6803c1f7ec01c801 /src/server | |
| parent | add nginx + php-fpm deployment example (diff) | |
| download | zagan-bet-f07221b4e1d8aa464a44fe566884ccc0565406e9.tar.gz zagan-bet-f07221b4e1d8aa464a44fe566884ccc0565406e9.zip | |
v3.2.0: straight and split bets anywhere on the felt; add history command
Diffstat (limited to '')
| -rw-r--r-- | src/server/core.rs | 34 | ||||
| -rw-r--r-- | src/server/database.rs | 27 |
2 files changed, 61 insertions, 0 deletions
diff --git a/src/server/core.rs b/src/server/core.rs index 4b68ccb..89264f3 100644 --- a/src/server/core.rs +++ b/src/server/core.rs | |||
| @@ -172,6 +172,21 @@ impl ServerCore { | |||
| 172 | self.handle_auth(state, parts[1], parts[2]) | 172 | self.handle_auth(state, parts[1], parts[2]) |
| 173 | } | 173 | } |
| 174 | } | 174 | } |
| 175 | "HISTORY" => { | ||
| 176 | if parts.len() > 2 { | ||
| 177 | "ERROR Invalid HISTORY format. Usage: HISTORY [count]".to_string() | ||
| 178 | } else { | ||
| 179 | match parts.get(1) { | ||
| 180 | Some(raw) => match raw.parse::<u32>() { | ||
| 181 | Ok(count) if count > 0 => { | ||
| 182 | self.handle_history(state, count.min(crate::history::MAX_HISTORY)) | ||
| 183 | } | ||
| 184 | _ => "ERROR Invalid HISTORY count".to_string(), | ||
| 185 | }, | ||
| 186 | None => self.handle_history(state, crate::history::DEFAULT_HISTORY), | ||
| 187 | } | ||
| 188 | } | ||
| 189 | } | ||
| 175 | "PING" => "PONG".to_string(), | 190 | "PING" => "PONG".to_string(), |
| 176 | "INFO" => self.handle_info(state), | 191 | "INFO" => self.handle_info(state), |
| 177 | _ => msg.to_string(), | 192 | _ => msg.to_string(), |
| @@ -234,6 +249,25 @@ impl ServerCore { | |||
| 234 | } | 249 | } |
| 235 | } | 250 | } |
| 236 | 251 | ||
| 252 | fn handle_history(&mut self, state: &ConnectionState, limit: u32) -> String { | ||
| 253 | let Some(user) = state.user.as_deref() else { | ||
| 254 | return "ERROR Not logged in".to_string(); | ||
| 255 | }; | ||
| 256 | match database::recent_plays(&self.conn, user, limit) { | ||
| 257 | Ok(records) => match serde_json::to_string(&records) { | ||
| 258 | Ok(json) => format!("HISTORY {json}"), | ||
| 259 | Err(error) => { | ||
| 260 | eprintln!("History serialization failed for {user}: {error}"); | ||
| 261 | "ERROR Could not read history".to_string() | ||
| 262 | } | ||
| 263 | }, | ||
| 264 | Err(error) => { | ||
| 265 | eprintln!("History query failed for {user}: {error}"); | ||
| 266 | "ERROR Could not read history".to_string() | ||
| 267 | } | ||
| 268 | } | ||
| 269 | } | ||
| 270 | |||
| 237 | fn handle_info(&self, state: &ConnectionState) -> String { | 271 | fn handle_info(&self, state: &ConnectionState) -> String { |
| 238 | let Some(user) = state.user.as_deref() else { | 272 | let Some(user) = state.user.as_deref() else { |
| 239 | return "ERROR Not logged in".to_string(); | 273 | return "ERROR Not logged in".to_string(); |
diff --git a/src/server/database.rs b/src/server/database.rs index 6dd71a3..cfc48c1 100644 --- a/src/server/database.rs +++ b/src/server/database.rs | |||
| @@ -399,3 +399,30 @@ fn abandoned_details(raw: &str) -> String { | |||
| 399 | } | 399 | } |
| 400 | value.to_string() | 400 | value.to_string() |
| 401 | } | 401 | } |
| 402 | |||
| 403 | /// Most recent settled plays for a user, newest first. | ||
| 404 | pub fn recent_plays( | ||
| 405 | conn: &Connection, | ||
| 406 | username: &str, | ||
| 407 | limit: u32, | ||
| 408 | ) -> rusqlite::Result<Vec<crate::history::PlayRecord>> { | ||
| 409 | let mut statement = conn.prepare( | ||
| 410 | "SELECT game_type, bet_amount, winnings, balance_after, details, created_at | ||
| 411 | FROM plays | ||
| 412 | WHERE username = ?1 | ||
| 413 | ORDER BY created_at DESC, rowid DESC | ||
| 414 | LIMIT ?2", | ||
| 415 | )?; | ||
| 416 | let rows = statement.query_map(params![username, limit], |row| { | ||
| 417 | let details: String = row.get(4)?; | ||
| 418 | Ok(crate::history::PlayRecord { | ||
| 419 | game: row.get(0)?, | ||
| 420 | bet: row.get(1)?, | ||
| 421 | winnings: row.get(2)?, | ||
| 422 | balance_after: row.get(3)?, | ||
| 423 | at: row.get(5)?, | ||
| 424 | details: serde_json::from_str(&details).unwrap_or(serde_json::Value::Null), | ||
| 425 | }) | ||
| 426 | })?; | ||
| 427 | rows.collect() | ||
| 428 | } | ||
