diff options
| -rw-r--r-- | .envrc | 2 | ||||
| -rw-r--r-- | .gitignore | 2 | ||||
| -rw-r--r-- | flake.lock | 36 | ||||
| -rw-r--r-- | flake.nix | 20 | ||||
| -rw-r--r-- | src/game.rs | 169 |
5 files changed, 107 insertions, 122 deletions
@@ -1,3 +1,3 @@ watch_file flake.nix -eval "$(nix print-dev-env .#)" +eval "$(nix print-dev-env .# -L)" @@ -5,3 +5,5 @@ *.log user_id_mapping.json restrict.json +/result + @@ -17,7 +17,9 @@ }, "naersk": { "inputs": { - "nixpkgs": "nixpkgs" + "nixpkgs": [ + "nixpkgs" + ] }, "locked": { "lastModified": 1610977739, @@ -35,16 +37,18 @@ }, "nixpkgs": { "locked": { - "lastModified": 1609369662, - "narHash": "sha256-Nwk8WE4LEF+RxzVAYaitugYONyXYT7Grx9ndRHG+qFM=", - "owner": "NixOS", + "lastModified": 1611355196, + "narHash": "sha256-XVL+K2lPm/5cEx4Pe9mDyn7ok51YJK5gTjEVRnlpWFE=", + "owner": "nixos", "repo": "nixpkgs", - "rev": "ff97a25fc6da512edf8fb32cf27f001e0d7382c0", + "rev": "ce4a93e13a73a53028f9e86a8a8c7f21fbc93196", "type": "github" }, "original": { - "id": "nixpkgs", - "type": "indirect" + "owner": "nixos", + "ref": "release-20.09", + "repo": "nixpkgs", + "type": "github" } }, "nixpkgs-mozilla": { @@ -63,27 +67,11 @@ "type": "github" } }, - "nixpkgs_2": { - "locked": { - "lastModified": 1611387354, - "narHash": "sha256-pqJ2+zNh3qPPXX6dXYVmeEIH+GcjL7B9Z+EVQUZRPxg=", - "owner": "nixos", - "repo": "nixpkgs", - "rev": "4affc40a50dbabf2216176307a507b9225e01be7", - "type": "github" - }, - "original": { - "owner": "nixos", - "ref": "master", - "repo": "nixpkgs", - "type": "github" - } - }, "root": { "inputs": { "flake-utils": "flake-utils", "naersk": "naersk", - "nixpkgs": "nixpkgs_2", + "nixpkgs": "nixpkgs", "nixpkgs-mozilla": "nixpkgs-mozilla" } } @@ -1,6 +1,6 @@ { inputs = { - nixpkgs.url = "github:nixos/nixpkgs/master"; + nixpkgs.url = "github:nixos/nixpkgs/release-20.09"; flake-utils.url = "github:numtide/flake-utils"; nixpkgs-mozilla = { @@ -8,7 +8,10 @@ flake = false; }; - naersk.url = "github:nmattia/naersk"; + naersk = { + url = "github:nmattia/naersk"; + inputs.nixpkgs.follows = "nixpkgs"; + }; }; description = "thulani discord bot"; @@ -20,6 +23,10 @@ ... } @ inputs: (flake-utils.lib.eachDefaultSystem (system: let + barepkgs = import nixpkgs { + inherit system; + }; + pkgs = import nixpkgs { inherit system; @@ -37,6 +44,8 @@ in { cargo = rust; rustc = rust; + + naerskRust = rust; }) ]; }; @@ -67,7 +76,14 @@ buildInputs = (with pkgs; [ cargo rustc + + barepkgs.rustracer + # (rustracer.overrideAttrs (old: { + # dontCheck = true; + # })) ]) ++ deps; + + RUST_SRC_PATH = "${pkgs.naerskRust}/lib/rustlib/src/rust"; }; defaultPackage = pkg; diff --git a/src/game.rs b/src/game.rs index 626c7ff..3f78fe0 100644 --- a/src/game.rs +++ b/src/game.rs @@ -1,5 +1,6 @@ use std::{ convert::Infallible, + fs, iter, result::Result as StdResult, str::{ @@ -18,14 +19,15 @@ use log::{ error, info, }; -use serde::{ - Deserialize, -}; +use serde::Deserialize; use serenity::{ framework::standard::{ + macros::{ + command, + group, + }, ArgError, Args, - macros::{command, group}, }, model::{ channel::Message, @@ -43,8 +45,8 @@ use anyhow::{ use lazy_static::lazy_static; use crate::{ - Result, util::CtxExt, + Result, CONFIG, }; @@ -67,7 +69,8 @@ lazy_static! { static ref SPREADSHEET_URL: Url = Url::parse(&format!( "https://sheets.googleapis.com/v4/spreadsheets/{}/values:batchGet", &CONFIG.sheets.spreadsheet, - )).expect("parsing spreadsheet url"); + )) + .expect("parsing spreadsheet url"); } #[derive(Deserialize, Debug, Clone, PartialEq, Eq, Hash)] @@ -88,36 +91,35 @@ struct ProfileInfo { } lazy_static! { - static ref USER_MAP_STR: &'static str = str::from_utf8(&include_bytes!("../user_id_mapping.json")[..]).unwrap(); - + static ref USER_MAP_STR: String = fs::read_to_string("user_id_mapping.json").unwrap(); static ref USER_INFO_MAP: FnvHashMap<String, ProfileInfo> = { - let v: Vec<UserInfo> = serde_json::from_str(*USER_MAP_STR).unwrap(); + let v: Vec<UserInfo> = serde_json::from_str(&USER_MAP_STR).unwrap(); v.into_iter() .map(|ui| { - let UserInfo { name, profile } = ui; + let UserInfo { + name, + profile, + } = ui; (name, profile) }) .collect::<FnvHashMap<_, _>>() }; - static ref DISCORD_MAP: FnvHashMap<UserId, String> = { - USER_INFO_MAP.clone().into_iter() - .map(|(name, profile)| { - (UserId(profile.discord_user_id), name) - }) + USER_INFO_MAP + .clone() + .into_iter() + .map(|(name, profile)| (UserId(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)) - }) + USER_INFO_MAP + .clone() + .into_iter() + .filter_map(|(_, profile)| profile.steam_id.map(|sid| (UserId(profile.discord_user_id), sid))) .collect::<FnvHashMap<_, _>>() }; - static ref ALPHABET: Vec<char> = (0..26).map(|x| (x + b'a') as char).collect(); } @@ -180,9 +182,7 @@ pub fn get_user_id<S: AsRef<str>>(g: &Guild, s: S) -> StdResult<UserId, UserLook 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.user.read().name.to_lowercase() == s); if let Some(m) = exact_match { return Ok(m.user_id()); @@ -192,23 +192,19 @@ pub fn get_user_id<S: AsRef<str>>(g: &Guild, s: S) -> StdResult<UserId, UserLook 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.read().name.to_lowercase() == s); 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), 1 => Ok(opts.into_iter().next().unwrap()), - x => Err(UserLookupError::Ambiguous(x)) + x => Err(UserLookupError::Ambiguous(x)), } } @@ -219,16 +215,11 @@ fn game(ctx: &mut Context, msg: &Message, args: Args) -> Result<()> { } 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 = 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().guild(&ctx).ok_or(anyhow!("couldn't find guild"))?; - let guild = guild - .read(); + let guild = guild.read(); let user_args: Vec<String> = if args.rest().is_empty() { Vec::new() @@ -274,22 +265,19 @@ fn _game(ctx: &mut Context, msg: &Message, mut args: Args, min_status: GameStatu let pairs = guild .voice_states .iter() - .filter_map(|(uid, voice)| { - voice.channel_id.map(|cid| (*uid, cid)) - }) + .filter_map(|(uid, voice)| voice.channel_id.map(|cid| (*uid, cid))) .collect::<FnvHashMap<_, _>>(); - let channel = pairs - .get(&msg.author.id) - .cloned() - .unwrap_or(CONFIG.discord.voice_channel()); + let channel = pairs.get(&msg.author.id).cloned().unwrap_or(CONFIG.discord.voice_channel()); users = pairs .iter() .filter_map(|(uid, cid)| { if *cid == channel { DISCORD_MAP.get(uid).map(|s| s.to_lowercase()) - } else { None } + } else { + None + } }) .collect::<FnvHashSet<_>>(); } @@ -308,7 +296,9 @@ fn _game(ctx: &mut Context, msg: &Message, mut args: Args, min_status: GameStatu if users.contains(&user) { Some((user, i)) - } else { None } + } else { + None + } }) .collect::<FnvHashMap<_, _>>(); @@ -318,22 +308,21 @@ fn _game(ctx: &mut Context, msg: &Message, mut args: Args, min_status: GameStatu .map(|(user, col)| { let empty_hash_set: FnvHashSet<_> = vec![].into_iter().collect(); - let mut game_map = vec! [ + let mut game_map = vec![ (GameStatus::Installed, empty_hash_set.clone()), (GameStatus::NotInstalled, empty_hash_set.clone()), (GameStatus::NotOwned, empty_hash_set.clone()), (GameStatus::Unknown, empty_hash_set), ] - .into_iter() - .collect::<FnvHashMap<_, _>>(); + .into_iter() + .collect::<FnvHashMap<_, _>>(); - (1..data[*col].len()) - .for_each(|i| { - let status = &data_ref[*col][i].parse::<GameStatus>().unwrap_or(GameStatus::Unknown); - let game = &data_ref[0][i]; + (1..data[*col].len()).for_each(|i| { + 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); - }); + game_map.get_mut(status).unwrap().insert(game); + }); (user, game_map) }) @@ -349,24 +338,19 @@ fn _game(ctx: &mut Context, msg: &Message, mut args: Args, min_status: GameStatu statuses .iter() - .fold(iter::empty().collect::<FnvHashSet<_>>(), |acc, s| { - acc.union(&game_map[s]).cloned().collect() - }) + .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() - }); + .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(); } - let mut games_formatted = games_in_common.iter().sorted_by(|a, b| { - a.to_lowercase().cmp(&b.to_lowercase()) - }).join("\n"); + let mut games_formatted = + games_in_common.iter().sorted_by(|a, b| a.to_lowercase().cmp(&b.to_lowercase())).join("\n"); if games_formatted.is_empty() { games_formatted = "**LITERALLY NOTHING**".to_owned(); @@ -418,16 +402,11 @@ 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"))?; + let guild = guild.read().guild(&ctx).ok_or(anyhow!("couldn't find guild"))?; - let guild = guild - .read(); + let guild = guild.read(); get_user_id(guild.borrow(), arg_user.unwrap()).map_err(Error::from)? }; @@ -446,8 +425,7 @@ pub fn updategaem(ctx: &mut Context, msg: &Message, mut args: Args) -> Result<() let spreadsheet = load_spreadsheet()?; - 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..], @@ -458,23 +436,20 @@ pub fn updategaem(ctx: &mut Context, msg: &Message, mut args: Args) -> Result<() static ref APPID_REGEX: Regex = Regex::new(r#"(?i)^\s*app\s*id\s*$"#).unwrap(); } - let appid_column = (0..spreadsheet.len()) - .find(|x| APPID_REGEX.is_match(&spreadsheet[*x][0])); + let appid_column = (0..spreadsheet.len()).find(|x| APPID_REGEX.is_match(&spreadsheet[*x][0])); let appid_column = match appid_column { 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 ctx.send(msg.channel_id, "SPREADSHEET BROKE", msg.tts); }, }; 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")?; @@ -502,25 +477,29 @@ 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)?.json::<SteamResp>()?.response.games.into_iter().map(|ge| ge.app_id).collect::<FnvHashSet<_>>(); let found_games = missing_appids - .filter_map(|(ai, x)| if games_owned.contains(&ai) { - Some(&spreadsheet[0][x + 1]) - } else { - None + .filter_map(|(ai, x)| { + if games_owned.contains(&ai) { + Some(&spreadsheet[0][x + 1]) + } else { + None + } }) .join("\n"); if found_games.len() > 0 { - ctx.send(msg.channel_id, &format!("{} games owned on steam that are missing from the list:\n{}", - found_games.chars().filter(|x| *x == '\n').count() + 1, - found_games), msg.tts) + ctx.send( + msg.channel_id, + &format!( + "{} games owned on steam that are missing from the list:\n{}", + found_games.chars().filter(|x| *x == '\n').count() + 1, + found_games + ), + msg.tts, + ) } else { ctx.send(msg.channel_id, "up to date", msg.tts) } |
