diff options
| -rw-r--r-- | .github/workflows/lint-test.yml | 4 | ||||
| -rw-r--r-- | .pre-commit-config.yaml | 9 | ||||
| -rw-r--r-- | bot/exts/filtering/_filters/antispam/mentions.py | 4 | ||||
| -rw-r--r-- | bot/exts/info/code_snippets.py | 15 | ||||
| -rw-r--r-- | bot/exts/moderation/infraction/_scheduler.py | 2 | ||||
| -rw-r--r-- | bot/exts/utils/attachment_pastebin_uploader.py | 4 | ||||
| -rw-r--r-- | pyproject.toml | 1 | ||||
| -rw-r--r-- | uv.lock | 2 |
8 files changed, 33 insertions, 8 deletions
diff --git a/.github/workflows/lint-test.yml b/.github/workflows/lint-test.yml index 98a73e132..0089ca3bf 100644 --- a/.github/workflows/lint-test.yml +++ b/.github/workflows/lint-test.yml @@ -20,14 +20,14 @@ jobs: uses: actions/checkout@v5 - name: Install uv - uses: astral-sh/setup-uv@v6 + uses: astral-sh/setup-uv@v7 with: enable-cache: true cache-dependency-glob: "uv.lock" activate-environment: true - name: Install dependencies - run: uv sync --frozen + run: uv sync --locked - name: Run pre-commit hooks run: SKIP=ruff pre-commit run --all-files diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 01eb141ec..e77b8a0b0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -10,10 +10,17 @@ repos: args: [--markdown-linebreak-ext=md] - repo: local hooks: + - id: uv-lock + name: uv-lock + description: "Automatically run 'uv lock' on your project dependencies" + entry: uv lock + language: system + files: ^(uv\.lock|pyproject\.toml|uv\.toml)$ + pass_filenames: false - id: ruff name: ruff description: Run ruff linting - entry: uv run --frozen ruff check --force-exclude + entry: uv run --locked ruff check --force-exclude language: system 'types_or': [python, pyi] require_serial: true diff --git a/bot/exts/filtering/_filters/antispam/mentions.py b/bot/exts/filtering/_filters/antispam/mentions.py index 6d541a28c..1f2616328 100644 --- a/bot/exts/filtering/_filters/antispam/mentions.py +++ b/bot/exts/filtering/_filters/antispam/mentions.py @@ -68,8 +68,8 @@ class MentionsFilter(UniqueFilter): # that is both not in the cache, and deleted while running this function. # In such a situation, this will throw an error which we catch. try: - resolved = await bot.instance.get_partial_messageable(resolved.channel_id).fetch_message( - resolved.message_id + resolved = await bot.instance.get_partial_messageable(ref.channel_id).fetch_message( + ref.message_id ) except NotFound: log.info("Could not fetch the reference message as it has been deleted.") diff --git a/bot/exts/info/code_snippets.py b/bot/exts/info/code_snippets.py index 6f67eda3c..1ba4151c7 100644 --- a/bot/exts/info/code_snippets.py +++ b/bot/exts/info/code_snippets.py @@ -5,6 +5,7 @@ from typing import Any from urllib.parse import quote_plus import discord +import yarl from aiohttp import ClientResponseError from discord.ext.commands import Cog @@ -272,6 +273,20 @@ class CodeSnippets(Cog): for pattern, handler in self.pattern_handlers: for match in pattern.finditer(content): + # ensure that the matched URL meets url normalization rules. + # parsing an absolute url with yarl resolves all parent urls such as `/../`, + # we then check the regex again to make sure our groups stay the same + unsanitized = match.group(0) + normalized = str(yarl.URL(unsanitized)) + if normalized != unsanitized: + match = pattern.fullmatch(normalized) + if not match: + log.info( + "Received code snippet url %s which " + "attempted to circumvent url normalisation.", + unsanitized + ) + continue try: result = await handler(**match.groupdict()) except ClientResponseError as error: diff --git a/bot/exts/moderation/infraction/_scheduler.py b/bot/exts/moderation/infraction/_scheduler.py index 93d435556..8e6d49fea 100644 --- a/bot/exts/moderation/infraction/_scheduler.py +++ b/bot/exts/moderation/infraction/_scheduler.py @@ -121,7 +121,7 @@ class InfractionScheduler: await partial_message.delete() log.trace(f"Deleted infraction message {message_id} in channel {channel_id}.") except discord.NotFound: - log.warning(f"Channel or message {message_id} not found in channel {channel_id}.") + log.info(f"Channel or message {message_id} not found in channel {channel_id}.") except discord.Forbidden: log.info(f"Bot lacks permissions to delete message {message_id} in channel {channel_id}.") except discord.HTTPException as e: diff --git a/bot/exts/utils/attachment_pastebin_uploader.py b/bot/exts/utils/attachment_pastebin_uploader.py index 9a805dd66..1ea74b509 100644 --- a/bot/exts/utils/attachment_pastebin_uploader.py +++ b/bot/exts/utils/attachment_pastebin_uploader.py @@ -77,8 +77,8 @@ class AutoTextAttachmentUploader(commands.Cog): @commands.Cog.listener() async def on_message(self, message: discord.Message) -> None: """Listens for messages containing attachments and offers to upload them to the pastebin.""" - # Check if the message contains an embedded file and is not sent by a bot. - if message.author.bot or not any("charset" in a.content_type for a in message.attachments): + # Check if the message contains an embedded file and is not sent by a bot or in DMs. + if message.author.bot or not message.guild or not any("charset" in a.content_type for a in message.attachments): return log.trace(f"Offering to upload attachments for {message.author} in {message.channel}, message {message.id}") diff --git a/pyproject.toml b/pyproject.toml index e58ea4a50..65d6ab42a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -25,6 +25,7 @@ dependencies = [ "sentry-sdk==2.22.0", "tenacity==9.0.0", "tldextract==5.1.3", + "yarl==1.22.0", ] name = "bot" version = "1.0.1" @@ -205,6 +205,7 @@ dependencies = [ { name = "sentry-sdk" }, { name = "tenacity" }, { name = "tldextract" }, + { name = "yarl" }, ] [package.dev-dependencies] @@ -242,6 +243,7 @@ requires-dist = [ { name = "sentry-sdk", specifier = "==2.22.0" }, { name = "tenacity", specifier = "==9.0.0" }, { name = "tldextract", specifier = "==5.1.3" }, + { name = "yarl", specifier = "==1.22.0" }, ] [package.metadata.requires-dev] |