Commit 9b5985aa authored by tec's avatar tec
Browse files

Merge branch 'master' into 'expired_member'

# Conflicts:
#   src/ldap.rs
parents 9b26653c 62de747a
Pipeline #242 failed with stages
/target/
Cargo.lock
**/*.rs.bk
src/discord_token
ucc-bot.log
This diff is collapsed.
......@@ -37,12 +37,6 @@ pub struct UccbotConfig {
pub bind_address: String,
}
#[derive(Debug, Deserialize)]
pub struct UccbotSecrets {
pub ldap_pass: String,
pub discord_token: String,
}
pub fn ldap_bind_address() -> String {
"ldaps://samson.ucc.asn.au:636".to_string()
}
......@@ -60,6 +54,12 @@ impl UccbotConfig {
}
}
#[derive(Debug, Deserialize)]
pub struct UccbotSecrets {
pub ldap_pass: String,
pub discord_token: String,
}
pub type ReactRoleMap = IndexMap<String, id::RoleId>;
#[derive(Debug, Deserialize, Clone)]
......
......@@ -29,6 +29,19 @@ react_role_messages:
🥤: 691852097003585577
cpu: 674255083063738368
🎮: 691852441091833896
🤖: 696241187035676763
📐: 696241431550885888
🧬: 696241817397624862
: 696241928492286044
🧮: 696242272844382209
💸: 696242320609378345
📚: 696257213068607518
🎨: 696242397407084614
: 696242439962230854
🌥️: 696242479527100506
: 696242521738838016
🌤: 696242572288589864
: 696242617301860403
- message: 674653030817464370 # Operating System
mapping:
win10: 674255085307691039
......@@ -47,6 +60,7 @@ react_role_messages:
atom_: 674255748426891274
intellij: 674255748959567901
npp: 674255750297812993
eclipse: 696281046924394526
- message: 674653069526695946 # Programming (1)
mapping:
html: 674255751031685130
......
......@@ -24,14 +24,14 @@ pub fn ldap_search(username: &str) -> Option<LDAPUser> {
.search(
"cn=Users,dc=ad,dc=ucc,dc=gu,dc=uwa,dc=edu,dc=au",
Scope::Subtree,
&format!("(cn={})", username),
&format!("(cn={})", ldap3::ldap_escape(username)),
vec!["when_created", "displayName", "name", "loginShell"],
)
.expect("LDAP error")
.success()
.expect("LDAP search error");
if rs.is_empty() {
return None;
return None
}
let result = SearchEntry::construct(rs[0].clone()).attrs;
Some(LDAPUser {
......
......@@ -31,6 +31,7 @@ mod reaction_roles;
mod token_management;
mod user_management;
mod voting;
use rand::seq::SliceRandom;
use config::{CONFIG, SECRETS};
use reaction_roles::{add_role_by_reaction, remove_role_by_reaction};
......@@ -38,6 +39,19 @@ use util::get_string_from_react;
struct Handler;
pub const MENTION_RESPONSES: &[&str] = &[
"Oh hello there",
"Stop bothering me. I'm busy.",
"You know, I'm trying to keep track of this place. I don't need any more distractions.",
"Don't you have better things to do?",
"(sigh) what now?",
"Yes, yes, I know I'm brilliant",
"What do I need to do to catch a break around here? Eh.",
"Mmmmhmmm. I'm still around, don't mind me.",
"You know, some people would consider this rude. Luckily I'm not one of those people. In fact, I'm not even a person.",
"Perhaps try bothering someone else for a change."
];
impl EventHandler for Handler {
// Set a handler for the `message` event - so that whenever a new message
// is received - the closure (or function) passed will be called.
......@@ -46,6 +60,18 @@ impl EventHandler for Handler {
// events can be dispatched simultaneously.
fn message(&self, ctx: Context, msg: Message) {
if !(msg.content.starts_with(&CONFIG.command_prefix)) {
if msg.content.contains(&format!("<@!{}>", CONFIG.bot_id)) // desktop mentions
|| msg.content.contains(&format!("<@{}>", CONFIG.bot_id))
// mobile mentions
{
send_message!(
msg.channel_id,
&ctx.http,
MENTION_RESPONSES
.choose(&mut rand::thread_rng())
.expect("We couldn't get any sass")
);
}
return;
}
let message_content: Vec<_> = msg.content[1..].splitn(2, ' ').collect();
......@@ -65,13 +91,14 @@ impl EventHandler for Handler {
"motion" => voting::Commands::motion(ctx, msg.clone(), content),
"poll" => voting::Commands::poll(ctx, msg.clone(), content),
"cowsay" => voting::Commands::cowsay(ctx, msg.clone(), content),
"logreact" => {
e!("Error deleting logreact prompt: {:?}", msg.delete(&ctx));
send_message!(
msg.channel_id,
&ctx.http,
"React to this to log the ID (for the next 5min)"
"source" => {
let mut mesg = MessageBuilder::new();
mesg.push(
"You want to look at my insides!? Eurgh.\nJust kidding, you can go over ",
);
mesg.push_italic("every inch");
mesg.push(" of me here: https://gitlab.ucc.asn.au/UCC/discord-bot 😉");
send_message!(msg.channel_id, &ctx.http, mesg.build());
}
"help" => {
// Plaintext version, keep in case IRC users kick up a fuss
......@@ -108,6 +135,14 @@ impl EventHandler for Handler {
}
}
// undocumented (in !help) functins
"logreact" => {
e!("Error deleting logreact prompt: {:?}", msg.delete(&ctx));
send_message!(
msg.channel_id,
&ctx.http,
"React to this to log the ID (for the next 5min)"
);
}
"ldap" => send_message!(
msg.channel_id,
&ctx.http,
......
......@@ -103,10 +103,19 @@ pub fn sync_all_role_reactions(ctx: &Context) {
" message #{}: Removing non-role react '{}'",
i, react_as_string
);
for _illegal_react in
&message.reaction_users(ctx, react.reaction_type.clone(), Some(100), None)
for illegal_react_user in &message
.reaction_users(&ctx.http, react.reaction_type.clone(), Some(100), None)
.unwrap_or(vec![])
{
warn!(" need to implement react removal");
message
.channel_id
.delete_reaction(
&ctx.http,
message.id,
Some(illegal_react_user.id),
react.reaction_type.clone(),
)
.expect("Unable to delete react");
}
}
for (react, role) in *mapping {
......
......@@ -75,7 +75,7 @@ pub fn parse_token(discord_user: &User, encrypted_token: &str) -> Result<String,
let token_username = token_components[2];
if token_discord_user != discord_user.id.0.to_string() {
warn!("... attempt failed : DiscordID mismatch");
return Err(TokenError::DiscordIdMismatch);
return Err(TokenError::DiscordIdMismatch)
}
let time_delta_seconds = Utc::now().timestamp() - token_timestamp.timestamp();
if time_delta_seconds > TOKEN_LIFETIME {
......@@ -83,7 +83,7 @@ pub fn parse_token(discord_user: &User, encrypted_token: &str) -> Result<String,
"... attempt failed : token expired ({} seconds old)",
time_delta_seconds
);
return Err(TokenError::TokenExpired);
return Err(TokenError::TokenExpired)
}
info!(
"... verification successful (token {} seconds old)",
......
......@@ -14,17 +14,18 @@ use crate::ldap::{ldap_exists, ldap_search};
use crate::token_management::*;
pub fn new_member(ctx: &Context, mut new_member: Member) {
// TODO see if it's an old (registered) user re-joining, and act accordingly
let mut message = MessageBuilder::new();
message.push("Nice to see you here ");
message.mention(&new_member);
message.push_line("! Would you care to introduce yourself?");
message.push_line("If you're not sure where to start, perhaps you could tell us about your projects, your first computer…");
message.push_line("You should also know that we follow the Freenode Channel Guidelines: https://freenode.net/changuide, and try to avoid defamatory content.");
message.push_line("Make sure to check out ");
message.push("Make sure to check out ");
message.mention(&CONFIG.readme_channel);
message.push_line(" to get yourself some roles for directed pings 😊, and ");
message.push(" to get yourself some roles for directed pings 😊, and ");
message.push_mono(format!("{}register username", CONFIG.command_prefix));
message.push_line(" to link to your UCC account.");
message.push(" to link to your UCC account.");
send_message!(CONFIG.welcome_channel, &ctx, message.build());
let mut message = MessageBuilder::new();
......@@ -230,16 +231,25 @@ impl Commands {
}
pub fn profile(ctx: Context, msg: Message, name: &str) {
let possible_member: Option<database::Member> = match if name.trim().is_empty() {
info!(
"{} (discord name) wants to look at their own profile",
&msg.author.name
);
database::get_member_info(&msg.author.id.0)
} else {
info!("Searching for a profile for {}", &name);
database::get_member_info_from_username(&name)
} {
Ok(member) => Some(member),
Err(why) => {
warn!("Could not find member {:?}", why);
warn!("Could not find member {}, {:?}", &name, why);
if name.len() != 3 {
None
} else {
info!(
"Searching for a profile for the TLA '{}'",
&name.to_uppercase()
);
match database::get_member_info_from_tla(&name.to_uppercase()) {
Ok(member) => Some(member),
Err(_) => None,
......@@ -256,6 +266,7 @@ impl Commands {
return;
}
let member = possible_member.unwrap();
info!("Found matching profile, UCC username: {}", &member.username);
let result = msg.channel_id.send_message(&ctx.http, |m| {
m.embed(|embed| {
embed.colour(serenity::utils::Colour::LIGHTER_GREY);
......@@ -267,7 +278,7 @@ impl Commands {
f.text(&user.name);
f.icon_url(
user.static_avatar_url()
.expect("Expected user to have avatar"),
.unwrap_or(String::from("https://www.ucc.asn.au/logos/ucc-logo.png")),
);
f
});
......
......@@ -15,7 +15,7 @@ impl Commands {
let motion = content;
if !motion.is_empty() {
create_motion(&ctx, &msg, motion);
return;
return
}
send_message!(
msg.channel_id,
......@@ -34,7 +34,7 @@ impl Commands {
let topic = content;
if !topic.is_empty() {
create_poll(&ctx, &msg, topic);
return;
return
}
send_message!(
msg.channel_id,
......@@ -193,7 +193,7 @@ fn get_cached_motion(ctx: &Context, msg: &Message) -> MotionInfo {
fn set_cached_motion(id: serenity::model::id::MessageId, motion_info: MotionInfo) {
if let Some(motion) = MOTIONS_CACHE.lock().unwrap().get_mut(&id) {
*motion = motion_info;
return;
return
}
warn!("{}", "Couldn't find motion in cache to set");
}
......@@ -208,7 +208,7 @@ macro_rules! tiebreaker {
} else {
0.0
}
};
}
}
fn update_motion(
......@@ -225,10 +225,8 @@ fn update_motion(
let abstain_votes = motion_info.votes.get(&CONFIG.abstain_vote).unwrap().len() as isize - 1;
let for_strength = for_votes as f32 + tiebreaker!(ctx, &CONFIG.for_vote, motion_info);
let against_strength =
against_votes as f32 + tiebreaker!(ctx, &CONFIG.against_vote, motion_info);
let abstain_strength =
abstain_votes as f32 + tiebreaker!(ctx, &CONFIG.abstain_vote, motion_info);
let against_strength = against_votes as f32 + tiebreaker!(ctx, &CONFIG.against_vote, motion_info);
let abstain_strength = abstain_votes as f32 + tiebreaker!(ctx, &CONFIG.abstain_vote, motion_info);
let old_embed = msg.embeds[0].clone();
let topic = old_embed.clone().title.unwrap();
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment