def insert_note(*, user: User, author: User, type_: RecordType, timestamp: datetime=None, expires: datetime=None, body: str) -> Record: # Validation/defaults if timestamp is None: timestamp = datetime.utcnow() logger.info("Inserting note...") logger.debug("note: user={!r} author={!r} type={.name} timestamp={} expires={} body={!r}" .format( user, author, type_, get_timestamp_str(timestamp), get_timestamp_str(expires) if expires else None, body) ) rec = Record(user=user, author=author, type=type_, timestamp=timestamp, expires=expires, body=body) session.add(rec) session.commit() return rec
def message_log_str(message: discord.Message) -> str: """ Convert a :cls:`discord.Message` object to a string suitable for logging or tracing the message. Format looks like: [2012-01-01 12:34:56] <#channel:username#1234> "Message here" """ return "[{}] <#{!s}:{!s}> {!r}"\ .format(get_timestamp_str(message), message.channel, message.author, message.content)
async def on_message(self, message): """ Message handler. Check all non-mod messages for filtered words. """ is_mod = check_role( self.config.get("discord", "mod_roles", []) + self.config.get("discord", "admin_roles", []), message) is_pm = isinstance(message.channel, discord.PrivateChannel) if not is_mod and not is_pm: message_string = str(message.content) del_match = self.engines['delete'].check_message(message_string) warn_match = self.engines['warn'].check_message(message_string) # logging if del_match or warn_match: if del_match: log_fmt = "Found filter match [auto-delete] '{1}' in {0}" else: # is_warn log_fmt = "Found filter match (auto-warn) '{2}' in {0}" logger.info( log_fmt.format(message_log_str(message), del_match, warn_match)) # delete if del_match: logger.debug("Deleting message") await self.bot.delete_message(message) # warn if del_match or warn_match: logger.debug("Preparing and sending filter warning") filter_type = 'delete' if del_match else 'warn' match_text = del_match if del_match else warn_match em = discord.Embed(color=self.match_warn_color[filter_type]) em.set_author(name=self.match_headings[filter_type]) em.add_field(name="User", value=message.author.mention, inline=True) em.add_field(name="Channel", value=message.channel.mention, inline=True) em.add_field(name="Timestamp", value=get_timestamp_str(message), inline=True) em.add_field(name="Match Text", value=match_text, inline=True) em.add_field(name="Content", value=natural_truncate(message_string, Limits.EMBED_FIELD_VALUE), inline=False) await self.bot.send_message(self.dest_current, embed=em)
async def request(self, ctx, *, content: str): """ Submit a bug report or feature request to the bot DevOps Team. Everyone can use this, but please make sure that your request is clear and has enough enough details. This is especially true for us to be able to track down and fix bugs: we need information like what were you trying to do, what did you expect to happen, what actually happened? Quote exact error messages and give dates/times). Please note that any submissions made via this system may be publicly tracked via the GitHub repo. By submitting a request via this system, you give us permission to post your username and message, verbatim or altered, to a public issue tracker for the purposes of bot development and project management. Abuse may be treated in the same way as other forms of spam on the Discord server. """ logger.debug("request(): {}".format(message_log_str(ctx.message))) em = discord.Embed(color=0x80AAFF) em.set_author(name="User Issue Submission") em.add_field(name="User", value=ctx.message.author.mention, inline=True) try: em.add_field(name="Channel", value=ctx.message.channel.mention, inline=True) except AttributeError: # probably a private channel em.add_field(name="Channel", value=ctx.message.channel, inline=True) em.add_field(name="Timestamp", value=get_timestamp_str(ctx.message), inline=True) em.add_field(name="Content", value=content, inline=False) await self.bot.send_message(self.ch_request, embed=em) await self.bot.say( "Your issue was submitted to the bot DevOps team. " "If you have any questions or if there's an urgent problem, " "please feel free to contact the moderators.")
async def show_records(self, dest: discord.Object, *, user: Optional[User], records: List[Record], group: List[User] = None, box_title: str, page: int = None, total_pages: int = 1, total_records: int = None, short=False): if group is not None: group_users = group else: group_users = [] embed_color = 0xAA80FF title = box_title if page is not None: footer = 'Page {}/{} (Total {} records)'.format( page, total_pages, total_records) else: footer = '' # must be empty string for len() later, not None user_fields = OrderedDict() def make_embed() -> discord.Embed: return discord.Embed(color=embed_color, title=title) if not short and user: user_fields[user.name] = self.format_display_user(user) user_fields['Aliases'] = '\n'.join(a.name for a in user.aliases) or 'None' if group_users: user_fields['Links'] = '\n'.join( user_mention(u.discord_id) for u in group_users if u != user) or 'None' len_user_info = len(title) + len(footer) total_fields = len(user_fields) em = make_embed() for field_name, field_value in user_fields.items(): em.add_field(name=field_name, value=field_value, inline=True) len_user_info += len(field_name) + len(field_value) # separator if not short: sep_name = 'Records Listing' sep_value = self.EMBED_SEPARATOR em.add_field(name=sep_name, value=sep_value, inline=False) total_fields += 1 len_user_info += len(sep_name) + len(sep_value) len_records = 0 for rec in records: # Compile record info record_fields = OrderedDict() rec_title = "Record #{:04d}".format(rec.record_id) record_fields[rec_title] = get_timestamp_str( rec.timestamp) + ' UTC' if rec.expires: expire_str = get_timestamp_str(rec.expires) + ' UTC' if rec.expires <= datetime.utcnow(): record_fields['Expires'] = expire_str + '\n**EXPIRED**' else: record_fields['Expires'] = expire_str else: record_fields['Expires'] = 'Never' # If this record is from a grouped user, show this if user and rec.user_id != user.user_id: record_fields['Linked from'] = self.format_display_user( rec.user) elif short: # If no user info section, show the record user individually record_fields['User'] = "******"\ .format(rec.user.name, self.format_display_user(rec.user)) contents = ('{} by {}'.format(rec.type.name.title(), rec.author.name), '{}{}'.format(rec.body[:self.EMBED_FIELD_LEN], self.EMBED_SEPARATOR)) fields_rec = len(record_fields) + 1 len_rec = sum(len(name) + len(value) for name, value in record_fields.items()) + \ sum(len(s) for s in contents) # If the length is too long, split the message here # Kinda hacky, we send the current embed and rebuild a new one here # 0.95 safety factor - I don't know how Discord counts the 6000 embed limit... too_many_fields = total_fields + fields_rec > Limits.EMBED_FIELD_NUM embed_too_long = len_user_info + len_records + len_rec > int( 0.95 * Limits.EMBED_TOTAL) if too_many_fields or embed_too_long: await self.bot.send_message(dest, embed=em) em = make_embed() len_user_info = len(title) # that's all for this next embed len_records = 0 total_fields = 0 # Configure record info in embed for field_name, field_value in record_fields.items(): em.add_field(name=field_name, value=field_value, inline=True) len_records += len(field_name) + len(field_value) em.add_field(name=contents[0], value=contents[1], inline=False) len_records += len_rec total_fields += fields_rec if footer: em.set_footer(text=footer) await self.bot.send_message(dest, embed=em)