示例#1
0
    async def on_member_ban(self, guild: discord.Guild,
                            member: discord.Member) -> None:
        """Log ban event to user log."""
        if guild.id != GuildConstant.id:
            return

        if member.id in self._ignored[Event.member_ban]:
            self._ignored[Event.member_ban].remove(member.id)
            return

        await self.send_log_message(
            Icons.user_ban,
            Colours.soft_red,
            "User banned",
            format_user(member),
            thumbnail=member.avatar_url_as(static_format="png"),
            channel_id=Channels.user_log)
示例#2
0
文件: antispam.py 项目: Kronifer/bot
    async def upload_messages(self, actor_id: int, modlog: ModLog) -> None:
        """Method that takes care of uploading the queue and posting modlog alert."""
        triggered_by_users = ", ".join(format_user(m) for m in self.members)
        triggered_in_channel = f"**Triggered in:** {self.triggered_in.mention}\n" if len(
            self.channels) > 1 else ""
        channels_description = ", ".join(channel.mention
                                         for channel in self.channels)

        mod_alert_message = (
            f"**Triggered by:** {triggered_by_users}\n"
            f"{triggered_in_channel}"
            f"**Channels:** {channels_description}\n"
            f"**Rules:** {', '.join(rule for rule in self.rules)}\n")

        messages_as_list = list(self.messages.values())
        first_message = messages_as_list[0]
        # For multiple messages and those with attachments or excessive newlines, use the logs API
        if any((len(messages_as_list) > 1, len(first_message.attachments) > 0,
                first_message.content.count('\n') > 15)):
            url = await modlog.upload_log(self.messages.values(), actor_id,
                                          self.attachments)
            mod_alert_message += f"A complete log of the offending messages can be found [here]({url})"
        else:
            mod_alert_message += "Message:\n"
            content = first_message.clean_content
            remaining_chars = 4080 - len(mod_alert_message)

            if len(content) > remaining_chars:
                url = await modlog.upload_log([first_message], actor_id,
                                              self.attachments)
                log_site_msg = f"The full message can be found [here]({url})"
                content = content[:remaining_chars -
                                  (3 + len(log_site_msg))] + "..."

            mod_alert_message += content

        await modlog.send_log_message(
            icon_url=Icons.filtering,
            colour=Colour(Colours.soft_red),
            title="Spam detected!",
            text=mod_alert_message,
            thumbnail=first_message.author.display_avatar.url,
            channel_id=Channels.mod_alerts,
            ping_everyone=AntiSpamConfig.ping_everyone)
示例#3
0
文件: modlog.py 项目: kwzrd/pydis-bot
    async def on_member_join(self, member: discord.Member) -> None:
        """Log member join event to user log."""
        if member.guild.id != GuildConstant.id:
            return

        now = datetime.utcnow()
        difference = abs(relativedelta(now, member.created_at))

        message = format_user(member) + "\n\n**Account age:** " + humanize_delta(difference)

        if difference.days < 1 and difference.months < 1 and difference.years < 1:  # New user account!
            message = f"{Emojis.new} {message}"

        await self.send_log_message(
            Icons.sign_in, Colours.soft_green,
            "User joined", message,
            thumbnail=member.avatar_url_as(static_format="png"),
            channel_id=Channels.user_log
        )
示例#4
0
    async def pardon_voice_ban(self, user_id: int, guild: discord.Guild, reason: t.Optional[str]) -> t.Dict[str, str]:
        """Add Voice Verified role back to user, DM them a notification, and return a log dict."""
        user = guild.get_member(user_id)
        log_text = {}

        if user:
            # DM user about infraction expiration
            notified = await _utils.notify_pardon(
                user=user,
                title="Voice ban ended",
                content="You have been unbanned and can verify yourself again in the server.",
                icon_url=_utils.INFRACTION_ICONS["voice_ban"][1]
            )

            log_text["Member"] = format_user(user)
            log_text["DM"] = "Sent" if notified else "**Failed**"
        else:
            log_text["Info"] = "User was not found in the guild."

        return log_text
