diff --git a/Cargo.lock b/Cargo.lock index dc0cfec..aca3b89 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,6 +8,15 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "aho-corasick" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +dependencies = [ + "memchr", +] + [[package]] name = "anyhow" version = "1.0.52" @@ -173,6 +182,8 @@ version = "0.1.0" dependencies = [ "anyhow", "irc", + "lazy_static", + "regex", "serde", "serenity", "tokio", @@ -974,6 +985,23 @@ dependencies = [ "bitflags", ] +[[package]] +name = "regex" +version = "1.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" + [[package]] name = "remove_dir_all" version = "0.5.3" diff --git a/Cargo.toml b/Cargo.toml index bd28cc6..09cf20d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,8 @@ anyhow = "1.0.52" irc = "0.15" toml = "0.5" serde = "1.0" +regex = "1.5.4" +lazy_static = "1.4" [dependencies.tokio] version = "1.15.0" @@ -18,4 +20,4 @@ features = ["full"] [dependencies.serenity] version = "0.10" default-features = false -features = ["builder", "cache", "client", "gateway", "model", "utils", "native_tls_backend"] \ No newline at end of file +features = ["builder", "cache", "client", "gateway", "model", "utils", "native_tls_backend"] diff --git a/src/main.rs b/src/main.rs index f240e39..41c9af1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,6 +20,9 @@ use irc::{ proto::Command, }; +use regex::Regex; +use lazy_static::lazy_static; + use serde::Deserialize; #[derive(Deserialize)] @@ -189,6 +192,11 @@ async fn irc_loop( members: Vec, ) -> anyhow::Result<()> { let mut avatar_cache: HashMap> = HashMap::new(); + let mut id_cache: HashMap> = HashMap::new(); + + lazy_static! { + static ref PING_NICK_1: Regex = Regex::new(r"^[\w+]+:").unwrap(); + } client.identify()?; let mut stream = client.stream()?; @@ -197,6 +205,31 @@ async fn irc_loop( print!("{}", orig_message); if let Command::PRIVMSG(_, ref message) = orig_message.command { let nickname = orig_message.source_nickname().unwrap(); + if PING_NICK_1.is_match(message) { + if let Some(mat) = PING_NICK_1.find(message) { + let slice = &message[mat.start()..mat.end() - 1]; + if id_cache.get(slice).is_none() { + let mut found = false; + for member in &members { + let nick = match &member.nick { + Some(s) => s.to_owned(), + None => member.user.name.clone() + }; + + if nick == slice { + found = true; + let id = member.user.id.0; + id_cache.insert(nickname.to_string(), Some(id)); + break; + } + } + + if !found { + id_cache.insert(nickname.to_string(), None); + } + } + } + } if let Some(ref webhook) = webhook { if avatar_cache.get(nickname).is_none() { let mut found = false; @@ -218,6 +251,8 @@ async fn irc_loop( avatar_cache.insert(nickname.to_string(), None); // user is not in the guild } } + + webhook .execute(&http, false, |w| { if let Some(cached) = avatar_cache.get(nickname) { @@ -225,15 +260,35 @@ async fn irc_loop( w.avatar_url(url); } } + if let Some(cached) = id_cache.get(nickname) { + if let &Some(id) = cached { + w.content(PING_NICK_1.replace(message, format!("<@{}>", id))); + } else { + w.content(message); + } + } else { + w.content(message); + } w.username(nickname); - w.content(message); w }) .await?; } else { - channel_id - .say(&http, format!("{}: {}", nickname, message)) - .await?; + if let Some(cached) = id_cache.get(nickname) { + if let &Some(id) = cached { + channel_id + .say(&http, format!("{}: {}", nickname, PING_NICK_1.replace(message, format!("<@{}>", id)))) + .await?; + } else { + channel_id + .say(&http, format!("{}: {}", nickname, message)) + .await?; + } + } else { + channel_id + .say(&http, format!("{}: {}", nickname, message)) + .await?; + } } } else if let Command::JOIN(_, _, _) = orig_message.command { let nickname = orig_message.source_nickname().unwrap();