Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
158 commits
Select commit Hold shift + click to select a range
8d11cab
Updated dependencies
Ersatz77 Apr 9, 2026
0362c74
Added Pydantic support
Ersatz77 Apr 22, 2026
3388629
Added `to_hex()`
Ersatz77 Apr 22, 2026
e025896
Made the config use Pydantic
Ersatz77 Apr 22, 2026
2864305
Updated dependencies
Ersatz77 Apr 23, 2026
5cb8465
Moved some functions around
Ersatz77 Apr 23, 2026
43a0502
Changed when configured extensions are validated
Ersatz77 Jun 12, 2026
b7303b0
Removed the old `help_chat` extension since it hasn't been used in years
Ersatz77 Jun 12, 2026
64372b7
Reworked the Json database to use Pydantic
Ersatz77 Jun 12, 2026
07bd173
Moved the old Json database to a "v1" folder so we can incrementally …
Ersatz77 Jun 12, 2026
53c0468
Updated imports
Ersatz77 Jun 12, 2026
390ea93
Updated dependencies
Ersatz77 Jun 12, 2026
5e03d01
`/sudo export database` now works with `JsonDB`
Ersatz77 Jun 12, 2026
beb873d
Updated the help forums to use JsonDB
Ersatz77 Jun 13, 2026
300c403
Updated predicates and types
Ersatz77 Jun 14, 2026
fa3d896
Updated discord.py to 2.7
Ersatz77 Jun 15, 2026
9a588d3
Reworked model validator
Ersatz77 Jun 30, 2026
083ac33
Made custom Pydantic exceptions inherit from `ValueError`
Ersatz77 Jun 30, 2026
a210c7c
Added more types and enums
Ersatz77 Jun 30, 2026
4ecad0e
Moved guards to automod extension
Ersatz77 Jun 30, 2026
6a16e62
Reworked automod events
Ersatz77 Jun 30, 2026
c29b849
Removed unnecessary file.
Ersatz77 Jun 30, 2026
c75f1a0
Moved reference types to their own file
Ersatz77 Jun 30, 2026
bf996b7
Added triggers and started reimplementing `AutomodRule`
Ersatz77 Jun 30, 2026
bc43c5e
Events no longer contain metadata
Ersatz77 Jul 2, 2026
5659443
Added a context dataclass that's passed to triggers, conditions, and …
Ersatz77 Jul 2, 2026
2d9b43c
Removed `IntegerRange` from commanderbot.lib
Ersatz77 Jul 8, 2026
8bf5570
Moved some data from `AutomodEvent` to `AutomodContext`
Ersatz77 Jul 8, 2026
7682ff5
Updated docstring.
Ersatz77 Jul 8, 2026
4ee790e
Fixed an issue where `RolesGuard` would ignore `Members` and not `Users`
Ersatz77 Jul 8, 2026
eff23ed
Added a `count` parameter to `has_any()`
Ersatz77 Jul 8, 2026
c488303
Added a type alias for `timedelta` that has a Json schema for Pydantic
Ersatz77 Jul 8, 2026
6f0e8d6
Renamed some types and `AutomodRule` now checks if a trigger is disabled
Ersatz77 Jul 8, 2026
e88b231
Updated docstrings
Ersatz77 Jul 9, 2026
1040b3f
Removed a few files we're not using now.
Ersatz77 Jul 9, 2026
6d34343
Added a type for Unicode normalization literals
Ersatz77 Jul 9, 2026
5ed8598
Reworked conditions
Ersatz77 Jul 9, 2026
c748083
Added missing `await`
Ersatz77 Jul 9, 2026
709d270
Updated comment
Ersatz77 Jul 12, 2026
8c3d70d
Updated comments
Ersatz77 Jul 12, 2026
47dd0f4
Added a constant that's `True` if OCR is supported
Ersatz77 Jul 12, 2026
71bd62b
`is_user` now returns `True` if a `Member` is passed to it. Members a…
Ersatz77 Jul 12, 2026
684646b
`AutomodContext` can now format strings with context data
Ersatz77 Jul 12, 2026
16283a9
Added more conditions
Ersatz77 Jul 14, 2026
e36d9be
Changed some default values
Ersatz77 Jul 14, 2026
5360e58
Added more options to the database config
Ersatz77 Jul 14, 2026
6c35c67
Changed some default values
Ersatz77 Jul 14, 2026
39f54f4
Reworked actions
Ersatz77 Jul 16, 2026
4cd507b
Changed some defaults in database config
Ersatz77 Jul 16, 2026
11dcafb
`message_to_file`, `str_to_file`, and `send_message_or_file` now uses…
Ersatz77 Jul 16, 2026
f065415
Added optional dependencies for OCR.
Ersatz77 Jul 16, 2026
96d7d12
Added a max number of forum tags
Ersatz77 Jul 16, 2026
d05c7d7
Removed unused files
Ersatz77 Jul 16, 2026
c30b2dc
Fixed schema generation
Ersatz77 Jul 16, 2026
7537023
Added a process pool that anything can use
Ersatz77 Jul 23, 2026
e1e71ae
Changed some default values
Ersatz77 Jul 23, 2026
1ddec5e
Updated dependencies
Ersatz77 Jul 23, 2026
d638c01
Changed some names
Ersatz77 Jul 23, 2026
637fe6e
Added types for Tesseract language and script names
Ersatz77 Jul 23, 2026
110b206
Added `attachments` to automod events
Ersatz77 Jul 23, 2026
fa500ac
Added a condition that will OCR any attachments in context
Ersatz77 Jul 24, 2026
e419532
Changed how attachments are accessed
Ersatz77 Jul 24, 2026
4ec4776
Changed context metadata to a dataclass
Ersatz77 Jul 30, 2026
82fd00a
Updated OCR condition
Ersatz77 Jul 30, 2026
1ec3aae
Changed a metadata name
Ersatz77 Aug 3, 2026
c2c41bd
Changed how OCR results are extracted
Ersatz77 Aug 3, 2026
758cd4a
Started implementing buckets
Ersatz77 Aug 3, 2026
370f785
Added library for mime types
Ersatz77 Aug 4, 2026
e199b24
Changed how mime types are used
Ersatz77 Aug 4, 2026
5794a32
Added missing function call
Ersatz77 Aug 4, 2026
79375d8
Added a bucket for flagged image attachments
Ersatz77 Aug 4, 2026
3129c2a
Added a bucket for message history along with a trigger for message f…
Ersatz77 Aug 4, 2026
d81beca
Added an `ImageHash` alias that works with Pydantic
Ersatz77 Aug 4, 2026
a82050c
Changed some variable names
Ersatz77 Aug 4, 2026
ce69d56
Fixed incorrect import
Ersatz77 Aug 4, 2026
01039a3
Made rules hashable
Ersatz77 Aug 4, 2026
60a648f
Fixed missing `MessageFrequency` trigger
Ersatz77 Aug 4, 2026
982487b
Fixed return type
Ersatz77 Aug 4, 2026
cd124d5
Removed `async` from a few functions
Ersatz77 Aug 4, 2026
8d9235e
Removed `async` from a few functions
Ersatz77 Aug 4, 2026
403f4c4
Fixed targets
Ersatz77 Aug 5, 2026
e7e7a57
Fixed an issue where `FlagsGuard` couldn't be validated
Ersatz77 Aug 5, 2026
576637e
Renamed a few things
Ersatz77 Aug 5, 2026
72d54ea
Added `AutomodBucketRef` to make it easier to resolve buckets
Ersatz77 Aug 5, 2026
f8ef6f4
Added a way to bulk delete messages from an actor or author
Ersatz77 Aug 5, 2026
2a300cf
Changed some variable names
Ersatz77 Aug 5, 2026
d1c6a9a
Updated comment
Ersatz77 Aug 5, 2026
a25ba97
Added a condition that checks if any image attachments have already b…
Ersatz77 Aug 5, 2026
6e20251
Made `clear()` async again
Ersatz77 Aug 5, 2026
ea3700d
Fixed comment
Ersatz77 Aug 5, 2026
9f5421c
Fixed issues found by Ruff
Ersatz77 Aug 6, 2026
b88ccf5
Fixed issues found by Ruff
Ersatz77 Aug 6, 2026
6181425
Fixed issues found by Ruff
Ersatz77 Aug 6, 2026
5307370
Changed `pass` to `...` in `@abstractmethod`s
Ersatz77 Aug 6, 2026
993b9f4
Fixed issues found by Ruff
Ersatz77 Aug 6, 2026
0abec69
Update automod options and exceptions
Ersatz77 Aug 6, 2026
f009ba3
Added missing json schema input
Ersatz77 Aug 6, 2026
f358b43
Changed how task results are iterated over
Ersatz77 Aug 6, 2026
19200ed
Fixed an issue where phashes weren't being generated properly.
Ersatz77 Aug 6, 2026
e4ef49d
Fixed issues found by Ruff
Ersatz77 Aug 6, 2026
0f993ba
Fixed issues found by Ty
Ersatz77 Aug 7, 2026
cef2f9f
Fixed issues found by Ty
Ersatz77 Aug 7, 2026
6a8a0e1
Fixed issues found by Ty
Ersatz77 Aug 7, 2026
18ce792
Added range validation
Ersatz77 Aug 7, 2026
2c07022
Added an action that makes the bot type in the channel in context
Ersatz77 Aug 7, 2026
5abf53a
Updated `uv_build` version
Ersatz77 Aug 12, 2026
5b14a88
Added `LogChannel`
Ersatz77 Aug 12, 2026
af019e6
Changed formatting
Ersatz77 Aug 12, 2026
38b7fab
Added default log channel override to rules
Ersatz77 Aug 12, 2026
8ec3f2e
Added more exceptions
Ersatz77 Aug 12, 2026
9ef53c9
Rewrote logic that dispatches events and manages rules
Ersatz77 Aug 12, 2026
48c3e76
Changed field formatting
Ersatz77 Aug 13, 2026
f42f8a7
Added a way to get the message and channel count across all user records
Ersatz77 Aug 13, 2026
63f1783
The default log can now be managed and started working on bucket comm…
Ersatz77 Aug 13, 2026
5152338
Updated dependencies
Ersatz77 Aug 14, 2026
ccf4f09
Added badges for Ruff and Ty
Ersatz77 Aug 14, 2026
ed4db41
Updated Ty
Ersatz77 Aug 15, 2026
2388471
Moved `Timedelta` to a separate file
Ersatz77 Aug 15, 2026
68fcc8c
Changed type hint
Ersatz77 Aug 15, 2026
4ccb331
Moved some files around
Ersatz77 Aug 15, 2026
401a3b9
Forgot to commit lock file
Ersatz77 Aug 15, 2026
642c237
Added `guild` attribute
Ersatz77 Aug 15, 2026
ef94fb8
Added commands for managing buckets
Ersatz77 Aug 15, 2026
1599f02
Moved UIs to their own files
Ersatz77 Aug 15, 2026
631a484
Added missing entry in `__all__`
Ersatz77 Aug 15, 2026
5febcbd
Made `custom_id` optional
Ersatz77 Aug 15, 2026
53a4262
Wrong exception was being thrown
Ersatz77 Aug 15, 2026
0751089
Added missing `await`
Ersatz77 Aug 15, 2026
8a54019
Renamed some classes and functions
Ersatz77 Aug 15, 2026
744e15b
Updated `.gitignore`
Ersatz77 Aug 15, 2026
62442ec
Updated formatting
Ersatz77 Aug 19, 2026
4d63c94
Added triggers for timeouts
Ersatz77 Aug 19, 2026
bff1ef2
Added autocomplete
Ersatz77 Aug 19, 2026
0d0f198
Updated dependencies
Ersatz77 Aug 19, 2026
d1579cc
Updated changelog
Ersatz77 Aug 21, 2026
0208add
Global process pool now uses pebble
Ersatz77 Aug 21, 2026
faa9bf9
Handled an edge case where the image couldn't be decoded
Ersatz77 Aug 21, 2026
bf10c03
Simplified phash calculation
Ersatz77 Aug 21, 2026
8840280
handled an edge case where `phash` is `None`
Ersatz77 Aug 21, 2026
f645322
Improved the code that submits tasks to the global process pool
Ersatz77 Aug 21, 2026
9e0422a
Removed unused dependencies
Ersatz77 Aug 21, 2026
f44d05f
Removed unused dependencies
Ersatz77 Aug 21, 2026
615e7b7
Updated `uv.lock`
Ersatz77 Aug 21, 2026
5faf26b
Added missing comment
Ersatz77 Aug 21, 2026
21242e8
Simplified logic that detect timeouts
Ersatz77 Aug 21, 2026
dec3918
Updated changelog
Ersatz77 Aug 21, 2026
8193788
Updated changelog
Ersatz77 Aug 25, 2026
1f4ad54
Updated timeout logic
Ersatz77 Aug 25, 2026
4779981
`ReactionsGuard` can now filter an interable of reactions
Ersatz77 Aug 25, 2026
ce2948c
Changed the max number of OCR workers to the max number of attachments
Ersatz77 Aug 25, 2026
76b1e2f
Added a constant for the max number of attachments
Ersatz77 Aug 25, 2026
8f1b735
Removed `none_of` condition. Use `inverted` with `all_of` or `any_of`
Ersatz77 Aug 25, 2026
42da787
Forgot to change a literal
Ersatz77 Aug 25, 2026
6b5219e
Added a condition that checks if a message has reactions
Ersatz77 Aug 25, 2026
375079a
Added `max_pool_workers` to `CommanderBot`
Ersatz77 Aug 25, 2026
8a1f7c4
Updated dependencies
Ersatz77 Aug 25, 2026
885ce4a
Changed how `log_message` resolves channels
Ersatz77 Aug 26, 2026
60eeab7
Added `send_view` and fixed a few issues
Ersatz77 Aug 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
17 changes: 8 additions & 9 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
.pytest_cache/
**/__pycache__
.vscode/
*.code-workspace