示例#5
0
    async def upload_messages(self, actor_id: int, modlog: ModLog) -> None:
        """Method that takes care of uploading the queue and posting modlog alert."""
        triggered_by_users = ", ".join(format_user(m) for m in self.members)
        triggered_in_channel = f"**Triggered in:** {self.triggered_in.mention}\n" if len(self.channels) > 1 else ""
        channels_description = ", ".join(channel.mention for channel in self.channels)

        mod_alert_message = (
            f"**Triggered by:** {triggered_by_users}\n"
            f"{triggered_in_channel}"
            f"**Channels:** {channels_description}\n"
            f"**Rules:** {', '.join(rule for rule in self.rules)}\n"
        )

        # For multiple messages or those with excessive newlines, use the logs API
        if len(self.messages) > 1 or 'newlines' in self.rules:
            url = await modlog.upload_log(self.messages.values(), actor_id, self.attachments)
            mod_alert_message += f"A complete log of the offending messages can be found [here]({url})"
        else:
            mod_alert_message += "Message:\n"
            [message] = self.messages.values()
            content = message.clean_content
            remaining_chars = 4080 - len(mod_alert_message)

            if len(content) > remaining_chars:
                content = content[:remaining_chars] + "..."

            mod_alert_message += f"{content}"

        *_, last_message = self.messages.values()
        await modlog.send_log_message(
            icon_url=Icons.filtering,
            colour=Colour(Colours.soft_red),
            title="Spam detected!",
            text=mod_alert_message,
            thumbnail=last_message.author.avatar_url_as(static_format="png"),
            channel_id=Channels.mod_alerts,
            ping_everyone=AntiSpamConfig.ping_everyone
        )
示例#6
0
    async def pardon_infraction(self,
                                ctx: Context,
                                infr_type: str,
                                user: UserSnowflake,
                                send_msg: bool = True) -> None:
        """
        Prematurely end an infraction for a user and log the action in the mod log.

        If `send_msg` is True, then a pardoning confirmation message will be sent to
        the context channel.  Otherwise, no such message will be sent.
        """
        log.trace(f"Pardoning {infr_type} infraction for {user}.")

        # Check the current active infraction
        log.trace(f"Fetching active {infr_type} infractions for {user}.")
        response = await self.bot.api_client.get('bot/infractions',
                                                 params={
                                                     'active': 'true',
                                                     'type': infr_type,
                                                     'user__id': user.id
                                                 })

        if not response:
            log.debug(f"No active {infr_type} infraction found for {user}.")
            await ctx.send(
                f":x: There's no active {infr_type} infraction for user {user.mention}."
            )
            return

        # Deactivate the infraction and cancel its scheduled expiration task.
        log_text = await self.deactivate_infraction(response[0],
                                                    send_log=False)

        log_text["Member"] = messages.format_user(user)
        log_text["Actor"] = ctx.author.mention
        log_content = None
        id_ = response[0]['id']
        footer = f"ID: {id_}"

        # Accordingly display whether the user was successfully notified via DM.
        dm_emoji = ""
        if log_text.get("DM") == "Sent":
            dm_emoji = ":incoming_envelope: "
        elif "DM" in log_text:
            dm_emoji = f"{constants.Emojis.failmail} "

        # Accordingly display whether the pardon failed.
        if "Failure" in log_text:
            confirm_msg = ":x: failed to pardon"
            log_title = "pardon failed"
            log_content = ctx.author.mention

            log.warning(
                f"Failed to pardon {infr_type} infraction #{id_} for {user}.")
        else:
            confirm_msg = ":ok_hand: pardoned"
            log_title = "pardoned"

            log.info(f"Pardoned {infr_type} infraction #{id_} for {user}.")

        # Send a confirmation message to the invoking context.
        if send_msg:
            log.trace(
                f"Sending infraction #{id_} pardon confirmation message.")
            await ctx.send(
                f"{dm_emoji}{confirm_msg} infraction **{' '.join(infr_type.split('_'))}** for {user.mention}. "
                f"{log_text.get('Failure', '')}")

        # Move reason to end of entry to avoid cutting out some keys
        log_text["Reason"] = log_text.pop("Reason")

        # Send a log message to the mod log.
        await self.mod_log.send_log_message(
            icon_url=_utils.INFRACTION_ICONS[infr_type][1],
            colour=Colours.soft_green,
            title=f"Infraction {log_title}: {' '.join(infr_type.split('_'))}",
            thumbnail=user.avatar_url_as(static_format="png"),
            text="\n".join(f"{k}: {v}" for k, v in log_text.items()),
            footer=footer,
            content=log_content,
        )
