diff --git a/Cargo.toml b/Cargo.toml index 1c8ee1ff0f5b797d2df45822587757ccd444344d..8b097e6749d173f1e0002afb4bceb7c523f43e84 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,13 +5,13 @@ authors = ["tec <tec@ucc.gu.uwa.edu.au>"] edition = "2018" [dependencies] +base64 = "^0.11" chrono = "^0.4.10" lazy_static = "^1.4.0" log = "^0.4.8" +openssl = "^0.10" rand = "^0.7.2" serde = "^1.0.104" serde_yaml = "^0.8" serenity = "0.8.0" simplelog = "^0.7.4" -openssl = "^0.10" -base64 = "^0.11" diff --git a/src/reaction_roles.rs b/src/reaction_roles.rs index 75c0e93457229664d60dc283be3b9e525155a1ee..6affc31e7c4d2604d53b7aef295e21a86c85c139 100644 --- a/src/reaction_roles.rs +++ b/src/reaction_roles.rs @@ -2,7 +2,7 @@ use crate::config::CONFIG; use crate::util::{get_react_from_string, get_string_from_react}; use serenity::{ client::Context, - model::{channel::Message, channel::Reaction, id::UserId, id::RoleId}, + model::{channel::Message, channel::Reaction, id::RoleId, id::UserId}, }; use std::collections::{HashMap, HashSet}; use std::iter::FromIterator; @@ -13,12 +13,25 @@ pub fn add_role_by_reaction(ctx: Context, msg: Message, added_reaction: Reaction .iter() .find(|rrm| rrm.message == msg.id) .and_then(|reaction_mapping| { - let react_as_string = get_string_from_react(added_reaction.emoji); + let react_as_string = get_string_from_react(added_reaction.clone().emoji); reaction_mapping.mapping.get(&react_as_string) }) .and_then(|role_id| { + info!( + "{} requested role {}", + added_reaction + .user_id + .to_user(&ctx) + .expect("Unable to get user") + .name, + role_id + ); ctx.http - .add_member_role(CONFIG.server_id, *msg.author.id.as_u64(), *role_id.as_u64()) + .add_member_role( + CONFIG.server_id, + added_reaction.user_id.0, + *role_id.as_u64(), + ) .ok() }); } @@ -29,19 +42,27 @@ pub fn remove_role_by_reaction(ctx: Context, msg: Message, removed_reaction: Rea .iter() .find(|rrm| rrm.message == msg.id) .and_then(|reaction_mapping| { - let react_as_string = get_string_from_react(removed_reaction.emoji); + let react_as_string = get_string_from_react(removed_reaction.clone().emoji); reaction_mapping.mapping.get(&react_as_string) }) .and_then(|role_id| { + info!("{} requested removal of role {}", msg.author.name, role_id); ctx.http - .remove_member_role(CONFIG.server_id, *msg.author.id.as_u64(), *role_id.as_u64()) + .remove_member_role( + CONFIG.server_id, + removed_reaction.user_id.0, + *role_id.as_u64(), + ) .ok() }); } pub fn sync_all_role_reactions(ctx: Context) { + info!("Syncing roles to reactions"); let messages_with_role_mappings = get_all_role_reaction_message(&ctx); + info!(" Sync: reaction messages fetched"); let guild = ctx.http.get_guild(CONFIG.server_id).unwrap(); + info!(" Sync: guild fetched"); // this method supports paging, but we probably don't need it since the server only has a couple of // hundred members. the Reaction.users() method can apparently only retrieve 100 users at once, but // this one seems to work fine when set to 1000 (I tried 10,000 but the api returned a 400) @@ -49,11 +70,17 @@ pub fn sync_all_role_reactions(ctx: Context) { .http .get_guild_members(CONFIG.server_id, Some(1000), None) .unwrap(); + info!(" Sync: all members fetched"); - let mut roles_to_add: HashMap<UserId, Vec<RoleId>> = HashMap::from_iter(all_members.iter().map(|m| (m.user_id(), Vec::new()))); - let mut roles_to_remove: HashMap<UserId, Vec<RoleId>> = HashMap::from_iter(all_members.iter().map(|m| (m.user_id(), Vec::new()))); + let mut roles_to_add: HashMap<UserId, Vec<RoleId>> = + HashMap::from_iter(all_members.iter().map(|m| (m.user_id(), Vec::new()))); + let mut roles_to_remove: HashMap<UserId, Vec<RoleId>> = + HashMap::from_iter(all_members.iter().map(|m| (m.user_id(), Vec::new()))); + let mut i = 0; for (message, mapping) in messages_with_role_mappings { + i += 1; + info!(" Sync: prossessing message #{}", i); for (react, role) in mapping { // the docs say this method can't retrieve more than 100 user reactions at a time, but it seems // to work fine when set to 255... @@ -71,24 +98,36 @@ pub fn sync_all_role_reactions(ctx: Context) { roles_to_add.get_mut(&user_id).unwrap().push(*role); } } else if member.roles.iter().any(|r| r == role) { - roles_to_remove.get_mut(&user_id).unwrap().push(*role); + roles_to_remove.get_mut(&user_id).unwrap().push(*role); } } } } + info!(" Sync: finished determing roles to add/remove"); for (user_id, roles) in roles_to_add { if !roles.is_empty() { - let mut member = all_members.iter().find(|m| m.user_id() == user_id).unwrap().clone(); + let mut member = all_members + .iter() + .find(|m| m.user_id() == user_id) + .unwrap() + .clone(); member.add_roles(ctx.http.clone(), &roles[..]).unwrap(); } } + info!(" Sync: (any) missing roles added"); for (user_id, roles) in roles_to_remove { if !roles.is_empty() { - let mut member = all_members.iter().find(|m| m.user_id() == user_id).unwrap().clone(); + let mut member = all_members + .iter() + .find(|m| m.user_id() == user_id) + .unwrap() + .clone(); member.remove_roles(ctx.http.clone(), &roles[..]).unwrap(); } } + info!(" Sync: (any) superflous roles removed"); + info!("Role reaction sync complete"); } fn get_all_role_reaction_message( @@ -98,7 +137,9 @@ fn get_all_role_reaction_message( &'static HashMap<String, serenity::model::id::RoleId>, )> { let guild = ctx.http.get_guild(CONFIG.server_id).unwrap(); + info!(" Find role-react message: guild determined"); let channels = ctx.http.get_channels(*guild.id.as_u64()).unwrap(); + info!(" Find role-react message: channels determined"); channels .iter() .flat_map(|channel| {