From: Ian Jackson Date: Sun, 15 Nov 2020 22:59:29 +0000 (+0000) Subject: wip join-game etc. X-Git-Tag: otter-0.2.0~505 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=commitdiff_plain;h=fcc68cd8bd7160c368c9392bfa7a5c4da0f7a793;p=otter.git wip join-game etc. Signed-off-by: Ian Jackson --- diff --git a/src/bin/otter.rs b/src/bin/otter.rs index 20f8a55e..91bd86e8 100644 --- a/src/bin/otter.rs +++ b/src/bin/otter.rs @@ -72,7 +72,7 @@ struct MainOpts { timezone: Option, // xxx default to UrlOnStdout // xxx options for others - access: Option>, + access: Option, socket_path: String, verbose: i32, } @@ -147,24 +147,31 @@ fn parse_args( pub fn ok_id(t: T) -> Result { Ok(t) } -fn main() { - #[derive(Debug)] - struct RawAccess(Box); - impl Clone for RawAccess { - fn clone(&self) -> Self { - (||{ - let s = serde_json::to_string(&self.0).context("ser")?; - let c = serde_json::from_str(&s).context("de")?; - Ok::<_,AE>(Self(c)) - })() - .with_context(|| format!("clone {:?} via serde failed", self)) - .unwrap() - } - } - impl From for RawAccess { - fn from(t: T) -> Self { RawAccess(Box::new(t)) } - } +pub fn clone_via_serde> + (t: &T) -> T +{ + (||{ + let s = serde_json::to_string(t).context("ser")?; + let c = serde_json::from_str(&s).context("de")?; + Ok::<_,AE>(c) + })() + .with_context(|| format!("clone {:?} via serde failed", t)) + .unwrap() +} +#[derive(Debug)] +struct AccessOpt(Box); +impl Clone for AccessOpt { + fn clone(&self) -> Self { Self(clone_via_serde(&self.0)) } +} +impl From for AccessOpt { + fn from(t: T) -> Self { AccessOpt(Box::new(t)) } +} +impl From for Box { + fn from(a: AccessOpt) -> Self { a.0 } +} + +fn main() { #[derive(Default,Debug)] struct RawMainArgs { account: Option, @@ -172,7 +179,7 @@ fn main() { socket_path: Option, nick: Option, timezone: Option, - access: Option, + access: Option, verbose: i32, config_filename: Option, subcommand: String, @@ -227,7 +234,7 @@ fn main() { "increase verbosity (default is short progress messages)"); access.metavar("TOKEN").add_option( &["--fixed-token"], - MapStore(|s| Ok(Some(RawAccess(Box::new(FixedToken { token: RawToken (s.to_string()) }))))), + MapStore(|s| Ok(Some(AccessOpt(Box::new(FixedToken { token: RawToken (s.to_string()) }))))), "use fixed game access token TOKEN (for administrators only)r" ); ap @@ -236,7 +243,6 @@ fn main() { access, socket_path, verbose, config_filename, subcommand, subargs, }|{ - let access = access.map(|RawAccess(a)| a); let account : AccountName = account.map(Ok::<_,APE>).unwrap_or_else(||{ let user = env::var("USER").map_err(|e| ArgumentParseError( format!("default account needs USER env var: {}", &e) @@ -689,11 +695,11 @@ mod join_game { } } let mut wantup = Wantup(false); - let ad = AccountDetails { + let mut ad = AccountDetails { account: ma.account.clone(), - nick: ma.nick.clone(), + nick: wantup.u(&ma.nick), timezone: wantup.u(&ma.timezone), - access: wantup.u(&ma.access), + access: wantup.u(&ma.access).map(Into::into), }; fn is_no_account(r: &Result) -> bool { @@ -704,25 +710,6 @@ mod join_game { else { return false } } } - fn fail_need_access() -> Impossible { - eprintln!("Need to make your account and set your access token delivery method. Please pass the --access option."); - exit(EXIT_SITUATION); - } - - if wantup.0 { - let resp = conn.cmd(&MC::UpdateAccount(ad.clone())); - let resp = if is_no_account(&resp) { - if ad.access.is_none() { fail_need_access(); } - conn.cmd(&ME::CreateAccount(ad.clone())) - } else { - resp - }; - match resp { - Ok(MR::Fine) => (), - Ok(x) => anyhow!("unexpected response to UpdateAccount: {:?}", &x)?, - Err(x) => throw!(x), - } - } let mut chan = ConnForGame { conn, @@ -730,15 +717,36 @@ mod join_game { how: MgmtGameUpdateMode::Online, }; + { + let mut desc; + let mut resp; + if wantup.0 { + desc = "UpdateAccount"; + resp = chan.conn.cmd(&MC::UpdateAccount(clone_via_serde(&ad))) + .map(|_|()); + } else { + desc = "AlterGame--Noop"; + resp = chan.alter_game(vec![MGI::Noop], None) + .map(|_|()); + }; + if is_no_account(&resp) { + ad.access.get_or_insert(Box::new(UrlOnStdout)); + desc = "CreateAccount"; + resp = conn.cmd(&MC::CreateAccount(clone_via_serde(&ad))) + .map(|_|()); + } + resp.with_context(||format!("response to {}", &desc))?; + } + let insns = vec![ - MGI::JoinGame { nick: ma.nick.clone() }, + MGI::JoinGame { details: MgmtPlayerDetails { nick: ma.nick.clone() } }, ]; - let resp = chan.alter_game(insns, |_| Ok(())); - if is_no_account(&resp) { fail_need_access(); } - match resp? { + let resp = chan.alter_game(insns, None)?; + + match resp.as_slice() { [MGR::JoinGame { nick, player, token }] => { println!("joined game as player #{} {:?}", - player.get_idx_version().0, + player.0.get_idx_version().0, &nick); for l in &token.lines { if l.contains(char::is_control) { @@ -749,7 +757,7 @@ mod join_game { } } } - x => anyhow!("unexpected response to JoinGame: {:?}", &x)?, + x => throw!(anyhow!("unexpected response to JoinGame: {:?}", &x)), } Ok(())