Add prefix customization command
This commit is contained in:
@@ -253,6 +253,36 @@ impl Server {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_or_create_by_id(
|
||||
id: u64,
|
||||
session: &Session,
|
||||
http: &Client,
|
||||
) -> Result<Self, DatabaseOrDiscordError> {
|
||||
let server = Server::get_by_id(id, session)
|
||||
.await
|
||||
.map_err(DatabaseOrDiscordError::Database)?;
|
||||
|
||||
if let Some(server) = server {
|
||||
Ok(server)
|
||||
} else {
|
||||
let server: Server = http
|
||||
.guild(Id::new(id))
|
||||
.await
|
||||
.map_err(DatabaseOrDiscordError::Discord)?
|
||||
.model()
|
||||
.await
|
||||
.map_err(|_| DatabaseOrDiscordError::DiscordDeserializationFailed)?
|
||||
.into();
|
||||
|
||||
server
|
||||
.insert(session)
|
||||
.await
|
||||
.map_err(DatabaseOrDiscordError::Database)?;
|
||||
|
||||
Ok(server)
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn insert(&self, session: &Session) -> Result<(), DatabaseError> {
|
||||
session
|
||||
.query_unpaged(
|
||||
|
||||
@@ -31,6 +31,10 @@ impl FromArguments for String {
|
||||
}
|
||||
}
|
||||
|
||||
/// Consumes the entire remaining string as a single argument. If no string is remaining, it
|
||||
/// returns an empty string.
|
||||
///
|
||||
/// Parsing this argument type never fails.
|
||||
pub struct GreedyString(pub String);
|
||||
|
||||
impl FromArguments for GreedyString {
|
||||
|
||||
@@ -20,6 +20,9 @@ pub enum CommandError {
|
||||
|
||||
#[error("A database operation failed due to an inconsistent state")]
|
||||
DatabaseInconsistentState,
|
||||
|
||||
#[error("The command was used in DMs, but it can only be used in servers")]
|
||||
ServerCommandRunInDMs,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
@@ -66,7 +69,10 @@ pub fn get_command_parts<'a>(prefix: &str, message: &'a str) -> Option<CommandPa
|
||||
.to_ascii_lowercase()
|
||||
.starts_with(&prefix.to_ascii_lowercase())
|
||||
{
|
||||
let message = message_trimmed_start.split_at(prefix.len()).1.trim_ascii_start();
|
||||
let message = message_trimmed_start
|
||||
.split_at(prefix.len())
|
||||
.1
|
||||
.trim_ascii_start();
|
||||
|
||||
match message.split_once(" ") {
|
||||
Some((name, args)) => Some(CommandParts::new(name, args)),
|
||||
|
||||
@@ -32,7 +32,10 @@ impl<T: Send + Sync + 'static> OnMessageHandler<T> for CommandRunner {
|
||||
|
||||
if let Some(command) = command {
|
||||
command
|
||||
.execute(CommandContext::new(event, rt.clone(), &prefixes[0]), parts.args)
|
||||
.execute(
|
||||
CommandContext::new(event, rt.clone(), &prefixes[0]),
|
||||
parts.args,
|
||||
)
|
||||
.await?;
|
||||
|
||||
break;
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
use async_trait::async_trait;
|
||||
|
||||
use crate::{
|
||||
constants::DEFAULT_PREFIX,
|
||||
database::models::Server,
|
||||
discord::sanitizing::SanitizeDiscordMarkdown,
|
||||
framework::commands::{
|
||||
Command, CommandError,
|
||||
arguments::{Argument, GreedyString, ParseArguments},
|
||||
context::CommandContext,
|
||||
},
|
||||
state::State,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PrefixCommand;
|
||||
|
||||
#[async_trait]
|
||||
impl Command<State> for PrefixCommand {
|
||||
fn name(&self) -> &'static str {
|
||||
"prefix"
|
||||
}
|
||||
|
||||
fn aliases(&self) -> &'static [&'static str] {
|
||||
&["p"]
|
||||
}
|
||||
|
||||
fn description(&self) -> &'static str {
|
||||
"Sets the command prefix for the server."
|
||||
}
|
||||
|
||||
fn arguments(&self) -> &'static [Argument] {
|
||||
&[Argument {
|
||||
name: "prefix",
|
||||
is_optional: true,
|
||||
is_greedy: true,
|
||||
}]
|
||||
}
|
||||
|
||||
async fn execute(
|
||||
&self,
|
||||
ctx: CommandContext<'_, State>,
|
||||
args: &str,
|
||||
) -> Result<(), CommandError> {
|
||||
let prefix: GreedyString = ParseArguments::parse(args).unwrap();
|
||||
let mut prefix = prefix.trim();
|
||||
|
||||
let mut server = Server::get_or_create_by_id(
|
||||
ctx.event
|
||||
.guild_id
|
||||
.ok_or(CommandError::ServerCommandRunInDMs)?
|
||||
.get(),
|
||||
&ctx.rt.state.db,
|
||||
&ctx.rt.http,
|
||||
)
|
||||
.await
|
||||
.inspect_err(|e| log::error!("Failed to get or create server: {e}"))
|
||||
.map_err(|_| CommandError::DatabaseQueryFailed)?;
|
||||
|
||||
if prefix.is_empty() {
|
||||
prefix = DEFAULT_PREFIX;
|
||||
}
|
||||
|
||||
server.prefix = prefix.to_string();
|
||||
server
|
||||
.upsert(&ctx.rt.state.db)
|
||||
.await
|
||||
.map_err(|_| CommandError::DatabaseQueryFailed)?;
|
||||
|
||||
ctx.send()
|
||||
.content(format!(
|
||||
"✅ Prefix updated! Run `{}help` to see the new prefix.",
|
||||
prefix.sanitize(false)
|
||||
))
|
||||
.await
|
||||
.map_err(|e| {
|
||||
log::error!("Failed to send prefix update message: {e}");
|
||||
CommandError::MessageSendingFailed
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
//! Adding, updating, and removing servers from the database.
|
||||
//! Syncing servers with the database and server configuration commands.
|
||||
//!
|
||||
//! This sub-module is responsible for registering servers in the database, updating them when they
|
||||
//! update, and removing them when they get deleted or Payphone is kicked.
|
||||
|
||||
pub mod commands;
|
||||
pub mod events;
|
||||
|
||||
+13
-4
@@ -116,18 +116,26 @@ use tower_http::services::ServeDir;
|
||||
use twilight_gateway::Intents;
|
||||
|
||||
use crate::{
|
||||
cli::{Args, Commands}, constants::DEFAULT_PREFIX, database::models::Server, framework::{
|
||||
cli::{Args, Commands},
|
||||
constants::DEFAULT_PREFIX,
|
||||
database::models::Server,
|
||||
framework::{
|
||||
bot::{Bot, PrefixGetter},
|
||||
runtime::Runtime,
|
||||
}, groups::{
|
||||
},
|
||||
groups::{
|
||||
about::{commands::HelpCommand, components::HelpGoBackButton},
|
||||
calls::{
|
||||
commands::{CallCommand, HangupCommand, SkipCommand},
|
||||
events::MessageRedirector,
|
||||
},
|
||||
gateway::events::{ReadyHandler, ReconnectHandler},
|
||||
servers::events::{ServerCreateHandler, ServerDeleteHandler, ServerUpdateHandler},
|
||||
}, state::State
|
||||
servers::{
|
||||
commands::PrefixCommand,
|
||||
events::{ServerCreateHandler, ServerDeleteHandler, ServerUpdateHandler},
|
||||
},
|
||||
},
|
||||
state::State,
|
||||
};
|
||||
|
||||
mod cli;
|
||||
@@ -217,6 +225,7 @@ async fn start(token: String, database_addr: String) {
|
||||
.command(CallCommand::new())
|
||||
.command(SkipCommand)
|
||||
.command(HangupCommand)
|
||||
.command(PrefixCommand)
|
||||
.component(HelpGoBackButton)
|
||||
.on_ready(ReadyHandler)
|
||||
.on_reconnect(ReconnectHandler)
|
||||
|
||||
Reference in New Issue
Block a user