diff --git a/bot.py b/bot.py index 1b9a9f2c1f..ccececf8d6 100644 --- a/bot.py +++ b/bot.py @@ -1304,50 +1304,51 @@ async def handle_reaction_events(self, payload): except (discord.HTTPException, discord.InvalidArgument) as e: logger.warning("Failed to remove reaction: %s", e) - async def on_raw_reaction_add(self, payload): - await self.handle_reaction_events(payload) - + async def handle_react_to_contact(self, payload): react_message_id = tryint(self.config.get("react_to_contact_message")) react_message_emoji = self.config.get("react_to_contact_emoji") - if all((react_message_id, react_message_emoji)): - if payload.message_id == react_message_id: - if payload.emoji.is_unicode_emoji(): - emoji_fmt = payload.emoji.name - else: - emoji_fmt = f"<:{payload.emoji.name}:{payload.emoji.id}>" - - if emoji_fmt == react_message_emoji: - channel = self.get_channel(payload.channel_id) - member = channel.guild.get_member(payload.user_id) - if not member.bot: - message = await channel.fetch_message(payload.message_id) - await message.remove_reaction(payload.emoji, member) - await message.add_reaction(emoji_fmt) # bot adds as well - - if self.config["dm_disabled"] in ( - DMDisabled.NEW_THREADS, - DMDisabled.ALL_THREADS, - ): - embed = discord.Embed( - title=self.config["disabled_new_thread_title"], - color=self.error_color, - description=self.config["disabled_new_thread_response"], - ) - embed.set_footer( - text=self.config["disabled_new_thread_footer"], - icon_url=self.guild.icon_url, - ) - logger.info( - "A new thread using react to contact was blocked from %s due to disabled Modmail.", - member, - ) - return await member.send(embed=embed) + if ( + not all((react_message_id, react_message_emoji)) + or payload.message_id != react_message_id + ): + return + if payload.emoji.is_unicode_emoji(): + emoji_fmt = payload.emoji.name + else: + emoji_fmt = f"<:{payload.emoji.name}:{payload.emoji.id}>" - ctx = await self.get_context(message) - ctx.author = member - await ctx.invoke( - self.get_command("contact"), user=member, manual_trigger=False - ) + if emoji_fmt != react_message_emoji: + return + channel = self.get_channel(payload.channel_id) + member = channel.guild.get_member(payload.user_id) + if member.bot: + return + message = await channel.fetch_message(payload.message_id) + await message.remove_reaction(payload.emoji, member) + await message.add_reaction(emoji_fmt) # bot adds as well + + if self.config["dm_disabled"] in (DMDisabled.NEW_THREADS, DMDisabled.ALL_THREADS): + embed = discord.Embed( + title=self.config["disabled_new_thread_title"], + color=self.error_color, + description=self.config["disabled_new_thread_response"], + ) + embed.set_footer( + text=self.config["disabled_new_thread_footer"], icon_url=self.guild.icon_url, + ) + logger.info( + "A new thread using react to contact was blocked from %s due to disabled Modmail.", + member, + ) + return await member.send(embed=embed) + + ctx = await self.get_context(message) + await ctx.invoke(self.get_command("contact"), user=member, manual_trigger=False) + + async def on_raw_reaction_add(self, payload): + await asyncio.gather( + self.handle_reaction_events(payload), self.handle_react_to_contact(payload), + ) async def on_raw_reaction_remove(self, payload): if self.config["transfer_reactions"]: diff --git a/cogs/modmail.py b/cogs/modmail.py index 87b9d91e57..08930aa946 100644 --- a/cogs/modmail.py +++ b/cogs/modmail.py @@ -1002,7 +1002,7 @@ async def contact( `category`, if specified, may be a category ID, mention, or name. `user` may be a user ID, mention, or name. - `options` can be `silent` + `options` can be `silent` or `silently`. """ silent = False if isinstance(category, str): @@ -1018,19 +1018,28 @@ async def contact( exists = await self.bot.threads.find(recipient=user) if exists: - embed = discord.Embed( - color=self.bot.error_color, - description="A thread for this user already " - f"exists in {exists.channel.mention}.", - ) + desc = "A thread for this user already exists" + if exists.channel: + desc += f" in {exists.channel.mention}" + desc += "." + embed = discord.Embed(color=self.bot.error_color, description=desc) await ctx.channel.send(embed=embed, delete_after=3) else: + creator = ctx.author if manual_trigger else user + if await self.bot.is_blocked(user): + if not manual_trigger: # react to contact + return + + ref = f"{user.mention} is" if creator != user else "You are" + embed = discord.Embed( + color=self.bot.error_color, + description=f"{ref} currently blocked from contacting {self.bot.user.name}.", + ) + return await ctx.send(embed=embed) + thread = await self.bot.threads.create( - recipient=user, - creator=ctx.author, - category=category, - manual_trigger=manual_trigger, + recipient=user, creator=creator, category=category, manual_trigger=manual_trigger, ) if thread.cancelled: return @@ -1039,22 +1048,22 @@ async def contact( logger.info("Contacting user %s when Modmail DM is disabled.", user) if not silent and not self.bot.config.get("thread_contact_silently"): - if ctx.author.id == user.id: + if creator.id == user.id: description = "You have opened a Modmail thread." else: - description = f"{ctx.author.name} has opened a Modmail thread." + description = f"{creator.name} has opened a Modmail thread." em = discord.Embed( title="New Thread", description=description, color=self.bot.main_color, ) if self.bot.config["show_timestamp"]: em.timestamp = datetime.utcnow() - em.set_footer(icon_url=ctx.author.avatar_url) + em.set_footer(text=f"{creator}", icon_url=creator.avatar_url) await user.send(embed=em) embed = discord.Embed( title="Created Thread", - description=f"Thread started by {ctx.author.mention} for {user.mention}.", + description=f"Thread started by {creator.mention} for {user.mention}.", color=self.bot.main_color, ) await thread.wait_until_ready()