|
|
@ -0,0 +1,175 @@
|
|
|
|
|
|
|
|
#![feature(test)]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
extern crate test;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
use std::collections::HashMap;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
use dotenv::dotenv;
|
|
|
|
|
|
|
|
use regex::Regex;
|
|
|
|
|
|
|
|
use lazy_static::lazy_static;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
use serenity::async_trait;
|
|
|
|
|
|
|
|
use serenity::framework::standard::macros::{command, group};
|
|
|
|
|
|
|
|
use serenity::model::channel::Message;
|
|
|
|
|
|
|
|
use serenity::model::gateway::Ready;
|
|
|
|
|
|
|
|
use serenity::prelude::*;
|
|
|
|
|
|
|
|
use serenity::framework::standard::{StandardFramework, CommandResult};
|
|
|
|
|
|
|
|
use serenity::utils::MessageBuilder;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const QUESTION_WORDS: &str = "when|wen|how|is|will|add|will|can|has";
|
|
|
|
|
|
|
|
const END_WORDS: &str = "\\?|when|wen|added";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Trying my best to not use lookaheads here :'(
|
|
|
|
|
|
|
|
lazy_static! {
|
|
|
|
|
|
|
|
static ref LEET_CHARS: HashMap<char, Vec<&'static str>> = {
|
|
|
|
|
|
|
|
let mut m = HashMap::new();
|
|
|
|
|
|
|
|
m.insert('A', vec!["@", "4", "/\\", "/-\\", "^", "(L", "Д", "Á", "Ă", "Ǎ", "Â", "Ä", "À", "Ā", "Ą", "Å", "Ꞻ", "Ⱥ", "Ã", "Ạ", "Α", "А"]);
|
|
|
|
|
|
|
|
m.insert('B', vec!["I3", "8", "13", "|3", "ß", "!3", "(3", "/3", ")3", "|-]", "j3", "Ꞗ", "Ɓ", "Ƀ", "Ƃ", "Β", "ʙ", "В", "в", "Ᏼ", "ᏼ", "ᗷ", "ᛒ", "ℬ", "ꓐ", "Ꞵ", "B", "𐊂", "𐊡", "𐌁", "𝐁", "𝐵", "𝑩", "𝓑", "𝔅", "𝔹", "𝕭", "𝖡", "𝗕", "𝘉", "𝘽", "𝙱", "𝚩", "𝛣", "𝜝", "𝝗", "𝞑"]);
|
|
|
|
|
|
|
|
m.insert('C', vec!["[", "¢", "<", "(", "©", "Ć", "Č", "Ç", "Ĉ", "ɕ", "Ċ", "Ƈ", "Ꞔ", "C̱", "Ȼ", "С", "Ϲ", "Ꮯ", "ᑕ", "ℂ", "ℭ", "Ⅽ", "⊂", "Ⲥ", "⸦", "ꓚ", "C", "𐊢", "𐌂", "𐐕", "𐔜", "𑣩", "𑣲", "𝐂", "𝐶", "𝑪", "𝒞", "𝓒", "𝕮", "𝖢", "𝗖", "𝘊", "𝘾", "𝙲", "🝌"]);
|
|
|
|
|
|
|
|
m.insert('D', vec![]);
|
|
|
|
|
|
|
|
m.insert('E', vec!["3", "Ε", "Ξ", "Σ"]);
|
|
|
|
|
|
|
|
m.insert('F', vec![]);
|
|
|
|
|
|
|
|
m.insert('G', vec![]);
|
|
|
|
|
|
|
|
m.insert('H', vec!["#", "/-/", "\\-\\", "[-]", "]-[", ")-(", "(-)", ":-:", "|~|", "|-|", "]~[", "}{", "!-!", "1-1", "\\-/", "I+I", "Һ", "ʜ", "Η", "Н", "н", "Ꮋ", "ᕼ", "ℋ", "ℌ", "ℍ", "Ⲏ", "ꓧ", "ꮋ", "H", "𐋏", "𝐇", "𝐻", "𝑯", "𝓗", "𝕳", "𝖧", "𝗛", "𝘏", "𝙃", "𝙷", "𝚮", "𝛨", "𝜢", "𝝜", "𝞖"]);
|
|
|
|
|
|
|
|
m.insert('I', vec!["!", "1", "|", "][", "eye", "Í", "Ĭ", "Î", "Ï", "Ï", "Ϊ", "Ì", "Ī", "Į", "Ꞽ", "Ɨ", "Ĩ", "Ị", "Ι", "І", "Ɩ", "ǀ", "Ӏ", "׀", "ا", "١", "۱", "ߊ", "ᛁ", "ℐ", "ℑ", "ℓ", "Ⅰ", "ⅼ", "∣", "⏽", "Ⲓ", "ⵏ", "ꓲ", "ﺍ", "ﺎ", "1", "I", "l", "│", "𐊊", "𐌉", "𐌠", "𖼨", "𝐈", "𝐥", "𝐼", "𝑙", "𝑰", "𝒍", "𝓁", "𝓘", "𝓵", "𝔩", "𝕀", "𝕝", "𝕴", "𝖑", "𝖨", "𝗅", "𝗜", "𝗹", "𝘐", "𝘭", "𝙄", "𝙡", "𝙸", "𝚕", "𝚰", "𝛪", "𝜤", "𝝞", "𝞘", "𝟏", "𝟙", "𝟣", "𝟭", "𝟷", "𞣇", "Ί"]);
|
|
|
|
|
|
|
|
m.insert('J', vec![]);
|
|
|
|
|
|
|
|
m.insert('K', vec!["|<", "Κ"]);
|
|
|
|
|
|
|
|
m.insert('L', vec!["£", "|_", "Ỻ", "Ɬ", "Ļ", "Ľ", "Ŀ", "ɭ", "Ɫ", "Ł", "ʟ", "Ꮮ", "ᒪ", "ℒ", "Ⳑ", "ⳑ", "ꓡ", "ꮮ", "𐐛", "𐑃", "𐔦", "𑢣", "𑢲", "𖼖", "𝈪", "𝐋", "𝐿", "𝑳", "𝓛", "𝔏", "𝕃", "𝕷", "𝖫", "𝗟", "𝘓", "𝙇", "𝙻"]);
|
|
|
|
|
|
|
|
m.insert('M', vec!["/\\/\\", "/V\\", "[V]", "|\\/|", "^^", "<\\/>", "{V}", "(V)", "|\\|\\", "]\\/[", "NN", "M̈", "Ṁ", "Ɱ", "M̃", "Μ", "Ϻ", "М", "Ꮇ", "ᗰ", "ᛖ", "ℳ", "Ⅿ", "Ⲙ", "ꓟ", "M", "𐊰", "𐌑", "𝐌", "𝑀", "𝑴", "𝓜", "𝔐", "𝕄", "𝕸", "𝖬", "𝗠", "𝘔", "𝙈", "𝙼", "𝚳", "𝛭", "𝜧", "𝝡", "𝞛"]);
|
|
|
|
|
|
|
|
m.insert('N', vec!["Ν", "Π"]);
|
|
|
|
|
|
|
|
m.insert('O', vec!["0", "()", "oh", "[]", "<>", "Ø", "Ó", "Ŏ", "Ô", "Ö", "Ő", "Ò", "Ơ", "Ō", "Ǫ", "Ɵ", "Õ", "Ọ", "Œ", "Ο", "Θ", "Φ", "Ω", "О", "Օ", "Ȯ", "Ỏ", "໐", "ဝ", "၀", "Ჿ", "ዐ", "ᴏ", "ᴑ", "ℴ", "Ⲟ", "Ⲟ", "ⵔ", "〇", "ꓳ", "0", "O", "O", "𐊒", "𐊫", "𐐄", "𐐄", "𐓂", "𐓂", "𐔖", "𑓐", "𑢵", "𑢷", "𑣠", "𝐎", "𝐨", "𝑂", "𝑜", "𝑶", "𝒐", "𝒪", "𝓞", "𝓸", "𝔒", "𝔬", "𝕆", "𝕠", "𝕺", "𝖔", "𝖮", "𝗈", "𝗢", "𝗼", "𝘖", "𝘰", "𝙊", "𝙤", "𝙾", "𝚘", "𝚶", "𝛐", "𝛔", "𝛰", "𝜊", "𝜎", "𝜪", "𝝄", "𝝈", "𝝤", "𝝾", "𝞂", "𝞞", "𝞸", "𝞼", "𝟎", "𝟘", "𝟢", "𝟬", "𝟶", "🯰", "Ό"]);
|
|
|
|
|
|
|
|
m.insert('U', vec!["(_)", "|_|", "v", "L|", "บ", "Ú", "Ŭ", "Û", "Ṳ", "Ü", "Ű", "Ù", "ʮ", "Ư", "Ū", "Ų", "Ů", "Ꞿ", "Ʉ", "ʯ", "Ũ", "Ụ"]);
|
|
|
|
|
|
|
|
m.insert('P', vec!["Ρ"]);
|
|
|
|
|
|
|
|
m.insert('Q', vec![]);
|
|
|
|
|
|
|
|
m.insert('R', vec!["I2", "9", "|`", "|~", "|?", "/2", "|^", "lz", "7", "2", "12", "®", "[z", "Я", "|2", "ꝶ", "Ŕ", "Ř", "ɾ", "Ɍ", "℞", "ꝵ", "Ꞧ", "Ɽ", "Ʀ", "ʀ", "Ꭱ", "Ꮢ", "ᖇ", "ᚱ", "ℛ", "ℜ", "ℝ", "ꓣ", "ꭱ", "ꮢ", "R", "𐒴", "𖼵", "𝈖", "𝐑", "𝑅", "𝑹", "𝓡", "𝕽", "𝖱", "𝗥", "𝘙", "𝙍", "𝚁"]);
|
|
|
|
|
|
|
|
m.insert('S', vec!["z"]);
|
|
|
|
|
|
|
|
m.insert('T', vec!["7", "Τ"]);
|
|
|
|
|
|
|
|
m.insert('V', vec![]);
|
|
|
|
|
|
|
|
m.insert('X', vec!["><", "}{", "ecks", "×", ")(", "][", "X̱", "cks", "Χ", "Х", "᙭", "ᚷ", "Ⅹ", "╳", "Ⲭ", "ⵝ", "ꓫ", "Ꭓ", "X", "𐊐", "𐊴", "𐌗", "𐌢", "𐔧", "𑣬", "𝐗", "𝑋", "𝑿", "𝒳", "𝓧", "𝔛", "𝕏", "𝖃", "𝖷", "𝗫", "𝘟", "𝙓", "𝚇", "𝚾", "𝛸", "𝜲", "𝝬", "𝞦"]);
|
|
|
|
|
|
|
|
return m;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[group]
|
|
|
|
|
|
|
|
#[commands(ping)]
|
|
|
|
|
|
|
|
struct General;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct Handler;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[async_trait]
|
|
|
|
|
|
|
|
impl EventHandler for Handler {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async fn message(&self, ctx: Context, msg: Message) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let mut message = String::from(&msg.content).to_uppercase();
|
|
|
|
|
|
|
|
message.retain(|c| !c.is_whitespace()); // Remove the whitespaces
|
|
|
|
|
|
|
|
message = translate_from_leet(message).to_lowercase(); // Transform as many l33t characters into normal english
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//println!("{}", message);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if message.contains("mochi") {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let case1 = "(".to_owned() + QUESTION_WORDS + ").*mochi.*(" + END_WORDS + "|)";
|
|
|
|
|
|
|
|
let case2 = "(".to_owned() + QUESTION_WORDS + ").*mochi";
|
|
|
|
|
|
|
|
let case3 = "^mochi.*(".to_owned() + END_WORDS + "|)";
|
|
|
|
|
|
|
|
let case4 = "^mochi$";
|
|
|
|
|
|
|
|
let regex = format!(r"{}|{}|{}|{}", case1, case2, case3, case4);
|
|
|
|
|
|
|
|
let re = Regex::new(®ex).unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if re.is_match(&message) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let reply = MessageBuilder::new()
|
|
|
|
|
|
|
|
.push("https://tenor.com/view/will-smith-chris-rock-jada-pinkett-smith-oscars2022-smack-gif-25234614 ")
|
|
|
|
|
|
|
|
.mention(&msg.author.mention())
|
|
|
|
|
|
|
|
.push_bold_safe(" N O")
|
|
|
|
|
|
|
|
.build();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if let Err(err) = msg.channel_id.say(ctx, reply).await {
|
|
|
|
|
|
|
|
println!("Error sending message: {:?}", err);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else if message.contains("roblox") {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if let Err(err) = msg.delete(ctx).await {
|
|
|
|
|
|
|
|
println!("Error sending message: {:?}", err);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async fn ready(&self, _: Context, ready: Ready) {
|
|
|
|
|
|
|
|
println!("{} is connected!", ready.user.name);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[tokio::main]
|
|
|
|
|
|
|
|
async fn main() {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Loading in the .env file that holds the environment variables
|
|
|
|
|
|
|
|
dotenv().ok();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Loading the discord token from the .env file
|
|
|
|
|
|
|
|
let token = dotenv::var("DISCORD_TOKEN").expect("Expected a Discord Token");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Setting up the intents
|
|
|
|
|
|
|
|
let intents =
|
|
|
|
|
|
|
|
GatewayIntents::GUILD_MESSAGES
|
|
|
|
|
|
|
|
| GatewayIntents::DIRECT_MESSAGES
|
|
|
|
|
|
|
|
| GatewayIntents::MESSAGE_CONTENT;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Setting up the framework for commands setting the prefix and groups assigned to it
|
|
|
|
|
|
|
|
let framework = StandardFramework::new()
|
|
|
|
|
|
|
|
.configure(|c| c
|
|
|
|
|
|
|
|
.with_whitespace(true)
|
|
|
|
|
|
|
|
.prefix("~")
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
//.group(&GENERAL_GROUP);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let mut client = Client::builder(token, intents)
|
|
|
|
|
|
|
|
.event_handler(Handler)
|
|
|
|
|
|
|
|
.framework(framework)
|
|
|
|
|
|
|
|
.await
|
|
|
|
|
|
|
|
.expect("Error creating the client");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if let Err(err) = client.start().await {
|
|
|
|
|
|
|
|
println!("Startup Error: {:?}", err);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn translate_from_leet(mut text: String) -> String {
|
|
|
|
|
|
|
|
for (key, leet) in LEET_CHARS.iter() {
|
|
|
|
|
|
|
|
for s in leet {
|
|
|
|
|
|
|
|
if !text.contains(s) {
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
text = text.replace(s, key.to_string().as_str());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
return text;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[command]
|
|
|
|
|
|
|
|
async fn ping(ctx: &Context, msg: &Message) -> CommandResult {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
msg.channel_id.say(&ctx.http, "Pong!").await.expect("Cannot send message!");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return Ok(());
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|
|
|
|
mod tests {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
use test::Bencher;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
|
|
|
fn translator_test() {
|
|
|
|
|
|
|
|
let res = translate_from_leet(String::from("m0<|-|!"));
|
|
|
|
|
|
|
|
assert_eq!(&res, "mochi");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
|
|
|
|
fn translator_bench(b: &mut Bencher) {
|
|
|
|
|
|
|
|
b.iter(|| translate_from_leet(String::from("m0<|-|!")));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|