2222SOFTWARE.
2323'''
2424
25- __version__ = '1.5.1 '
25+ __version__ = '1.5.2 '
2626
2727from contextlib import redirect_stdout
2828from urllib .parse import urlparse
@@ -58,16 +58,24 @@ def __init__(self):
5858 def _add_commands (self ):
5959 '''Adds commands automatically'''
6060 self .remove_command ('help' )
61+ print ('-------------------------' )
62+ print ('┌┬┐┌─┐┌┬┐┌┬┐┌─┐┬┬' ,
63+ '││││ │ │││││├─┤││' ,
64+ '┴ ┴└─┘─┴┘┴ ┴┴ ┴┴┴─┘' , sep = '\n ' )
65+ print (f'v{ __version__ } ' )
66+ print ('Author: kyb3r' )
6167 for attr in dir (self ):
6268 cmd = getattr (self , attr )
6369 if isinstance (cmd , commands .Command ):
6470 self .add_command (cmd )
71+
6572 @property
6673 def config (self ):
6774 try :
6875 with open ('config.json' ) as f :
6976 config = json .load (f )
7077 except FileNotFoundError :
78+ print ('config.json not found, falling back to env vars.' )
7179 config = {}
7280 config .update (os .environ )
7381 return config
@@ -105,12 +113,13 @@ async def wrapper(self, ctx, *args, **kwargs):
105113 return wrapper
106114
107115 async def on_connect (self ):
108- print ('---------------' )
109- print ('Modmail connected!' )
116+ print ('-------------------------' )
117+ print ('Connected to gateway.' )
118+
110119 self .session = aiohttp .ClientSession ()
111120 status = os .getenv ('STATUS' ) or self .config .get ('STATUS' )
112121 if status :
113- print (f'Setting Status to { status } ' )
122+ print (f'Changing presence. ' )
114123 await self .change_presence (activity = discord .Game (status ))
115124 else :
116125 print ('No status set.' )
@@ -127,15 +136,14 @@ def guild(self):
127136 async def on_ready (self ):
128137 '''Bot startup, sets uptime.'''
129138 print (textwrap .dedent (f'''
130- ---------------
131- Client is ready!
132- ---------------
133- Author: kyb3r
134- ---------------
139+ -------------------------
140+ Client ready.
141+ -------------------------
135142 Logged in as: { self .user }
136143 User ID: { self .user .id }
137- ---------------
138- ''' ))
144+ Guild ID: { self .guild .id if self .guild else 0 }
145+ -------------------------
146+ ''' ).strip ())
139147
140148 async def on_message (self , message ):
141149 if message .author .bot :
@@ -185,6 +193,14 @@ async def on_message_edit(self, before, after):
185193 embed .description = after .content
186194 await msg .edit (embed = embed )
187195 break
196+
197+ async def on_command_error (self , ctx , error ):
198+ if isinstance (error , (commands .MissingRequiredArgument , commands .UserInputError )):
199+ prefix = self .config .get ('PREFIX' , 'm.' )
200+ em = discord .Embed (color = discord .Color .green ())
201+ em .title = f'`{ prefix } { ctx .command .signature } `'
202+ em .description = ctx .command .help
203+ await ctx .send (embed = em )
188204
189205 def overwrites (self , ctx , modrole = None ):
190206 '''Permision overwrites for the guild.'''
@@ -209,6 +225,7 @@ def help_embed(self, prefix):
209225 f'`{ prefix } about` - Shows general information about the bot.\n ' \
210226 f'`{ prefix } contact` - Allows a moderator to initiate a thread with a given recipient.\n ' \
211227 f'`{ prefix } reply` - Sends a message to the current thread\' s recipient.\n ' \
228+ f'`{ prefix } edit` - Edit a message sent by the reply command.\n ' \
212229 f'`{ prefix } close` - Closes the current thread and deletes the channel.\n ' \
213230 f'`{ prefix } archive` - Closes the thread and moves the channel to archive category.\n ' \
214231 f'`{ prefix } block` - Blocks a user from using modmail.\n ' \
@@ -269,7 +286,7 @@ async def get_latest_updates(self, limit=3):
269286
270287 short_sha = commit ['sha' ][:6 ]
271288 html_url = commit ['html_url' ]
272- message = commit ['commit' ]['message' ]
289+ message = commit ['commit' ]['message' ]. splitlines ()[ 0 ]
273290 author_name = commit ['author' ]['login' ]
274291
275292 latest_commits += f'[`{ short_sha } `]({ html_url } ) { message } - { author_name } \n '
@@ -293,6 +310,7 @@ def uptime(self):
293310 @commands .command ()
294311 @trigger_typing
295312 async def help (self , ctx ):
313+ '''Shows the help message'''
296314 prefix = self .config .get ('PREFIX' , 'm.' )
297315
298316 em1 = self .help_embed (prefix )
@@ -308,6 +326,7 @@ async def help(self, ctx):
308326 @commands .command ()
309327 @trigger_typing
310328 async def about (self , ctx ):
329+ '''Shows information about the bot.'''
311330 em = discord .Embed (color = discord .Color .green (), timestamp = datetime .datetime .utcnow ())
312331 em .set_author (name = 'Mod Mail - Information' , icon_url = self .user .avatar_url )
313332 em .set_thumbnail (url = self .user .avatar_url )
@@ -722,6 +741,8 @@ async def send_mail(self, message, channel, from_mod, delete_message=True):
722741 async def process_reply (self , message , user_id = None ):
723742 user_id = user_id or int (re .findall (r'\d+' , message .channel .topic )[0 ])
724743 user = self .get_user (user_id )
744+ if not message .content and not message .attachments :
745+ raise commands .UserInputError ('msg is required argument.' )
725746 if not user :
726747 return await message .channel .send ('This user does not share any servers with the bot and is thus unreachable.' )
727748 await asyncio .gather (
@@ -836,6 +857,41 @@ async def reply(self, ctx, *, msg=''):
836857 user_id = await self .find_user_id_from_channel (ctx .channel )
837858 if user_id :
838859 await self .process_reply (ctx .message , user_id = user_id )
860+
861+ async def _edit_thread_message (self , channel , message_id , message ):
862+ async for msg in channel .history ():
863+ if msg .embeds :
864+ embed = msg .embeds [0 ]
865+ if f'Moderator - { message_id } ' in embed .footer .text :
866+ if ' - (Edited)' not in embed .footer .text :
867+ embed .set_footer (text = embed .footer .text + ' - (Edited)' )
868+ embed .description = message
869+ await msg .edit (embed = embed )
870+ break
871+
872+ def edit_thread_message (self , user , channel , message_id , message ):
873+ return asyncio .gather (
874+ self ._edit_thread_message (user , message_id , message ),
875+ self ._edit_thread_message (channel , message_id , message )
876+ )
877+
878+ @commands .command ()
879+ async def edit (self , ctx , message_id : int , * , new_message ):
880+ '''Edit a message that was sent using the reply command.
881+
882+ `<message_id>` is the id shown in the footer of thread messages.
883+ `<new_message>` is the new message that will be edited in.
884+ '''
885+ categ = ctx .channel .category
886+ if categ and categ .name in 'Mod Mail Archives' :
887+ if ctx .channel .topic and 'User ID:' in ctx .channel .topic :
888+ user = self .get_user (int (re .findall (r'\d+' , ctx .channel .topic )[0 ]))
889+ await self .edit_thread_message (user , ctx .channel , message_id , new_message )
890+ if not ctx .channel .topic :
891+ user_id = await self .find_user_id_from_channel (ctx .channel )
892+ if user_id :
893+ user = self .get_user (user_id )
894+ await self .edit_thread_message (user , ctx .channel , message_id , new_message )
839895
840896 @commands .command ()
841897 @trigger_typing
@@ -875,7 +931,7 @@ async def _status(self, ctx, *, message):
875931 em .color = discord .Color .green ()
876932 em .set_footer (text = 'Note: this change is temporary.' )
877933 await ctx .send (embed = em )
878-
934+
879935 @commands .command ()
880936 @trigger_typing
881937 @commands .has_permissions (manage_channels = True )
0 commit comments