diff --git a/src/handle_events.rs b/src/handle_events.rs index 283acb4..97f4abe 100644 --- a/src/handle_events.rs +++ b/src/handle_events.rs @@ -39,7 +39,7 @@ impl EventHandler for Handler { } async fn ready(&self, _ctx: Context, ready: Ready) { - info!(target: "Wordy", "{} is connected!", ready.user.name); + info!(target: "wordy", "{} is connected!", ready.user.name); } async fn guild_create(&self, ctx: Context, guild: Guild, _is_new: bool) { @@ -49,6 +49,7 @@ impl EventHandler for Handler { async fn message(&self, _ctx: Context, message: Message) { if let Some(guild_id) = message.guild_id { + trace!(target: "wordy", "Read a new message from {}", message.author.name); self.message(guild_id, message.channel_id, message.author.id, message.content); } } diff --git a/src/handler.rs b/src/handler.rs index 75cf99b..1b794ce 100644 --- a/src/handler.rs +++ b/src/handler.rs @@ -12,19 +12,22 @@ use serenity::{ application_command::ApplicationCommandInteraction, InteractionResponseType::ChannelMessageWithSource, }, - id::GuildId, prelude::{UserId, ChannelId, Guild}, Timestamp + id::GuildId, prelude::{UserId, ChannelId, Guild, Channel}, Timestamp }, prelude::*, utils::Color }; use futures::future::join_all; use lazy_static::lazy_static; use wordcloud_rs::{Token, WordCloud, Colors}; -use crate::{idiom::{Idioms, tokenize, self}, discord_emojis::DiscordEmojis, handler_util::read_past}; +use crate::{idiom::{Idioms, tokenize}, discord_emojis::DiscordEmojis, handler_util::read_past}; const READ_PAST: u64 = 1000; const DAYS: i64 = 100; lazy_static! { static ref RE_EMO: Regex = Regex::new(r"").unwrap(); + static ref RE_TAG: Regex = Regex::new(r"<@(\d*)>").unwrap(); + static ref RE_CHAN: Regex = Regex::new(r"<#(\d*)>").unwrap(); + static ref RE_ROLE: Regex = Regex::new(r"<@&(\d*)>").unwrap(); } fn convert_color(color: Color) -> Rgb { @@ -52,20 +55,36 @@ impl Handler { if let Some(mut idiom) = self.idioms.get_mut(&guild_id) { idiom.update(channel_id, member_id, tokenize(message)); } else { - warn!(target: "Wordy", "Guild {} isn't registered yet.", guild_id); + warn!(target: "wordy", "Guild {} isn't registered yet.", guild_id); } } - async fn to_wc_tokens(&self, tokens: Vec<(String, f32)>) -> Vec<(Token, f32)> { + async fn to_wc_tokens( + &self, tokens: Vec<(String, f32)>, http: &Arc + ) -> Vec<(Token, f32)> { join_all(tokens.into_iter().map(|(str, v)| async move { if let Some(capts) = RE_EMO.captures(&str) { - let id = capts.get(2).unwrap().as_str(); - if let Ok(img) = self.emojis.get(id).await { + let emo_id = capts.get(2).unwrap().as_str(); + if let Ok(img) = self.emojis.get(emo_id).await { (Token::Img(img), v) } else { let name = capts.get(1).unwrap().as_str(); (Token::Text(name.to_string()), v) } + } else if let Some(capts) = RE_TAG.captures(&str) { + let user_id = capts.get(1).unwrap().as_str().parse().unwrap(); + if let Ok(member) = http.get_user(user_id).await { + (Token::Text(format!("@{}", member.name)), v) + } else { + (Token::Text("@deleted_user".to_string()), v) + } + } else if let Some(capts) = RE_CHAN.captures(&str) { + let chan_id = capts.get(1).unwrap().as_str().parse().unwrap(); + match http.get_channel(chan_id).await { + Ok(Channel::Guild(channel)) => (Token::Text(format!("#{}", channel.name)), v), + Ok(Channel::Category(channel)) => (Token::Text(format!("#{}", channel.name)), v), + _ => (Token::Text("#deleted_channel".to_string()), v) + } } else { (Token::Text(str), v) } @@ -78,8 +97,8 @@ impl Handler { if let Some(guild_id) = command.guild_id { let member_id = member.user.id; let tokens = self.idioms.get(&guild_id).unwrap().idiom(member_id); - trace!(target: "Wordy", "/cloud: retrieved {} tokens for {}", tokens.len(), member.user.name); - let wc_tokens = self.to_wc_tokens(tokens).await; + trace!(target: "wordy", "/cloud: retrieved {} tokens for {}", tokens.len(), member.user.name); + let wc_tokens = self.to_wc_tokens(tokens, &ctx.http).await; let image = WordCloud::new() .colors(Colors::DoubleSplitCompl(convert_color(color))).generate(wc_tokens); let mut img_file = Cursor::new(Vec::new()); @@ -108,13 +127,13 @@ impl Handler { }) .await { - warn!(target: "Wordy", "/cloud: Response failed with `{}`", why); + warn!(target: "wordy", "/cloud: Response failed with `{}`", why); }; } else { - warn!(target: "Wordy", "/cloud: Couldn't get guild"); + warn!(target: "wordy", "/cloud: Couldn't get guild"); } } else { - warn!(target: "Wordy", "/cloud: Couldn't get member"); + warn!(target: "wordy", "/cloud: Couldn't get member"); } } @@ -129,7 +148,7 @@ impl Handler { ).unwrap(); if let Ok(channels) = guild.channels(&http).await { if !self.idioms.contains_key(&guild.id) { - info!(target: "Wordy", "Registering {} (id {})", guild.name, guild.id); + info!(target: "wordy", "Registering {} (id {})", guild.name, guild.id); self.idioms.insert(guild.id, Idioms::new()); let http = Arc::clone(&http); let idioms = Arc::clone(&self.idioms); @@ -143,7 +162,7 @@ impl Handler { ); } if len > 0 { - info!(target: "Wordy", "Read {} past messages in {}/{}", len, guild.name, channel.name()) + info!(target: "wordy", "Read {} past messages in {}/{}", len, guild.name, channel.name()) } } }); diff --git a/src/idiom/idiom.rs b/src/idiom/idiom.rs index 2517bce..79beabc 100644 --- a/src/idiom/idiom.rs +++ b/src/idiom/idiom.rs @@ -38,7 +38,7 @@ impl Idioms { } }; place_voc.add(idx, value); - let inctx_value = (-place_voc.get(&idx)).exp()*100.; + let inctx_value = (-place_voc.get(&idx)).exp()*50.; user_voc.add(idx, inctx_value); } } diff --git a/src/main.rs b/src/main.rs index f0ed510..a33c5e6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -19,11 +19,11 @@ fn get_token(name: &str) -> Option { if let Ok(token) = env::var(name) { Some(token) } else { - warn!(target: "Wordy", "Couldn't find the 'WORDY_TOKEN' environment variable, using token.txt as fallback"); + warn!(target: "wordy", "Couldn't find the 'WORDY_TOKEN' environment variable, using token.txt as fallback"); if let Ok(content) = read_to_string("token.txt") { Some(content) } else { - warn!(target: "Wordy", "Couldn't access token.txt"); + warn!(target: "wordy", "Couldn't access token.txt"); None } } @@ -31,7 +31,10 @@ fn get_token(name: &str) -> Option { #[tokio::main] async fn main() { - env_logger::builder().filter_module("Wordy", LevelFilter::Trace).init(); + env_logger::builder() + .filter_module("wordy", LevelFilter::Trace) + .filter_module("wordcloud", LevelFilter::Warn) + .init(); // Configure the client with your Discord bot token in the environment. let token = get_token("WORDY_TOKEN").unwrap(); let http = Http::new(&token); @@ -57,6 +60,6 @@ async fn main() { // Shards will automatically attempt to reconnect, and will perform // exponential backoff until it reconnects. if let Err(why) = client.start().await { - error!(target: "Wordy", "Client error: {:?}", why); + error!(target: "wordy", "Client error: {:?}", why); } }