diff options
| author | 2020-11-25 17:05:42 +0100 | |
|---|---|---|
| committer | 2020-11-25 17:05:42 +0100 | |
| commit | c673d77f53286b9704cd1b9758a570af4d549e12 (patch) | |
| tree | 9c3fcdb69d5b92ce7b206f250d3becc644b835de | |
| parent | fixing code to be flake8 compliant (diff) | |
| parent | Add Mark as a code owner of CI and Docker files (diff) | |
Merge branch 'master' into master
| -rw-r--r-- | .github/CODEOWNERS | 27 | ||||
| -rw-r--r-- | .github/workflows/build.yml | 2 | ||||
| -rw-r--r-- | .github/workflows/deploy.yml | 5 | ||||
| -rw-r--r-- | bot/constants.py | 3 | ||||
| -rw-r--r-- | bot/exts/help_channels.py | 29 | ||||
| -rw-r--r-- | bot/exts/moderation/infraction/_scheduler.py | 22 | ||||
| -rw-r--r-- | bot/exts/moderation/infraction/superstarify.py | 77 | ||||
| -rw-r--r-- | config-default.yml | 3 | ||||
| -rw-r--r-- | deployment.yaml | 21 | 
9 files changed, 106 insertions, 83 deletions
| diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index cf5f1590d..5f5386222 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1 +1,26 @@ -* @python-discord/core-developers +# Request Joe and Dennis for any PR +* @jb3 @Den4200 + +# Extensions +**/bot/exts/backend/sync/**             @MarkKoz +**/bot/exts/filters/*token_remover.py   @MarkKoz +**/bot/exts/moderation/*silence.py      @MarkKoz +bot/exts/info/codeblock/**              @MarkKoz +bot/exts/utils/extensions.py            @MarkKoz +bot/exts/utils/snekbox.py               @MarkKoz +bot/exts/help_channels.py               @MarkKoz + +# Utils +bot/utils/extensions.py                 @MarkKoz +bot/utils/function.py                   @MarkKoz +bot/utils/lock.py                       @MarkKoz +bot/utils/scheduling.py                 @MarkKoz + +# Tests +tests/_autospec.py                      @MarkKoz +tests/bot/exts/test_cogs.py             @MarkKoz + +# CI & Docker +.github/workflows/**                    @MarkKoz +Dockerfile                              @MarkKoz +docker-compose.yml                      @MarkKoz diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 706ab462f..6152f1543 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,7 +10,7 @@ on:  jobs:    build: -    if: github.event.workflow_run.conclusion == 'success' +    if: github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event == 'push'      name: Build & Push      runs-on: ubuntu-latest diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 90555a8ee..5a4aede30 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -23,6 +23,9 @@ jobs:        - name: Checkout code          uses: actions/checkout@v2 +        with: +          repository: python-discord/kubernetes +          token: ${{ secrets.REPO_TOKEN }}        - name: Authenticate with Kubernetes          uses: azure/k8s-set-context@v1 @@ -34,6 +37,6 @@ jobs:          uses: Azure/k8s-deploy@v1          with:            manifests: | -              deployment.yaml +              bot/deployment.yaml            images: 'ghcr.io/python-discord/bot:${{ steps.sha_tag.outputs.tag }}'            kubectl-version: 'latest' diff --git a/bot/constants.py b/bot/constants.py index 6c0ef913b..33ed29c39 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -248,6 +248,7 @@ class Colours(metaclass=YAMLGetter):      soft_red: int      soft_green: int      soft_orange: int +    bright_green: int  class DuckPond(metaclass=YAMLGetter): @@ -354,6 +355,8 @@ class Icons(metaclass=YAMLGetter):      voice_state_green: str      voice_state_red: str +    green_checkmark: str +  class CleanMessages(metaclass=YAMLGetter):      section = "bot" diff --git a/bot/exts/help_channels.py b/bot/exts/help_channels.py index f5a8b251b..ced2f72ef 100644 --- a/bot/exts/help_channels.py +++ b/bot/exts/help_channels.py @@ -28,17 +28,21 @@ This is a Python help channel. You can claim your own help channel in the Python  """  AVAILABLE_MSG = f""" -This help channel is now **available**, which means that you can claim it by simply typing your \ -question into it. Once claimed, the channel will move into the **Python Help: Occupied** category, \ -and will be yours until it has been inactive for {constants.HelpChannels.idle_minutes} minutes or \ -is closed manually with `!close`. When that happens, it will be set to **dormant** and moved into \ -the **Help: Dormant** category. - -Try to write the best question you can by providing a detailed description and telling us what \ -you've tried already. For more information on asking a good question, \ -check out our guide on **[asking good questions]({ASKING_GUIDE_URL})**. +**Send your question here to claim the channel** +This channel will be dedicated to answering your question only. Others will try to answer and help you solve the issue. + +**Keep in mind:** +• It's always ok to just ask your question. You don't need permission. +• Explain what you expect to happen and what actually happens. +• Include a code sample and error message, if you got any. + +For more tips, check out our guide on **[asking good questions]({ASKING_GUIDE_URL})**.  """ +AVAILABLE_TITLE = "Available help channel" + +AVAILABLE_FOOTER = f"Closes after {constants.HelpChannels.idle_minutes} minutes of inactivity or when you send !close." +  DORMANT_MSG = f"""  This help channel has been marked as **dormant**, and has been moved into the **Help: Dormant** \  category at the bottom of the channel list. It is no longer possible to send messages in this \ @@ -834,7 +838,12 @@ class HelpChannels(commands.Cog):          channel_info = f"#{channel} ({channel.id})"          log.trace(f"Sending available message in {channel_info}.") -        embed = discord.Embed(description=AVAILABLE_MSG) +        embed = discord.Embed( +            color=constants.Colours.bright_green, +            description=AVAILABLE_MSG, +        ) +        embed.set_author(name=AVAILABLE_TITLE, icon_url=constants.Icons.green_checkmark) +        embed.set_footer(text=AVAILABLE_FOOTER)          msg = await self.get_last_message(channel)          if self.match_bot_embed(msg, DORMANT_MSG): diff --git a/bot/exts/moderation/infraction/_scheduler.py b/bot/exts/moderation/infraction/_scheduler.py index bebade0ae..c062ae7f8 100644 --- a/bot/exts/moderation/infraction/_scheduler.py +++ b/bot/exts/moderation/infraction/_scheduler.py @@ -82,15 +82,27 @@ class InfractionScheduler:          ctx: Context,          infraction: _utils.Infraction,          user: UserSnowflake, -        action_coro: t.Optional[t.Awaitable] = None -    ) -> None: -        """Apply an infraction to the user, log the infraction, and optionally notify the user.""" +        action_coro: t.Optional[t.Awaitable] = None, +        user_reason: t.Optional[str] = None, +        additional_info: str = "", +    ) -> bool: +        """ +        Apply an infraction to the user, log the infraction, and optionally notify the user. + +        `user_reason`, if provided, will be sent to the user in place of the infraction reason. +        `additional_info` will be attached to the text field in the mod-log embed. + +        Returns whether or not the infraction succeeded. +        """          infr_type = infraction["type"]          icon = _utils.INFRACTION_ICONS[infr_type][0]          reason = infraction["reason"]          expiry = time.format_infraction_with_duration(infraction["expires_at"])          id_ = infraction['id'] +        if user_reason is None: +            user_reason = reason +          log.trace(f"Applying {infr_type} infraction #{id_} to {user}.")          # Default values for the confirmation message and mod log. @@ -126,7 +138,7 @@ class InfractionScheduler:                  log.error(f"Failed to DM {user.id}: could not fetch user (status {e.status})")              else:                  # Accordingly display whether the user was successfully notified via DM. -                if await _utils.notify_infraction(user, " ".join(infr_type.split("_")).title(), expiry, reason, icon): +                if await _utils.notify_infraction(user, infr_type.replace("_", " ").title(), expiry, user_reason, icon):                      dm_result = ":incoming_envelope: "                      dm_log_text = "\nDM: Sent" @@ -198,12 +210,14 @@ class InfractionScheduler:                  Member: {messages.format_user(user)}                  Actor: {ctx.author.mention}{dm_log_text}{expiry_log_text}                  Reason: {reason} +                {additional_info}              """),              content=log_content,              footer=f"ID {infraction['id']}"          )          log.info(f"Applied {infr_type} infraction #{id_} to {user}.") +        return not failed      async def pardon_infraction(              self, diff --git a/bot/exts/moderation/infraction/superstarify.py b/bot/exts/moderation/infraction/superstarify.py index adfe42fcd..96dfb562f 100644 --- a/bot/exts/moderation/infraction/superstarify.py +++ b/bot/exts/moderation/infraction/superstarify.py @@ -5,7 +5,7 @@ import textwrap  import typing as t  from pathlib import Path -from discord import Colour, Embed, Member +from discord import Embed, Member  from discord.ext.commands import Cog, Context, command, has_any_role  from discord.utils import escape_markdown @@ -143,57 +143,44 @@ class Superstarify(InfractionScheduler, Cog):          forced_nick = self.get_nick(id_, member.id)          expiry_str = format_infraction(infraction["expires_at"]) -        # Apply the infraction and schedule the expiration task. -        log.debug(f"Changing nickname of {member} to {forced_nick}.") -        self.mod_log.ignore(constants.Event.member_update, member.id) -        await member.edit(nick=forced_nick, reason=reason) -        self.schedule_expiration(infraction) +        # Apply the infraction +        async def action() -> None: +            log.debug(f"Changing nickname of {member} to {forced_nick}.") +            self.mod_log.ignore(constants.Event.member_update, member.id) +            await member.edit(nick=forced_nick, reason=reason)          old_nick = escape_markdown(old_nick)          forced_nick = escape_markdown(forced_nick) -        # Send a DM to the user to notify them of their new infraction. -        await _utils.notify_infraction( -            user=member, -            infr_type="Superstarify", -            expires_at=expiry_str, -            icon_url=_utils.INFRACTION_ICONS["superstar"][0], -            reason=f"Your nickname didn't comply with our [nickname policy]({NICKNAME_POLICY_URL})." +        superstar_reason = f"Your nickname didn't comply with our [nickname policy]({NICKNAME_POLICY_URL})." +        nickname_info = textwrap.dedent(f""" +            Old nickname: `{old_nick}` +            New nickname: `{forced_nick}` +        """).strip() + +        successful = await self.apply_infraction( +            ctx, infraction, member, action(), +            user_reason=superstar_reason, +            additional_info=nickname_info          ) -        # Send an embed with the infraction information to the invoking context. -        log.trace(f"Sending superstar #{id_} embed.") -        embed = Embed( -            title="Congratulations!", -            colour=constants.Colours.soft_orange, -            description=( -                f"Your previous nickname, **{old_nick}**, " -                f"was so bad that we have decided to change it. " -                f"Your new nickname will be **{forced_nick}**.\n\n" -                f"You will be unable to change your nickname until **{expiry_str}**.\n\n" -                "If you're confused by this, please read our " -                f"[official nickname policy]({NICKNAME_POLICY_URL})." +        # Send an embed with the infraction information to the invoking context if +        # superstar was successful. +        if successful: +            log.trace(f"Sending superstar #{id_} embed.") +            embed = Embed( +                title="Congratulations!", +                colour=constants.Colours.soft_orange, +                description=( +                    f"Your previous nickname, **{old_nick}**, " +                    f"was so bad that we have decided to change it. " +                    f"Your new nickname will be **{forced_nick}**.\n\n" +                    f"You will be unable to change your nickname until **{expiry_str}**.\n\n" +                    "If you're confused by this, please read our " +                    f"[official nickname policy]({NICKNAME_POLICY_URL})." +                )              ) -        ) -        await ctx.send(embed=embed) - -        # Log to the mod log channel. -        log.trace(f"Sending apply mod log for superstar #{id_}.") -        await self.mod_log.send_log_message( -            icon_url=_utils.INFRACTION_ICONS["superstar"][0], -            colour=Colour.gold(), -            title="Member achieved superstardom", -            thumbnail=member.avatar_url_as(static_format="png"), -            text=textwrap.dedent(f""" -                Member: {member.mention} -                Actor: {ctx.message.author.mention} -                Expires: {expiry_str} -                Old nickname: `{old_nick}` -                New nickname: `{forced_nick}` -                Reason: {reason} -            """), -            footer=f"ID {id_}" -        ) +            await ctx.send(embed=embed)      @command(name="unsuperstarify", aliases=("release_nick", "unstar"))      async def unsuperstarify(self, ctx: Context, member: Member) -> None: diff --git a/config-default.yml b/config-default.yml index 700406f4e..042d80408 100644 --- a/config-default.yml +++ b/config-default.yml @@ -27,6 +27,7 @@ style:          soft_red: 0xcd6d6d          soft_green: 0x68c290          soft_orange: 0xf9cb54 +        bright_green: 0x01d277      emojis:          defcon_disabled: "<:defcondisabled:470326273952972810>" @@ -119,6 +120,8 @@ style:          voice_state_green: "https://cdn.discordapp.com/emojis/656899770094452754.png"          voice_state_red: "https://cdn.discordapp.com/emojis/656899769905709076.png" +        green_checkmark: "https://raw.githubusercontent.com/python-discord/branding/master/icons/checkmark/green-checkmark-dist.png" +  guild:      id: 267624335836053506 diff --git a/deployment.yaml b/deployment.yaml deleted file mode 100644 index ca5ff5941..000000000 --- a/deployment.yaml +++ /dev/null @@ -1,21 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: -  name: bot -spec: -  replicas: 1 -  selector: -    matchLabels: -      app: bot -  template: -    metadata: -      labels: -        app: bot -    spec: -      containers: -      - name: bot -        image: ghcr.io/python-discord/bot:latest -        imagePullPolicy: Always -        envFrom: -        - secretRef: -            name: bot-env | 
