@@ -2,17 +2,23 @@ use indoc::formatdoc;
22use poise:: {
33 ChoiceParameter , CreateReply ,
44 serenity_prelude:: {
5- ButtonStyle , Colour , ComponentInteractionDataKind , CreateActionRow , CreateButton ,
6- CreateEmbed , CreateInteractionResponse , CreateInteractionResponseMessage , EditChannel ,
7- FormattedTimestamp , FormattedTimestampStyle , GetMessages , GuildChannel , Member ,
8- Mentionable , Timestamp ,
5+ ButtonStyle , ChannelType , Colour , ComponentInteractionDataKind , CreateActionRow ,
6+ CreateButton , CreateEmbed , CreateInteractionResponse , CreateInteractionResponseMessage ,
7+ EditChannel , FormattedTimestamp , FormattedTimestampStyle , GetMessages , GuildChannel ,
8+ Member , Mentionable , PermissionOverwrite , PermissionOverwriteType , Permissions , Timestamp ,
99 futures:: future:: { Either , select} ,
1010 } ,
1111} ;
1212use std:: { pin:: pin, time:: Duration } ;
1313use tokio:: time:: Instant ;
1414
15- use crate :: discord:: { Context , Error , utils:: ROLE_MUTED } ;
15+ use crate :: discord:: {
16+ Context , Error ,
17+ utils:: {
18+ CATEGORY_BETA , CATEGORY_COMMUNITY , CATEGORY_STAFF , EMOJI_LOADING , ROLE_BOTS , ROLE_EVERYONE ,
19+ ROLE_MUTED , ROLE_STAFF , ROLE_VIP ,
20+ } ,
21+ } ;
1622
1723/// Manages slowmode for a channel.
1824#[ poise:: command(
@@ -306,3 +312,169 @@ pub async fn mute(
306312 }
307313 Ok ( ( ) )
308314}
315+
316+ /// Staff command. Locks a channel, preventing members from sending messages.
317+ #[ poise:: command(
318+ slash_command,
319+ guild_only,
320+ default_member_permissions = "MANAGE_CHANNELS" ,
321+ required_bot_permissions = "MANAGE_CHANNELS"
322+ ) ]
323+ pub async fn lock ( ctx : Context < ' _ > ) -> Result < ( ) , Error > {
324+ let reply_handler = ctx
325+ . reply ( format ! ( "{} Attempting to lock channel ..." , EMOJI_LOADING ) )
326+ . await ?;
327+
328+ let mut channel = ctx. guild_channel ( ) . await . unwrap ( ) ;
329+ let category = channel. parent_id ;
330+ let is_priviledged_channel = match category {
331+ None => false ,
332+ Some ( category_id) => {
333+ let category = category_id
334+ . to_channel ( ctx. http ( ) )
335+ . await
336+ . map ( |channel| channel. guild ( ) )
337+ . unwrap ( ) ;
338+ category. is_some_and ( |category| {
339+ matches ! ( category. kind, ChannelType :: Category )
340+ && [ CATEGORY_BETA , CATEGORY_STAFF , CATEGORY_COMMUNITY ]
341+ . contains ( & category. name . as_str ( ) )
342+ } )
343+ }
344+ } ;
345+ if is_priviledged_channel {
346+ reply_handler
347+ . edit (
348+ ctx,
349+ CreateReply :: new ( ) . content (
350+ "This command is not suitable for this channel because of its category." ,
351+ ) ,
352+ )
353+ . await ?;
354+ return Ok ( ( ) ) ;
355+ }
356+
357+ let roles = channel. guild_id . roles ( ctx. http ( ) ) . await ?;
358+ let everyone_role = roles
359+ . values ( )
360+ . find ( |role| role. name == ROLE_EVERYONE )
361+ . ok_or ( format ! ( "Could not find `{}` role" , ROLE_EVERYONE ) ) ?;
362+ let staff_role = roles
363+ . values ( )
364+ . find ( |role| role. name == ROLE_STAFF )
365+ . ok_or ( format ! ( "Could not find `@{}` role" , ROLE_STAFF ) ) ?;
366+ let vip_role = roles
367+ . values ( )
368+ . find ( |role| role. name == ROLE_VIP )
369+ . ok_or ( format ! ( "Could not find `@{}` role" , ROLE_VIP ) ) ?;
370+ let bot_role = roles
371+ . values ( )
372+ . find ( |role| role. name == ROLE_BOTS )
373+ . ok_or ( format ! ( "Could not find `@{}` role" , ROLE_BOTS ) ) ?;
374+ channel
375+ . edit (
376+ ctx. http ( ) ,
377+ EditChannel :: new ( ) . permissions ( [
378+ PermissionOverwrite {
379+ allow : Permissions :: READ_MESSAGE_HISTORY ,
380+ deny : Permissions :: ADD_REACTIONS | Permissions :: SEND_MESSAGES ,
381+ kind : PermissionOverwriteType :: Role ( everyone_role. id ) ,
382+ } ,
383+ PermissionOverwrite {
384+ allow : Permissions :: ADD_REACTIONS
385+ | Permissions :: SEND_MESSAGES
386+ | Permissions :: READ_MESSAGE_HISTORY ,
387+ deny : Permissions :: empty ( ) ,
388+ kind : PermissionOverwriteType :: Role ( staff_role. id ) ,
389+ } ,
390+ PermissionOverwrite {
391+ allow : Permissions :: ADD_REACTIONS
392+ | Permissions :: SEND_MESSAGES
393+ | Permissions :: READ_MESSAGE_HISTORY ,
394+ deny : Permissions :: empty ( ) ,
395+ kind : PermissionOverwriteType :: Role ( vip_role. id ) ,
396+ } ,
397+ PermissionOverwrite {
398+ allow : Permissions :: ADD_REACTIONS
399+ | Permissions :: SEND_MESSAGES
400+ | Permissions :: READ_MESSAGE_HISTORY ,
401+ deny : Permissions :: empty ( ) ,
402+ kind : PermissionOverwriteType :: Role ( bot_role. id ) ,
403+ } ,
404+ ] ) ,
405+ )
406+ . await ?;
407+
408+ reply_handler
409+ . edit (
410+ ctx,
411+ CreateReply :: new ( ) . content ( "Locked the channel to public access." ) ,
412+ )
413+ . await ?;
414+ Ok ( ( ) )
415+ }
416+
417+ /// Staff command. Unlocks a channel, allowing members to speak after the channel was originally locked.
418+ #[ poise:: command(
419+ slash_command,
420+ guild_only,
421+ default_member_permissions = "MANAGE_CHANNELS" ,
422+ required_bot_permissions = "MANAGE_CHANNELS"
423+ ) ]
424+ pub async fn unlock ( ctx : Context < ' _ > ) -> Result < ( ) , Error > {
425+ let reply_handler = ctx
426+ . reply ( format ! (
427+ "{} Attempting to unlock channel ..." ,
428+ EMOJI_LOADING
429+ ) )
430+ . await ?;
431+
432+ let mut channel = ctx. guild_channel ( ) . await . unwrap ( ) ;
433+ let category = match channel. parent_id {
434+ None => None ,
435+ Some ( category_id) => {
436+ let category = category_id
437+ . to_channel ( ctx. http ( ) )
438+ . await
439+ . map ( |channel| channel. guild ( ) )
440+ . unwrap ( ) ;
441+ category. and_then ( |category| match category. kind {
442+ ChannelType :: Category => Some ( category) ,
443+ _ => None ,
444+ } )
445+ }
446+ } ;
447+ let roles = channel. guild_id . roles ( ctx. http ( ) ) . await ?;
448+ let everyone_role = roles
449+ . values ( )
450+ . find ( |role| role. name == ROLE_EVERYONE )
451+ . ok_or ( format ! ( "Could not find `{}` role" , ROLE_EVERYONE ) ) ?;
452+
453+ if let Some ( category) = category
454+ && [ CATEGORY_BETA , CATEGORY_STAFF , CATEGORY_COMMUNITY ] . contains ( & category. name . as_str ( ) )
455+ {
456+ reply_handler
457+ . edit (
458+ ctx,
459+ CreateReply :: new ( ) . content (
460+ "This command is not suitable for this channel because of its category." ,
461+ ) ,
462+ )
463+ . await ?;
464+ return Ok ( ( ) ) ;
465+ }
466+ channel
467+ . edit (
468+ ctx. http ( ) ,
469+ EditChannel :: new ( ) . permissions ( [ PermissionOverwrite {
470+ allow : Permissions :: empty ( ) ,
471+ deny : Permissions :: empty ( ) ,
472+ kind : PermissionOverwriteType :: Role ( everyone_role. id ) ,
473+ } ] ) ,
474+ )
475+ . await ?;
476+ reply_handler. edit ( ctx, CreateReply :: new ( ) .
477+ content ( "Unlocked the channel to public access. Please check if permissions need to be synced." )
478+ ) . await ?;
479+ Ok ( ( ) )
480+ }
0 commit comments