Esempio n. 1
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_,
                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
Esempio n. 2
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(get_timestamp_str(message),
                message.channel, message.author, message.content)
Esempio n. 3
0
    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)
Esempio n. 4
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=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.")
Esempio n. 5
0
    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)