async def on_raw_message_delete(self, data: RawMessageDeleteEvent): message = LoggedMessage.get_or_none(messageid=data.message_id) if message is not None: channel: discord.TextChannel = self.bot.get_channel( data.channel_id) user: discord.User = self.bot.get_user(message.author) hasUser = user is not None if hasUser and user.id in Configuration.getConfigVar( channel.guild.id, "IGNORED_USERS"): return channelid = Configuration.getConfigVar(channel.guild.id, "MINOR_LOGS") if channelid is not 0: logChannel: discord.TextChannel = self.bot.get_channel( channelid) if logChannel is not None and message.content != None and message.content != "": embed = discord.Embed( timestamp=datetime.datetime.utcfromtimestamp( time.time()), description=message.content) embed.set_author( name=user.name if hasUser else message.author, icon_url=user.avatar_url if hasUser else EmptyEmbed) embed.set_footer(text=f"Sent in #{channel.name}") name = Utils.clean_user(user) if hasUser else str( message.author) await logChannel.send( f":wastebasket: {Translator.translate('message_removed', channel.guild.id, name=name, user_id=user.id if hasUser else 'WEBHOOK', channel=channel.mention)}", embed=embed)
async def fetch_messages(ctx, message_id, channel_id): message = None logged_message = LoggedMessage.get_or_none(messageid=message_id) async with ctx.typing(): if logged_message is None: if channel_id is None: for channel in ctx.guild.text_channels: try: permissions = channel.permissions_for( channel.guild.me) if permissions.read_messages and permissions.read_message_history: message = await channel.fetch_message( message_id) channel_id = channel.id break except (NotFound, Forbidden): pass if message is None: raise TranslatedBadArgument('message_missing_channel', ctx) elif channel_id is None: channel_id = logged_message.channel channel = ctx.bot.get_channel(channel_id) if channel is None: raise TranslatedBadArgument('unknown_channel', ctx) elif message is None: try: permissions = channel.permissions_for(channel.guild.me) if permissions.read_messages and permissions.read_message_history: message = await channel.fetch_message(message_id) except (NotFound, Forbidden): raise TranslatedBadArgument('unknown_message', ctx) return logged_message, message
async def quote(self, ctx:commands.Context, message_id:int): """quote_help""" embed = None async with ctx.typing(): message = LoggedMessage.get_or_none(messageid=message_id) if message is None: for guild in self.bot.guilds: for channel in guild.text_channels: try: dmessage: discord.Message = await channel.get_message(message_id) for a in dmessage.attachments: LoggedAttachment.get_or_create(id=a.id, url=a.url, isImage=(a.width is not None or a.width is 0), messageid=message.id) message = LoggedMessage.create(messageid=message_id, content=dmessage.content, author=dmessage.author.id, timestamp = dmessage.created_at.timestamp(), channel=channel.id, server=dmessage.guild.id) except Exception as ex: #wrong channel pass if message is not None: break if message is not None: channel = self.bot.get_channel(message.channel) attachment = None attachments = LoggedAttachment.select().where(LoggedAttachment.messageid == message_id) if len(attachments) == 1: attachment = attachments[0] embed = discord.Embed(colour=discord.Color(0xd5fff), timestamp=datetime.utcfromtimestamp(message.timestamp)) if message.content is None or message.content == "": if attachment is not None: if attachment.isImage: embed.set_image(url=attachment.url) else: embed.add_field(name=Translator.translate("attachement_link", ctx), value=attachment.url) else: description = message.content embed = discord.Embed(colour=discord.Color(0xd5fff), description=description, timestamp=datetime.utcfromtimestamp(message.timestamp)) embed.add_field(name="", value=f"https://discordapp.com/channels/{channel.guild.id}/{channel.id}/{message_id}") if attachment is not None: if attachment.isImage: embed.set_image(url=attachment.url) else: embed.add_field(name=Translator.translate("attachement_link", ctx), value=attachment.url) try: user = await commands.MemberConverter().convert(ctx, message.author) except: user = await ctx.bot.get_user_info(message.author) embed.set_author(name=user.name, icon_url=user.avatar_url) embed.set_footer(text=Translator.translate("quote_footer", ctx, channel=self.bot.get_channel(message.channel).name, user=Utils.clean(ctx.author.display_name), message_id=message_id)) if embed is None: await ctx.send(Translator.translate("quote_not_found", ctx)) else: if channel.is_nsfw() and not ctx.channel.is_nsfw(): await ctx.send(f"{Emoji.get_chat_emoji('NO')} {Translator.translate('quote_nsfw_refused', ctx)}") return await ctx.send(embed=embed) if ctx.channel.permissions_for(ctx.me).manage_messages: await ctx.message.delete()
async def on_raw_bulk_message_delete(self, event: discord.RawBulkMessageDeleteEvent): if Features.is_logged(event.guild_id, "EDIT_LOGS"): message_list = dict() for mid in event.message_ids: message = LoggedMessage.get_or_none(LoggedMessage.messageid == mid) if message is not None: message_list[mid] = message if len(message_list) > 0: await Archive.archive_purge(self.bot, event.guild_id, collections.OrderedDict(sorted(message_list.items())))
async def buildCache(self, guild: discord.Guild, limit=None, startup=False): if limit is None: limit = 500 if startup else 50 GearbotLogging.info(f"Populating modlog with missed messages during downtime for {guild.name} ({guild.id}).") newCount = 0 editCount = 0 count = 0 no_access = 0 fetch_times = [] processing_times = [] for channel in guild.text_channels: permissions = channel.permissions_for(guild.get_member(self.bot.user.id)) if permissions.read_messages and permissions.read_message_history: async for message in channel.history(limit=limit, reverse=False, before=self.cache_message if startup else None): processing = time.perf_counter() if not self.running: GearbotLogging.info("Cog unloaded while still building cache, aborting.") return fetch = time.perf_counter() logged = LoggedMessage.get_or_none(messageid=message.id) fetch_times.append(time.perf_counter() - fetch) if logged is None: LoggedMessage.create(messageid=message.id, author=message.author.id, content=message.content, channel=channel.id, server=channel.guild.id) for a in message.attachments: LoggedAttachment.create(id=a.id, url=a.url, isImage=(a.width is not None or a.width is 0), messageid=message.id) newCount = newCount + 1 elif message.edited_at is not None: if logged.content != message.content: logged.content = message.content logged.save() editCount = editCount + 1 count = count + 1 processing_times.append(time.perf_counter() - processing) if count % min(75, int(limit / 2)) is 0: await asyncio.sleep(0) await asyncio.sleep(0) else: no_access += 1 GearbotLogging.info( f"Discovered {newCount} new messages and {editCount} edited in {guild.name} (checked {count})") total_fetch_time = sum(fetch_times) avg_fetch_time = (total_fetch_time / len(fetch_times)) * 1000 total_processing = (sum(processing_times)) * 1000 avg_processing = total_processing / len(processing_times) GearbotLogging.info(f"Average fetch time: {avg_fetch_time} (total fetch time: {total_fetch_time})") GearbotLogging.info(f"Average processing time: {avg_processing} (total of {total_processing})") GearbotLogging.info(f"Was unable to read messages from {no_access} channels")
async def on_raw_bulk_message_delete( self, event: discord.RawBulkMessageDeleteEvent): channel_id = Configuration.getConfigVar(event.guild_id, "MINOR_LOGS") if channel_id is not 0: message_list = dict() for mid in event.message_ids: message = LoggedMessage.get_or_none( LoggedMessage.messageid == mid) if message is not None: message_list[mid] = message await Archive.archive( self.bot, event.guild_id, collections.OrderedDict(sorted(message_list.items())))
async def get_message_data(bot, message_id): message = None if is_cache_enabled(bot) and not Object( message_id).created_at <= datetime.utcfromtimestamp(time.time() - 5 * 60): parts = await bot.redis_pool.hgetall(message_id) if len(parts) is 4: message = Message(message_id, int(parts["author"]), parts["content"], int(parts["channel"]), int(parts["server"])) if message is None: message = LoggedMessage.get_or_none( LoggedMessage.messageid == message_id) return message
async def on_raw_message_edit(self, event: RawMessageUpdateEvent): if event.data["channel_id"] == Configuration.getMasterConfigVar( "BOT_LOG_CHANNEL"): return message = LoggedMessage.get_or_none(messageid=event.message_id) if message is not None and "content" in event.data: channel: discord.TextChannel = self.bot.get_channel( int(event.data["channel_id"])) user: discord.User = self.bot.get_user(message.author) hasUser = user is not None channelid = Configuration.getConfigVar(channel.guild.id, "MINOR_LOGS") if channelid is not 0: logChannel: discord.TextChannel = self.bot.get_channel( channelid) if logChannel is not None: if message.content == event.data["content"]: #prob just pinned return if message.content is None or message.content == "": message.content = f"<{Translator.translate('no_content', channel.guild.id)}>" embed = discord.Embed(timestamp=datetime.datetime. utcfromtimestamp(time.time())) embed.set_author( name=user.name if hasUser else message.author, icon_url=user.avatar_url if hasUser else EmptyEmbed) embed.set_footer( text=Translator.translate('sent_in', channel.guild.id, channel=f"#{channel.name}")) embed.add_field( name=Translator.translate('before', channel.guild.id), value=Utils.trim_message(message.content, 1024), inline=False) embed.add_field( name=Translator.translate('after', channel.guild.id), value=Utils.trim_message(event.data["content"], 1024), inline=False) if not (hasUser and user.id in Configuration.getConfigVar( channel.guild.id, "IGNORED_USERS")): await logChannel.send( f":pencil: {Translator.translate('edit_logging', channel.guild.id, user=Utils.clean_user(user), user_id=user.id, channel=channel.mention)}", embed=embed) message.content = event.data["content"] message.save()
async def get_message_data(bot, message_id): message = None if is_cache_enabled(bot) and not Object( message_id).created_at <= datetime.utcfromtimestamp(time.time() - 5 * 60): parts = await bot.redis_pool.hgetall(f"messages:{message_id}") if len(parts) is 5: message = Message( message_id, int(parts["author"]), parts["content"], int(parts["channel"]), int(parts["server"]), parts["attachments"].split("|") if len(parts["attachments"]) > 0 else [], type=int(parts["type"]) if "type" in parts else None) if message is None: message = LoggedMessage.get_or_none( LoggedMessage.messageid == message_id) return message
async def on_raw_message_edit(self, event: RawMessageUpdateEvent): if event.data["channel_id"] == Configuration.get_master_var("BOT_LOG_CHANNEL"): return message = LoggedMessage.get_or_none(messageid=event.message_id) if message is not None and "content" in event.data and Features.is_logged(message.server, "EDIT_LOGS"): channel: discord.TextChannel = self.bot.get_channel(int(event.data["channel_id"])) if channel.guild is None: return user: discord.User = self.bot.get_user(message.author) hasUser = user is not None if message.content == event.data["content"]: # prob just pinned return if message.content is None or message.content == "": message.content = f"<{Translator.translate('no_content', channel.guild.id)}>" after = event.data["content"] if after is None or after == "": after = f"<{Translator.translate('no_content', channel.guild.id)}>" if not (hasUser and user.id in Configuration.get_var(channel.guild.id, "IGNORED_USERS") or user.id == channel.guild.me.id): GearbotLogging.log_to(channel.guild.id, "EDIT_LOGS", f":pencil: {Translator.translate('edit_logging', channel.guild.id, user=Utils.clean_user(user), user_id=user.id, channel=channel.mention)}") if Configuration.get_var(channel.guild.id, "EMBED_EDIT_LOGS"): embed = discord.Embed(timestamp=datetime.datetime.utcfromtimestamp(time.time())) embed.set_author(name=user.name if hasUser else message.author, icon_url=user.avatar_url if hasUser else EmptyEmbed) embed.set_footer( text=Translator.translate('sent_in', channel.guild.id, channel=f"#{channel.name}")) embed.add_field(name=Translator.translate('before', channel.guild.id), value=Utils.trim_message(message.content, 1024), inline=False) embed.add_field(name=Translator.translate('after', channel.guild.id), value=Utils.trim_message(after, 1024), inline=False) GearbotLogging.log_to(channel.guild.id, "EDIT_LOGS", embed=embed) else: clean_old = await Utils.clean(message.content, channel.guild) clean_new = await Utils.clean(after, channel.guild) GearbotLogging.log_to(channel.guild.id, "EDIT_LOGS", f"**Old:** {clean_old}", can_stamp=False) GearbotLogging.log_to(channel.guild.id, "EDIT_LOGS", f"**New:** {clean_new}", can_stamp=False) message.content = event.data["content"] message.save()
async def on_raw_message_delete(self, data: RawMessageDeleteEvent): if data.message_id in self.bot.data["message_deletes"]: self.bot.data["message_deletes"].remove(data.message_id) return message = LoggedMessage.get_or_none(messageid=data.message_id) if message is not None and Features.is_logged(message.server, "EDIT_LOGS"): guild = self.bot.get_guild(message.server) user: discord.User = self.bot.get_user(message.author) hasUser = user is not None if not hasUser or user.id in Configuration.get_var(guild.id, "IGNORED_USERS") or user.id == guild.me.id: return attachments = LoggedAttachment.select().where(LoggedAttachment.messageid == data.message_id) channel = self.bot.get_channel(message.channel) name = Utils.clean_user(user) if hasUser else str(message.author) GearbotLogging.log_to(guild.id, "EDIT_LOGS", f":wastebasket: {Translator.translate('message_removed', guild.id, name=name, user_id=user.id if hasUser else 'WEBHOOK', channel=channel.mention)}") if Configuration.get_var(channel.guild.id, "EMBED_EDIT_LOGS"): embed = discord.Embed(timestamp=datetime.datetime.utcfromtimestamp(time.time()), description=message.content) embed.set_author(name=user.name if hasUser else message.author, icon_url=user.avatar_url if hasUser else EmptyEmbed) embed.set_footer(text=f"Sent in #{channel.name}") if len(attachments) > 0: embed.add_field(name=Translator.translate('attachment_link', guild), value="\n".join(attachment.url for attachment in attachments)) GearbotLogging.log_to(guild.id, "EDIT_LOGS", embed=embed) else: cleaned_content = await Utils.clean(message.content, channel.guild) GearbotLogging.log_to(guild.id, "EDIT_LOGS", f"**Content:** {cleaned_content}", can_stamp=False) count = 1 for attachment in attachments: GearbotLogging.log_to(guild.id, "EDIT_LOGS", f"**Attachment{f' {count}' if len(attachments) > 1 else ''}:** <{attachment.url}>", can_stamp=False) count += 1