refactor commands

This commit is contained in:
Stachelbeere1248 2024-05-23 17:34:14 +02:00
parent f315eaae3d
commit 2707bcce9c
Signed by: Stachelbeere1248
SSH key fingerprint: SHA256:IozEKdw2dB8TZxkpPdMxcWSoWTIMwoLaCcZJ1AJnY2o
7 changed files with 518 additions and 450 deletions

747
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -7,9 +7,9 @@ edition = "2021"
[dependencies] [dependencies]
poise = "0.6.1" poise = "0.6.1"
serenity = { version = "0.12.0", default-features = false, features = ["client", "gateway", "model", "rustls_backend", "utils", "framework"] } serenity = { version = "0.12.1", default-features = false, features = ["client", "gateway", "model", "rustls_backend", "utils", "framework"] }
tokio = { version = "1.21.2", features = ["macros", "rt-multi-thread", "rt"] } tokio = { version = "1.37.0", features = ["macros", "rt-multi-thread", "rt"] }
env_logger = "0.11.2" env_logger = "0.11.3"
anyhow = "1.0.75" anyhow = "1.0.86"
tracing = "0.1.40" tracing = "0.1.40"
regex = "1.10.2" regex = "1.10.4"

View file

@ -1,17 +1,16 @@
use crate::commands::{command_helper, helpstart};
use crate::{Context, Error};
use std::string::String; use std::string::String;
#[poise::command(slash_command, guild_only)] use crate::{Context, Error};
use crate::commands::command_helper;
#[poise::command(slash_command, guild_only, owners_only)]
pub(crate) async fn bots( pub(crate) async fn bots(
ctx: Context<'_>, ctx: Context<'_>,
#[min = 0_u8] #[min = 0_u8]
#[description = "default: 0"] #[description = "default: 0"]
bots: u8, bots: u8,
) -> Result<(), Error> { ) -> Result<(), Error> {
helpstart::set_bots_available(bots).await; *ctx.data().bots.write().await = bots;
let reply = format!("{} bots are now registered as available", bots).to_string(); let reply = format!("{} bots are now registered as available", bots).to_string();
command_helper::send(ctx, reply).await command_helper::send_simple(ctx, reply).await
} }

View file

