1515log = logging .getLogger ("red.vrt.appeals.commands.admin" )
1616
1717
18- class MessageParser :
19- def __init__ (self , argument ):
20- if "-" not in argument :
21- raise commands .BadArgument ("Invalid format, must be `channelID-messageID`" )
22- try :
23- cid , mid = [i .strip () for i in argument .split ("-" )]
24- except ValueError :
25- raise commands .BadArgument ("Invalid format, must be `channelID-messageID`" )
26- try :
27- self .channel_id = int (cid )
28- except ValueError :
29- raise commands .BadArgument ("Channel ID must be an integer" )
30- try :
31- self .message_id = int (mid )
32- except ValueError :
33- raise commands .BadArgument ("Message ID must be an integer" )
34-
35-
3618class Admin (MixinMeta ):
3719 async def no_appealguild (self , ctx : commands .Context ):
3820 txt = (
@@ -161,7 +143,7 @@ async def view_appeal_settings(self, ctx: commands.Context):
161143
162144 def cname (cid : int ):
163145 if cid :
164- channel = self .bot .get_channel (cid )
146+ channel : discord . TextChannel = self .bot .get_channel (cid )
165147 if channel :
166148 return channel .mention
167149 else :
@@ -185,7 +167,9 @@ def cname(cid: int):
185167 f"**Appeal Message**: { appeal_msg } \n "
186168 f"**Alert Channel**: { cname (appealguild .alert_channel )} \n "
187169 f"**Appeal Limit**: { appealguild .appeal_limit } \n "
188- f"**Alert Roles**: { ', ' .join ([r .mention for r in roles ]) if roles else 'None set' } \n "
170+ f"**Discussion Threads**: { 'Enabled' if appealguild .discussion_threads else 'Disabled' } \n "
171+ f"**Vote Emojis**: { 'Enabled' if appealguild .vote_emojis else 'Disabled' } \n "
172+ f"**Alert Roles**: { ', ' .join ([r for r in roles ]) if roles else 'None set' } \n "
189173 f"**Questions**: { await AppealQuestion .count ().where (AppealQuestion .guild == ctx .guild .id )} "
190174 )
191175 embed = discord .Embed (
@@ -254,13 +238,13 @@ async def approve_appeal(self, ctx: commands.Context, submission_id: int, *, rea
254238 if not member :
255239 member = await self .bot .get_or_fetch_user (submission .user_id )
256240 # Send the submission to the approved channel and then delete from the pending channel
257- approved_channel = ctx .guild .get_channel (appealguild .approved_channel )
241+ approved_channel : discord . TextChannel = ctx .guild .get_channel (appealguild .approved_channel )
258242 if approved_channel :
259243 new_message = await approved_channel .send (embed = submission .embed (member ))
260244 await AppealSubmission .update ({AppealSubmission .message_id : new_message .id }).where (
261245 (AppealSubmission .id == submission_id ) & (AppealSubmission .guild == ctx .guild .id )
262246 )
263- pending_channel = ctx .guild .get_channel (appealguild .pending_channel )
247+ pending_channel : discord . TextChannel = ctx .guild .get_channel (appealguild .pending_channel )
264248 if pending_channel :
265249 if not pending_channel .permissions_for (ctx .guild .me ).manage_messages :
266250 await ctx .send (f"I do not have permissions to delete messages from { pending_channel .mention } " )
@@ -269,6 +253,8 @@ async def approve_appeal(self, ctx: commands.Context, submission_id: int, *, rea
269253 message = await pending_channel .fetch_message (submission .message_id )
270254 if message .thread :
271255 await message .thread .delete ()
256+ elif thread := ctx .guild .get_thread (submission .discussion_thread ):
257+ await thread .delete ()
272258 await message .delete ()
273259 except discord .NotFound :
274260 await ctx .send (f"Submission message not found in { pending_channel .mention } " )
@@ -349,16 +335,18 @@ async def deny_appeal(self, ctx: commands.Context, submission_id: int, *, reason
349335 submission .status = "denied"
350336 submission .reason = reason or ""
351337 await ctx .send (f"Successfully denied submission ID: { submission_id } " )
352- member = ctx .guild .get_member (submission .user_id ) or self .bot .get_user (submission .user_id )
338+ member = ctx .guild .get_member (submission .user_id )
339+ if not member :
340+ member = await self .bot .get_or_fetch_user (submission .user_id )
353341 # Send the submission to the denied channel and then delete from the pending channel
354- denied_channel = ctx .guild .get_channel (appealguild .denied_channel )
342+ denied_channel : discord . TextChannel = ctx .guild .get_channel (appealguild .denied_channel )
355343 if denied_channel :
356344 new_embed = submission .embed (member )
357345 new_message = await denied_channel .send (embed = new_embed )
358346 await AppealSubmission .update ({AppealSubmission .message_id : new_message .id }).where (
359347 (AppealSubmission .id == submission_id ) & (AppealSubmission .guild == ctx .guild .id )
360348 )
361- pending_channel = ctx .guild .get_channel (appealguild .pending_channel )
349+ pending_channel : discord . TextChannel = ctx .guild .get_channel (appealguild .pending_channel )
362350 if pending_channel :
363351 if not pending_channel .permissions_for (ctx .guild .me ).manage_messages :
364352 await ctx .send (f"I do not have permissions to delete messages from { pending_channel .mention } " )
@@ -367,6 +355,8 @@ async def deny_appeal(self, ctx: commands.Context, submission_id: int, *, reason
367355 message = await pending_channel .fetch_message (submission .message_id )
368356 if message .thread :
369357 await message .thread .delete ()
358+ elif thread := ctx .guild .get_thread (submission .discussion_thread ):
359+ await thread .delete ()
370360 await message .delete ()
371361 except discord .NotFound :
372362 await ctx .send (f"Submission message not found in { pending_channel .mention } " )
@@ -396,7 +386,7 @@ async def delete_appeal(self, ctx: commands.Context, submission_id: int):
396386 )
397387 if not submission :
398388 return await ctx .send ("No submission found with that ID." )
399- channel = ctx .guild .get_channel (getattr (appealguild , f"{ submission .status } _channel" ))
389+ channel : discord . TextChannel = ctx .guild .get_channel (getattr (appealguild , f"{ submission .status } _channel" ))
400390 if channel :
401391 if not channel .permissions_for (ctx .guild .me ).manage_messages :
402392 await ctx .send (f"I do not have permissions to delete messages from { channel .mention } " )
@@ -463,6 +453,16 @@ async def set_channels(
463453 if not appealguild :
464454 return await self .no_appealguild (ctx )
465455
456+ permissions = {
457+ "View Channel" : channel .permissions_for (ctx .guild .me ).view_channel ,
458+ "Send Messages" : channel .permissions_for (ctx .guild .me ).send_messages ,
459+ "Embed Links" : channel .permissions_for (ctx .guild .me ).embed_links ,
460+ "Create Threads" : channel .permissions_for (ctx .guild .me ).create_public_threads ,
461+ }
462+ for perm , has_perm in permissions .items ():
463+ if not has_perm :
464+ return await ctx .send (f"I don't have the `{ perm } ` permission in { channel .mention } !" )
465+
466466 if channel_type == "pending" :
467467 if channel .id == appealguild .pending_channel :
468468 return await ctx .send ("That channel is already set as the pending appeals channel." )
@@ -508,19 +508,21 @@ async def create_appeal_message(self, ctx: commands.Context, channel: discord.Te
508508
509509 @ensure_db_connection ()
510510 @appealset .command (name = "appealmessage" )
511- async def set_appeal_message (self , ctx : commands .Context , message : MessageParser ):
511+ async def set_appeal_message (self , ctx : commands .Context , message : discord . Message ):
512512 """
513513 Set the message where users will appeal from
514514 Message format: `channelID-messageID`
515515 """
516516 appealguild = await AppealGuild .objects ().get (AppealGuild .id == ctx .guild .id )
517517 if not appealguild :
518518 return await self .no_appealguild (ctx )
519- channel = ctx .guild .get_channel (message .channel_id )
519+ channel = ctx .guild .get_channel (message .channel . id )
520520 if not channel :
521521 return await ctx .send ("Invalid channel ID provided." )
522+ if not isinstance (channel , discord .TextChannel ):
523+ return await ctx .send ("The provided channel ID is not a text channel." )
522524 try :
523- msg = await channel .fetch_message (message .message_id )
525+ msg = await channel .fetch_message (message .channel . id )
524526 except discord .NotFound :
525527 return await ctx .send ("Invalid message ID provided." )
526528 except discord .Forbidden :
@@ -546,11 +548,11 @@ async def add_appeal_question(self, ctx: commands.Context, *, question: str):
546548 count = await AppealQuestion .count ().where (AppealQuestion .guild == appealguild )
547549 if count >= 24 :
548550 return await ctx .send ("You can only have up to 24 questions in the appeal form." )
549- question = AppealQuestion (
551+ question_obj = AppealQuestion (
550552 guild = ctx .guild .id ,
551553 question = question ,
552554 )
553- await question .save ()
555+ await question_obj .save ()
554556 await ctx .send ("Successfully added the question to the appeal form." )
555557 await self .refresh (ctx )
556558
@@ -778,15 +780,16 @@ async def set_alert_roles(self, ctx: commands.Context, *, role: discord.Role | i
778780 These roles will be pinged in the appeal server, NOT the target server.
779781 """
780782 rid = role .id if isinstance (role , discord .Role ) else role
783+ role_name = role .mention if isinstance (role , discord .Role ) else f"<@&{ rid } >"
781784 appealguild = await AppealGuild .objects ().get (AppealGuild .id == ctx .guild .id )
782785 if not appealguild :
783786 return await self .no_appealguild (ctx )
784787 if rid in appealguild .alert_roles :
785788 appealguild .alert_roles .remove (rid )
786- await ctx .send (f"Removed { role . name } from the alert roles." )
789+ await ctx .send (f"Removed { role_name } from the alert roles." )
787790 else :
788791 appealguild .alert_roles .append (rid )
789- await ctx .send (f"Added { role . name } to the alert roles." )
792+ await ctx .send (f"Added { role_name } to the alert roles." )
790793 await AppealGuild .update ({AppealGuild .alert_roles : appealguild .alert_roles }).where (
791794 AppealGuild .id == ctx .guild .id
792795 )
@@ -804,9 +807,11 @@ async def set_alert_channel(self, ctx: commands.Context, *, channel: discord.Tex
804807 if not appealguild :
805808 return await self .no_appealguild (ctx )
806809 if isinstance (channel , int ):
807- channel = self .bot .get_channel (channel )
810+ channel : discord . TextChannel = self .bot .get_channel (channel )
808811 if not channel :
809812 return await ctx .send ("Invalid channel ID provided." )
813+ if not isinstance (channel , discord .TextChannel ):
814+ return await ctx .send ("You must provide a valid text channel." )
810815 if channel :
811816 await AppealGuild .update ({AppealGuild .alert_channel : channel .id }).where (AppealGuild .id == ctx .guild .id )
812817 return await ctx .send (f"Successfully set the alert channel to { channel .mention } " )
@@ -827,7 +832,7 @@ async def refresh(self, ctx: discord.Guild | commands.Context) -> str | None:
827832 await ctx .send (f"Appeal system not ready yet: { reason } " )
828833 return reason
829834 appealguild = await AppealGuild .objects ().get (AppealGuild .id == guild .id )
830- channel = guild .get_channel (appealguild .appeal_channel )
835+ channel : discord . TextChannel = guild .get_channel (appealguild .appeal_channel )
831836 message = await channel .fetch_message (appealguild .appeal_message )
832837 view = AppealView (custom_id = f"{ appealguild .id } " )
833838 await message .edit (view = view )
@@ -915,3 +920,33 @@ async def set_button_emoji(
915920 )
916921 await ctx .send ("Successfully removed the button emoji" , view = view )
917922 await self .refresh (ctx )
923+
924+ @ensure_db_connection ()
925+ @appealset .command (name = "discussionthreads" )
926+ async def toggle_discussion_threads (self , ctx : commands .Context ):
927+ """Toggle whether appeals will have a discussion thread created for them"""
928+ appealguild = await AppealGuild .objects ().get (AppealGuild .id == ctx .guild .id )
929+ if not appealguild :
930+ return await self .no_appealguild (ctx )
931+ if appealguild .discussion_threads :
932+ appealguild .discussion_threads = False
933+ await ctx .send ("Successfully disabled discussion threads for appeals." )
934+ else :
935+ appealguild .discussion_threads = True
936+ await ctx .send ("Successfully enabled discussion threads for appeals." )
937+ await appealguild .save ([AppealGuild .discussion_threads ])
938+
939+ @ensure_db_connection ()
940+ @appealset .command (name = "voteemojis" )
941+ async def toggle_vote_emojis (self , ctx : commands .Context ):
942+ """Toggle whether appeals will have vote emojis added to them"""
943+ appealguild = await AppealGuild .objects ().get (AppealGuild .id == ctx .guild .id )
944+ if not appealguild :
945+ return await self .no_appealguild (ctx )
946+ if appealguild .vote_emojis :
947+ appealguild .vote_emojis = False
948+ await ctx .send ("Successfully disabled vote emojis for appeals." )
949+ else :
950+ appealguild .vote_emojis = True
951+ await ctx .send ("Successfully enabled vote emojis for appeals." )
952+ await appealguild .save ([AppealGuild .vote_emojis ])
0 commit comments