Overview
The Pin command allows moderators to pin or unpin messages in Discord channels. This is a context menu command that toggles the pin state of the selected message.
This command requires semester moderator role or MANAGE_MESSAGES permission.
Permissions Required
To use this command, you must meet one of these requirements:
- Be registered in the
semestermods database table
- Have the
MANAGE_MESSAGES Discord permission
Usage
- Right-click on any message in a channel
- Select “Apps” → “Toggle Pin State”
- The bot will pin the message if it’s unpinned, or unpin it if it’s already pinned
Parameters
The message to pin or unpin (selected via context menu)
Examples
Pinning a Message
Action: Right-click on an unpinned message and select “Toggle Pin State”
Response:
The message will now appear in the channel’s pinned messages.
Unpinning a Message
Action: Right-click on a pinned message and select “Toggle Pin State”
Response:
The message will be removed from the channel’s pinned messages.
Implementation Details
From moderation.rs:35-54:
#[poise::command(
context_menu_command = "Toggle Pin State",
check = "has_mod_or_semestermod",
ephemeral,
guild_only
)]
pub async fn pin(
ctx: Context<'_>,
#[description = "The message to pin"] message: serenity::Message,
) -> Result<(), Error> {
if message.pinned {
message
.unpin(&ctx.serenity_context())
.await
.map_err(Error::Serenity)?;
ctx.say("Unpinned message").await.map_err(Error::Serenity)?;
} else {
message
.pin(&ctx.serenity_context())
.await
.map_err(Error::Serenity)?;
ctx.say("Pinned message").await.map_err(Error::Serenity)?;
}
Ok(())
}
Permission Check
The has_mod_or_semestermod function checks:
async fn has_mod_or_semestermod(ctx: Context<'_>) -> Result<bool, Error> {
let db = &ctx.data().db;
let member = ctx.author_member().await.unwrap();
// Check if user is in semestermods table
let has_perms = sqlx::query("SELECT user_id FROM semestermods WHERE user_id = $1")
.bind(member.user.id.0 as i64)
.fetch_optional(db)
.await
.map_err(Error::Database)?
.is_some();
if has_perms {
Ok(true)
} else if member
.permissions(ctx)
.map_err(Error::Serenity)?
.contains(Permissions::MANAGE_MESSAGES)
{
return Ok(true);
} else {
return Ok(false);
}
}
The command is ephemeral, meaning the response is only visible to the user who invoked it.