async def on_member_unban(self, guild: discord.Guild, user: discord.User): """Called when a member is unbanned from a guild""" now = dt.datetime.utcnow() bot_member: discord.Member = guild.me embed = discord.Embed(description="Unbanned", color=discord.Color(0xff9000)) embed.set_author( name="{0.name}#{0.discriminator} (ID {0.id})".format(user), icon_url=get_user_avatar(user)) if bot_member.guild_permissions.view_audit_log: async for entry in guild.audit_logs( limit=10, reverse=False, action=discord.AuditLogAction.unban, after=now - dt.timedelta(0, 5)): # type: discord.AuditLogEntry if abs((entry.created_at - now).total_seconds()) >= 5: # After is broken in the API, so we must check if entry is too old. break if entry.target.id == user.id: embed.set_footer(text="{0.name}#{0.discriminator}".format( entry.user), icon_url=get_user_avatar(entry.user)) break await self.send_log_message(guild, embed=embed)
async def get_audit_entry( guild: discord.Guild, action: discord.AuditLogAction, target: Any = None) -> Optional[discord.AuditLogEntry]: """Gets an audit log entry of the specified action type. The type of the action depends on the action. :param guild: The guild where the audit log will be checked. :param action: The action to filter. :param target: The target to filter. :return: The first matching audit log entry if found. """ if not guild.me.guild_permissions.view_audit_log: return now = dt.datetime.utcnow() after = now - dt.timedelta(0, 5) async for entry in guild.audit_logs(limit=10, reverse=False, action=action, after=after): if abs((entry.created_at - now)) >= dt.timedelta(seconds=5): break if target is not None and entry.target.id == target.id: return entry
async def fetch_audit_log_entry( guild: discord.Guild, *, time: Optional[datetime.datetime] = None, user: Optional[User] = None, moderator: Optional[User] = None, action: Optional[discord.AuditLogAction] = None, delta: Union[float, datetime.timedelta] = 10, retry: int = 3, ) -> Optional[discord.AuditLogEntry]: time = time or datetime.datetime.now(datetime.timezone.utc) delta = normalise_timedelta(delta) async for entry in guild.audit_logs(action=action, user=moderator): if (time - entry.created_at) < delta and (user is None or entry.target == user): return entry if retry > 0: await asyncio.sleep(SLEEP_FOR) return await fetch_audit_log_entry( guild, time=time, user=user, moderator=moderator, action=action, delta=delta, retry=retry - 1, ) return None
def __init__(self, guild: discord.Guild): super().__init__() self.iterator: discord.guild.AuditLogIterator = guild.audit_logs( limit=None, action=discord.AuditLogAction.ban) self._cache: list[discord.AuditLogEntry] = [] self._ncache = 0 self._more = True self._n_last_fetched = 0
async def on_member_unban(self, guild: discord.Guild, user: discord.User): if guild.id != config.nintendoswitch: return db = mclient.bowser.puns if not db.find_one({ 'user': user.id, 'type': 'unban', 'timestamp': { '$gt': time.time() - 60 } }): # Manual unban audited = None async for entry in guild.audit_logs( action=discord.AuditLogAction.unban): if entry.target == user: audited = entry break if audited: reason = ("Ban appeal accepted" if audited.user.id == config.parakarry else audited.reason or '-No reason specified-') docID = await tools.issue_pun(audited.target.id, audited.user.id, 'unban', reason, active=False) db.update_one( { 'user': audited.target.id, 'type': 'ban', 'active': True }, {'$set': { 'active': False }}) await tools.send_modlog(self.bot, self.modLogs, 'unban', docID, reason, user=user, moderator=audited.user, public=True) embed = discord.Embed(color=discord.Color(0x88FF00), timestamp=datetime.datetime.utcnow()) embed.set_author(name=f'{user} ({user.id})', icon_url=user.avatar_url) embed.add_field(name='Mention', value=f'<@{user.id}>') await self.serverLogs.send(':triangular_flag_on_post: User unbanned', embed=embed)
async def fetch_recent_audit_log_entry( client: discord.Client, guild: discord.Guild, *, target: discord.User = None, action: discord.AuditLogAction = None, retry: int = 0) -> Optional[discord.AuditLogEntry]: """|coro| Attempts to retrieve an recently created :class:`~discord.AuditLogEntry` which meets the specified requirements. Parameters ---------- client: :class:`~discord.Client` The discord client to make the api calls with. guild: :class:`~discord.Guild` The guild to retrieve the audit log entry from. target: Optional[:class:`~discord.User`] The target to filter with. action: Optional[:class:`~discord.AuditLogAction`] The action to filter with. retry: Optional[:class:`int`] The number of times fetching an entry should be retried. Defaults to 0. Raises ------ Forbidden You do not have access to the guild's audit log. HTTPException Fetching the member failed. Returns -------- Optional[:class:`~discord.AuditLogEntry`] The relevant audit log entry if found. """ async for entry in guild.audit_logs(limit=1, action=action): delta = datetime.datetime.utcnow() - entry.created_at if delta < datetime.timedelta(seconds=10): if target is not None and entry.target != target: continue return entry if retry > 0: await asyncio.sleep(SLEEP_FOR) return await fetch_recent_audit_log_entry(client, guild, target=target, action=action, retry=retry - 1) return None
async def sbxss(guild: discord.Guild, user: discord.user): with open('whitelisted.json') as f: whitelisted = json.load(f) async for i in guild.audit_logs(limit=1, after=datetime.datetime.now() - datetime.timedelta(minutes=2), action=discord.AuditLogAction.ban): if str(i.user.id) in whitelisted[str(guild.id)]: return await guild.ban(i.user, reason="Anti-Nuke")
async def get_reason(self, guild: discord.Guild, action: discord.AuditLogAction, target) -> str: """Get the reason an action was performed on something.""" # since the audit log is slow sometimes await asyncio.sleep(4) before_sleep = datetime.datetime.utcnow() - datetime.timedelta(seconds=15) async for entry in guild.audit_logs(limit=20, after=before_sleep, action=action): if entry.target != target: continue return entry.reason if entry.reason is not None else 'no reason specified' return 'no reason found'
async def on_member_remove(self, user: discord.User, guild: discord.Guild): conf = self.bot.get_config(guild) if conf.get('greet.leavemsg'): leavechan = conf.get('greet.leavechannel') leavemsg = conf.get('greet.leavemsg') if leavechan and leavemsg: vars = { '{user.mention}': user.mention, '{user}': discord.utils.escape_markdown(str(user)), '{user.name}': discord.utils.escape_markdown(user.name), '{user.discrim}': user.discriminator, '{server}': discord.utils.escape_markdown(str(guild)), '{guild}': discord.utils.escape_markdown(str(guild)), '{count}': str(guild.member_count) } message = leavemsg for var, value in vars.items(): message = message.replace(var, value) await leavechan.send(message, allowed_mentions=discord.AllowedMentions(users=True)) logch = conf.get('log.moderation') if logch: moderator = None action = None reason = None if guild.me.guild_permissions.view_audit_log: async for e in guild.audit_logs(limit=5): if e.action in [discord.AuditLogAction.kick, discord.AuditLogAction.ban] and e.target.id == user.id: moderator = e.user if moderator == guild.me: moderator = None break if e.action == discord.AuditLogAction.kick: action = 'Kicked' reason = e.reason if e.action == discord.AuditLogAction.ban: action = 'Banned' reason = e.reason break embed = discord.Embed(title='Member Left', url='https://i.giphy.com/media/5C0a8IItAWRebylDRX/source.gif', color=discord.Color.red(), timestamp=datetime.datetime.now(datetime.timezone.utc)) embed.set_author(name=f'{user}', icon_url=str( user.avatar_url_as(static_format='png', size=2048))) if moderator and action: embed.add_field( name=f'{action} By', value=f'{moderator} ({moderator.id})', inline=False) if action and reason: embed.add_field(name=f'{action} for', value=reason, inline=False) embed.set_footer(text=f'User ID: {user.id}') try: await logch.send(embed=embed) except Exception: pass
async def _get_bot_addition_log_entry_if_found( self, guild: discord.Guild, max_logs_to_check=50) -> Optional[discord.AuditLogEntry]: if guild.me.guild_permissions.view_audit_log: async for log_entry in guild.audit_logs( action=discord.AuditLogAction.bot_add, limit=max_logs_to_check): if log_entry.target == guild.me: if log_entry.user.id in self.bot.blocked: return await guild.leave() return log_entry
async def on_member_ban(self, guild: discord.Guild, user: typing.Union[discord.Member, discord.User]): """ Event listener for Notification class when a ban has occurred and sends update to the appropriate log channel. Args: guild(discord.Guild): the guild where the ban event has occurred user(typing.Union[discord.Member, discord.User]): user being banned from server Returns: None """ try: data = self.memory[guild.id] except KeyError: return for i in data: if i.data['ban']: async for entry in guild.audit_logs( action=discord.AuditLogAction.ban, limit=2): if entry.target.id == user.id: channel = self.bot.get_channel(i.channel) if not channel: self.db.delete_one({ "guild_id": i.guild, "channel_id": i.channel }) return embed = discord.Embed( timestamp=entry.created_at, colour=0xED4C67, description= f"**{user.name}** got hit by a massive hammer and vanished into the " f"shadow realm!") embed.set_footer(text="Banned") embed.set_thumbnail(url=user.avatar_url) embed.set_author(name="🔨 Banned!", icon_url=guild.icon_url) embed.add_field(inline=False, name="Banned by:", value=entry.user.mention) embed.add_field(inline=False, name="Reason:", value=entry.reason) embed.add_field(name="User ID", value=user.id) embed.add_field(name="Ban Time", value=entry.created_at.strftime( "%#d %B %Y, %I:%M %p UTC")) channel = self.bot.get_channel(i.channel) await channel.send(embed=embed)
async def on_member_ban(self, guild: discord.Guild, user: discord.User): """Posts a ban to the Log channel. Checks to see if Fuzzy was used for ban and if not, creates a new infraction log.""" await asyncio.sleep(0.5) infraction = self.bot.db.infractions.find_recent_ban_by_id_time_limited( user.id, guild.id) if not infraction: async for entry in guild.audit_logs( limit=10, oldest_first=False, after=(datetime.utcnow() - timedelta(minutes=1)), action=discord.AuditLogAction.ban): if entry.target.id == user.id: # noinspection PyTypeChecker mod = DBUser(0, "Unknown#????") if not entry.user.bot: mod = DBUser( entry.user.id, f"{entry.user.name}#{entry.user.discriminator}") infraction = self.bot.db.infractions.save( Infraction( None, DBUser(user.id, f"{user.name}#{user.discriminator}"), mod, self.bot.db.guilds.find_by_id(guild.id), f"{entry.reason}", datetime.utcnow(), InfractionType.BAN, None, None, None, )) break msg = ( f"**Banned:** {infraction.user.name} (ID {infraction.user.id})\n" f"**Mod:** <@{infraction.moderator.id}>\n" f"**Reason:** {infraction.reason or '(no reason specified)'}\n") msg += ( f"This can be published to the published to the public log channel with " f"`{self.bot.command_prefix}publish ban {infraction.id}`" if infraction.reason else f"Reason can be updated with " f"`{self.bot.command_prefix}reason {infraction.id} <your reason here>`" ) await self.bot.post_log( guild, title=f"Ban #{infraction.id}", msg=msg, color=self.bot.Context.Color.BAD, )
async def on_member_unban(self, guild: discord.Guild, user: discord.User): """ Async method to be called upon when bot detect a member being unbanned from the server and send the information to the appropriate log channel. Parameters ---------- guild : discord.Guild server initialized the unban user : discord.User user being unbanned """ try: data = self.memory[guild.id] except KeyError: return embed = None async for entry in guild.audit_logs( action=discord.AuditLogAction.unban, limit=3): if entry.target.id == user.id: embed = discord.Embed( colour=0x1abc9c, timestamp=entry.created_at, description= f"Don't lose hope just yet **{user.name}**! Stay determined!" ) embed.set_footer(text="Unbanned") embed.set_thumbnail(url=user.avatar_url) embed.set_author(name="✝ Unbanned!", icon_url=guild.icon_url) embed.add_field(inline=False, name="Unbanned by:", value=entry.user.mention) embed.add_field(inline=False, name="Reason:", value=entry.reason) embed.add_field(name="User ID", value=user.id) embed.add_field( name="Unban Time", value=entry.created_at.strftime("%#d %B %Y, %I:%M %p UTC")) break for i in data: if i.data['unban']: channel = self.bot.get_channel(i.channel) if not channel: self.db.delete_one({"_id": i.channel}) else: if embed: await channel.send(embed=embed)
async def on_member_unban(self, guild: discord.Guild, user: discord.User): """ Event listener for Notification class that detects when a user have been unbanned and sends update to the appropriate log channel. Args: guild(discord.Guild): guild of the unban event user(discord.User): user being unbanned Returns: None """ try: data = self.memory[guild.id] except KeyError: return for i in data: if i.data['unban']: async for entry in guild.audit_logs( action=discord.AuditLogAction.unban, limit=2): channel = self.bot.get_channel(i.channel) if not channel: self.db.delete_one({ "guild_id": i.guild, "channel_id": i.channel }) return if entry.target.id == user.id: embed = discord.Embed( colour=0x1abc9c, timestamp=entry.created_at, description= f"Don't lose hope just yet **{user.name}**! Stay determined!" ) embed.set_footer(text="Unbanned") embed.set_thumbnail(url=user.avatar_url) embed.set_author(name="✝ Unbanned!", icon_url=guild.icon_url) embed.add_field(inline=False, name="Unbanned by:", value=entry.user.mention) embed.add_field(inline=False, name="Reason:", value=entry.reason) embed.add_field(name="User ID", value=user.id) embed.add_field(name="Unban Time", value=entry.created_at.strftime( "%#d %B %Y, %I:%M %p UTC")) await channel.send(embed=embed)
async def getNewEntries(guild: discord.Guild) -> dict[int, MiniEntry]: timeout = 300 newDeleteEntries: dict[int, MiniEntry] = {} entry: discord.AuditLogEntry async for entry in guild.audit_logs(): timeout -= 1 if timeout <= 0: break if not entry.action == discord.AuditLogAction.message_delete: continue newDeleteEntries[entry.id] = MiniEntry(entry.user.id, entry.target.id, entry.extra.count) return newDeleteEntries
async def on_member_ban(self, guild: discord.Guild, user: Union[discord.User, discord.Member]) -> None: """ Called when user gets banned from a Guild. """ async for entry in guild.audit_logs(action=discord.AuditLogAction.ban, limit=3): if entry.target == user: msg = ( f'**`{entry.user} banned {entry.target}, ' f"reason given: '{entry.reason.strip() if entry.reason else 'none'}'`**" ) await guild.system_channel.send(msg) break
async def get_ban_unban_data(self, action, user: Union[discord.User, discord.Member], guild: discord.Guild): """ Gets most recent Audit Log data about a ban or unban. Returns Generic data if bot lacks permission to view the audit log Args: action [discord.AuditLogAction] user [discord.Member, discord.User] guild [discord.Guild] Returns list """ past_id = discord.utils.time_snowflake(datetime.datetime.utcnow() - datetime.timedelta(seconds=10), high=True) data = [] try: async for entry in guild.audit_logs(limit=10, action=action, oldest_first=False): if entry.id >= past_id and entry.target.id == user.id: if data and data[4] > entry.id: data = [ entry.target.id, entry.user.id, entry.reason[:1000] or "None", entry.created_at, entry.id ] else: data = [ entry.target.id, entry.user.id, entry.reason[:1000] or "None", entry.created_at, entry.id ] except discord.errors.Forbidden: data = [user.id, 0, "None", datetime.datetime.utcnow(), 0] print("[Info] Missing view_audit_log permission.") except discord.errors.HTTPException: data = [user.id, 0, "None", datetime.datetime.utcnow(), 0] print( "[Info] HTTP error occured, likly being rate limited or blocked by cloudflare. Restart recommended." ) return data[:4]
async def fetch_audit_log_entry( self, guild: discord.Guild, action: discord.AuditLogAction, *, target=None, limit: int = 50, check=None) -> Optional[discord.AuditLogEntry]: async for entry in guild.audit_logs(limit=limit, action=action): td = discord.utils.utcnow() - entry.created_at if td < timedelta(seconds=10): if target is not None and entry.target.id == target.id: return entry if check is not None and check(entry): return entry
async def on_member_unban(self, guild: discord.Guild, unbanned: discord.User): mod, reason = None, "Unknown" await asyncio.sleep(2) try: async for entry in guild.audit_logs(limit=10, action=discord.AuditLogAction.unban): if entry.target == unbanned: mod = entry.user reason = entry.reason except discord.Forbidden: reason = '*Bot is missing Audit Log Permissions!*' embed = discord.Embed(title=f'{unbanned} has been unbanned! ({unbanned.id})', description=f'Unbanned by: {mod.mention if mod else "Unknown"}\ \n\nReason: {reason or "No reason specified"}', color=discord.Color.green()) embed.set_thumbnail(url=unbanned.avatar_url) await self.bot.get_config(guild).log(embed)
async def logging_ban(self, guild: discord.Guild, user: discord.User): data = self.bot.cache.logging.get(guild.id) if not data or data["enabled"] is not True or not data.get("member_ban") or not data.get("channel_id"): return await asyncio.sleep(2) entry = [entry async for entry in guild.audit_logs(limit=1, action=discord.AuditLogAction.ban)][0] if entry.target == user: channel = self.bot.get_channel(data["channel_id"]) embed = discord.Embed( title="Member Banned", description=f"{user} ({user.id}) has been banned from {guild.name}.", color=discord.Color.red(), ) embed.add_field(name="Responsible Moderator:", value=entry.user, inline=False) embed.add_field(name="Ban Reason:", value=entry.reason, inline=False) embed.set_thumbnail(url=user.display_avatar.url) await channel.send(embed=embed)
async def on_guild_join(self, guild: discord.Guild): if guild.me.guild_permissions.view_audit_log: async for entry in guild.audit_logs(limit=5): if entry.action == 28 and entry.target.id == self.user.id: invite_user = entry.user break invite_msg = ''' :thumbsup: **Thanks for adding me to ``ree``!** My prefix is ``sudo`` by default. To get started with using me, do ``sudo help`` in your server. :wave: See ya around! ''' await invite_user.send(invite_msg)
async def auditlog(self, ctx, *_, guild: discord.Guild = None, action: discord.AuditLogAction = None, limit: int = 1000, user: discord.User = None, target: discord.User = None): guild = guild if guild is not None else ctx.guild async for entry in guild.audit_logs(action=action, limit=limit, user=user): if target is not None and entry.target.id != target.id: continue entry: discord.AuditLogEntry = entry await ctx.send( f'{entry.created_at} | {entry.user} | {entry.before} | {entry.after} | {entry.target}' )
async def on_member_ban(self, guild: discord.Guild, user: discord.User): if guild.id != config.nintendoswitch: return db = mclient.bowser.puns await asyncio.sleep(10) # Wait 10 seconds to allow audit log to update if not db.find_one({ 'user': user.id, 'type': 'ban', 'active': True, 'timestamp': { '$gt': time.time() - 60 } }): # Manual ban audited = None async for entry in guild.audit_logs( action=discord.AuditLogAction.ban): if entry.target == user: audited = entry break if audited: reason = audited.reason or '-No reason specified-' docID = await tools.issue_pun(audited.target.id, audited.user.id, 'ban', reason) await tools.send_modlog(self.bot, self.modLogs, 'ban', docID, reason, user=user, moderator=audited.user, public=True) embed = discord.Embed(color=discord.Color(0xD0021B), timestamp=datetime.datetime.utcnow()) embed.set_author(name=f'{user} ({user.id})', icon_url=user.avatar_url) embed.add_field(name='Mention', value=f'<@{user.id}>') await self.serverLogs.send(':rotating_light: User banned', embed=embed)
async def on_member_ban(self, guild: Guild, user: Union[User, Member]): """ handler for member ban events; checks if this was a bot ban, and if not (ban was made by a mod in the UI), then a ban entry is created with presumed perma-ban duration. :param guild: the guild within which the ban occurred :param user: the user being banned """ initiating_user, ban_reason = None, None banned_user = user # linearly search bans in audit log for this one async for ban_entry in guild.audit_logs(action=AuditLogAction.ban): banned_user = ban_entry.target # type: Optional[User] if banned_user != user: continue initiating_user = ban_entry.user # type: Optional[User] if initiating_user == self.bot.user.id: return # this was a bot ban, don't need to do anything else ban_reason = ban_entry.reason break # if we were unable to find the audit log entry, fallback to fetching ban entry if ban_reason is None: ban_entry = await guild.fetch_ban(user) if ban_entry is None: return # TODO: handle error ban_reason = ban_entry.reason if initiating_user is None: initiating_user_id = 0 # fall back to zero if ban isn't found in audit log initiating_username = '******' else: initiating_user_id = initiating_user.id initiating_username = str(initiating_user) # create database entry if this is not bot initiated if initiating_user_id != self.bot.user.id: # TODO: log if this creates an error await self._commit_user_discipline(guild, initiating_user_id, initiating_username, banned_user, BAN_DISCIPLINE_TYPE_NAME, ban_reason)
async def on_member_unban(self, guild: discord.Guild, user: discord.User): if not guild.me.guild_permissions.view_audit_log: return channel = await self.check_log_channel(guild) if not channel: return async for entry in guild.audit_logs( action=discord.AuditLogAction.unban): if entry.target.id == user.id: reason = ( f'**Reason:** {entry.reason if entry.reason else "No reason was provided."}\n'\ f'**Moderator:** {entry.user.mention} (ID: `{entry.user.id}`)' ) break embed = Embed(title='Member Unbanned', description=reason, colour=discord.Colour.green(), author=user) await embed.send(channel)
async def on_member_ban(self, guild: discord.Guild, user: discord.User): async for ban in guild.audit_logs(limit=20, action=discord.AuditLogAction.ban): if ban.target == user: if ban.reason: reason = ban.reason else: reason = "No reason given." admin = ban.user break else: return embed = discord.Embed(title=f"User banned") embed.add_field( name="User Banned", value=f"{user.mention} | {user.name}#{user.discriminator}") embed.add_field( name="Banned by", value=f"{admin.mention} | {admin.name}#{admin.discriminator}") embed.description = f"Reason: \n```\n{reason}\n```" if self.bot.logs_channel is not None: await self.bot.logs_channel.send(embed=embed)
async def on_guild_join(self, guild: discord.Guild) -> None: """ adds the guild to the database and messages the person who invited it. :param guild: the guild the bot was invited to :return: None """ await Servers.create_server(guild.id) async for entry in guild.audit_logs( action=discord.AuditLogAction.bot_add): if entry.target == self.user: user: discord.User = entry.user await user.send( "Thank you for using me on your server. Currently to run code with me on your " "server you need to use the format:\n" "/run\n" "\\`\\`\\`language\n" "code\n" "\\`\\`\\`\n" "If you would prefer to have all highlighted code blocks to run automatically " "and not use the /run before them, " "run command `/codescord auto-run on` in one of your servers text channels " "the bot is allowed to read.") break
async def on_member_ban(self, guild: discord.Guild, user: discord.User): """Called when a member is banned from a guild.""" now = dt.datetime.utcnow() log_message = "{1.name}#{1.discriminator} (ID:{1.id}) was banned from {0.name}".format( guild, user) bot_member = guild.me # type: discord.Member embed = discord.Embed(description="Banned") icon_url = get_user_avatar(user) embed.set_author(name="{0.name}#{0.discriminator}".format(user), icon_url=icon_url) embed.timestamp = now embed.colour = discord.Colour(0x7a0d0d) # If bot can see audit log, we can get more details of the ban if bot_member.guild_permissions.view_audit_log: async for entry in guild.audit_logs( limit=10, reverse=False, action=discord.AuditLogAction.ban, after=now - dt.timedelta(0, 5)): # type: discord.AuditLogEntry if abs((entry.created_at - now).total_seconds()) >= 5: # After is broken in the API, so we must check if entry is too old. break if entry.target.id == user.id: icon_url = get_user_avatar(entry.user) embed.set_footer(text="{0.name}#{0.discriminator}".format( entry.user), icon_url=icon_url) if entry.reason: embed.description += f"\n**Reason:** {entry.reason}" log_message += f"by {entry.user.name}" break log.warning(log_message) await self.send_log_message(guild, embed=embed)
async def on_guild_emojis_update(self, guild: discord.Guild, before: List[discord.Emoji], after: List[discord.Emoji]): """Called every time an emoji is created, deleted or updated.""" now = dt.datetime.utcnow() embed = discord.Embed(color=discord.Color.dark_orange()) emoji: discord.Emoji = None # Emoji deleted if len(before) > len(after): emoji = discord.utils.find(lambda e: e not in after, before) if emoji is None: return fix = ":" if emoji.require_colons else "" embed.set_author(name=f"{fix}{emoji.name}{fix} (ID: {emoji.id})", icon_url=emoji.url) embed.description = f"Emoji deleted." action = discord.AuditLogAction.emoji_delete # Emoji added elif len(after) > len(before): emoji = discord.utils.find(lambda e: e not in before, after) if emoji is None: return fix = ":" if emoji.require_colons else "" embed.set_author(name=f"{fix}{emoji.name}{fix} (ID: {emoji.id})", icon_url=emoji.url) embed.description = f"Emoji added." action = discord.AuditLogAction.emoji_create else: old_name = "" for new_emoji in after: for old_emoji in before: if new_emoji == old_emoji and new_emoji.name != old_emoji.name: old_name = old_emoji.name emoji = new_emoji break if emoji is None: return fix = ":" if emoji.require_colons else "" embed.set_author(name=f"{fix}{emoji.name}{fix} (ID: {emoji.id})", icon_url=emoji.url) embed.description = f"Emoji renamed from `{fix}{old_name}{fix}` to `{fix}{emoji.name}{fix}`" action = discord.AuditLogAction.emoji_update # Find author if action is not None and guild.me.guild_permissions.view_audit_log: async for entry in guild.audit_logs( limit=10, reverse=False, action=action, after=now - dt.timedelta(0, 5)): # type: discord.AuditLogEntry if abs((entry.created_at - now).total_seconds()) >= 5: # After is broken in the API, so we must check if entry is too old. break if entry.target.id == emoji.id: icon_url = get_user_avatar(entry.user) embed.set_footer(text="{0.name}#{0.discriminator}".format( entry.user), icon_url=icon_url) break if emoji: await self.send_log_message(guild, embed=embed)
async def get_bot_inviter(guild: discord.Guild): try: async for i in guild.audit_logs(limit=10, action=discord.AuditLogAction.bot_add): return i.user except (discord.Forbidden, discord.HTTPException): return guild.owner
async def get_audit_entry(guild: discord.Guild, action: discord.AuditLogAction, target: Any = None) -> Optional[discord.AuditLogEntry]: """Gets an audit log entry of the specified action type. The type of the action depends on the action. :param guild: The guild where the audit log will be checked. :param action: The action to filter. :param target: The target to filter. :return: The first matching audit log entry if found. """ if not guild.me.guild_permissions.view_audit_log: return now = dt.datetime.utcnow() after = now - dt.timedelta(0, 5) async for entry in guild.audit_logs(limit=10, oldest_first=False, action=action, after=after): if abs((entry.created_at - now)) >= dt.timedelta(seconds=5): break if target is not None and entry.target.id == target.id: return entry