diff --git a/.gitignore b/.gitignore index 15bdd96..a9554ab 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /target /.idea *.iml +bot_token \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 1f87b7f..28c9562 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,12 +1,5 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -[[package]] -name = "DiscordBot" -version = "0.1.0" -dependencies = [ - "serenity", -] - [[package]] name = "adler" version = "0.2.3" @@ -14,10 +7,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e" [[package]] -name = "async-trait" -version = "0.1.42" +name = "ansi_term" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d3a45e77e34375a7923b1e8febb049bb011f064714a8e17a1a616fef01da13d" +checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +dependencies = [ + "winapi", +] + +[[package]] +name = "async-trait" +version = "0.1.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b98e84bbb4cbcdd97da190ba0c58a1bb0de2c1fdf67d159e192ed766aeca722" dependencies = [ "proc-macro2", "quote", @@ -40,6 +42,17 @@ dependencies = [ "webpki-roots 0.20.0", ] +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + [[package]] name = "autocfg" version = "1.0.1" @@ -124,10 +137,25 @@ dependencies = [ ] [[package]] -name = "command_attr" -version = "0.3.3" +name = "clap" +version = "2.33.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef54b146e4ff8a036b9d632fd48c183c9757992535e5f557275f4a01dfd9c7c7" +checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" +dependencies = [ + "ansi_term", + "atty", + "bitflags", + "strsim", + "textwrap", + "unicode-width", + "vec_map", +] + +[[package]] +name = "command_attr" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fe1f0b69fde68f40ea2ee6ca8db23bc40d2e593db884659a65d8486032cc65b" dependencies = [ "proc-macro2", "quote", @@ -325,6 +353,15 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" +[[package]] +name = "hermit-abi" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c" +dependencies = [ + "libc", +] + [[package]] name = "http" version = "0.2.3" @@ -427,6 +464,15 @@ dependencies = [ "bytes 0.5.6", ] +[[package]] +name = "instant" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec" +dependencies = [ + "cfg-if", +] + [[package]] name = "ipnet" version = "2.3.0" @@ -460,6 +506,15 @@ version = "0.2.85" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ccac4b00700875e6a07c6cde370d44d32fa01c5a65cdd2fca6858c479d28bb3" +[[package]] +name = "lock_api" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0382880606dff6d15c9476c416d18690b72742aa7b605bb6dd6ec9030fbf07eb" +dependencies = [ + "scopeguard", +] + [[package]] name = "log" version = "0.4.14" @@ -558,6 +613,16 @@ dependencies = [ "autocfg", ] +[[package]] +name = "num_cpus" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" +dependencies = [ + "hermit-abi", + "libc", +] + [[package]] name = "once_cell" version = "1.5.2" @@ -570,6 +635,37 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +[[package]] +name = "owo-colors" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2386b4ebe91c2f7f51082d4cefa145d030e33a1842a96b12e4885cc3c01f7a55" + +[[package]] +name = "parking_lot" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall", + "smallvec", + "winapi", +] + [[package]] name = "percent-encoding" version = "2.1.0" @@ -705,6 +801,15 @@ dependencies = [ "rand_core", ] +[[package]] +name = "redox_syscall" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85dd92e586f7355c633911e11f77f3d12f04b1b1bd76a198bd34ae3af8341ef2" +dependencies = [ + "bitflags", +] + [[package]] name = "reqwest" version = "0.11.0" @@ -776,6 +881,12 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + [[package]] name = "sct" version = "0.6.0" @@ -876,6 +987,12 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" +[[package]] +name = "smallvec" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" + [[package]] name = "socket2" version = "0.3.19" @@ -900,16 +1017,51 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] -name = "syn" -version = "1.0.60" +name = "strsim" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c700597eca8a5a762beb35753ef6b94df201c81cca676604f547495a0d7f0081" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" + +[[package]] +name = "syn" +version = "1.0.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6498a9efc342871f91cc2d0d694c674368b4ceb40f62b65a7a08c3792935e702" dependencies = [ "proc-macro2", "quote", "unicode-xid", ] +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "thiserror" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0f4a65597094d4483ddaed134f409b2cb7c1beccf25201a9f73c719254fa98e" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "time" version = "0.1.44" @@ -938,24 +1090,25 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.1.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6714d663090b6b0acb0fa85841c6d66233d150cdb2602c8f9b8abb03370beb3f" +checksum = "e8190d04c665ea9e6b6a0dc45523ade572c088d2e6566244c1122671dbf4ae3a" dependencies = [ "autocfg", "bytes 1.0.1", "libc", "memchr", "mio", + "num_cpus", "pin-project-lite", "tokio-macros", ] [[package]] name = "tokio-macros" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42517d2975ca3114b22a16192634e8241dc5cc1f130be194645970cc1c371494" +checksum = "caf7b11a536f46a809a8a9f0bb4237020f70ecbf115b842360afb127ea2fda57" dependencies = [ "proc-macro2", "quote", @@ -987,6 +1140,15 @@ dependencies = [ "tokio", ] +[[package]] +name = "toml" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" +dependencies = [ + "serde", +] + [[package]] name = "tower-service" version = "0.3.1" @@ -1099,6 +1261,12 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-width" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" + [[package]] name = "unicode-xid" version = "0.2.1" @@ -1135,6 +1303,24 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f4bf03e0ca70d626ecc4ba6b0763b934b6f2976e8c744088bb3c1d646fbb1ad0" +[[package]] +name = "uwuify" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3db6840b7adcfd2e866c79157cc890ecdbbc1f739607134039ae64eaa6c07e24" +dependencies = [ + "clap", + "owo-colors", + "parking_lot", + "thiserror", +] + +[[package]] +name = "vec_map" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" + [[package]] name = "version_check" version = "0.9.2" @@ -1269,6 +1455,18 @@ dependencies = [ "webpki", ] +[[package]] +name = "widertom" +version = "0.1.0" +dependencies = [ + "async-trait", + "lazy_static", + "serenity", + "tokio", + "toml", + "uwuify", +] + [[package]] name = "winapi" version = "0.3.9" diff --git a/Cargo.toml b/Cargo.toml index 2edd504..768d9ce 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "DiscordBot" +name = "widertom" version = "0.1.0" authors = ["Nilstrieb "] edition = "2018" @@ -7,4 +7,13 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -serenity = "0.10.2" \ No newline at end of file +tokio = { version = "1.0", features = ["macros", "rt-multi-thread"] } +uwuify = "^0.2" +async-trait = "0.1.50" +lazy_static = "1.4.0" +toml = "0.5.8" + +[dependencies.serenity] +version = "0.10.2" +default-features = false +features = ["client", "gateway", "rustls_backend", "model", "framework", "standard_framework", "cache", "http", "utils"] diff --git a/config.toml b/config.toml new file mode 100644 index 0000000..58a2a30 --- /dev/null +++ b/config.toml @@ -0,0 +1,8 @@ +emotes = [ + ["conny", 838137360667508786], + ["rene", 832636011917606912], + ["yuki", 820785209527631892], + ["nick", 816429590687776839], + ["nils", 816429379654516796], + ["tom", 811324632082415626], +] \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..25733a1 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,53 @@ +use std::collections::HashMap; +use std::fs; + +use lazy_static::lazy_static; +use serenity::client::Context; +use serenity::framework::standard::{macros::hook}; +use serenity::model::channel::{Message, ReactionType}; +use serenity::model::id::EmojiId; +use toml::Value; + +lazy_static! { + static ref REACTION_EMOTES: HashMap = { + let err = "Invalid config file"; + let mut m = HashMap::new(); + + let config = fs::read_to_string("config.toml").expect("Config file not found. Add 'config.toml' to this directory"); + let value = config.parse::().expect(err); + let emotes = value.get("emotes").expect(err); + + for v in emotes.as_array().expect(err) { + let name = v[0].as_str().expect(err).to_string(); + let id = EmojiId(v[1].as_integer().expect(err).clone() as u64); + m.insert(name, id); + } + m + }; +} + + +#[hook] +pub async fn normal_message(ctx: &Context, msg: &Message) { + if msg.content == "tom" { + reply(" <:tom:811324632082415626>", &msg, &ctx).await; + } + + for (name, id) in REACTION_EMOTES.iter() { + if msg.content.contains(name) { + if let Err(why) = msg.react(&ctx.http, ReactionType::Custom { + animated: false, + id: *id, + name: Some(name.to_string()), + }).await { + println!("Error reacting: {}", why); + } + } + } +} + +pub async fn reply(txt: &str, msg: &Message, ctx: &Context) { + if let Err(why) = msg.channel_id.say(&ctx.http, txt).await { + println!("Error sending message: {:?}", why); + } +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index e7a11a9..d37fba5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,132 @@ -fn main() { - println!("Hello, world!"); +use std::collections::HashSet; +use std::fs; + +use serenity::{ + async_trait, + model::{channel::Message, gateway::Ready}, + prelude::*, +}; +use serenity::client::Context; +use serenity::framework::standard::{Args, CommandGroup, CommandResult, help_commands, HelpOptions, macros::{command, group, help}, +}; +use serenity::framework::StandardFramework; +use serenity::http::Http; +use serenity::model::id::UserId; +use serenity::utils::{content_safe, ContentSafeOptions}; +use uwuifier::uwuify_str_sse; + +use widertom::normal_message; + +#[group] +#[commands(say)] +#[description = "General widetom commands"] +struct General; + +#[group] +#[commands(uwuify)] +#[description = "meme commands"] +struct Meme; + + +struct Handler; + +#[async_trait] +impl EventHandler for Handler { + async fn ready(&self, _: Context, ready: Ready) { + println!("{} is connected!", ready.user.name); + } +} + + +#[tokio::main] +async fn main() { + + let token = fs::read_to_string("bot_token") + .expect("Expected bot token in file 'bot_token'"); + + let http = Http::new_with_token(&token); + + let (owners, bot_id) = match http.get_current_application_info().await { + Ok(info) => { + let mut owners = HashSet::new(); + if let Some(team) = info.team { + owners.insert(team.owner_user_id); + } else { + owners.insert(info.owner.id); + } + match http.get_current_user().await { + Ok(bot_id) => (owners, bot_id.id), + Err(why) => panic!("Could not access the bot id: {:?}", why), + } + } + Err(why) => panic!("Could not access application info: {:?}", why), + }; + + let framework = StandardFramework::new() + .configure(|c| c + .with_whitespace(false) + .on_mention(Some(bot_id)) + .prefix("<:tom:811324632082415626> ") + .delimiter(" ") + .owners(owners) + ) + .normal_message(normal_message) + .help(&MY_HELP) + .group(&GENERAL_GROUP) + .group(&MEME_GROUP); + + let mut client = Client::builder(&token) + .event_handler(Handler) + .framework(framework) + .await + .expect("Err creating client"); + + if let Err(why) = client.start().await { + println!("Client error: {:?}", why); + } +} + +#[command] +async fn say(ctx: &Context, msg: &Message, args: Args) -> CommandResult { + let settings = if let Some(guild_id) = msg.guild_id { + ContentSafeOptions::default() + .clean_channel(false) + .display_as_member_from(guild_id) + } else { + ContentSafeOptions::default() + .clean_channel(false) + .clean_role(false) + }; + + let content = content_safe(&ctx.cache, &args.rest(), &settings).await; + msg.channel_id.say(&ctx.http, &content).await?; + Ok(()) +} + +#[command] +async fn uwuify(ctx: &Context, msg: &Message, args: Args) -> CommandResult { + let uwu = uwuify_str_sse(args.rest()); + msg.channel_id.say(&ctx.http, uwu).await?; + Ok(()) +} + + +#[help] +#[individual_command_tip = +"w i d e t o m\n\n\ +tom moment."] +#[command_not_found_text = "Could not find: `{}`."] +#[max_levenshtein_distance(3)] +#[strikethrough_commands_tip_in_dm = ""] +#[strikethrough_commands_tip_in_guild = ""] +pub async fn my_help( + context: &Context, + msg: &Message, + args: Args, + help_options: &'static HelpOptions, + groups: &[&'static CommandGroup], + owners: HashSet, +) -> CommandResult { + let _ = help_commands::with_embeds(context, msg, args, help_options, groups, owners).await; + Ok(()) }