async def check_tattletale(reaction: discord.Reaction): if reaction.emoji != REACTION_EMOJI or reaction.count < REACTION_THRESHOLD: return m = reaction.message if m.author.bot: return # If enough users have flagged a message, take the following actions: # - Remove the flagged message # - Time out the flagged user # - Notify staff, both of the offending message as well as who reacted, for potential abuse # Limited rollout: Only count reactions by users with certain role reactors = [x async for x in reaction.users()] num_valid_reactors = len([x for x in reactors if check_roles(x, TTL_ROLES)]) if num_valid_reactors < REACTION_THRESHOLD: return reactor_list = "\n".join([str(x) for x in reactors]) if not m.author.is_timed_out(): await m.author.timeout(timedelta(minutes=TIMEOUT_MIN)) try: await m.delete() msg_txt = combine_message(m) staff_chan = client.get_channel(MAILBOX) report = f"Users have flagged a message by <@{m.author.id}> in <#{m.channel.id}>: {msg_txt}.\n\nThese are the users who flagged:\n {reactor_list}" await staff_chan.send(report) except discord.NotFound: pass
async def addReaction(self, reaction: discord.Reaction): try: message: discord.Message message = reaction.message name = message.channel.name if str(name).startswith("school-work-sports"): name = "ssr" emoji_name = "" if reaction.custom_emoji: emoji_name = reaction.emoji.name else: emoji_name = str(emoji.demojize(reaction.emoji)).replace( ":", "") date = str(message.created_at).split(".")[0] user: discord.User async for user in reaction.users(): #command = 'INSERT INTO `' + name + '` VALUES ("' + user.name + '","' + message.author.name + '","' + emoji_name + '","' + date + '")' command = f'INSERT INTO `{name}` VALUES ("{user.name}","{message.author.name}","{emoji_name}","{date}")' self.cursor.execute(command) self.mydb.commit() except: pass
async def remove_reactions(self, reaction: discord.Reaction) -> None: """Remove all candy/skull reactions.""" try: async for user in reaction.users(): await reaction.message.remove_reaction(reaction.emoji, user) except discord.HTTPException: pass
async def get_user_ids(r: discord.Reaction) -> Set[int]: """ Extracts user ids from a discord reaction. This only exists because testing anything involving discord reactions is a pain, and we want to mock it out. """ pids = set() async for u in r.users(): pids.add(u.id) return pids
async def filter_bot_user_reactions(reaction: Reaction): return [user async for user in reaction.users() if not user.bot]
async def archive(self, message: Message, reaction: Reaction) -> None: """ Archive the given message by sending it in the archive channel and removing it from the queue. @param message: discord.Message: The message to archive @param reaction: discord.Reaction: Reaction that triggered the archive event @return: """ # Get the archive channel try: channel = message.guild.get_channel( self.get_server_conf(message.guild).archive.id) if channel is None: self.get_server_conf(message.guild).set_archive(None) raise TypeError if not channel.permissions_for(message.guild.me).send_messages: raise ValueError # Channel exists, but the bot can't send messages in there. except (TypeError, AttributeError, ValueError) as e: reactor: Optional[Member] = None async for user in reaction.users( ): # Find the manager that tried to archive this message to mention them. if user == self.user: continue reactor = user break await reaction.remove(reactor) if type(e) == ValueError: m = await message.channel.send( "**I don't have permission to send messages in the archive channel!**" ) else: m = await message.channel.send( f"{reactor.mention} There is not yet an archive channel for this server. " f"Use the `{PREFIX}archive` command in the channel you wish to use as " f"archive.") await asyncio.sleep(7) await m.delete() return # Create the embed to send in the archive channel author = message.author embed = Embed( title= f"Question by {author.display_name} ({author.name}#{author.discriminator}) in " f"#{message.channel}", timestamp=message.created_at, colour=0xeeeeee) embed.set_thumbnail(url=author.avatar_url) embed.add_field(name=f"{author.display_name}:", value=message.content, inline=False) # Look for relevant messages to include in the archive. async for m in message.channel.history( after=message, limit=100): # Look in history from `message` to now if m.author == message.guild.me: # Ignore the bot continue if m.author == author: # Add messages from the same user to the chain embed.add_field(name=f"{m.author.display_name}:", value=m.content, inline=False) await m.delete() elif m.reference is not None: # Add messages that reply to the question's author if isinstance(ref := m.reference.resolved, Message) and ref.author == author: embed.add_field(name=f"{m.author.display_name} replied:", value=m.content, inline=False) await m.delete() elif author in m.mentions: # Add messages that mention the author of the question embed.add_field(name=f"{m.author.display_name}:", value=m.content, inline=False) await m.delete()