diff options
Diffstat (limited to 'src/game.rs')
| -rw-r--r-- | src/game.rs | 176 |
1 files changed, 107 insertions, 69 deletions
diff --git a/src/game.rs b/src/game.rs index 0f6637e..362e304 100644 --- a/src/game.rs +++ b/src/game.rs @@ -2,12 +2,12 @@ use std::{ convert::Infallible, fs, iter, + path::PathBuf, result::Result as StdResult, str::{ self, FromStr, }, - path::PathBuf, }; use fnv::{ @@ -44,27 +44,20 @@ use anyhow::{ Error, }; use lazy_static::lazy_static; +use serenity::framework::standard::CommandResult; use crate::{ - util::CtxExt, + util, Result, CONFIG, }; -pub use self::GAME_GROUP as GROUP; +pub use self::Game as GROUP; -group!({ - name: "game", - options: { - only_in: "guild", - }, - commands: [ - game, - installedgame, - ownedgame, - updategaem, - ], -}); +#[group] +#[prefix = "game"] +#[commands(game, installedgame, ownedgame, updategaem)] +pub struct Game; lazy_static! { static ref SPREADSHEET_URL: Url = Url::parse(&format!( @@ -101,7 +94,8 @@ lazy_static! { static ref USER_INFO_MAP: FnvHashMap<String, ProfileInfo> = { let v: Vec<UserInfo> = serde_json::from_str(&USER_MAP_STR).unwrap(); - let result = v.into_iter() + let result = v + .into_iter() .map(|ui| { let UserInfo { name, @@ -112,7 +106,11 @@ lazy_static! { }) .collect::<FnvHashMap<_, _>>(); - log::info!("loaded user info for {} users ({:#?})", result.len(), result.keys().collect::<Vec<_>>()); + log::info!( + "loaded user info for {} users ({:#?})", + result.len(), + result.keys().collect::<Vec<_>>() + ); result }; @@ -120,14 +118,16 @@ lazy_static! { USER_INFO_MAP .clone() .into_iter() - .map(|(name, profile)| (UserId(profile.discord_user_id), name)) + .map(|(name, profile)| (UserId::new(profile.discord_user_id), name)) .collect::<FnvHashMap<_, _>>() }; static ref STEAM_MAP: FnvHashMap<UserId, u64> = { USER_INFO_MAP .clone() .into_iter() - .filter_map(|(_, profile)| profile.steam_id.map(|sid| (UserId(profile.discord_user_id), sid))) + .filter_map(|(_, profile)| { + profile.steam_id.map(|sid| (UserId::new(profile.discord_user_id), sid)) + }) .collect::<FnvHashMap<_, _>>() }; static ref ALPHABET: Vec<char> = (0..26).map(|x| (x + b'a') as char).collect(); @@ -163,13 +163,13 @@ impl FromStr for GameStatus { #[command] #[aliases("installedgaem")] -pub fn installedgame(ctx: &mut Context, msg: &Message, args: Args) -> Result<()> { +pub async fn installedgame(ctx: &Context, msg: &Message, args: Args) -> CommandResult { _game(ctx, msg, args, GameStatus::Installed) } #[command] #[aliases("ownedgaem")] -pub fn ownedgame(ctx: &mut Context, msg: &Message, args: Args) -> Result<()> { +pub async fn ownedgame(ctx: &Context, msg: &Message, args: Args) -> CommandResult { _game(ctx, msg, args, GameStatus::NotInstalled) } @@ -186,30 +186,34 @@ pub fn get_user_id<S: AsRef<str>>(g: &Guild, s: S) -> StdResult<UserId, UserLook let s = s.as_ref().trim_start_matches("@").to_lowercase(); if let Some(info) = USER_INFO_MAP.get(&s) { - return Ok(UserId(info.discord_user_id)); + return Ok(UserId::new(info.discord_user_id)); } let nicks = g.members_nick_containing(&s, false, false); { - let exact_match = nicks.iter().find(|m| m.user.read().name.to_lowercase() == s); + let exact_match = nicks.iter().find(|(m, _)| m.display_name().to_lowercase() == s); - if let Some(m) = exact_match { - return Ok(m.user_id()); + if let Some((m, _)) = exact_match { + return Ok(m.user.id); } } let usernames = g.members_username_containing(&s, false, false); { - let exact_match = usernames.iter().find(|m| m.user.read().name.to_lowercase() == s); + let exact_match = usernames.iter().find(|(m, _)| m.user.name.to_lowercase() == s); - if let Some(m) = exact_match { - return Ok(m.user_id()); + if let Some((m, _)) = exact_match { + return Ok(m.user.id); } } - let opts = nicks.into_iter().chain(usernames.into_iter()).map(|member| member.user_id()).collect::<FnvHashSet<_>>(); + let opts = nicks + .into_iter() + .chain(usernames.into_iter()) + .map(|(member, _)| member.user.id) + .collect::<FnvHashSet<_>>(); match opts.len() { 0 => Err(UserLookupError::NotFound), @@ -220,16 +224,19 @@ pub fn get_user_id<S: AsRef<str>>(g: &Guild, s: S) -> StdResult<UserId, UserLook #[command] #[aliases("gaem")] -fn game(ctx: &mut Context, msg: &Message, args: Args) -> Result<()> { - _game(ctx, msg, args, GameStatus::Installed) +async fn game(ctx: &Context, msg: &Message, args: Args) -> CommandResult { + _game(ctx, msg, args, GameStatus::Installed).await } -fn _game(ctx: &mut Context, msg: &Message, mut args: Args, min_status: GameStatus) -> Result<()> { - let guild = msg.channel_id.to_channel(&ctx)?.guild().ok_or(anyhow!("couldn't find guild"))?; - - let guild = guild.read().guild(&ctx).ok_or(anyhow!("couldn't find guild"))?; - - let guild = guild.read(); +async fn _game( + ctx: &Context, + msg: &Message, + mut args: Args, + min_status: GameStatus, +) -> CommandResult { + let guild = + msg.channel_id.to_channel(&ctx).await?.guild().ok_or(anyhow!("couldn't find guild"))?; + let guild = guild.guild(&ctx).ok_or_else(|| anyhow!("couldn't find guild"))?; let user_args: Vec<String> = if args.rest().is_empty() { Vec::new() @@ -248,12 +255,22 @@ fn _game(ctx: &mut Context, msg: &Message, mut args: Args, min_status: GameStatu match possible { Err(UserLookupError::NotFound) => { - let _ = ctx.send(msg.channel_id, &format!("didn't recognize {}", &u), msg.tts); + let _ = util::send( + ctx, + msg.channel_id, + &format!("didn't recognize {}", &u), + msg.tts, + ); None }, Ok(x) => Some(x), Err(UserLookupError::Ambiguous(x)) => { - let _ = ctx.send(msg.channel_id, &format!("too many matches ({}) for {}", x, &u), msg.tts); + let _ = util::send( + ctx, + msg.channel_id, + &format!("too many matches ({}) for {}", x, &u), + msg.tts, + ); None }, } @@ -294,11 +311,11 @@ fn _game(ctx: &mut Context, msg: &Message, mut args: Args, min_status: GameStatu if inferred && users.len() < 2 || !inferred && users.len() < 1 { info!("too few known users to make game comparison"); - ctx.send(msg.channel_id, "yer too lonely", msg.tts)?; + util::send(ctx, msg.channel_id, "yer too lonely", msg.tts).await?; return Ok(()); } - let data = load_spreadsheet()?; + let data = load_spreadsheet().await?; let user_indexes = (0..data.len()) .filter_map(|i| { @@ -328,7 +345,8 @@ fn _game(ctx: &mut Context, msg: &Message, mut args: Args, min_status: GameStatu .collect::<FnvHashMap<_, _>>(); (1..data[*col].len()).for_each(|i| { - let status = &data_ref[*col][i].parse::<GameStatus>().unwrap_or(GameStatus::Unknown); + let status = + &data_ref[*col][i].parse::<GameStatus>().unwrap_or(GameStatus::Unknown); let game = &data_ref[0][i]; game_map.get_mut(status).unwrap().insert(game); @@ -338,23 +356,29 @@ fn _game(ctx: &mut Context, msg: &Message, mut args: Args, min_status: GameStatu }) .collect::<FnvHashMap<_, _>>(); - let statuses = vec![GameStatus::Installed, GameStatus::NotOwned, GameStatus::NotInstalled, GameStatus::Unknown] - .into_iter() - .filter(|s| s <= &min_status) - .collect::<Vec<_>>(); + let statuses = vec![ + GameStatus::Installed, + GameStatus::NotOwned, + GameStatus::NotInstalled, + GameStatus::Unknown, + ] + .into_iter() + .filter(|s| s <= &min_status) + .collect::<Vec<_>>(); let mut games_in_common = { let game_map = user_games.values().nth(0).unwrap(); - statuses - .iter() - .fold(iter::empty().collect::<FnvHashSet<_>>(), |acc, s| acc.union(&game_map[s]).cloned().collect()) + statuses.iter().fold(iter::empty().collect::<FnvHashSet<_>>(), |acc, s| { + acc.union(&game_map[s]).cloned().collect() + }) }; for (_user, game_map) in user_games.iter() { - let relevant_games = statuses - .iter() - .fold(iter::empty().collect::<FnvHashSet<_>>(), |acc, s| acc.union(&game_map[s]).cloned().collect()); + let relevant_games = + statuses.iter().fold(iter::empty().collect::<FnvHashSet<_>>(), |acc, s| { + acc.union(&game_map[s]).cloned().collect() + }); games_in_common = games_in_common.intersection(&relevant_games).cloned().collect(); } @@ -366,12 +390,12 @@ fn _game(ctx: &mut Context, msg: &Message, mut args: Args, min_status: GameStatu games_formatted = "**LITERALLY NOTHING**".to_owned(); } - ctx.send(msg.channel_id, &games_formatted, msg.tts)?; + util::send(ctx, msg.channel_id, &games_formatted, msg.tts).await?; Ok(()) } -fn load_spreadsheet() -> Result<Vec<Vec<String>>> { +async fn load_spreadsheet() -> Result<Vec<Vec<String>>> { let mut u = SPREADSHEET_URL.clone(); u.query_pairs_mut() @@ -382,7 +406,7 @@ fn load_spreadsheet() -> Result<Vec<Vec<String>>> { let req = reqwest::Request::new(reqwest::Method::GET, u); let client = reqwest::Client::new(); - let mut resp = client.execute(req)?; + let resp = client.execute(req).await?; #[derive(Deserialize)] struct Resp { @@ -395,14 +419,14 @@ fn load_spreadsheet() -> Result<Vec<Vec<String>>> { values: Vec<Vec<String>>, } - let resp = resp.json::<Resp>()?; + let resp = resp.json::<Resp>().await?; Ok(resp.value_ranges.into_iter().next().unwrap().values) } #[command] #[aliases("updategame")] -pub fn updategaem(ctx: &mut Context, msg: &Message, mut args: Args) -> Result<()> { +pub async fn updategaem(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult { use regex::Regex; let arg_user = args.single_quoted::<String>(); @@ -412,7 +436,8 @@ pub fn updategaem(ctx: &mut Context, msg: &Message, mut args: Args) -> Result<() } else { use std::borrow::Borrow; - let guild = msg.channel_id.to_channel(&ctx)?.guild().ok_or(anyhow!("couldn't find guild"))?; + let guild = + msg.channel_id.to_channel(&ctx)?.guild().ok_or(anyhow!("couldn't find guild"))?; let guild = guild.read().guild(&ctx).ok_or(anyhow!("couldn't find guild"))?; @@ -425,21 +450,24 @@ pub fn updategaem(ctx: &mut Context, msg: &Message, mut args: Args) -> Result<() let username = match DISCORD_MAP.get(&user) { Some(s) => s, - None => return ctx.send(msg.channel_id, "WHO THE FUCK ARE YE", msg.tts), + None => return util::send(ctx, msg.channel_id, "WHO THE FUCK ARE YE", msg.tts).await, }; let steam_id = match STEAM_MAP.get(&user) { Some(u) => u, - None => return ctx.send(msg.channel_id, "WHO ARE YE ON STEAM", msg.tts), + None => return util::send(ctx, msg.channel_id, "WHO ARE YE ON STEAM", msg.tts).await, }; - let spreadsheet = load_spreadsheet()?; + let spreadsheet = load_spreadsheet().await?; - let user_column = (0..spreadsheet.len()).find(|x| spreadsheet[*x][0].to_lowercase() == username.to_lowercase()); + let user_column = (0..spreadsheet.len()) + .find(|x| spreadsheet[*x][0].to_lowercase() == username.to_lowercase()); let user_column = match user_column { Some(c) => &spreadsheet[c][1..], - None => return ctx.send(msg.channel_id, "YER NOT IN THE SPREADSHEET", msg.tts), + None => { + return util::send(ctx, msg.channel_id, "YER NOT IN THE SPREADSHEET", msg.tts).await; + }, }; lazy_static! { @@ -452,14 +480,16 @@ pub fn updategaem(ctx: &mut Context, msg: &Message, mut args: Args) -> Result<() Some(c) => &spreadsheet[c][1..], None => { error!("didn't find an appid column in the spreadsheet"); - return ctx.send(msg.channel_id, "SPREADSHEET BROKE", msg.tts); + return util::send(ctx, msg.channel_id, "SPREADSHEET BROKE", msg.tts).await; }, }; let missing_appids = (0..user_column.len()) .filter_map(|x| user_column[x].parse::<GameStatus>().ok().map(|s| (x, s))) .filter(|(_, s)| *s == GameStatus::Unknown || *s == GameStatus::NotOwned) - .filter_map(|(x, _)| appid_column.get(x).and_then(|s| s.parse::<u64>().ok().map(|appid| (appid, x)))); + .filter_map(|(x, _)| { + appid_column.get(x).and_then(|s| s.parse::<u64>().ok().map(|appid| (appid, x))) + }); let mut u = Url::parse("https://api.steampowered.com/IPlayerService/GetOwnedGames/v1")?; @@ -487,8 +517,15 @@ pub fn updategaem(ctx: &mut Context, msg: &Message, mut args: Args) -> Result<() play_time: u64, } - let games_owned = - reqwest::get(u)?.json::<SteamResp>()?.response.games.into_iter().map(|ge| ge.app_id).collect::<FnvHashSet<_>>(); + let games_owned = reqwest::get(u) + .await? + .json::<SteamResp>() + .await? + .response + .games + .into_iter() + .map(|ge| ge.app_id) + .collect::<FnvHashSet<_>>(); let found_games = missing_appids .filter_map(|(ai, x)| { @@ -501,7 +538,8 @@ pub fn updategaem(ctx: &mut Context, msg: &Message, mut args: Args) -> Result<() .join("\n"); if found_games.len() > 0 { - ctx.send( + util::send( + ctx, msg.channel_id, &format!( "{} games owned on steam that are missing from the list:\n{}", @@ -511,6 +549,6 @@ pub fn updategaem(ctx: &mut Context, msg: &Message, mut args: Args) -> Result<() msg.tts, ) } else { - ctx.send(msg.channel_id, "up to date", msg.tts) + util::send(ctx, msg.channel_id, "up to date", msg.tts) } } |
