Skip to content

Commit

Permalink
Add command to pin message to a thread (#37)
Browse files Browse the repository at this point in the history
Closes #8, currently this bypasses any checks for moderators, although I
can remove that if wanted.
  • Loading branch information
GnomedDev authored Sep 6, 2024
1 parent b60b2bd commit d0d0f80
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 8 deletions.
30 changes: 22 additions & 8 deletions src/checks.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,29 @@
use anyhow::{anyhow, Error};

use crate::types::Context;

pub async fn check_is_moderator(ctx: Context<'_>) -> Result<bool, Error> {
let author = ctx
.author_member()
.await
.ok_or(anyhow!("Failed to fetch server member."))?;
pub fn is_moderator(ctx: Context<'_>) -> bool {
let mod_role_id = ctx.data().mod_role_id;
match ctx {
Context::Application(app_context) => {
let Some(member) = &app_context.interaction.member else {
// Invoked outside guild
return false;
};

member.roles.contains(&mod_role_id)
}
Context::Prefix(msg_context) => {
let Some(member) = &msg_context.msg.member else {
// Command triggered outside MessageCreateEvent?
return false;
};

let user_has_moderator_role = author.roles.contains(&ctx.data().mod_role_id);
member.roles.contains(&mod_role_id)
}
}
}

pub async fn check_is_moderator(ctx: Context<'_>) -> anyhow::Result<bool> {
let user_has_moderator_role = is_moderator(ctx);
if !user_has_moderator_role {
ctx.send(
poise::CreateReply::default()
Expand Down
1 change: 1 addition & 0 deletions src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ pub mod crates;
pub mod godbolt;
pub mod modmail;
pub mod playground;
pub mod thread_pin;
pub mod utilities;
58 changes: 58 additions & 0 deletions src/commands/thread_pin.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
use anyhow::Result;

use poise::serenity_prelude as serenity;

use crate::types::Context;

enum ThreadPinError {
NoChannel,
NotThread,
ThreadLocked,
NotThreadOwner,
}

async fn can_pin_in_thread(ctx: Context<'_>) -> Result<(), ThreadPinError> {
if crate::checks::is_moderator(ctx) {
return Ok(());
}

let Some(channel) = ctx.guild_channel().await else {
return Err(ThreadPinError::NoChannel);
};

let Some(thread_metadata) = channel.thread_metadata else {
return Err(ThreadPinError::NotThread);
};

if thread_metadata.locked {
return Err(ThreadPinError::ThreadLocked);
}

if channel.owner_id != Some(ctx.author().id) {
return Err(ThreadPinError::NotThreadOwner);
}

Ok(())
}

#[poise::command(context_menu_command = "Pin Message to Thread", guild_only)]
pub async fn thread_pin(ctx: Context<'_>, message: serenity::Message) -> Result<()> {
let reply = match can_pin_in_thread(ctx).await {
Ok(()) => {
message.pin(ctx.serenity_context()).await?;
"Pinned message to your thread!"
}
Err(ThreadPinError::NoChannel) => "Error: Cannot fetch any information about this channel!",
Err(ThreadPinError::NotThread) => "This channel is not a thread!",
Err(ThreadPinError::NotThreadOwner) => {
"You did not create this thread, so cannot pin messages to it."
}
Err(ThreadPinError::ThreadLocked) => {
"This thread has been locked, so this cannot be performed."
}
};

let reply = poise::CreateReply::default().content(reply).ephemeral(true);
ctx.send(reply).await?;
Ok(())
}
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ async fn serenity(
commands::utilities::cleanup(),
commands::utilities::ban(),
commands::utilities::selftimeout(),
commands::thread_pin::thread_pin(),
commands::modmail::modmail(),
commands::modmail::modmail_context_menu_for_message(),
commands::modmail::modmail_context_menu_for_user(),
Expand Down

0 comments on commit d0d0f80

Please sign in to comment.