Initial commit

master
Wynd 2023-03-27 18:51:15 +03:00
commit 7bae2e8a4d
5 changed files with 225 additions and 0 deletions

17
.editorconfig 100644
View File

@ -0,0 +1,17 @@
# Editor configuration, see https://editorconfig.org
root = true
[*]
charset = utf-8
indent_style = tab
indent_size = 4
insert_final_newline = false
trim_trailing_whitespace = true
[*.md]
max_line_length = off
trim_trailing_whitespace = false
[*.yml]
indent_style = space
indent_size = 2

17
.gitignore vendored 100644
View File

@ -0,0 +1,17 @@
# Generated by Cargo
# will have compiled files and executables
debug/
target/
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
Cargo.lock
# These are backup files generated by rustfmt
**/*.rs.bk
# MSVC Windows builds of rustc generate these, which store debugging information
*.pdb
# Self explanatory really
.env

12
Cargo.toml 100644
View File

@ -0,0 +1,12 @@
[package]
name = "mochiless"
version = "0.1.0"
authors = ["Wynd"]
edition = "2021"
[dependencies]
tokio = { version = "1.18.1", features = ["macros", "rt-multi-thread"] }
serenity = { version = "0.11.1", default-features = false, features = ["client", "gateway", "rustls_backend", "model", "framework", "standard_framework"] }
dotenv = { version = "0.15.0" }
regex = { version = "1.5.5" }
lazy_static = { version = "1.4.0" }

4
rustfmt.toml 100644
View File

@ -0,0 +1,4 @@
unstable_features = true
reorder_imports = true
brace_style = "AlwaysNextLine"
max_width = 80

175
src/main.rs 100644
View File

@ -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", "", "Ɓ", "Ƀ‎", "Ƃ‎", "Β", "ʙ", "В", "в", "", "", "", "", "", "", "", "", "𐊂", "𐊡", "𐌁", "𝐁", "𝐵", "𝑩", "𝓑", "𝔅", "𝔹", "𝕭", "𝖡", "𝗕", "𝘉", "𝘽", "𝙱", "𝚩", "𝛣", "𝜝", "𝝗", "𝞑"]);
m.insert('C', vec!["[", "¢", "<", "(", "©", "Ć‎", "Č", "Ç", "Ĉ‎", "ɕ‎", "Ċ‎", "Ƈ‎", "Ꞔ‎", "", "Ȼ", "С", "Ϲ", "", "", "", "", "", "", "", "", "", "", "𐊢", "𐌂", "𐐕", "𐔜", "𑣩", "𑣲", "𝐂", "𝐶", "𝑪", "𝒞", "𝓒", "𝕮", "𝖢", "𝗖", "𝘊", "𝘾", "𝙲", "🝌"]);
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", "Һ", "ʜ", "Η", "Н", "н", "", "", "", "", "", "", "", "", "", "𐋏", "𝐇", "𝐻", "𝑯", "𝓗", "𝕳", "𝖧", "𝗛", "𝘏", "𝙃", "𝙷", "𝚮", "𝛨", "𝜢", "𝝜", "𝞖"]);
m.insert('I', vec!["!", "1", "|", "][", "eye", "Í", "Ĭ", "Î‎", "Ï‎", "Ï", "Ϊ", "Ì‎", "Ī", "Į", "", "Ɨ‎", "Ĩ‎", "Ị‎", "Ι", "І", "Ɩ", "ǀ", "Ӏ", "׀", "ا", "١", "۱", "ߊ", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "𐊊", "𐌉", "𐌠", "𖼨", "𝐈", "𝐥", "𝐼", "𝑙", "𝑰", "𝒍", "𝓁", "𝓘", "𝓵", "𝔩", "𝕀", "𝕝", "𝕴", "𝖑", "𝖨", "𝗅", "𝗜", "𝗹", "𝘐", "𝘭", "𝙄", "𝙡", "𝙸", "𝚕", "𝚰", "𝛪", "𝜤", "𝝞", "𝞘", "𝟏", "𝟙", "𝟣", "𝟭", "𝟷", "𞣇", "Ί"]);
m.insert('J', vec![]);
m.insert('K', vec!["|<", "Κ"]);
m.insert('L', vec!["£", "|_", "Ỻ‎", "", "Ļ", "Ľ", "Ŀ", "ɭ", "", "Ł‎", "ʟ", "", "", "", "", "", "", "", "𐐛", "𐑃", "𐔦", "𑢣", "𑢲", "𖼖", "𝈪", "𝐋", "𝐿", "𝑳", "𝓛", "𝔏", "𝕃", "𝕷", "𝖫", "𝗟", "𝘓", "𝙇", "𝙻"]);
m.insert('M', vec!["/\\/\\", "/V\\", "[V]", "|\\/|", "^^", "<\\/>", "{V}", "(V)", "|\\|\\", "]\\/[", "NN", "", "Ṁ‎", "", "", "Μ", "Ϻ", "М", "", "", "", "", "", "", "", "", "𐊰", "𐌑", "𝐌", "𝑀", "𝑴", "𝓜", "𝔐", "𝕄", "𝕸", "𝖬", "𝗠", "𝘔", "𝙈", "𝙼", "𝚳", "𝛭", "𝜧", "𝝡", "𝞛"]);
m.insert('N', vec!["Ν", "Π"]);
m.insert('O', vec!["0", "()", "oh", "[]", "<>", "Ø", "Ó", "Ŏ", "Ô‎", "Ö", "Ő‎", "Ò", "Ơ", "Ō", "Ǫ", "Ɵ", "Õ", "", "Œ", "Ο", "Θ", "Φ", "Ω", "О", "Օ", "Ȯ", "", "", "", "", "Ჿ", "", "", "", "", "", "", "", "", "", "", "", "", "𐊒", "𐊫", "𐐄", "𐐄", "𐓂", "𐓂", "𐔖", "𑓐", "𑢵", "𑢷", "𑣠", "𝐎", "𝐨", "𝑂", "𝑜", "𝑶", "𝒐", "𝒪", "𝓞", "𝓸", "𝔒", "𝔬", "𝕆", "𝕠", "𝕺", "𝖔", "𝖮", "𝗈", "𝗢", "𝗼", "𝘖", "𝘰", "𝙊", "𝙤", "𝙾", "𝚘", "𝚶", "𝛐", "𝛔", "𝛰", "𝜊", "𝜎", "𝜪", "𝝄", "𝝈", "𝝤", "𝝾", "𝞂", "𝞞", "𝞸", "𝞼", "𝟎", "𝟘", "𝟢", "𝟬", "𝟶", "🯰", "Ό"]);
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", "ꝶ‎", "Ŕ", "Ř‎", "ɾ", "Ɍ", "", "ꝵ‎", "", "", "Ʀ", "ʀ", "", "", "", "", "", "", "", "", "", "", "", "𐒴", "𖼵", "𝈖", "𝐑", "𝑅", "𝑹", "𝓡", "𝕽", "𝖱", "𝗥", "𝘙", "𝙍", "𝚁"]);
m.insert('S', vec!["z"]);
m.insert('T', vec!["7", "Τ"]);
m.insert('V', vec![]);
m.insert('X', vec!["><", "}{", "ecks", "×", ")(", "][", "", "cks", "Χ", "Х", "", "", "", "", "", "", "", "", "", "𐊐", "𐊴", "𐌗", "𐌢", "𐔧", "𑣬", "𝐗", "𝑋", "𝑿", "𝒳", "𝓧", "𝔛", "𝕏", "𝖃", "𝖷", "𝗫", "𝘟", "𝙓", "𝚇", "𝚾", "𝛸", "𝜲", "𝝬", "𝞦"]);
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(&regex).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<|-|!")));
}
}