From 8c93f69081f0012e9a97ffc59adb7129bc1593ee Mon Sep 17 00:00:00 2001 From: salmonik Date: Sun, 1 Nov 2026 18:51:05 +0100 Subject: v4.0.5: login and registration as core commands --- src/client/core.rs | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 69 insertions(+), 2 deletions(-) (limited to 'src/client/core.rs') diff --git a/src/client/core.rs b/src/client/core.rs index 37ba916..98f109f 100644 --- a/src/client/core.rs +++ b/src/client/core.rs @@ -66,7 +66,7 @@ pub enum Effect { Quit, } -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq)] enum Pending { Spin, RouletteSpin, @@ -77,6 +77,8 @@ enum Pending { CrashCashout, CrashForfeit, History, + Login { user: String }, + Register, Ping, Echo, Info, @@ -105,6 +107,8 @@ pub struct ClientCore { screen: Screen, /// Last plays fetched with `history`. play_history: Vec, + /// Why the last login or registration attempt failed. + login_error: Option, } impl ClientCore { @@ -123,6 +127,7 @@ impl ClientCore { crash_started: None, screen: Screen::Lobby, play_history: Vec::new(), + login_error: None, } } @@ -137,6 +142,9 @@ impl ClientCore { } pub fn set_logged_in(&mut self, user: Option) { + if user.is_some() { + self.login_error = None; + } self.logged_in = user; } @@ -312,6 +320,25 @@ impl ClientCore { } Err(message) => print_line(message), }, + Some(Pending::Login { user }) => match auth_result(reply) { + Ok(()) => { + self.logged_in = Some(user.clone()); + self.login_error = None; + self.screen = Screen::Lobby; + print_line(format!("Logged in as {user}")) + } + Err(message) => { + self.login_error = Some(message.clone()); + print_line(format!("Authentication failed: {message}")) + } + }, + Some(Pending::Register) => match register_result(reply) { + Ok(()) => print_line("Account created. Log in to play."), + Err(message) => { + self.login_error = Some(message.clone()); + print_line(format!("Registration failed: {message}")) + } + }, Some(Pending::Ping) => { if reply.trim() == "PONG" { print_line("Pong") @@ -404,7 +431,23 @@ impl ClientCore { let game = self.current_game_type().map(str::to_string); match command { - Command::Play { game, bet } => self.play_game(&game, bet), + Command::Login { user, credential } => { + if !self.connected { + return print_line("Not connected. Use 'connect :' first."); + } + self.login_error = None; + self.pending = Some(Pending::Login { user: user.clone() }); + vec![Effect::SendLine(format!("AUTH {user} {credential}"))] + } + Command::Register { user, credential } => { + if !self.connected { + return print_line("Not connected. Use 'connect :' first."); + } + self.login_error = None; + self.pending = Some(Pending::Register); + vec![Effect::SendLine(format!("REGISTER {user} {credential}"))] + } + Command::Play { game, bet } => self.play_game(&game, bet), Command::History { limit } => self.load_history(limit), Command::ShowLobby => { self.screen = Screen::Lobby; @@ -412,6 +455,7 @@ impl ClientCore { } Command::Logout => { self.logged_in = None; + self.login_error = None; self.screen = Screen::Lobby; print_line("Logged out") } @@ -1070,6 +1114,7 @@ impl ClientCore { .into_iter() .map(|(game, name)| (game.to_string(), name.to_string())) .collect(), + login_error: self.login_error.clone(), }), }) } @@ -1086,6 +1131,28 @@ impl ClientCore { } } +fn auth_result(reply: &str) -> Result<(), String> { + let reply = reply.trim(); + if reply.starts_with("OK") { + return Ok(()); + } + Err(reply + .strip_prefix("ERROR") + .map(|message| message.trim().to_string()) + .unwrap_or_else(|| reply.to_string())) +} + +fn register_result(reply: &str) -> Result<(), String> { + let reply = reply.trim(); + if reply.starts_with("REGISTERED") { + return Ok(()); + } + Err(reply + .strip_prefix("ERROR") + .map(|message| message.trim().to_string()) + .unwrap_or_else(|| reply.to_string())) +} + fn print_line(message: impl Into) -> Vec { vec![Effect::Print(vec![message.into()])] } -- cgit v1.2.3