def _get_record_fields(self, record: Record, show_user=False, show_grouped_user=False)\ -> (OrderedDict, OrderedDict): record_fields = OrderedDict() rec_title = "Record {}".format(self.format_record_id(record.record_id)) record_fields[rec_title] = format_timestamp(record.timestamp) if record.expires: expire_str = format_timestamp(record.expires) if record.expires <= datetime.utcnow(): record_fields['Expires'] = expire_str + '\n**EXPIRED**' else: record_fields['Expires'] = expire_str else: record_fields['Expires'] = 'Never' if show_grouped_user: record_fields['Linked from'] = self.format_display_user( record.user) elif show_user: record_fields['User'] = "******" \ .format(record.user.name, self.format_display_user(record.user)) contents = OrderedDict() content_title = '{} by {}'.format(record.type.name.title(), record.author.name) contents[content_title] = '{}{}'\ .format(record.body[:self.EMBED_FIELD_LEN], self.EMBED_SEPARATOR) return record_fields, contents
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_, format_timestamp(timestamp), format_timestamp(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
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=format_timestamp(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 on_message(self, message: discord.Message): """ Message handler. Check all non-mod messages for filtered words. """ is_mod = check_role( self.config.discord.get("mod_roles", []) + self.config.discord.get("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=format_timestamp(message), inline=True) em.add_field(name="Match Text", value=match_text, inline=True) em.add_field(name="Message Link", value='[Message link]({})'.format( get_jump_url(message)), inline=True) em.add_field(name="Content", value=natural_truncate(message_string, Limits.EMBED_FIELD_VALUE), inline=False) await self.bot.send_message(self.channel_current, embed=em)
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(format_timestamp(message), message.channel, message.author, message.content)
async def request(self, ctx, *, content: str): """!kazhelp description: Submit a bug report or feature request to the {{name}} bot team. details: | Everyone can use this command, but please make sure that: * Your issue is clear and sufficiently detailed. * You submit **one issue per command**. Do not include multiple issues in one command, or split up one issue into multiple commands. Otherwise the bot team will get mad at you =P If you're reporting a bug, include the answers to the questions: * What were you trying to do? Include the *exact* command you tried to use, if any. * What error messages were given by the bot? *Exact* message. * Where and when did this happen? Ideally, link the message itself (message menu > Copy Link). IMPORTANT: Any submissions made via this system may be tracked publicly. By submitting a request via this system, you give us permission to post your username and message, verbatim or altered, to a public database for the purpose of project management. IMPORTANT: Abuse of this command may be treated as channel spam, and enforced accordingly. NOTE: The three command names do not differ from each other. They are defined purely for convenience. examples: - command: | .request When trying to use the `.roll 3d20` command, I get the message: "An error occurred! Details have been logged. Let a mod know so we can investigate." This only happens with d20, I've tried d12 and d6 with no problems. The last time this happened in #tabletop on 2018-01-31 at 5:24PM PST. """ 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=format_timestamp(ctx.message), inline=True) em.add_field(name="Content", value=content, inline=False) await self.bot.send_message(self.cog_config.channel_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.")
def insert_join(*, user: User, direction: JoinDirection, timestamp: datetime = None) -> JoinRecord: # Validation/defaults if timestamp is None: timestamp = datetime.utcnow() logger.info("Inserting join record...") logger.debug("join: user={!r} direction={.name} timestamp={}".format( user, direction, format_timestamp(timestamp))) rec = JoinRecord(user=user, direction=direction, timestamp=timestamp) session.add(rec) session.commit() return rec
def merge_records_joins(self, r: Sequence[Record], j: Sequence[JoinRecord]): """ Merge display strings for joins into a record list ready for display. """ # we want to append records coming *after* the record into the record preceding it # so let's iterate backwards rr = reversed(tuple(heapq.merge(r, j, key=lambda x: x.timestamp))) rmerged = [] join_strings = [] for record in rr: if isinstance(record, JoinRecord): dir_mark = r'\>\>\> JOIN' if record.direction == JoinDirection.join else r'<<< PART' ts = format_timestamp(record.timestamp) u = self.format_display_user(record.user) join_strings.append("**{} {} {}**".format(dir_mark, ts, u)) elif isinstance(record, Record): record.display_append = '\n'.join(reversed(join_strings)) rmerged.append(record) join_strings.clear() else: raise TypeError(record) if join_strings: # still some join strings left w/o a record rmerged.append(DummyRecord(text='\n'.join(reversed(join_strings)))) return reversed(rmerged)
def __repr__(self): return "<JoinRecord(join_id={:d}, timestamp={}, user_id={:d}, direction={.name})>" \ .format(self.join_id, format_timestamp(self.timestamp), self.user_id, self.direction)