diff --git a/Cargo.lock b/Cargo.lock index b60c552..fd07f14 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -107,6 +107,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" + [[package]] name = "block-buffer" version = "0.10.4" @@ -295,6 +301,29 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "env_logger" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" +dependencies = [ + "humantime", + "is-terminal", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "errno" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860" +dependencies = [ + "libc", + "windows-sys", +] + [[package]] name = "flate2" version = "1.0.28" @@ -495,6 +524,12 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + [[package]] name = "hyper" version = "0.14.27" @@ -588,6 +623,17 @@ version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" +[[package]] +name = "is-terminal" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +dependencies = [ + "hermit-abi", + "rustix", + "windows-sys", +] + [[package]] name = "itoa" version = "1.0.9" @@ -609,6 +655,12 @@ version = "0.2.149" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" +[[package]] +name = "linux-raw-sys" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f" + [[package]] name = "lock_api" version = "0.4.11" @@ -848,7 +900,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -958,6 +1010,19 @@ version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +[[package]] +name = "rustix" +version = "0.38.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67ce50cb2e16c2903e30d1cbccfd8387a74b9d4c938b6a4c5ec6cc7556f7a8a0" +dependencies = [ + "bitflags 2.4.1", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + [[package]] name = "rustls" version = "0.20.9" @@ -1091,7 +1156,7 @@ dependencies = [ "async-trait", "async-tungstenite", "base64 0.13.1", - "bitflags", + "bitflags 1.3.2", "bytes", "cfg-if", "chrono", @@ -1206,7 +1271,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" dependencies = [ - "bitflags", + "bitflags 1.3.2", "core-foundation", "system-configuration-sys", ] @@ -1221,6 +1286,15 @@ dependencies = [ "libc", ] +[[package]] +name = "termcolor" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64" +dependencies = [ + "winapi-util", +] + [[package]] name = "thiserror" version = "1.0.50" @@ -1636,6 +1710,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +dependencies = [ + "winapi", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -1731,6 +1814,7 @@ dependencies = [ name = "zmp-bot" version = "0.1.0" dependencies = [ + "env_logger", "poise", "serenity", "tokio", diff --git a/Cargo.toml b/Cargo.toml index 8b88ea4..5a16145 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,3 +9,4 @@ edition = "2021" poise = "0.5.6" serenity = { version = "0.11.6", default-features = false, features = ["client", "gateway", "model", "rustls_backend", "utils"]} tokio = { version = "1.21.2", features = ["macros", "rt-multi-thread"] } +env_logger = "0.10.0" diff --git a/src/commands/lfg.rs b/src/commands/lfg.rs new file mode 100644 index 0000000..e5af020 --- /dev/null +++ b/src/commands/lfg.rs @@ -0,0 +1,101 @@ +use crate::commands::lfg::Difficulty::Normal; +use crate::commands::lfg::Mode::Casual; +use crate::Context; +use crate::Error; +use serenity::model::id::RoleId; +use serenity::model::mention::Mention; +use serenity::model::mention::Mention::Role; +use serenity::prelude::Mentionable; +#[derive(Debug, poise::ChoiceParameter)] +pub enum Map { + #[name = "Dead End"] + DeadEnd, + #[name = "Bad Blood"] + BadBlood, + #[name = "Alien Arcadium"] + AlienArcadium, +} +#[derive(Debug, poise::ChoiceParameter)] +pub enum Mode { + #[name = "Casual"] + Casual, + #[name = "Speedrun"] + Speedrun, + #[name = "Challenge"] + Challenge, +} +#[derive(Debug, poise::ChoiceParameter)] +pub enum Difficulty { + #[name = "Normal"] + Normal, + #[name = "Hard"] + Hard, + #[name = "R.I.P."] + Rip, +} +#[poise::command(slash_command)] +pub(crate) async fn lfg( + ctx: Context<'_>, + #[rename = "map"] map: Map, + #[rename = "difficulty"] difficulty: Option, + + #[rename = "mode"] + #[description = "play-style"] + mode: Option, + + #[min = 1_u8] + #[max = 3_u8] + #[description = "default: 1"] + #[rename = "current"] + current_players: Option, + + #[min = 2_u8] + #[max = 4_u8] + #[description = "default: 4"] + #[rename = "desired"] + desired_players: Option, + + #[description = "optional extra message"] + #[rename = "message"] + note: Option, +) -> Result<(), Error> { + let current = current_players.unwrap_or(1); + let mut desired = desired_players.unwrap_or(4); + if current >= desired { + desired = 4 + } + let ping: Mention; + match mode.unwrap_or(Casual) { + Casual => match map { + Map::DeadEnd => ping = Role(RoleId(1005837123921915914)), + Map::BadBlood => ping = Role(RoleId(1140190470698438666)), + Map::AlienArcadium => ping = Role(RoleId(1105917281898336356)), + }, + Mode::Speedrun => ping = Role(RoleId(1005836989595144243)), + Mode::Challenge => ping = Role(RoleId(1005836864680361994)), + } + + let mut reply = format!( + "{} is looking for {}\n{}/{} {} {}", + ctx.author().mention(), + ping, + current, + desired, + map.name(), + difficulty.unwrap_or(Normal).name() + ); + if note.is_some() { + reply.push_str(format!("\nNote: {}", note.unwrap()).as_str()) + } + + if let Err(why) = ctx + .send(|m| { + m.content(reply) + .allowed_mentions(|am| am.parse(serenity::builder::ParseValue::Roles)) + }) + .await + { + println!("Error sending message: {:?}", why) + } + Ok(()) +} diff --git a/src/commands/mod.rs b/src/commands/mod.rs new file mode 100644 index 0000000..46e8194 --- /dev/null +++ b/src/commands/mod.rs @@ -0,0 +1 @@ +pub(crate) mod lfg; diff --git a/src/main.rs b/src/main.rs index 7138e73..c7c7950 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,54 +1,52 @@ -use std::env; +mod commands; -use serenity::{ - async_trait, - model::{ - channel::Message, - gateway::Ready - }, - prelude::* -}; +use std::collections::HashSet; +use std::convert::Into; +use poise::serenity_prelude as serenity; +use serenity::model::id::UserId; -struct Handler; - -#[async_trait] -impl EventHandler for Handler { - - async fn message(&self, ctx: Context, msg: Message) { - if msg.content == "!ping" { - let pong = msg.channel_id.say(&ctx, "Pong!").await; - if let Err(why) = pong { - println!("Error sending message: {:?}", why); - } - - let dm = msg.author.dm(&ctx,|m| m.content(" ")).await; - if let Err(why) = dm { - println!("t {:?}", why) - } - } - } - async fn ready(&self, _: Context, ready: Ready) { - println!("{} is connected!", ready.user.name); - } -} +type Error = Box; +type Context<'a> = poise::Context<'a, Data, Error>; +// User data, which is stored and accessible in all command invocations +pub struct Data {} #[tokio::main] async fn main() { - // Configure the client with your Discord bot token in the environment. - let token = env::var("DISCORD_TOKEN").expect("Expected a token in the environment"); + let mut owners = HashSet::new(); + owners.insert(UserId(449579075531440128_u64)); + let framework = poise::Framework::builder() + .options(poise::FrameworkOptions { + commands: vec![commands::lfg::lfg()], + prefix_options: poise::PrefixFrameworkOptions { + prefix: Some("~".into()), + ..Default::default() + }, + on_error: |error| { + Box::pin(async move { + match error { + poise::FrameworkError::ArgumentParse { error, .. } => { + if let Some(error) = error.downcast_ref::() { + println!("Found a RoleParseError: {:?}", error); + } else { + println!("Not a RoleParseError :("); + } + } + other => poise::builtins::on_error(other).await.unwrap(), + } + }) + },owners, + ..Default::default() + }) + .token(std::env::var("DISCORD_TOKEN").unwrap()) + .intents( + serenity::GatewayIntents::non_privileged() | serenity::GatewayIntents::MESSAGE_CONTENT, + ) + .setup(move |ctx, _ready, framework| { + Box::pin(async move { + poise::builtins::register_globally(ctx, &framework.options().commands).await?; + Ok(Data {}) + }) + }); - // Set gateway intents, which decides what events the bot will be notified about - let intents = GatewayIntents::GUILD_MESSAGES - | GatewayIntents::DIRECT_MESSAGES - | GatewayIntents::MESSAGE_CONTENT - | GatewayIntents::GUILD_MEMBERS; - - - - - - let mut client: Client = Client::builder(&token, intents).event_handler(Handler).await.expect("Err creating client"); - if let Err(why) = client.start().await { - println!("Client error: {:?}", why); - } -} \ No newline at end of file + framework.run().await.unwrap(); +}