diff --git a/src/feature/mod.rs b/src/feature/mod.rs index 0e30925..d4010fb 100644 --- a/src/feature/mod.rs +++ b/src/feature/mod.rs @@ -39,6 +39,8 @@ pub async fn build_framework( ticket::command::ticket_panel(), ticket::command::ticket_blacklist_add(), ticket::command::ticket_blacklist_remove(), + ticket::command::ticket_add(), + ticket::command::ticket_remove(), moderation::command::clear(), moderation::command::slowmode(), moderation::command::warn(), diff --git a/src/feature/ticket/command.rs b/src/feature/ticket/command.rs index cf6ee86..4cd87fb 100644 --- a/src/feature/ticket/command.rs +++ b/src/feature/ticket/command.rs @@ -69,3 +69,80 @@ pub async fn ticket_blacklist_remove( .await?; Ok(()) } + +/// Adds user to current ticket (staff only, must be ticket channel). +#[poise::command( + slash_command, + prefix_command, + guild_only, + required_permissions = "MANAGE_CHANNELS" +)] +pub async fn ticket_add( + ctx: Ctx<'_>, + #[description = "User to add"] user: serenity::all::User, +) -> anyhow::Result<()> { + let channel_id = ctx.channel_id(); + if let Some(pool) = service::pool() { + if service::get_opener(pool, channel_id.get()).await.is_none() { + ctx.send(CreateReply::default().content("Not a ticket channel.").ephemeral(true)) + .await?; + return Ok(()); + } + } + service::add_user_to_ticket(ctx.http(), channel_id, user.id.get()).await?; + let _ = channel_id + .send_message( + ctx.http(), + serenity::all::CreateMessage::new().content(format!( + "<@{}> added <@{}> to ticket", + ctx.author().id, + user.id + )), + ) + .await; + ctx.send(CreateReply::default().content(format!("Added <@{}>", user.id)).ephemeral(true)) + .await?; + Ok(()) +} + +/// Removes user from current ticket. +#[poise::command( + slash_command, + prefix_command, + guild_only, + required_permissions = "MANAGE_CHANNELS" +)] +pub async fn ticket_remove( + ctx: Ctx<'_>, + #[description = "User to remove"] user: serenity::all::User, +) -> anyhow::Result<()> { + let channel_id = ctx.channel_id(); + if let Some(pool) = service::pool() { + if service::get_opener(pool, channel_id.get()).await.is_none() { + ctx.send(CreateReply::default().content("Not a ticket channel.").ephemeral(true)) + .await?; + return Ok(()); + } + if Some(user.id.get()) == service::get_opener(pool, channel_id.get()).await { + ctx.send( + CreateReply::default().content("Cannot remove ticket opener.").ephemeral(true), + ) + .await?; + return Ok(()); + } + } + service::remove_user_from_ticket(ctx.http(), channel_id, user.id.get()).await?; + let _ = channel_id + .send_message( + ctx.http(), + serenity::all::CreateMessage::new().content(format!( + "<@{}> removed <@{}>", + ctx.author().id, + user.id + )), + ) + .await; + ctx.send(CreateReply::default().content(format!("Removed <@{}>", user.id)).ephemeral(true)) + .await?; + Ok(()) +} diff --git a/src/feature/ticket/service/mod.rs b/src/feature/ticket/service/mod.rs index e7d6fa7..e91a993 100644 --- a/src/feature/ticket/service/mod.rs +++ b/src/feature/ticket/service/mod.rs @@ -65,6 +65,43 @@ pub async fn cleanup_ticket(p: &SqlitePool, c: u64) { let _ = sqlx::query("DELETE FROM tickets WHERE channel_id=?").bind(c.to_string()).execute(p).await; let _ = sqlx::query("DELETE FROM ticket_claims WHERE channel_id=?").bind(c.to_string()).execute(p).await; } +pub async fn add_user_to_ticket( + http: &Http, + channel_id: ChannelId, + user_id: u64, +) -> anyhow::Result<()> { + let uid = serenity::all::UserId::new(user_id); + let is_thread = matches!(http.get_channel(channel_id).await, Ok(serenity::all::Channel::Guild(gc)) if gc.thread_metadata.is_some()); + if is_thread { + channel_id.add_thread_member(http, uid).await?; + } else { + let overwrite = serenity::all::PermissionOverwrite { + allow: serenity::all::Permissions::VIEW_CHANNEL + | serenity::all::Permissions::SEND_MESSAGES + | serenity::all::Permissions::READ_MESSAGE_HISTORY, + deny: serenity::all::Permissions::empty(), + kind: serenity::all::PermissionOverwriteType::Member(uid), + }; + channel_id.create_permission(http, overwrite).await?; + } + Ok(()) +} +pub async fn remove_user_from_ticket( + http: &Http, + channel_id: ChannelId, + user_id: u64, +) -> anyhow::Result<()> { + let uid = serenity::all::UserId::new(user_id); + let is_thread = matches!(http.get_channel(channel_id).await, Ok(serenity::all::Channel::Guild(gc)) if gc.thread_metadata.is_some()); + if is_thread { + channel_id.remove_thread_member(http, uid).await?; + } else { + channel_id + .delete_permission(http, serenity::all::PermissionOverwriteType::Member(uid)) + .await?; + } + Ok(()) +} #[rustfmt::skip] pub async fn fetch_transcript(h: &Http, ch: ChannelId) -> String { let mut all=Vec::new();