@ -1,8 +1,8 @@
use crate::{Context, Error};
use serenity::all::CreateAllowedMentions;
use std::time::Duration; use std::time::Duration;
pub(crate) async fn send(ctx: Context<'_>, reply: String) -> Result<(), Error> { use crate::{Context, Error};
pub(crate) async fn send_simple(ctx: Context<'_>, reply: String) -> Result<(), Error> {
if let Err(why) = ctx if let Err(why) = ctx
.send(poise::CreateReply { .send(poise::CreateReply {
content: Some(reply), content: Some(reply),
@ -10,7 +10,7 @@ pub(crate) async fn send(ctx: Context<'_>, reply: String) -> Result<(), Error> {
attachments: vec![], attachments: vec![],
ephemeral: None, ephemeral: None,
components: None, components: None,
allowed_mentions: Some(CreateAllowedMentions::new().all_roles(true)), allowed_mentions: None,
reply: false, reply: false,
__non_exhaustive: (), __non_exhaustive: (),
}) })
@ -21,7 +21,7 @@ pub(crate) async fn send(ctx: Context<'_>, reply: String) -> Result<(), Error> {
Ok(()) Ok(())
} }
pub(crate) fn cooldown(ctx: &Context, user: u64, global: u64) -> Option<Result<(), Error>> { pub(crate) fn cooldown(ctx: &Context, user: u64, global: u64) -> Result<(), Error> {
let mut cooldown_tracker = ctx.command().cooldowns.lock().unwrap(); let mut cooldown_tracker = ctx.command().cooldowns.lock().unwrap();
let cooldown_durations = poise::CooldownConfig { let cooldown_durations = poise::CooldownConfig {
global: Some(Duration::from_secs(global)), global: Some(Duration::from_secs(global)),
@ -32,12 +32,7 @@ pub(crate) fn cooldown(ctx: &Context, user: u64, global: u64) -> Option<Result<(
__non_exhaustive: (), __non_exhaustive: (),
}; };
match cooldown_tracker.remaining_cooldown((*ctx).cooldown_context(), &cooldown_durations) { match cooldown_tracker.remaining_cooldown((*ctx).cooldown_context(), &cooldown_durations) {
Some(remaining) => Some(Err( Some(remaining) => Err(format!("Please wait {} seconds", remaining.as_secs()).into()),
format!("Please wait {} seconds", remaining.as_secs()).into() None => Ok(cooldown_tracker.start_cooldown((*ctx).cooldown_context())),
)),
None => {
cooldown_tracker.start_cooldown((*ctx).cooldown_context());
None
}
} }
} }

View file

@ -1,12 +1,11 @@
use crate::commands::command_helper; use poise::CreateReply;
use crate::{Context, Error};
static mut BOTS_AVAILABLE: u8 = 0; use crate::{Context, Error};
use crate::commands::command_helper;
#[poise::command(slash_command, guild_only)] #[poise::command(slash_command, guild_only)]
pub(crate) async fn helpstart( pub(crate) async fn helpstart(
ctx: Context<'_>, ctx: Context<'_>,
#[min = 1_u8] #[min = 1_u8]
#[max = 3_u8] #[max = 3_u8]
#[description = "amount of players in your party, DO NOT include bots"] #[description = "amount of players in your party, DO NOT include bots"]
@ -14,22 +13,26 @@ pub(crate) async fn helpstart(
current_players: u8, current_players: u8,
) -> Result<(), Error> { ) -> Result<(), Error> {
let needed_players = 4 - current_players; let needed_players = 4 - current_players;
let bots = unsafe { BOTS_AVAILABLE }; let bots = *ctx.data().bots.read().await;
let reply = if bots >= needed_players { let mut reply = CreateReply::default();
"Bots available. Please use <@424767825001971715> in the bot-commands channel instead."
.to_string() reply = if bots >= needed_players {
reply.content("Bots available. Please use <@424767825001971715> in the bot-commands channel instead.")
.ephemeral(true)
} else { } else {
if let Some(value) = command_helper::cooldown(&ctx, 1200, 600) { match command_helper::cooldown(&ctx, 1200, 600) {
return value; Ok(_) => reply
.content(format!(
"<@&1008075054971621448>\nneed: {}",
needed_players - bots
))
.ephemeral(false),
Err(why) => reply.content(why.to_string()).ephemeral(true),
}
}; };
format!("<@&1008075054971621448>\nneed: {}", needed_players - bots) if let Err(why) = ctx.send(reply).await {
}; println!("Error sending message: {why}")
command_helper::send(ctx, reply).await
}
pub async fn set_bots_available(bots: u8) {
unsafe {
BOTS_AVAILABLE = bots;
} }
Ok(())
} }

View file

@ -1,14 +1,13 @@
use poise::{ChoiceParameter, CreateReply};
use serenity::all::CreateAllowedMentions;
//from main.rs
use crate::{Context, Error};
use crate::commands::command_helper::cooldown;
// //
use crate::commands::lfg::Difficulty::Normal; use crate::commands::lfg::Difficulty::Normal;
use crate::commands::lfg::Map::*; use crate::commands::lfg::Map::*;
use crate::commands::lfg::Mode::*; use crate::commands::lfg::Mode::*;
//from main.rs
use crate::{Context, Error};
//
use crate::commands::command_helper;
use poise::ChoiceParameter;
use serenity::model::mention::Mention;
use serenity::model::mention::Mention::Role;
#[derive(Debug, poise::ChoiceParameter, PartialEq)] #[derive(Debug, poise::ChoiceParameter, PartialEq)]
pub enum Map { pub enum Map {
@ -29,8 +28,8 @@ pub enum Mode {
Challenge, Challenge,
#[name = "Challenge of the week"] #[name = "Challenge of the week"]
Event, Event,
#[name = "Tournament Practice"] //#[name = "Tournament Practice"]
Tournament //Tournament,
} }
#[derive(Debug, poise::ChoiceParameter)] #[derive(Debug, poise::ChoiceParameter)]
pub enum Difficulty { pub enum Difficulty {
@ -71,52 +70,61 @@ pub(crate) async fn lfg(
#[rename = "message"] #[rename = "message"]
note: Option<String>, note: Option<String>,
) -> Result<(), Error> { ) -> Result<(), Error> {
if let Some(value) = command_helper::cooldown(&ctx, 600, 300) {
return value;
}
let mut reply = CreateReply::default();
reply = match cooldown(&ctx, 600, 300) {
Ok(_) => {
let current = current_players.unwrap_or(1); let current = current_players.unwrap_or(1);
let mut desired = desired_players.unwrap_or(4); let mut desired = desired_players.unwrap_or(4);
if current >= desired { if current >= desired {
desired = 4 desired = 4
} }
let map_name: &str = map.name(); let map_name: &str = map.name();
let ping: Mention; let ping = match mode {
match mode {
Casual => match map { Casual => match map {
DeadEnd => ping = Role(1005837123921915914.into()), DeadEnd => 1005837123921915914,
BadBlood => ping = Role(1140190470698438666.into()), BadBlood => 1140190470698438666,
AlienArcadium => ping = Role(1105917281898336356.into()), AlienArcadium => 1105917281898336356,
}, },
Speedrun => ping = Role(1005836989595144243.into()), Speedrun => 1005836989595144243,
Challenge => ping = Role(1005836864680361994.into()), Challenge => 1005836864680361994,
Event => ping = Role(1175116511095050331.into()), Event => 1175116511095050331,
Tournament => ping = Role(1210508966036242445.into()), //Tournament => 1210508966036242445,
} };
let diff_name: &str = if map != AlienArcadium { let difficulty = match map {
difficulty.unwrap_or(Normal).name() DeadEnd => difficulty.unwrap_or(Normal),
} else { BadBlood => difficulty.unwrap_or(Normal),
Normal.name() AlienArcadium => Normal,
}; };
let mut reply = format!( let mut reply_content = format!(
"{c}/{d} {e} {f} {b}", "<@&{ping}> {current}/{desired} {map_name}",
b = ping,
c = current,
d = desired,
e = map_name,
f = diff_name
); );
match difficulty {
Normal => {},
Difficulty::Hard | Difficulty::Rip => {
reply_content.push(' ');
reply_content.push_str(difficulty.name());
}
}
match note {
None => {},
Some(note) => {
reply_content.push_str(format!("\nNote: {note}").as_str());
}
}
reply.content(reply_content)
.ephemeral(false)
.allowed_mentions(CreateAllowedMentions::new()
.roles(vec![ping])
)
},
Err(why) => reply.content(why.to_string()).ephemeral(true),
};
if note.is_some() { if let Err(why) = ctx.send(reply).await {
let t = note.unwrap(); println!("Error sending message: {why}");
let regex = regex::Regex::new("(<@&?[0-9]*>)|(@everyone|@here)").unwrap();
if regex.is_match(&t) {
reply = String::from("Your Note seems to match a ping <:Maark:1128577127931985950>");
} else {
reply.push_str(format!("\nNote: {}", t).as_str());
} }
} Ok(())
command_helper::send(ctx, reply).await
} }

View file

@ -1,12 +1,17 @@
mod commands;
use poise::{async_trait, serenity_prelude as serenity};
use serenity::{client::EventHandler, model::id::UserId, FullEvent};
use std::collections::HashSet; use std::collections::HashSet;
use std::convert::Into; use std::convert::Into;
use serenity::all::{ActivityData}; use std::sync::Arc;
struct Data {} // User data, which is stored and accessible in all command invocations use poise::{async_trait, serenity_prelude as serenity};
use serenity::{client::EventHandler, FullEvent, model::id::UserId};
use serenity::all::ActivityData;
use tokio::sync::RwLock;
mod commands;
struct Data {
bots: Arc<RwLock<u8>>
} // User data, which is stored and accessible in all command invocations
type Error = Box<dyn std::error::Error + Send + Sync>; type Error = Box<dyn std::error::Error + Send + Sync>;
type Context<'a> = poise::Context<'a, Data, Error>; type Context<'a> = poise::Context<'a, Data, Error>;
struct ReadyHandler; struct ReadyHandler;
@ -39,13 +44,6 @@ async fn main() {
on_error: |error| { on_error: |error| {
Box::pin(async move { Box::pin(async move {
match error { match error {
poise::FrameworkError::ArgumentParse { error, .. } => {
if let Some(error) = error.downcast_ref::<serenity::RoleParseError>() {
println!("Found a RoleParseError: {:?}", error);
} else {
println!("Not a RoleParseError :(");
}
}
other => poise::builtins::on_error(other).await.unwrap(), other => poise::builtins::on_error(other).await.unwrap(),
} }
}) })
@ -62,7 +60,9 @@ async fn main() {
.setup(move |ctx, _ready, framework| { .setup(move |ctx, _ready, framework| {
Box::pin(async move { Box::pin(async move {
poise::builtins::register_globally(ctx, &framework.options().commands).await?; poise::builtins::register_globally(ctx, &framework.options().commands).await?;
Ok(Data {}) Ok(Data {
bots: Arc::new(RwLock::new(0)),
})
}) })
}) })
.build(); .build();