laying the groundwork for the new argument system
cleaning up the source tree work towards dynamic loading of command plugins
This commit is contained in:
parent
f878530e44
commit
1afa975c6a
12 changed files with 276 additions and 76 deletions
41
Cargo.lock
generated
41
Cargo.lock
generated
|
@ -645,6 +645,8 @@ name = "info"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"nopalmo",
|
"nopalmo",
|
||||||
|
"tokio",
|
||||||
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -680,6 +682,16 @@ version = "0.2.155"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
|
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libloading"
|
||||||
|
version = "0.8.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"windows-targets 0.52.5",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "linux-raw-sys"
|
name = "linux-raw-sys"
|
||||||
version = "0.4.14"
|
version = "0.4.14"
|
||||||
|
@ -750,19 +762,21 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mio"
|
name = "mio"
|
||||||
version = "0.8.11"
|
version = "1.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
|
checksum = "4569e456d394deccd22ce1c1913e6ea0e54519f577285001215d33557431afe4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"hermit-abi",
|
||||||
"libc",
|
"libc",
|
||||||
"wasi",
|
"wasi",
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nopalmo"
|
name = "nopalmo"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"libloading",
|
||||||
"phf",
|
"phf",
|
||||||
"rand",
|
"rand",
|
||||||
"regex",
|
"regex",
|
||||||
|
@ -786,16 +800,6 @@ dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "num_cpus"
|
|
||||||
version = "1.16.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
|
|
||||||
dependencies = [
|
|
||||||
"hermit-abi",
|
|
||||||
"libc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "object"
|
name = "object"
|
||||||
version = "0.32.2"
|
version = "0.32.2"
|
||||||
|
@ -1491,28 +1495,27 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio"
|
name = "tokio"
|
||||||
version = "1.37.0"
|
version = "1.39.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787"
|
checksum = "daa4fb1bc778bd6f04cbfc4bb2d06a7396a8f299dc33ea1900cedaa316f467b1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"backtrace",
|
"backtrace",
|
||||||
"bytes",
|
"bytes",
|
||||||
"libc",
|
"libc",
|
||||||
"mio",
|
"mio",
|
||||||
"num_cpus",
|
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"signal-hook-registry",
|
"signal-hook-registry",
|
||||||
"socket2",
|
"socket2",
|
||||||
"tokio-macros",
|
"tokio-macros",
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio-macros"
|
name = "tokio-macros"
|
||||||
version = "2.2.0"
|
version = "2.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
|
checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
|
|
@ -16,6 +16,7 @@ path = "src/main.rs"
|
||||||
members = ["commands/info"]
|
members = ["commands/info"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
libloading = "0.8.5"
|
||||||
phf = { version = "0.11.2", features = ["phf_macros"] }
|
phf = { version = "0.11.2", features = ["phf_macros"] }
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
regex = "1.10.4"
|
regex = "1.10.4"
|
||||||
|
|
|
@ -2,9 +2,9 @@
|
||||||
name = "info"
|
name = "info"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
crate-type = ["cdylib"]
|
||||||
[lib]
|
|
||||||
crate-type = ["rlib"]
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
tokio = { version = "1.39.2", features = ["full"] }
|
||||||
|
tracing = "0.1.40"
|
||||||
nopalmo = { path = "../../" }
|
nopalmo = { path = "../../" }
|
|
@ -0,0 +1,43 @@
|
||||||
|
use nopalmo_lib::PluginError;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
use tokio::task;
|
||||||
|
|
||||||
|
type AsyncFn = Box<dyn Fn() -> task::JoinHandle<Result<(), PluginError>> + Send + Sync>;
|
||||||
|
|
||||||
|
static FUNCTION_MAP: ::std::sync::OnceLock<Arc<Mutex<HashMap<String, AsyncFn>>>> =
|
||||||
|
::std::sync::OnceLock::new();
|
||||||
|
|
||||||
|
#[allow(improper_ctypes_definitions)]
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn register_functions(function_map: Arc<Mutex<HashMap<String, AsyncFn>>>) {
|
||||||
|
if let Err(_) = FUNCTION_MAP.set(Arc::clone(&function_map)) {
|
||||||
|
tracing::error!("Could not set function map oncelock in `info` plugin.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let example_function: AsyncFn = Box::new(|| {
|
||||||
|
task::spawn(async {
|
||||||
|
tracing::info!("example_function is running");
|
||||||
|
// Simulate some async work
|
||||||
|
tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
|
||||||
|
tracing::info!("example_function completed");
|
||||||
|
// Return an error for demonstration
|
||||||
|
Err(PluginError::FunctionError(
|
||||||
|
"Something went wrong".to_string(),
|
||||||
|
))
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
function_map
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.insert("example_function".to_string(), example_function);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern "C" fn unregister_functions() {
|
||||||
|
if let Some(function_map) = FUNCTION_MAP.get() {
|
||||||
|
function_map.lock().unwrap().remove("example_function");
|
||||||
|
}
|
||||||
|
}
|
|
@ -1 +1,3 @@
|
||||||
pub const GLOBAL_PREFIX: char = ';';
|
pub const COMMAND_PREFIX: &'static str = ";";
|
||||||
|
pub const SHORT_ARGUMENT_PREFIX: &'static str = "-";
|
||||||
|
pub const LONG_ARGUMENT_PREFIX: &'static str = "--";
|
||||||
|
|
109
src/lib/arguments.rs
Normal file
109
src/lib/arguments.rs
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Default)]
|
||||||
|
pub struct ArgumentStorage {
|
||||||
|
arguments: Vec<Argument>,
|
||||||
|
long_key_to_id: HashMap<String, usize>,
|
||||||
|
short_key_to_id: HashMap<String, usize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ArgumentStorage {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add(&mut self, long: Option<String>, short: Option<String>, argument: Argument) {
|
||||||
|
let mut index = None;
|
||||||
|
for i in 0..self.arguments.len() {
|
||||||
|
if self.arguments.get(i).is_none() {
|
||||||
|
index = Some(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(index) = index {
|
||||||
|
self.arguments[index] = argument;
|
||||||
|
|
||||||
|
if let Some(long) = long {
|
||||||
|
self.long_key_to_id.insert(long, index);
|
||||||
|
}
|
||||||
|
if let Some(short) = short {
|
||||||
|
self.long_key_to_id.insert(short, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn remove(&mut self, long: Option<String>, short: Option<String>) {
|
||||||
|
|
||||||
|
match (long, short) {
|
||||||
|
(None, None) => todo!(),
|
||||||
|
(None, Some(short_key)) => {
|
||||||
|
let short_index = *self.short_key_to_id.get(&short_key).unwrap();
|
||||||
|
self.short_key_to_id.remove(&short_key);
|
||||||
|
|
||||||
|
let mut long_to_remove = None;
|
||||||
|
|
||||||
|
for (long_key, long_index) in &self.long_key_to_id {
|
||||||
|
// hate cloning here but i couldnt figure out how to avoid it
|
||||||
|
if short_index == *long_index {
|
||||||
|
long_to_remove = Some(long_key.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(long_to_remove) = long_to_remove {
|
||||||
|
self.long_key_to_id.remove(&long_to_remove);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(Some(long_key), None) => {
|
||||||
|
let long_index = *self.long_key_to_id.get(&long_key).unwrap();
|
||||||
|
self.long_key_to_id.remove(&long_key);
|
||||||
|
|
||||||
|
let mut short_to_remove = None;
|
||||||
|
|
||||||
|
for (short_key, short_index) in &self.short_key_to_id {
|
||||||
|
// hate cloning here but i couldnt figure out how to avoid it
|
||||||
|
if long_index == *short_index {
|
||||||
|
short_to_remove = Some(short_key.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(short_to_remove) = short_to_remove {
|
||||||
|
self.short_key_to_id.remove(&short_to_remove);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(Some(long_key), Some(short_key)) => {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
self.long_key_to_id.remove(&long_key);
|
||||||
|
self.short_key_to_id.remove(&short_key);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum ArgumentKind {
|
||||||
|
Short,
|
||||||
|
Long,
|
||||||
|
WildCard,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, PartialOrd)]
|
||||||
|
pub struct Argument {
|
||||||
|
pub pretty_name: &'static str,
|
||||||
|
// we will use usize as an argument id system, the arguments will be available inside the argument cache
|
||||||
|
// the bool is for if its required or not
|
||||||
|
pub sub_arguments: Vec<(ArgumentContainer, bool)>,
|
||||||
|
pub requires_prefix: bool,
|
||||||
|
|
||||||
|
pub long_name: Option<&'static str>, // change to vec?
|
||||||
|
pub short_name: Option<&'static str>, // change to vec?
|
||||||
|
// /// use 0 for any position, 1 or more for positionals
|
||||||
|
// pub position: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, PartialOrd)]
|
||||||
|
pub enum ArgumentContainer {
|
||||||
|
Value(String),
|
||||||
|
Argument(usize)
|
||||||
|
}
|
|
@ -1,3 +0,0 @@
|
||||||
pub struct Argument {
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
pub struct DiscordPermission {
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,54 +1,73 @@
|
||||||
|
use std::{fmt::Debug, time::Duration};
|
||||||
|
|
||||||
pub mod arguments;
|
pub mod arguments;
|
||||||
pub mod discord_permissions;
|
|
||||||
|
|
||||||
use self::arguments::Argument;
|
use arguments::ArgumentStorage;
|
||||||
use ::serenity::all::{Context, GuildId, Message};
|
use serenity::all::{Context, GuildId, Message};
|
||||||
use ::std::collections::HashMap;
|
|
||||||
use ::std::time::Duration;
|
|
||||||
use discord_permissions::DiscordPermission;
|
|
||||||
|
|
||||||
#[cfg(feature = "premium_features")]
|
#[derive(Debug)]
|
||||||
pub enum PremiumLevel {
|
pub enum PluginError {
|
||||||
Free,
|
FunctionError(String),
|
||||||
Tier1,
|
Other(String),
|
||||||
Tier2,
|
|
||||||
Tier3,
|
|
||||||
Super,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum CommandType {
|
impl core::fmt::Display for PluginError {
|
||||||
General,
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||||
Moderation,
|
match self {
|
||||||
Fun,
|
PluginError::FunctionError(msg) => write!(f, "Function error: {}", msg),
|
||||||
Info,
|
PluginError::Other(msg) => write!(f, "Other error: {}", msg),
|
||||||
Extra,
|
}
|
||||||
Unknown,
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Command<DMC: Sync + Send, GMC: Sync + Send, CommandReturn: Send + Sync> {
|
impl std::error::Error for PluginError {}
|
||||||
|
|
||||||
|
pub struct Command<DMC, GMC, CommandReturn> {
|
||||||
pub run_dm_command: Box<dyn Fn(&DMC, Context, Message) -> CommandReturn>,
|
pub run_dm_command: Box<dyn Fn(&DMC, Context, Message) -> CommandReturn>,
|
||||||
pub run_guild_command: Box<dyn Fn(&GMC, Context, Message, GuildId) -> CommandReturn>,
|
pub run_guild_command: Box<dyn Fn(&GMC, Context, Message, GuildId) -> CommandReturn>,
|
||||||
pub aliases: Vec<String>,
|
pub aliases: Vec<String>,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub command_type: CommandType,
|
pub command_category: String,
|
||||||
pub help: String,
|
pub help: String,
|
||||||
pub usage: String,
|
pub usage: String,
|
||||||
pub timeout: Duration, // TODO make this dynamic?
|
pub timeout: Duration, // TODO make this dynamic?
|
||||||
|
|
||||||
pub arguments: HashMap<String, Argument>,
|
pub arguments: ArgumentStorage,
|
||||||
pub permissions: Vec<DiscordPermission>,
|
pub required_caller_discord_permissions: ::serenity::all::Permissions,
|
||||||
|
|
||||||
#[cfg(feature = "nsfw_features")]
|
#[cfg(feature = "nsfw_features")]
|
||||||
pub is_nsfw: bool,
|
pub is_nsfw: bool,
|
||||||
#[cfg(feature = "premium_features")]
|
#[cfg(feature = "premium_features")]
|
||||||
pub premium_kind: PremiumLevel,
|
pub premium_kind: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl<DMC: Send + Sync, GMC: Send + Sync, CommandReturn: Send + Sync> Sync
|
unsafe impl<DMC, GMC, CommandReturn> Sync for Command<DMC, GMC, CommandReturn> {}
|
||||||
for Command<DMC, GMC, CommandReturn>
|
unsafe impl<DMC, GMC, CommandReturn> Send for Command<DMC, GMC, CommandReturn> {}
|
||||||
{
|
|
||||||
}
|
impl<DMC, GMC, CommandReturn> Debug for Command<DMC, GMC, CommandReturn> {
|
||||||
unsafe impl<DMC: Send + Sync, GMC: Send + Sync, CommandReturn: Send + Sync> Send
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
for Command<DMC, GMC, CommandReturn>
|
let mut binding = f.debug_struct("Command");
|
||||||
{
|
binding
|
||||||
|
.field(
|
||||||
|
"run_dm_command",
|
||||||
|
&::std::any::type_name_of_val(&self.run_dm_command),
|
||||||
|
)
|
||||||
|
.field(
|
||||||
|
"run_guild_command",
|
||||||
|
&::std::any::type_name_of_val(&self.run_guild_command),
|
||||||
|
)
|
||||||
|
.field("aliases", &self.aliases)
|
||||||
|
.field("name", &self.name)
|
||||||
|
.field("command_type", &self.command_category)
|
||||||
|
.field("help", &self.help)
|
||||||
|
.field("usage", &self.usage)
|
||||||
|
.field("timeout", &self.timeout)
|
||||||
|
.field("arguments", &self.arguments)
|
||||||
|
.field("permissions", &self.required_caller_discord_permissions);
|
||||||
|
#[cfg(feature = "nsfw_features")]
|
||||||
|
binding.field("is_nsfw", &self.is_nsfw);
|
||||||
|
#[cfg(feature = "premium_features")]
|
||||||
|
binding.field("premium_kind", &self.premium_kind);
|
||||||
|
binding.finish()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
54
src/main.rs
54
src/main.rs
|
@ -1,25 +1,29 @@
|
||||||
|
#![deny(clippy::unwrap_used)]
|
||||||
|
#![deny(clippy::expect_used)]
|
||||||
|
#![deny(clippy::pedantic)]
|
||||||
|
|
||||||
//#![feature(async_fn_traits)]
|
//#![feature(async_fn_traits)]
|
||||||
|
|
||||||
// mod commands;
|
// mod commands;
|
||||||
// use nopalmo_lib;
|
// use nopalmo_lib;
|
||||||
|
|
||||||
mod constants;
|
mod constants;
|
||||||
mod permissions;
|
// mod permissions;
|
||||||
mod system_messages;
|
mod system_messages;
|
||||||
mod tasks;
|
mod tasks;
|
||||||
|
|
||||||
use ::std::collections::hash_map::HashMap;
|
// use ::std::collections::hash_map::HashMap;
|
||||||
|
|
||||||
use std::error::Error;
|
// use std::error::Error;
|
||||||
use std::future::Future;
|
// use std::future::Future;
|
||||||
use std::pin::Pin;
|
// use std::pin::Pin;
|
||||||
use std::sync::atomic::AtomicBool;
|
use std::sync::atomic::AtomicBool;
|
||||||
use std::sync::Arc;
|
// use std::sync::Arc;
|
||||||
use std::time::Duration;
|
// use std::time::Duration;
|
||||||
|
|
||||||
use nopalmo_lib::discord_permissions::DiscordPermission;
|
// use discord_permissions::DiscordPermission;
|
||||||
use nopalmo_lib::Command;
|
// use nopalmo_lib::Command;
|
||||||
use serenity::all::GuildId;
|
// use serenity::all::GuildId;
|
||||||
// use commands::Command;
|
// use commands::Command;
|
||||||
use serenity::model::channel::Message;
|
use serenity::model::channel::Message;
|
||||||
use serenity::model::gateway::Ready;
|
use serenity::model::gateway::Ready;
|
||||||
|
@ -31,6 +35,34 @@ use serenity::prelude::*;
|
||||||
// pub type CommandReturn = Pin<Box<dyn Future<Output = ()>>>;
|
// pub type CommandReturn = Pin<Box<dyn Future<Output = ()>>>;
|
||||||
// pub type CommandReturn = ();
|
// pub type CommandReturn = ();
|
||||||
|
|
||||||
|
|
||||||
|
// pub mod discord_permissions;
|
||||||
|
|
||||||
|
// use self::arguments::Argument;
|
||||||
|
use ::serenity::all::Context;
|
||||||
|
|
||||||
|
// use discord_permissions::DiscordPermission;
|
||||||
|
|
||||||
|
// #[cfg(feature = "premium_features")]
|
||||||
|
// pub enum PremiumLevel {
|
||||||
|
// Free,
|
||||||
|
// Tier1,
|
||||||
|
// Tier2,
|
||||||
|
// Tier3,
|
||||||
|
// Super,
|
||||||
|
// }
|
||||||
|
|
||||||
|
// pub enum CommandType {
|
||||||
|
// General,
|
||||||
|
// Moderation,
|
||||||
|
// Fun,
|
||||||
|
// Info,
|
||||||
|
// Extra,
|
||||||
|
// Unknown,
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct Handler {
|
struct Handler {
|
||||||
// TODO use data field instead?
|
// TODO use data field instead?
|
||||||
// system_sender: Mutex<mpsc::Sender<system_messages::SystemMessage>>,
|
// system_sender: Mutex<mpsc::Sender<system_messages::SystemMessage>>,
|
||||||
|
@ -54,7 +86,7 @@ impl EventHandler for Handler {
|
||||||
async fn message(&self, ctx: Context, msg: Message) {
|
async fn message(&self, ctx: Context, msg: Message) {
|
||||||
let prefix_regex = format!(
|
let prefix_regex = format!(
|
||||||
r"^({}|{}|<@{}>)\s?",
|
r"^({}|{}|<@{}>)\s?",
|
||||||
constants::GLOBAL_PREFIX,
|
constants::COMMAND_PREFIX,
|
||||||
"NPO_PFX",
|
"NPO_PFX",
|
||||||
ctx.cache.current_user().id
|
ctx.cache.current_user().id
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
pub struct Permission {
|
|
||||||
|
|
||||||
}
|
|
|
@ -18,7 +18,7 @@ pub async fn status_timer(
|
||||||
cache.user_count(),
|
cache.user_count(),
|
||||||
cache.guild_count()
|
cache.guild_count()
|
||||||
)),
|
)),
|
||||||
ActivityData::watching(format!("for {}help", constants::GLOBAL_PREFIX)),
|
ActivityData::watching(format!("for {}help", constants::COMMAND_PREFIX)),
|
||||||
ActivityData::listening("Infected Mushroom"),
|
ActivityData::listening("Infected Mushroom"),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue