Example #1
0
    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
Example #2
0
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
Example #3
0
    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.")
Example #4
0
    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)
Example #5
0
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)
Example #6
0
    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.")
Example #7
0
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
Example #8
0
    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)
Example #9
0
 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)