示例#7
0
文件: management.py 项目: lxnn/bot
    async def infraction_edit(
        self,
        ctx: Context,
        infraction: Infraction,
        duration: t.Union[Expiry, allowed_strings("p", "permanent"), None],   # noqa: F821
        *,
        reason: str = None
    ) -> None:
        """
        Edit the duration and/or the reason of an infraction.

        Durations are relative to the time of updating and should be appended with a unit of time.
        Units (∗case-sensitive):
        \u2003`y` - years
        \u2003`m` - months∗
        \u2003`w` - weeks
        \u2003`d` - days
        \u2003`h` - hours
        \u2003`M` - minutes∗
        \u2003`s` - seconds

        Use "l", "last", or "recent" as the infraction ID to specify that the most recent infraction
        authored by the command invoker should be edited.

        Use "p" or "permanent" to mark the infraction as permanent. Alternatively, an ISO 8601
        timestamp can be provided for the duration.
        """
        if duration is None and reason is None:
            # Unlike UserInputError, the error handler will show a specified message for BadArgument
            raise commands.BadArgument("Neither a new expiry nor a new reason was specified.")

        infraction_id = infraction["id"]

        request_data = {}
        confirm_messages = []
        log_text = ""

        if duration is not None and not infraction['active']:
            if reason is None:
                await ctx.send(":x: Cannot edit the expiration of an expired infraction.")
                return
            confirm_messages.append("expiry unchanged (infraction already expired)")
        elif isinstance(duration, str):
            request_data['expires_at'] = None
            confirm_messages.append("marked as permanent")
        elif duration is not None:
            request_data['expires_at'] = duration.isoformat()
            expiry = time.format_infraction_with_duration(request_data['expires_at'])
            confirm_messages.append(f"set to expire on {expiry}")
        else:
            confirm_messages.append("expiry unchanged")

        if reason:
            request_data['reason'] = reason
            confirm_messages.append("set a new reason")
            log_text += f"""
                Previous reason: {infraction['reason']}
                New reason: {reason}
            """.rstrip()
        else:
            confirm_messages.append("reason unchanged")

        # Update the infraction
        new_infraction = await self.bot.api_client.patch(
            f'bot/infractions/{infraction_id}',
            json=request_data,
        )

        # Re-schedule infraction if the expiration has been updated
        if 'expires_at' in request_data:
            # A scheduled task should only exist if the old infraction wasn't permanent
            if infraction['expires_at']:
                self.infractions_cog.scheduler.cancel(new_infraction['id'])

            # If the infraction was not marked as permanent, schedule a new expiration task
            if request_data['expires_at']:
                self.infractions_cog.schedule_expiration(new_infraction)

            log_text += f"""
                Previous expiry: {infraction['expires_at'] or "Permanent"}
                New expiry: {new_infraction['expires_at'] or "Permanent"}
            """.rstrip()

        changes = ' & '.join(confirm_messages)
        await ctx.send(f":ok_hand: Updated infraction #{infraction_id}: {changes}")

        # Get information about the infraction's user
        user_id = new_infraction['user']
        user = ctx.guild.get_member(user_id)

        if user:
            user_text = messages.format_user(user)
            thumbnail = user.avatar_url_as(static_format="png")
        else:
            user_text = f"<@{user_id}>"
            thumbnail = None

        await self.mod_log.send_log_message(
            icon_url=constants.Icons.pencil,
            colour=discord.Colour.blurple(),
            title="Infraction edited",
            thumbnail=thumbnail,
            text=textwrap.dedent(f"""
                Member: {user_text}
                Actor: <@{new_infraction['actor']}>
                Edited by: {ctx.message.author.mention}{log_text}
            """)
        )
示例#8
0
            log_text += f"""
                Previous expiry: {until_expiration(infraction['expires_at']) or "Permanent"}
                New expiry: {until_expiration(new_infraction['expires_at']) or "Permanent"}
            """.rstrip()

        changes = ' & '.join(confirm_messages)
        await ctx.send(
            f":ok_hand: Updated infraction #{infraction_id}: {changes}")

        # Get information about the infraction's user
        user_id = new_infraction['user']
        user = await get_or_fetch_member(ctx.guild, user_id)

        if user:
            user_text = messages.format_user(user)
            thumbnail = user.display_avatar.url
        else:
            user_text = f"<@{user_id}>"
            thumbnail = None

        await self.mod_log.send_log_message(icon_url=constants.Icons.pencil,
                                            colour=discord.Colour.og_blurple(),
                                            title="Infraction edited",
                                            thumbnail=thumbnail,
                                            text=textwrap.dedent(f"""
                Member: {user_text}
                Actor: <@{new_infraction['actor']}>
                Edited by: {ctx.message.author.mention}{log_text}
            """),
                                            footer=f"ID: {infraction_id}")
示例#9
0
 def format_log_message(msg: Message, token: str) -> str:
     """Return the generic portion of the log message to send for `token` being censored in `msg`."""
     return LOG_MESSAGE.format(author=format_user(msg.author),
                               channel=msg.channel.mention,
                               token=token)