Skip to content

Commit

Permalink
fixed reaction / delete
Browse files Browse the repository at this point in the history
  • Loading branch information
Taaku18 committed Dec 13, 2019
1 parent 52ec750 commit f6044de
Show file tree
Hide file tree
Showing 9 changed files with 145 additions and 93 deletions.
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ This project mostly adheres to [Semantic Versioning](https://semver.org/spec/v2.
however, insignificant breaking changes does not guarantee a major version bump, see the reasoning [here](https://github.com/kyb3r/modmail/issues/319).


# v3.4.0-dev6
# v3.4.0-dev7

(Development update, very likely to be unstable!)

Expand All @@ -25,6 +25,8 @@ however, insignificant breaking changes does not guarantee a major version bump,
- New command `?freply`, which behaves exactly like `?reply` with the addition that you can substitute `{channel}`, `{recipient}`, and `{author}` to be their respective values.
- New command `?repair`, repair any broken Modmail thread (with help from @officialpiyush).
- Recipient get feedback when they edit message.
- Chained delete for DMs now comes with a message.
- poetry (in case someone needs it).

### Changed

Expand All @@ -42,6 +44,8 @@ however, insignificant breaking changes does not guarantee a major version bump,
- Fixed a lot of issues with `?edit` and `?delete` and recipient message edit.
- Masked the error: "AttributeError: 'int' object has no attribute 'name'"
- Channel delete event will not be checked until discord.py fixes this issue.
- Chained reaction.
- Chained delete for thread channels.

### Internal

Expand Down
2 changes: 1 addition & 1 deletion Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ motor = ">=2.0.0"
natural = "==0.2.0"
isodate = ">=0.6.0"
dnspython = "~=1.16.0"
parsedatetime = "==2.4"
parsedatetime = "==2.5"
aiohttp = "<3.6.0,>=3.3.0"
python-dotenv = ">=0.10.3"
pipenv = "*"
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<br>

<a href="#">
<img src="https://img.shields.io/badge/Latest%20Version-v3.3.2-7289da?style=for-the-badge&logo=data:image/gif;base64,R0lGODlhGAAYAPcAAAAAADQ+Yj5MdThCaEFOekNQfWt5e1lqfEdVhVpriVx1iVtsnFZpll1xlF1znFx5mGNtjGR7hWNzjGd5iWJunGNslmN0lGl1lGN5lWt7lWR0nGp1nWR5nGt8nHJ9l3J9jFxto1xtqlZqqF5zpF15pV10rVx5q1Z2ql1us150s114sV50uVd1smJupGNurGN0pGp1pGR6o2t7o2F0rml0rGR5rGt8q3J9pGNus2Fvu2Bzs2p2smR5s2t7tGF0u2N6vGp7u2l1uXJ+uGJ1wWV7w2l+xWl+yl5zwHWDiWyCmHODnHiGmHSLkW2CpGuEqnSCpHqMo3ODrHWKrXyMq3iHp3yTqGyEtWqFunKDs3uLtHSGvXSMvHuMu3eItnyTs3yTu3iUuW+RsV+ApmuCxG2Dy22LxnSMxHuMxHGGzXSLzXqLzXWFxXyTw3uSy3WSx26E0W+N2m+L1XKG03SL1XmL1HOL2HmL23WF2XiS1m+QyHOK4XmL4XaH4nGM5ImXm4WOlJSjnoOOq4OOpYSUrImXqJOcqYONt4OUtIybtIOUu4ycvImYt5OcuIyiqZekqYyiupOjvJurvJimtp+yvqKruae2ua23trLCucPHvIOMxoOUxIuaw4eYyJKbyISW1YiW0o2kyJWlxJqpxZWkzJury5aoxp6xxZ2zyZio1Jyy2Yuk0aOsyKOyxKOzzKy8zKq2yLO7xqOr1KSz1Ku706W026y73Ki21bK716u75LS95KSu4Zyx6bPDzLjGx63B2LPD1LTE3LvL3brI17/S2bbKzrTE47rF47zM5L3M67bH577R5L7R67zK8rjM8MLM3MPK1sTT3crU3MjW2dLZ2srUy8PN5MTO68nP68jL48TS5MnT5cbR68jS7M3b7Mva5dTb6MTO8srO8szF8MXR8snS8c3a8cnY+NXb9tDL7dnm6dzk8tro99Pq9uTp6+r17fr77eTr/efr+Oz09OXz/Ov0/e37/uj39fX19fX89fz+9vP1/fX9/f7//vr2/ODl4sK75yH5BAEAAAAALAAAAAAYABgAAAj/AAEAmFOnoMGDCAvGmRNHYMKHEOdIhEgRIcGKGDMeTJVO00WNBj194/frFik5IOvgqdaP371N26xpefORYq57/HI+s7Vtmy0eKCmmapcz575FPXt+SfHmociiRae1SroNWIoVTQ2uxAk15yJg1awl7ZSCaUE82uRxhTpt1TNXq0Ip2pSobIqCc0iVoqsI0ipXr1bhywfVXxYdiA3Sourz2dqc8lbNQJz4bDWqix73E7ZjhgrKOjYmvfWLbZcZqCdTPjjHGLdtibi2U5Q6NWiEqqq64ifvVe3at1nX2tTuWQ/QyIMfxHOGi+rkyeMklPMDuvWaBqlbj469IPUU2ykPCOw+53t4AAEBADs=">
<img src="https://img.shields.io/badge/Latest%20Version-v3.4-7289da?style=for-the-badge&logo=data:image/gif;base64,R0lGODlhGAAYAPcAAAAAADQ+Yj5MdThCaEFOekNQfWt5e1lqfEdVhVpriVx1iVtsnFZpll1xlF1znFx5mGNtjGR7hWNzjGd5iWJunGNslmN0lGl1lGN5lWt7lWR0nGp1nWR5nGt8nHJ9l3J9jFxto1xtqlZqqF5zpF15pV10rVx5q1Z2ql1us150s114sV50uVd1smJupGNurGN0pGp1pGR6o2t7o2F0rml0rGR5rGt8q3J9pGNus2Fvu2Bzs2p2smR5s2t7tGF0u2N6vGp7u2l1uXJ+uGJ1wWV7w2l+xWl+yl5zwHWDiWyCmHODnHiGmHSLkW2CpGuEqnSCpHqMo3ODrHWKrXyMq3iHp3yTqGyEtWqFunKDs3uLtHSGvXSMvHuMu3eItnyTs3yTu3iUuW+RsV+ApmuCxG2Dy22LxnSMxHuMxHGGzXSLzXqLzXWFxXyTw3uSy3WSx26E0W+N2m+L1XKG03SL1XmL1HOL2HmL23WF2XiS1m+QyHOK4XmL4XaH4nGM5ImXm4WOlJSjnoOOq4OOpYSUrImXqJOcqYONt4OUtIybtIOUu4ycvImYt5OcuIyiqZekqYyiupOjvJurvJimtp+yvqKruae2ua23trLCucPHvIOMxoOUxIuaw4eYyJKbyISW1YiW0o2kyJWlxJqpxZWkzJury5aoxp6xxZ2zyZio1Jyy2Yuk0aOsyKOyxKOzzKy8zKq2yLO7xqOr1KSz1Ku706W026y73Ki21bK716u75LS95KSu4Zyx6bPDzLjGx63B2LPD1LTE3LvL3brI17/S2bbKzrTE47rF47zM5L3M67bH577R5L7R67zK8rjM8MLM3MPK1sTT3crU3MjW2dLZ2srUy8PN5MTO68nP68jL48TS5MnT5cbR68jS7M3b7Mva5dTb6MTO8srO8szF8MXR8snS8c3a8cnY+NXb9tDL7dnm6dzk8tro99Pq9uTp6+r17fr77eTr/efr+Oz09OXz/Ov0/e37/uj39fX19fX89fz+9vP1/fX9/f7//vr2/ODl4sK75yH5BAEAAAAALAAAAAAYABgAAAj/AAEAmFOnoMGDCAvGmRNHYMKHEOdIhEgRIcGKGDMeTJVO00WNBj194/frFik5IOvgqdaP371N26xpefORYq57/HI+s7Vtmy0eKCmmapcz575FPXt+SfHmociiRae1SroNWIoVTQ2uxAk15yJg1awl7ZSCaUE82uRxhTpt1TNXq0Ip2pSobIqCc0iVoqsI0ipXr1bhywfVXxYdiA3Sourz2dqc8lbNQJz4bDWqix73E7ZjhgrKOjYmvfWLbZcZqCdTPjjHGLdtibi2U5Q6NWiEqqq64ifvVe3at1nX2tTuWQ/QyIMfxHOGi+rkyeMklPMDuvWaBqlbj469IPUU2ykPCOw+53t4AAEBADs=">
</a>

<br>
Expand Down
104 changes: 65 additions & 39 deletions bot.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version__ = "3.4.0-dev6"
__version__ = "3.4.0-dev7"


import asyncio
Expand Down Expand Up @@ -78,7 +78,7 @@ def __init__(self):
"Your MONGO_URI might be copied wrong, try re-copying from the source again. "
"Otherwise noted in the following message:"
)
logger.critical(str(e))
logger.critical(e)
sys.exit(0)

self.plugin_db = PluginDatabaseClient(self)
Expand Down Expand Up @@ -506,7 +506,7 @@ async def convert_emoji(self, name: str) -> str:
try:
name = await converter.convert(ctx, name.strip(":"))
except commands.BadArgument as e:
logger.warning("%s is not a valid emoji. %s.", str(e))
logger.warning("%s is not a valid emoji. %s.", e)
raise
return name

Expand Down Expand Up @@ -697,12 +697,14 @@ async def get_thread_cooldown(self, author: discord.Member):
return

@staticmethod
async def add_reaction(msg, reaction):
async def add_reaction(msg, reaction: discord.Reaction) -> bool:
if reaction != "disable":
try:
await msg.add_reaction(reaction)
except (discord.HTTPException, discord.InvalidArgument):
logger.warning("Failed to add reaction %s.", reaction, exc_info=True)
except (discord.HTTPException, discord.InvalidArgument) as e:
logger.warning("Failed to add reaction %s: %s.", reaction, e)
return False
return True

async def process_dm_modmail(self, message: discord.Message) -> None:
"""Processes messages sent to the bot."""
Expand Down Expand Up @@ -955,26 +957,43 @@ async def on_raw_reaction_add(self, payload):
close_emoji = await self.convert_emoji(self.config["close_emoji"])

if isinstance(channel, discord.DMChannel):
if str(reaction) == str(close_emoji): # closing thread
if not self.config.get("recipient_thread_close"):
return
thread = await self.threads.find(recipient=user)
ts = message.embeds[0].timestamp if message.embeds else None
thread = await self.threads.find(recipient=user)
if not thread:
return

if (
message.embeds
and str(reaction) == str(close_emoji)
and self.config.get("recipient_thread_close")
):
ts = message.embeds[0].timestamp
if thread and ts == thread.channel.created_at:
# the reacted message is the corresponding thread creation embed
await thread.close(closer=user)
# closing thread
return await thread.close(closer=user)
if not thread.recipient.dm_channel:
await thread.recipient.create_dm()
try:
linked_message = await thread.find_linked_message_from_dm(
message, either_direction=True
)
except ValueError as e:
logger.warning("Failed to find linked message for reactions: %s", e)
return
else:
if not message.embeds:
thread = await self.threads.find(channel=channel)
if not thread:
return
try:
_, linked_message = await thread.find_linked_messages(
message.id, either_direction=True
)
except ValueError as e:
logger.warning("Failed to find linked message for reactions: %s", e)
return
message_id = str(message.embeds[0].author.url).split("/")[-1]
if message_id.isdigit():
thread = await self.threads.find(channel=message.channel)
channel = thread.recipient.dm_channel
if not channel:
channel = await thread.recipient.create_dm()
async for msg in channel.history():
if msg.id == int(message_id):
await msg.add_reaction(reaction)

if await self.add_reaction(linked_message, reaction):
await self.add_reaction(message, reaction)

async def on_guild_channel_delete(self, channel):
if channel.guild != self.modmail_guild:
Expand All @@ -986,7 +1005,8 @@ async def on_guild_channel_delete(self, channel):
mod = entry.user
except AttributeError as e:
# discord.py broken implementation with discord API
logger.warning("Failed to retrieve audit log: %s.", str(e))
# TODO: waiting for dpy
logger.warning("Failed to retrieve audit log: %s.", e)
return

if mod == self.user:
Expand Down Expand Up @@ -1035,35 +1055,37 @@ async def on_member_join(self, member):

async def on_message_delete(self, message):
"""Support for deleting linked messages"""
# TODO: use audit log to check if modmail deleted the message
if message.embeds and not isinstance(message.channel, discord.DMChannel):
message_id = str(message.embeds[0].author.url).split("/")[-1]
if message_id.isdigit():
thread = await self.threads.find(channel=message.channel)

channel = thread.recipient.dm_channel

async for msg in channel.history():
if msg.embeds and msg.embeds[0].author:
url = str(msg.embeds[0].author.url)
if message_id == url.split("/")[-1]:
return await msg.delete()
thread = await self.threads.find(channel=message.channel)
try:
await thread.delete_message(message)
except ValueError as e:
if str(e) not in {"DM message not found.", " Malformed thread message."}:
logger.warning("Failed to find linked message to delete: %s", e)
else:
thread = await self.threads.find(recipient=message.author)
message = await thread.find_linked_message_from_dm(message)
embed = message.embeds[0]
embed.set_footer(text=f"{embed.footer.text} (deleted)", icon_url=embed.footer.icon_url)
await message.edit(embed=embed)

async def on_bulk_message_delete(self, messages):
await discord.utils.async_all(self.on_message_delete(msg) for msg in messages)

async def on_message_edit(self, before, after):
if after.author.bot:
return
if before.content == after.content:
return

if isinstance(after.channel, discord.DMChannel):
thread = await self.threads.find(recipient=before.author)
try:
await thread.edit_dm_message(after, after.content)
except ValueError:
_, blocked_emoji = await self.retrieve_emoji()
try:
await after.add_reaction(blocked_emoji)
except (discord.HTTPException, discord.InvalidArgument):
pass
await self.add_reaction(after, blocked_emoji)
else:
embed = discord.Embed(
description="Successfully Edited Message", color=self.main_color
Expand Down Expand Up @@ -1173,7 +1195,7 @@ async def before_post_metadata(self):
self.metadata_loop.cancel()


if __name__ == "__main__":
def main():
try:
# noinspection PyUnresolvedReferences
import uvloop
Expand All @@ -1185,3 +1207,7 @@ async def before_post_metadata(self):

bot = ModmailBot()
bot.run()


if __name__ == "__main__":
main()
34 changes: 11 additions & 23 deletions cogs/modmail.py
Original file line number Diff line number Diff line change
Expand Up @@ -312,10 +312,7 @@ async def move(self, ctx, category: discord.CategoryChannel, *, specifics: str =
await thread.recipient.send(embed=embed)

sent_emoji, _ = await self.bot.retrieve_emoji()
try:
await ctx.message.add_reaction(sent_emoji)
except (discord.HTTPException, discord.InvalidArgument):
pass
await self.bot.add_reaction(ctx.message, sent_emoji)

async def send_scheduled_close_message(self, ctx, after, silent=False):
human_delta = human_timedelta(after.dt)
Expand Down Expand Up @@ -561,10 +558,7 @@ async def nsfw(self, ctx):
"""Flags a Modmail thread as NSFW (not safe for work)."""
await ctx.channel.edit(nsfw=True)
sent_emoji, _ = await self.bot.retrieve_emoji()
try:
await ctx.message.add_reaction(sent_emoji)
except (discord.HTTPException, discord.InvalidArgument):
pass
await self.bot.add_reaction(ctx.message, sent_emoji)

@commands.command()
@checks.has_permissions(PermissionLevel.SUPPORTER)
Expand All @@ -573,10 +567,7 @@ async def sfw(self, ctx):
"""Flags a Modmail thread as SFW (safe for work)."""
await ctx.channel.edit(nsfw=False)
sent_emoji, _ = await self.bot.retrieve_emoji()
try:
await ctx.message.add_reaction(sent_emoji)
except (discord.HTTPException, discord.InvalidArgument):
pass
await self.bot.add_reaction(ctx.message, sent_emoji)

@commands.command()
@checks.has_permissions(PermissionLevel.SUPPORTER)
Expand Down Expand Up @@ -872,7 +863,7 @@ async def edit(self, ctx, message_id: Optional[int] = None, *, message: str):
)

sent_emoji, _ = await self.bot.retrieve_emoji()
return await ctx.message.add_reaction(sent_emoji)
await self.bot.add_reaction(ctx.message, sent_emoji)

@commands.command()
@checks.has_permissions(PermissionLevel.SUPPORTER)
Expand Down Expand Up @@ -921,10 +912,7 @@ async def contact(
await thread.wait_until_ready()
await thread.channel.send(embed=embed)
sent_emoji, _ = await self.bot.retrieve_emoji()
try:
await ctx.message.add_reaction(sent_emoji)
except (discord.HTTPException, discord.InvalidArgument):
pass
await self.bot.add_reaction(ctx.message, sent_emoji)
await asyncio.sleep(3)
await ctx.message.delete()

Expand Down Expand Up @@ -1173,7 +1161,7 @@ async def delete(self, ctx, message_id: int = None):
)

sent_emoji, _ = await self.bot.retrieve_emoji()
return await ctx.message.add_reaction(sent_emoji)
await self.bot.add_reaction(ctx.message, sent_emoji)

@commands.command()
@checks.has_permissions(PermissionLevel.SUPPORTER)
Expand All @@ -1188,7 +1176,7 @@ async def repair(self, ctx):
if user_id == -1:
logger.info("Setting current channel's topic to User ID.")
await ctx.channel.edit(topic=f"User ID: {ctx.thread.id}")
return await ctx.message.add_reaction(sent_emoji)
return await self.bot.add_reaction(ctx.message, sent_emoji)

logger.info("Attempting to fix a broken thread %s.", ctx.channel.name)

Expand All @@ -1200,7 +1188,7 @@ async def repair(self, ctx):
if thread is not None:
logger.debug("Found thread with tempered ID.")
await ctx.channel.edit(reason="Fix broken Modmail thread", topic=f"User ID: {user_id}")
return await ctx.message.add_reaction(sent_emoji)
return await self.bot.add_reaction(ctx.message, sent_emoji)

# find genesis message to retrieve User ID
async for message in ctx.channel.history(limit=10, oldest_first=True):
Expand Down Expand Up @@ -1229,7 +1217,7 @@ async def repair(self, ctx):
await ctx.channel.edit(
reason="Fix broken Modmail thread", topic=f"User ID: {user_id}"
)
return await ctx.message.add_reaction(sent_emoji)
return await self.bot.add_reaction(ctx.message, sent_emoji)

else:
logger.warning("No genesis message found.")
Expand Down Expand Up @@ -1280,11 +1268,11 @@ async def repair(self, ctx):
await ctx.channel.edit(
reason="Fix broken Modmail thread", name=name, topic=f"User ID: {user.id}"
)
return await ctx.message.add_reaction(sent_emoji)
return await self.bot.add_reaction(ctx.message, sent_emoji)

elif len(users) >= 2:
logger.info("Multiple users with the same name and discriminator.")
return await ctx.message.add_reaction(blocked_emoji)
return await self.bot.add_reaction(ctx.message, blocked_emoji)

@commands.command()
@checks.has_permissions(PermissionLevel.ADMINISTRATOR)
Expand Down
6 changes: 3 additions & 3 deletions cogs/utility.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ async def send_error_message(self, error):
)
return await self.get_destination().send(embed=embed)

logger.warning("CommandNotFound: %s", str(error))
logger.warning("CommandNotFound: %s", error)

embed = discord.Embed(color=self.context.bot.error_color)
embed.set_footer(text=f'Command/Category "{command}" not found.')
Expand Down Expand Up @@ -1723,7 +1723,7 @@ def paginate(text: str):
exec(to_compile, env) # pylint: disable=exec-used
except Exception as exc:
await ctx.send(f"```py\n{exc.__class__.__name__}: {exc}\n```")
return await ctx.message.add_reaction("\u2049")
return await self.bot.add_reaction(ctx.message, "\u2049")

func = env["func"]
try:
Expand All @@ -1732,7 +1732,7 @@ def paginate(text: str):
except Exception:
value = stdout.getvalue()
await ctx.send(f"```py\n{value}{traceback.format_exc()}\n```")
return await ctx.message.add_reaction("\u2049")
return await self.bot.add_reaction(ctx.message, "\u2049")

else:
value = stdout.getvalue()
Expand Down
7 changes: 2 additions & 5 deletions core/paginator.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ async def create_base(self, item) -> None:
for reaction in self.reaction_map:
if len(self.pages) == 2 and reaction in "⏮⏭":
continue
await self.base.add_reaction(reaction)
await self.ctx.bot.add_reaction(self.base, reaction)

async def _create_base(self, item) -> None:
raise NotImplementedError
Expand Down Expand Up @@ -177,10 +177,7 @@ async def close(self, delete: bool = True) -> typing.Optional[Message]:
self.running = False

sent_emoji, _ = await self.ctx.bot.retrieve_emoji()
try:
await self.ctx.message.add_reaction(sent_emoji)
except (HTTPException, InvalidArgument):
pass
await self.ctx.bot.add_reaction(self.ctx.message, sent_emoji)

if delete:
return await self.base.delete()
Expand Down
Loading

0 comments on commit f6044de

Please sign in to comment.