diff --git a/src/commands/moderation_cmds.rs b/src/commands/moderation_cmds.rs index 666bd22..ac96c0f 100644 --- a/src/commands/moderation_cmds.rs +++ b/src/commands/moderation_cmds.rs @@ -2,6 +2,7 @@ use chrono::offset::Utc; use chrono_tz::{Tz, TZ_VARIANTS}; use levenshtein::levenshtein; use log::warn; +use poise::serenity_prelude::{ChannelId, Mentionable}; use super::autocomplete::timezone_autocomplete; use crate::{consts::THEME_COLOR, models::CtxData, Context, Error}; @@ -148,11 +149,51 @@ pub async fn unset_allowed_dm(ctx: Context<'_>) -> Result<(), Error> { Ok(()) } +/// Set defaults for commands +#[poise::command( + slash_command, + identifying_name = "default", + default_member_permissions = "MANAGE_GUILD" +)] +pub async fn default(_ctx: Context<'_>) -> Result<(), Error> { + Ok(()) +} + +/// Set a default channel for reminders to be sent to +#[poise::command( + slash_command, + guild_only = true, + identifying_name = "default_channel", + default_member_permissions = "MANAGE_GUILD" +)] +pub async fn default_channel( + ctx: Context<'_>, + #[description = "Channel to send reminders to by default"] channel: Option, +) -> Result<(), Error> { + if let Some(mut guild_data) = ctx.guild_data().await { + guild_data.default_channel = channel.map(|c| c.0); + + guild_data.commit_changes(&ctx.data().database).await?; + + if let Some(channel) = channel { + ctx.send(|r| { + r.ephemeral(true).content(format!("Default channel set to {}", channel.mention())) + }) + .await?; + } else { + ctx.send(|r| r.ephemeral(true).content("Default channel unset.")).await?; + } + } + + Ok(()) +} + /// View the webhook being used to send reminders to this channel #[poise::command( slash_command, identifying_name = "webhook_url", - required_permissions = "ADMINISTRATOR" + required_permissions = "ADMINISTRATOR", + default_member_permissions = "ADMINISTRATOR" )] pub async fn webhook(ctx: Context<'_>) -> Result<(), Error> { match ctx.channel_data().await { diff --git a/src/commands/reminder_cmds.rs b/src/commands/reminder_cmds.rs index 3e320d0..a38f6f5 100644 --- a/src/commands/reminder_cmds.rs +++ b/src/commands/reminder_cmds.rs @@ -653,7 +653,9 @@ async fn create_reminder( let list = channels.map(|arg| parse_mention_list(&arg)).unwrap_or_default(); if list.is_empty() { - if ctx.guild_id().is_some() { + if let Some(channel_id) = ctx.default_channel().await { + vec![ReminderScope::Channel(channel_id.0)] + } else if ctx.guild_id().is_some() { vec![ReminderScope::Channel(ctx.channel_id().0)] } else { vec![ReminderScope::User(ctx.author().id.0)] diff --git a/src/main.rs b/src/main.rs index aa0d0cd..6a7a4c6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -120,6 +120,10 @@ async fn _main(tx: Sender<()>) -> Result<(), Box> { ], ..command_macro::macro_base() }, + poise::Command { + subcommands: vec![moderation_cmds::default_channel()], + ..moderation_cmds::default() + }, reminder_cmds::pause(), reminder_cmds::offset(), reminder_cmds::nudge(), diff --git a/src/models/guild_data.rs b/src/models/guild_data.rs index de595d7..1ce7b7f 100644 --- a/src/models/guild_data.rs +++ b/src/models/guild_data.rs @@ -1,4 +1,3 @@ -use poise::serenity_prelude::Guild; use sqlx::MySqlPool; use crate::GuildId; diff --git a/src/models/mod.rs b/src/models/mod.rs index e6e8dd5..a1da285 100644 --- a/src/models/mod.rs +++ b/src/models/mod.rs @@ -6,24 +6,23 @@ pub mod timer; pub mod user_data; use chrono_tz::Tz; -use poise::serenity_prelude::{async_trait, model::id::UserId}; +use log::warn; +use poise::serenity_prelude::{async_trait, model::id::UserId, ChannelId}; use crate::{ - models::{channel_data::ChannelData, user_data::UserData}, + models::{channel_data::ChannelData, guild_data::GuildData, user_data::UserData}, CommandMacro, Context, Data, Error, GuildId, }; #[async_trait] pub trait CtxData { async fn user_data + Send>(&self, user_id: U) -> Result; - async fn author_data(&self) -> Result; - async fn timezone(&self) -> Tz; - async fn channel_data(&self) -> Result; - + async fn guild_data(&self) -> Option; async fn command_macros(&self) -> Result>, Error>; + async fn default_channel(&self) -> Option; } #[async_trait] @@ -52,10 +51,38 @@ impl CtxData for Context<'_> { async fn command_macros(&self) -> Result>, Error> { self.data().command_macros(self.guild_id().unwrap()).await } + + async fn default_channel(&self) -> Option { + match self.guild_id() { + Some(guild_id) => { + let guild_data = GuildData::from_guild(guild_id, &self.data().database).await; + + match guild_data { + Ok(data) => data.default_channel.map(|c| ChannelId(c)), + + Err(e) => { + warn!("SQL error: {:?}", e); + + None + } + } + } + + None => None, + } + } + + async fn guild_data(&self) -> Option { + match self.guild_id() { + Some(guild_id) => GuildData::from_guild(guild_id, &self.data().database).await.ok(), + + None => None, + } + } } impl Data { - pub(crate) async fn command_macros( + pub async fn command_macros( &self, guild_id: GuildId, ) -> Result>, Error> {