Skip to content

Commit 059e937

Browse files
committed
Add an edit command that edits thread messages.
1 parent 82924d7 commit 059e937

File tree

1 file changed

+69
-13
lines changed

1 file changed

+69
-13
lines changed

bot.py

Lines changed: 69 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
SOFTWARE.
2323
'''
2424

25-
__version__ = '1.5.1'
25+
__version__ = '1.5.2'
2626

2727
from contextlib import redirect_stdout
2828
from 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

Comments
 (0)