venv/
.venv/
bot/
dist/
.ruff_cache/
.pytest_cache/
**/__pycache__/
*.egg-info/

.vscode/
*.code-workspace

bot/
dist/
.python-version
.venv

.env
*.sh
*.bat
109 changes: 108 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,112 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

### Removed

## [0.23.0]

### Added

- Added a new type of database (`JsonDB`) that uses Pydantic models
- This should be used going forward
- The old database classes can be accessed from `commanderbot.lib.databases.v1`
- Added an optional dependency group for OCR (Optical Character Recognition)
- Uses [tesserocr](https://github.com/sirfz/tesserocr)
- This is optional because it requires quite a bit of setup (Especially on Windows)
- Query `SUPPORTS_OCR` in `commanderbot.lib.constants` to check if it was added
- If added, it will add extra capabilities to the following extensions:
- `automod`
- The following library classes now support Pydantic:
- `AllowedMentions`
- `Color`
- `ChannelType`
- `Intents`
- `ImageHash`
- `Timedelta`
- `sudo`:
- Now supports exporting `JsonDB` databases
- Added a process pool to `CommanderBot` that any extension can use

### Changed

- Updated discord.py to 2.7
- The bot config now uses Pydantic
- `automod`:
- Completely rewritten from scratch to fix tons of issues that have piled up over the years
- Now uses slash commands
- Now uses components v2
- Now uses `JsonDB` and Pydantic models
- Rule metadata now has it's own class instead of being combined with the rule
- Rules **must** be written in Json now (Sorry Arcensoth)
- You can now export the Json schema for rules
- This is useful for creating rules in a text editor
- Rules now receive an `AutomodContext` instead of an `AutomodEvent`
- This gives you access to:
- The bot
- The guild state that received the event
- The logger instance for that guild state
- The rule being ran
- The event
- Metadata now uses a dataclass instead of a `dict`
- Added support for caching attachment data
- String formatting using context data now uses `string.Template`
- Added support for buckets
- Closes ([Old repo #63](https://github.com/CommanderBot-Dev/commanderbot-py/pull/63))
- These can be used to persist data between events
- Available bucket types:
- `flagged_image_attachments`
- `message_history`
- New triggers:
- `discord_automod_blocked_member_interactions`
- `discord_automod_blocked_message`
- `discord_automod_timed_out`
- `member_gained_flags`
- `member_lost_flags`
- `member_timeout_started`
- `member_timeout_ended`
- `message_frequency`
- New conditions:
- `actor_has_all_flags`
- `actor_has_any_flags`
- `author_has_all_flags`
- `author_has_any_flags`
- `has_flagged_image_attachments`
- `image_attachments_contain`
- `random_chance`
- `randomize`
- `return_false`
- `return_true`
- New actions:
- `add_to_bucket`
- `delete_actor_messages`
- `delete_author_messages`
- `randomize`
- `sequence`
- `timeout_actor`
- `timeout_author`
- `type_in_channel`
- New events:
- `DiscordAutomodBlockedMemberInteractions`
- `DiscordAutomodBlockedMessage`
- `DiscordAutomodTimedOut`
- `GuildChannelPinsUpdated`
- `MessageFrequency`
- New guards:
- `CategoriesGuard`
- `ChannelTypesGuard`
- `DiscordAutomodRulesGuard`
- `FlagsGuard`
- `help_forum`:
- Now uses `JsonDB` and Pydantic models (This is just a direct port with no optimizations)

### Fixed

- `mcdoc`:
- Fixed an issue where application emojis weren't being used

### Removed

- `help_chat`:
- It hasn't been used in ages and is pretty outdated now

## [0.22.0] - 2026-01-06

### Fixed
Expand Down Expand Up @@ -410,7 +516,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

- Implemented `status` and `faq` extensions as an exercise for developing `commanderbot-lib`

[unreleased]: https://github.com/MinecraftCommands/commanderbot-py/compare/v0.22.0...HEAD
[unreleased]: https://github.com/MinecraftCommands/commanderbot-py/compare/v0.23.0...HEAD
[0.23.0]: https://github.com/MinecraftCommands/commanderbot-py/compare/v0.22.0...v0.23.0
[0.22.0]: https://github.com/MinecraftCommands/commanderbot-py/compare/v0.21.0...v0.22.0
[0.21.0]: https://github.com/MinecraftCommands/commanderbot-py/compare/v0.20.0...v0.21.0
[0.20.0]: https://github.com/MinecraftCommands/commanderbot-py/compare/v0.19.0...v0.20.0
Expand Down
12 changes: 8 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@

A collection of utilities and extensions for discord.py bots.

[![uv-badge]](https://github.com/astral-sh/uv/)
[![package-badge]](https://pypi.python.org/pypi/commanderbot/)
[![version-badge]](https://pypi.python.org/pypi/commanderbot/)
[![uv-badge]](https://github.com/astral-sh/uv)
[![ruff-badge]](https://github.com/astral-sh/ruff)
[![ty-badge]](https://github.com/astral-sh/ty)
[![package-badge]](https://pypi.python.org/pypi/commanderbot)
[![version-badge]](https://pypi.python.org/pypi/commanderbot)

## Requirements

- Python 3.14+
- discord.py 2.6+
- discord.py 2.7+

## Running your bot

Expand Down Expand Up @@ -75,5 +77,7 @@ The current set of configuration options is limited. The following is an example
```

[uv-badge]: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json&style=flat-square
[ruff-badge]: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json&style=flat-square
[ty-badge]: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ty/main/assets/badge/v0.json&style=flat-square
[package-badge]: https://img.shields.io/pypi/v/commanderbot.svg?style=flat-square
[version-badge]: https://img.shields.io/pypi/pyversions/commanderbot.svg?style=flat-square
3 changes: 2 additions & 1 deletion commanderbot/core/application_emoji_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

from commanderbot.core.exceptions import ApplicationEmojiDoesNotExist
from commanderbot.lib import EmojiID
from commanderbot.lib.predicates import is_emoji_id


class ApplicationEmojiManager:
Expand All @@ -19,7 +20,7 @@ def _get_from_cache(self, emoji: str | EmojiID) -> Optional[Emoji]:
return e

# Try to find the emoji by its ID
if isinstance(emoji, EmojiID):
if is_emoji_id(emoji):
for e in self._cache.values():
if e.id == emoji:
return e
Expand Down
9 changes: 5 additions & 4 deletions commanderbot/core/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,19 +50,20 @@ def run():
# Read config file
log.info(f"Configuration file: {parsed_args.config}")
log.debug("Parsing configuration file...")
config = Config.from_file(parsed_args.config) # type: ignore
config = Config.model_validate_json(parsed_args.config.read_text())
config.log_info()
log.debug("Successfully parsed configuration file!")

# Get bot token
bot_token = os.environ.get("BOT_TOKEN", None)

if not bot_token:
log.warning(
"Bot token provided in a form other than the BOT_TOKEN environment variable."
"Bot token provided in a form other than the BOT_TOKEN environment variable"
)

if parsed_args.token:
log.info("Using bot token provided as an argument.")
log.info("Using bot token provided as an argument")
bot_token = parsed_args.token

elif parsed_args.tokenfile:
Expand All @@ -78,6 +79,6 @@ def run():
bot = CommanderBot(config, parsed_args.synctree)
bot.run(bot_token)

log.warning("Bot has shut down.")
log.warning("Bot has shut down!")

log.info("Goodbye!")
23 changes: 12 additions & 11 deletions commanderbot/core/command_tree.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from collections import defaultdict
from collections.abc import Iterable
from dataclasses import dataclass, field
from logging import Logger, getLogger
from typing import Iterable, Optional, TypeAlias
from typing import Optional, override

from discord import AppCommandType
from discord.abc import Snowflake
Expand All @@ -11,8 +12,8 @@

__all__ = ("CachingCommandTree",)

Cache: TypeAlias = dict[str, AppCommand]
GuildType: TypeAlias = Snowflake | GuildID
type Cache = dict[str, AppCommand]
type GuildType = Snowflake | GuildID


@dataclass
Expand Down Expand Up @@ -47,7 +48,7 @@ def update(self, commands: list[AppCommand], *, override: bool = False):
def traverse_options(options: list[AppCommandGroup | Argument]):
for option in options:
if isinstance(option, AppCommandGroup):
self._cache[option.qualified_name] = option # type: ignore
self._cache[option.qualified_name] = option # type: ignore[ty:invalid-assignment]
traverse_options(option.options)

# Add commands and their options
Expand Down Expand Up @@ -90,7 +91,7 @@ def _get_cache(
if guild:
return self._guild_cache.get(self._guild_to_id(guild))
else:
self._global_cache
return self._global_cache

def _guild_to_id(self, guild: GuildType) -> GuildID:
return guild.id if isinstance(guild, Snowflake) else guild
Expand Down Expand Up @@ -154,7 +155,7 @@ async def build_guild_cache(self, guilds: Iterable[Snowflake]):

self._log.info("Finished building guild command cache.")

# @overrides CommandTree
@override
async def fetch_command(
self,
command_id: int,
Expand All @@ -174,7 +175,7 @@ async def fetch_command(
self.update_cache([command], guild=guild)
return command

# @overrides CommandTree
@override
async def fetch_commands(
self, *, guild: Optional[Snowflake] = None, use_cache: bool = True
) -> list[AppCommand]:
Expand All @@ -188,7 +189,7 @@ async def fetch_commands(
self.update_cache(commands, guild=guild, override=True)
return commands

# @overrides CommandTree
@override
async def sync(self, *, guild: Optional[Snowflake] = None) -> list[AppCommand]:
# Create log messages
sync_msg: str = "global app commands"
Expand All @@ -205,8 +206,8 @@ async def sync(self, *, guild: Optional[Snowflake] = None) -> list[AppCommand]:
except Exception as ex:
# Temporarily handle exception then re-raise it
# This is only so we can print the warning to the log
self._log.warn(f"Unable to sync {sync_msg}. Reason: {ex}")
raise ex
self._log.warning(f"Unable to sync {sync_msg}. Reason: {ex}")
raise

# Update cache
self._log.info(f"Started updating {cache_msg}...")
Expand All @@ -215,7 +216,7 @@ async def sync(self, *, guild: Optional[Snowflake] = None) -> list[AppCommand]:

return commands

# @overrides CommandTree
@override
def clear_commands(
self,
*,
Expand Down
Loading