-
-
Notifications
You must be signed in to change notification settings - Fork 43
Misc refactorings and optimizations #1160
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
- Updated the default Python version from 3.13 to 3.13.11 in the pre-commit configuration file to ensure compatibility with the latest features and improvements.
- Updated the Python version from 3.13.8 to 3.13.11 in multiple GitHub Actions workflows and the setup-python action to ensure consistency and compatibility with the latest features.
- Updated documentation to reflect the change of Python version from 3.13.8 to 3.13.11 across various files, ensuring consistency in the usage of the latest Python version in CI/CD configurations and Docker references.
- Introduced a new command `fix-sequences` that resets PostgreSQL sequences to the maximum ID value in their respective tables, addressing synchronization issues that can lead to duplicate key violations. - Updated the main application to include the new command, enhancing database management capabilities.
- Updated the Tux bot instance creation to retrieve intents from the configuration, enhancing flexibility in bot behavior based on user-defined settings. - This change allows for more granular control over the bot's event handling capabilities.
- Introduced a new method `send_after_defer` in the BaseCog class to streamline message sending after deferring, accommodating both slash and prefix commands. - This method enhances flexibility by allowing for optional content, embeds, and files, while also managing ephemeral messages and author mentions. - Improved error handling with logging for failed message sends, ensuring better debugging capabilities.
…tency environments - Introduced a new flag `first_ready` to track the initial on_ready event, improving state management. - Configured the HTTP client for high-latency environments early in the setup process to enhance performance and reliability during REST calls.
…er resolution - Introduced the `get_user_safe` function to retrieve users from the bot's cache before making REST API calls, improving performance in high-latency environments. - The function handles user fetching with error logging for better debugging and reliability.
- Introduced a new module to configure discord.py's HTTP client for optimal performance in high-latency, high-jitter environments. - Enhanced connection pooling and DNS caching settings, including adjustments to DNS cache TTL and keepalive timeout. - Implemented error handling and logging for configuration failures, ensuring graceful degradation and visibility into issues.
…ieval - Refactored the command permission checking logic to support batch retrieval of permissions for multiple commands, improving efficiency. - Introduced a new method `batch_get_command_permissions` to allow simultaneous permission checks for a list of command names, reducing database query overhead. - Updated logging to use trace level for parent command permission usage, enhancing clarity during permission checks.
- Updated the case creation logic to filter out the 'id' key from additional kwargs, ensuring that the database auto-generates the ID. - Added a warning log when 'id' is included in kwargs, enhancing clarity and preventing potential issues with manual ID assignment.
… processing - Introduced caching for user permission rank to reduce database queries during help operations. - Added a new method `_filter_commands_for_permission_check` to streamline the filtering of commands based on their permission requirements. - Enhanced `batch_can_run_commands` to efficiently check permissions for multiple commands, improving performance and reducing overhead. - Updated documentation for new methods and clarified permission checking logic.
…ocessing - Enhanced the permission checking logic in the TuxHelp class to utilize batch processing for subcommands, significantly improving performance. - Replaced individual permission checks with a batch check, reducing overhead and streamlining the command filtering process.
…rocessing - Improved the permission filtering logic in HelpNavigation by replacing individual permission checks with a batch processing approach, enhancing performance. - This change allows for faster permission validation for subcommands, streamlining the command filtering process.
- Introduced a new method `_send_embed` to streamline sending embeds for both slash and prefix commands, improving user experience. - Added validation methods for emoji, threshold, and channel permissions, providing clear error messages through embeds when validation fails. - Refactored the starboard command logic to utilize the new validation methods, ensuring better error handling and user feedback. - Improved overall code organization and readability by consolidating validation logic.
- Enhanced the on_ready method to check user statuses only on the first startup, reducing unnecessary REST calls during reconnects. - Implemented batch processing of members in chunks to improve performance and manage rate limits effectively. - Added logging to track the processing of members and completion of status role checks for better visibility.
…ion commands - Added early interaction deferral to acknowledge user commands before executing asynchronous tasks in various moderation commands, enhancing user experience. - Updated response handling to utilize interaction follow-ups where applicable, ensuring consistent feedback for users across different moderation actions.
…d avatar commands - Added early interaction deferral to the xkcd and avatar commands to acknowledge user interactions before executing asynchronous tasks, enhancing user experience. - Updated response handling to utilize interaction follow-ups where applicable, ensuring consistent feedback for users across both comic retrieval and avatar display functionalities.
…ing for level commands - Added early interaction deferral to level commands to acknowledge user interactions before executing asynchronous tasks, improving user experience. - Updated response handling to utilize interaction follow-ups where applicable, ensuring consistent feedback for users across level-related commands.
…confirmation handling - Added methods for error message handling and timeout duration validation to improve user feedback and command reliability. - Implemented early interaction deferral to acknowledge user commands before executing asynchronous tasks, enhancing user experience. - Refactored confirmation dialog handling to streamline user interactions and ensure consistent feedback across different command contexts.
… interaction handling - Introduced new methods for building converters and trying entity resolutions, improving the command's ability to handle various Discord objects. - Implemented early interaction deferral to acknowledge user commands before executing asynchronous tasks, enhancing user experience. - Updated response handling to utilize interaction follow-ups for sending error messages and embeds, ensuring consistent feedback across different contexts. - Refactored existing logic to streamline the command flow and improve code readability.
…ling for AFK, RemindMe, and Wiki commands - Added early interaction deferral to AFK, RemindMe, and Wiki commands to acknowledge user interactions before executing asynchronous tasks, enhancing user experience. - Updated response handling to utilize interaction follow-ups where applicable, ensuring consistent feedback for users across different command contexts.
- Added logic to ensure activity rotation starts only on the first ready event, preventing multiple tasks from starting on reconnects. - Introduced a delay before starting the activity rotation to ensure the bot is fully connected, addressing potential disconnection issues.
…nfiguration - Introduced a new BotIntents model to manage Discord bot gateway intents, including members, presences, and message content. - Updated the Config class to include BOT_INTENTS, allowing for easy configuration of bot intents. - Enhanced organization of configuration models by extracting intents-related settings into a dedicated model.
- Updated the Python version in .python-version and Containerfile to 3.13.11 for consistency. - Added mise.toml to specify the Python version for tools, ensuring compatibility across environments.
- Updated the Python image reference in the Containerfile to remove the specific SHA256 digest, streamlining the image definition for easier updates in the future.
Reviewer's GuideRefactors several Discord bot cogs to better support slash vs prefix behavior and high-latency environments, introduces batched permission checks and a sequence-fix CLI for the database, makes intents configurable, optimizes startup/on_ready handlers, and updates tooling/docs to Python 3.13.11. Class diagram for permission system batching and help integrationclassDiagram
class PermissionSystem {
+async get_command_permission(guild_id: int, command_name: str) PermissionCommand|None
+async batch_get_command_permissions(guild_id: int, command_names: list[str]) dict[str, PermissionCommand|None]
+async get_user_permission_rank(ctx: commands.Context[Any]) int
}
class HelpData {
-ctx: commands.Context[Any]|None
-command_mapping: dict[str, dict[str, commands.Command[Any,Any,Any]]]|None
-_cached_user_rank: int|None
+async can_run_command(command: commands.Command[Any,Any,Any]) bool
+async batch_can_run_commands(commands_list: list[commands.Command[Any,Any,Any]]) dict[commands.Command[Any,Any,Any], bool]
-_filter_commands_for_permission_check(commands_list: list[commands.Command[Any,Any,Any]]) tuple[dict[commands.Command[Any,Any,Any], bool], list[commands.Command[Any,Any,Any]]]
-_uses_permission_system(command: commands.Command[Any,Any,Any]) bool
-_is_owner_or_sysadmin() bool
+find_command(command_name: str) commands.Command[Any,Any,Any]|None
+find_parent_command(subcommand_name: str) commands.Command[Any,Any,Any]|None
}
class HelpNavigation {
-data: HelpData
-current_command_obj: commands.Command[Any,Any,Any]|None
-current_command: str|None
+async create_command_view() HelpView
}
class PermissionCommand {
+guild_id: int
+command_name: str
+required_rank: int
}
HelpNavigation --> HelpData : uses
HelpData --> PermissionSystem : uses
PermissionSystem --> PermissionCommand : returns
Class diagram for configurable bot intents and HTTP configurationclassDiagram
class Config {
+BOT_INFO: BotInfo
+BOT_INTENTS: BotIntents
+USER_IDS: UserIds
+DATABASE: DatabaseConfig
}
class BotIntents {
+presences: bool
+members: bool
+message_content: bool
+to_discord_intents() discord.Intents
}
class App {
-config: Config
+_create_bot_instance(owner_ids: set[int]) Tux
}
class Tux {
+http: HTTPClient
+first_ready: bool
+guilds_registered: asyncio.Event
+maintenance_mode: bool
+guilds: list[discord.Guild]
+async setup_hook() None
}
class HTTPClient {
-_HTTPClient__session: aiohttp.ClientSession
+ws_connect(url: str, **kwargs) Any
+request(method: str, url: str, **kwargs) Any
}
class aiohttp.ClientSession {
+connector: aiohttp.TCPConnector|None
}
class aiohttp.TCPConnector {
+limit: int
+limit_per_host: int
+ttl_dns_cache: int
+keepalive_timeout: float
}
class HttpConfigModule {
+configure_discord_http_client(bot: Tux) None
}
Config --> BotIntents : owns
App --> Config : uses
App --> Tux : creates
BotIntents --> "1" discord.Intents : builds
Tux --> HTTPClient : has
HTTPClient --> aiohttp.ClientSession : has
aiohttp.ClientSession --> aiohttp.TCPConnector : has
HttpConfigModule --> Tux : configures
Class diagram for new HTTP configuration helper and BaseCog messaging helperclassDiagram
class BaseCog {
+bot: Tux
+db: DatabaseService
+get_config(key: str, default: Any) Any
+async send_after_defer(ctx: commands.Context[Tux], content: str|None, embed: discord.Embed|None, embeds: list[discord.Embed]|None, file: discord.File|None, files: list[discord.File]|None, ephemeral: bool, mention_author: bool) discord.Message|None
}
class HttpConfigModule {
+configure_discord_http_client(bot: Tux) None
}
class Tux {
+http: HTTPClient
+first_ready: bool
+async setup_hook() None
}
class HTTPClient {
-_HTTPClient__session: aiohttp.ClientSession
}
class aiohttp.ClientSession {
+connector: aiohttp.TCPConnector|None
}
class aiohttp.TCPConnector {
+limit: int
+limit_per_host: int
+ttl_dns_cache: int
+keepalive_timeout: float
}
BaseCog <|-- SomeCog
BaseCog --> Tux : uses
Tux --> HTTPClient : has
HTTPClient --> aiohttp.ClientSession : has
aiohttp.ClientSession --> aiohttp.TCPConnector : has
HttpConfigModule --> Tux : configures
Flow diagram for on_ready startup, guild registration, and first_ready gatingflowchart TD
A_bot_start["Bot start"] --> B_connect["discord.py connects to gateway"]
B_connect --> C_on_ready_event["EventHandler.on_ready"]
C_on_ready_event --> D_register_guilds["Register guilds in database"]
D_register_guilds --> E_mark_registered["_guilds_registered = True"]
E_mark_registered --> F_set_event["bot.guilds_registered.set()"]
F_set_event --> G_first_ready_check{bot.first_ready?}
G_first_ready_check -- "False (first time)" --> H_set_first["bot.first_ready = True"]
H_set_first --> I_log_first["Log 'First on_ready event completed'"]
G_first_ready_check -- "True (reconnect)" --> J_skip_first["Skip first_ready changes"]
%% StatusRoles handler
C_status_ready["StatusRoles.on_ready"] --> K_maintenance{bot.maintenance_mode?}
K_maintenance -- "True" --> L_exit_status["Return (skip checks)"]
K_maintenance -- "False" --> M_first_ready_status{bot.first_ready?}
M_first_ready_status -- "False (first startup)" --> N_process_members["Process members in chunks per guild"]
N_process_members --> O_chunk_loop["For each chunk of ~20 non-bot members"]
O_chunk_loop --> P_gather["asyncio.gather(check_and_update_roles)"]
P_gather --> Q_sleep["asyncio.sleep(0.1) between chunks"]
Q_sleep --> O_chunk_loop
O_chunk_loop --> R_done_status["Completed status role checks"]
M_first_ready_status -- "True (not first)" --> S_skip_status["Log 'Skipping member check' and return"]
%% Activity handler
C_activity_ready["ActivityHandler.on_ready"] --> T_task_check{"_activity_task is None or done?"}
T_task_check -- "True" --> U_sleep2["asyncio.sleep(2)"]
U_sleep2 --> V_start_loop["Create task for _activity_loop()"]
T_task_check -- "False" --> W_skip_activity["Do nothing (task already running)"]
%% Synchronization via guilds_registered Event
F_set_event --> C_status_ready
F_set_event --> C_activity_ready
Flow diagram for db fix-sequences CLI commandflowchart TD
A_cmd["User runs: scripts.db fix-sequences"] --> B_typer_entry["fix_sequences() (Typer command)"]
B_typer_entry --> C_print_intro["Print intro and dry-run notice"]
C_print_intro --> D_run_async["asyncio.run(_fix_sequences(dry_run))"]
D_run_async --> E_create_service["Create DatabaseService(echo=False)"]
E_create_service --> F_connect_db["connect(CONFIG.database_url)"]
F_connect_db --> G_get_sequences["execute_query(_get_sequences, 'get_sequences')"]
G_get_sequences --> H_any_sequences{Any sequences found?}
H_any_sequences -- "No" --> I_print_none["Print 'No sequences found' and return"]
H_any_sequences -- "Yes" --> J_iterate["Loop over each sequence"]
J_iterate --> K_check_seq["execute_query(_check_and_fix_sequence, 'check_sequence')"]
K_check_seq --> L_discord_check{"max_id >= DISCORD_SNOWFLAKE_MIN?"}
L_discord_check -- "Yes" --> M_skip_discord["Print skip message (Discord ID)" ]
M_skip_discord --> J_iterate
L_discord_check -- "No" --> N_needs_fix{"next_value <= max_id?"}
N_needs_fix -- "No" --> O_in_sync["Print sequence in sync"]
O_in_sync --> J_iterate
N_needs_fix -- "Yes" --> P_compute_new["new_value = max(max_id, 1)"]
P_compute_new --> Q_dry_run{dry_run?}
Q_dry_run -- "True" --> R_print_dry["Print '[DRY RUN] Would reset' message"]
R_print_dry --> J_iterate
Q_dry_run -- "False" --> S_reset_call["execute_query(_reset_sequence, 'reset_sequence')"]
S_reset_call --> T_commit["setval(sequence, new_value, true) and commit"]
T_commit --> U_inc_counter["Increment fixes_applied and print success for sequence"]
U_inc_counter --> J_iterate
J_iterate --> V_done_all["Loop finished"]
V_done_all --> W_summary{fixes_applied > 0?}
W_summary -- "Yes" --> X_print_fixed["print_success('Fixed N sequence(s)')"]
W_summary -- "No and dry_run" --> Y_print_dry_all["Print 'All sequences are in sync (dry run)' "]
W_summary -- "No and not dry_run" --> Z_print_ok["print_success('All sequences are already in sync')"]
X_print_fixed --> AA_disconnect["disconnect()"]
Y_print_dry_all --> AA_disconnect
Z_print_ok --> AA_disconnect
AA_disconnect --> AB_exit["Return from CLI"]
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. WalkthroughThis PR is a comprehensive multi-faceted update that includes: (1) bumping Python runtime from 3.13.8 to 3.13.11 across CI/CD workflows and Docker configurations, (2) adding database sequence repair tooling and performance indexes, (3) implementing slash command interaction handling with deferred responses and context-aware messaging across moderation and utility modules, (4) introducing intent-based bot configuration and HTTP client optimization, (5) implementing TTL caching for guild configurations, and (6) improving permission system efficiency through batching. Changes
Estimated code review effort🎯 5 (Critical) | ⏱️ ~120 minutes Possibly related issues
Possibly related PRs
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Dependency Review✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.Scanned FilesNone |
…starboard configuration - Added early deferral for interactions to acknowledge user input before processing. - Refactored error handling to utilize a dedicated embed for error messages, improving user feedback and consistency in responses. - Streamlined the response logic by consolidating embed sending into a single method.
…bans - Introduced a composite index for efficient case lookups by guild and case number. - Added a composite index for querying expired temporary bans, optimizing performance for specific case status and type conditions.
- Consolidated response logic in the xkcd commands to improve type safety and reduce code duplication. - Utilized a kwargs dictionary to conditionally build response parameters for sending embeds, views, and ephemeral messages.
- Enhanced response logic to conditionally build payloads for sending messages and embeds, ensuring type safety. - Implemented checks for interaction response status to streamline message sending, improving user experience with ephemeral messages.
- Added a conditional check to defer interaction responses only when an interaction is present, enhancing user experience by ensuring timely feedback during ban operations.
- Added conditional checks to defer interaction responses only when an interaction is present, improving user experience by ensuring timely feedback during case operations. - Updated message sending logic to remove ephemeral flag when not in an interaction context, streamlining response handling.
…ClearAFK module - Added a conditional check to defer interaction responses only when an interaction is present, enhancing user experience during AFK status clearing. - Streamlined message sending by removing the ephemeral flag when not in an interaction context, ensuring clearer feedback for users.
… Jail module - Added conditional checks to defer interaction responses only when an interaction is present, improving user experience during jail operations. - Updated message sending logic to use follow-up messages for interactions, ensuring clearer feedback for users when no jail role or channel is found, or if the user is already jailed.
…n Slowmode module - Enhanced interaction deferral to acknowledge user input early when an interaction is present, improving user experience during slowmode operations. - Refactored message sending logic to utilize a dedicated method for consistent response handling, ensuring clarity in feedback for users across different contexts.
- Added a conditional check to defer interaction responses only when an interaction is present, enhancing user experience during kick operations.
…odules - Added conditional checks to defer interaction responses only when an interaction is present in PollBan, PollUnban, SnippetBan, and SnippetUnban modules, enhancing user experience during moderation operations.
- Added a conditional check to defer interaction responses only when an interaction is present, enhancing user experience during temporary ban operations.
- Added a conditional check to defer interaction responses only when an interaction is present, improving user experience during unban operations.
… Timeout and Untimeout modules - Added conditional checks to defer interaction responses only when an interaction is present, improving user experience during timeout and untimeout operations. - Updated message sending logic to utilize follow-up messages for interactions, ensuring consistent feedback for users across different contexts.
- Added a conditional check to defer interaction responses only when an interaction is present, improving user experience during unjail operations.
- Updated the reminder method to accept the reminder parameter as a keyword-only argument, improving clarity and usability when setting reminders.
…fTimeout module - Removed the ephemeral flag from message replies when not in an interaction context, ensuring clearer feedback for users. - Added a conditional check to defer interaction responses only when an interaction is present, enhancing user experience during self-timeout operations.
- Added a conditional check to defer interaction responses only when an interaction is present, enhancing user experience during warning operations.
- Updated the _log_error method to include the source context (command or interaction) and guild ID in the error logs, improving diagnosability of issues. - Refactored logging statements to provide clearer feedback on encountered errors, including additional context for better troubleshooting.
- Updated the EventHandler to mark the first ready state even if the bot setup is incomplete or fails, preventing unnecessary expensive checks on retries. - This change improves the reliability of the bot's readiness state handling.
…ommunicationService and ExecutionService - Integrated a shared cache manager for guild configurations in CommunicationService, improving efficiency in fetching log channel IDs. - Updated embed sending logic to differentiate between slash and prefix commands, ensuring consistent user feedback. - Enhanced ExecutionService with circuit breaker improvements, including LRU eviction for circuit entries and periodic cleanup to manage memory usage effectively. - Refactored moderation coordinator to execute Discord actions and case creation in parallel, optimizing performance during moderation actions.
- Added a new TTLCache class for thread-safe caching with automatic expiration of entries. - Implemented a GuildConfigCacheManager for managing guild configuration data, ensuring consistency and efficient access. - Updated the shared module to include TTLCache in the public API.
- Added a comment to indicate that cache invalidation is automatically managed by GuildConfigController.update_config, improving code clarity and maintainability.
src/tux/database/migrations/versions/2026_01_23_0138-0b3288704dea_add_case_perf_indexes.py
Dismissed
Show dismissed
Hide dismissed
src/tux/database/migrations/versions/2026_01_23_0138-0b3288704dea_add_case_perf_indexes.py
Dismissed
Show dismissed
Hide dismissed
src/tux/database/migrations/versions/2026_01_23_0138-0b3288704dea_add_case_perf_indexes.py
Dismissed
Show dismissed
Hide dismissed
src/tux/database/migrations/versions/2026_01_23_0138-0b3288704dea_add_case_perf_indexes.py
Dismissed
Show dismissed
Hide dismissed
src/tux/database/migrations/versions/2026_01_23_0138-0b3288704dea_add_case_perf_indexes.py
Dismissed
Show dismissed
Hide dismissed
src/tux/database/migrations/versions/2026_01_23_0138-0b3288704dea_add_case_perf_indexes.py
Dismissed
Show dismissed
Hide dismissed
- Replaced suppress with try-except for better error handling during channel conversion, ensuring that a None return value is properly managed in case of a CommandError.
- Changed the default Python version from 3.13.11 to 3.13 for consistency with the latest stable release.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (4)
src/tux/modules/moderation/unjail.py (2)
173-186: Bug: Usingctx.replyafterctx.defer()will fail for interactions.After deferring an interaction with
ctx.defer(), you must usectx.interaction.followup.send()for subsequent messages, notctx.reply(). The current code defers whenctx.interactionexists (line 175) but then usesctx.reply()for error responses (lines 180, 185), which will fail for slash command invocations.This should follow the same interaction-aware pattern used in
jail.py.🐛 Proposed fix
# Get jail role jail_role = await self.get_jail_role(ctx.guild) if not jail_role: - await ctx.reply("No jail role found.", mention_author=False) + if ctx.interaction: + await ctx.interaction.followup.send("No jail role found.", ephemeral=True) + else: + await ctx.reply("No jail role found.", mention_author=False) return # Check if user is jailed if not await self.is_jailed(ctx.guild.id, member.id): - await ctx.reply("User is not jailed.", mention_author=False) + if ctx.interaction: + await ctx.interaction.followup.send("User is not jailed.", ephemeral=True) + else: + await ctx.reply("User is not jailed.", mention_author=False) return
192-204: Same issue:ctx.replyused after defer insideperform_unjail.Line 203 also uses
ctx.reply()after the interaction has been deferred, which will fail for slash commands. Apply the same fix pattern here.🐛 Proposed fix
case = await self.get_latest_jail_case(guild_id, member.id) if not case: - await ctx.reply("No jail case found.", mention_author=False) + if ctx.interaction: + await ctx.interaction.followup.send("No jail case found.", ephemeral=True) + else: + await ctx.reply("No jail case found.", mention_author=False) returnsrc/tux/modules/moderation/unban.py (1)
133-148: Inconsistent response handling after defer.After deferring the interaction at line 135, the code uses
ctx.reply()at lines 144-147 and 155. For slash commands, after a defer you must usectx.interaction.followup.send()instead—ctx.reply()will fail or behave unexpectedly.Other commands in this PR (e.g.,
timeout,untimeout,slowmode) correctly use the followup pattern after deferring.🐛 Proposed fix
# First, try standard user conversion try: user = await commands.UserConverter().convert(ctx, username_or_id) except commands.UserNotFound: # If that fails, try more flexible ban list matching user = await self.resolve_user_from_ban_list(ctx, username_or_id) if not user: - await ctx.reply( - f"Could not find '{username_or_id}' in the ban list. Try using the exact username or ID.", - mention_author=False, - ) + msg = f"Could not find '{username_or_id}' in the ban list. Try using the exact username or ID." + if ctx.interaction: + await ctx.interaction.followup.send(msg, ephemeral=True) + else: + await ctx.reply(msg, mention_author=False) return # Check if the user is banned try: await ctx.guild.fetch_ban(user) except discord.NotFound: - await ctx.reply(f"{user} is not banned.", mention_author=False) + msg = f"{user} is not banned." + if ctx.interaction: + await ctx.interaction.followup.send(msg, ephemeral=True) + else: + await ctx.reply(msg, mention_author=False) returnsrc/tux/database/controllers/guild_config.py (1)
61-91: Ensure cache invalidation covers all log-channel update paths
update_configinvalidates the cache, but the per-field helpers (update_config_field/update_channel_field) callupdate_by_iddirectly. That means log-channel changes through those methods won’t invalidate the cache, leaving stale audit/mod IDs until TTL expiry.Consider routing field updates through
update_config(or invalidating insideupdate_config_field) to keep log routing consistent.Possible adjustment (apply in
update_config_field)return await self.update_config(guild_id, **{field_name: field_value})
🤖 Fix all issues with AI agents
In `@src/tux/modules/moderation/clearafk.py`:
- Line 43: The return type annotation ") -> discord.Message | None:" is
incorrect because the function never returns None; remove the "| None" so it
reads ") -> discord.Message" and update the function's docstring to state it
returns a discord.Message and will raise on send failure (or explicit
exception), not return None; apply the same fix to the other similar signatures
at the other occurrences (lines 56-57) so all type hints and docstrings
consistently reflect that the functions return discord.Message and raise on
failure.
In `@src/tux/modules/moderation/jail.py`:
- Around line 204-241: The current jail command handler uses inconsistent
response methods (ctx.send) and repeats the same interaction-vs-noninteraction
branching three times; update the non-interaction responses to use ctx.reply to
match unjail behavior and extract the repeated pattern into a small helper
(e.g., respond(ctx, message, *, ephemeral=True)) that checks ctx.interaction and
calls ctx.interaction.followup.send(...) or ctx.reply(...); apply this helper in
the code paths around get_jail_role, get_jail_channel, and is_jailed (and in the
main jail command function) so all messages use the helper and non-interaction
paths use ctx.reply consistently.
In `@src/tux/services/handlers/error/cog.py`:
- Around line 200-211: The log-level lookup using getattr(logger,
config.log_level.lower()) can raise AttributeError if config.log_level is
invalid; change the lookup in the error handler so it falls back to a safe
default (e.g., logger.error) by providing a default value when calling getattr
or validating config.log_level first; update the assignment to log_func in
cog.py (the variable named log_func that uses logger and config.log_level) to
use a fallback logger method to ensure the error path cannot itself raise.
🧹 Nitpick comments (11)
src/tux/modules/utility/self_timeout.py (4)
155-167: Consider usingmemberconsistently for DM and logging.The DM is sent to
ctx.author(line 158) but logging referencesmember(lines 162, 166). While they represent the same user, usingmemberthroughout would be more consistent.Suggested change
try: - await ctx.author.send( + await member.send( f'You have timed yourself out in guild {ctx.guild.name} for {duration_readable} with the reason "{reason}".', )
223-227: Add cooldown decorator per coding guidelines.The command lacks rate limiting, which is required per the coding guidelines for Discord commands. Self-timeout is a significant action that should have abuse prevention.
Suggested change
`@commands.hybrid_command`( name="self_timeout", aliases=["sto", "stimeout", "selftimeout"], ) `@commands.guild_only`() +@commands.cooldown(1, 60, commands.BucketType.user) async def self_timeout(Based on learnings, Discord commands should implement cooldowns and rate limiting.
307-310: Provide feedback when user cancels the timeout.When the user doesn't confirm, the command returns silently. Adding a brief message improves UX clarity.
Suggested change
confirmed = await self._send_confirmation_dialog(ctx, message_content) if not confirmed: + logger.debug(f"Self-timeout cancelled by {member.display_name} ({member.id})") + await self._send_error_message(ctx, "Self-timeout cancelled.") return
298-305: Consider usingduration_readablefor consistency.The warning message uses the raw
durationstring while other messages useduration_readable. Using the human-readable format throughout provides a more consistent user experience.Suggested change
message_content = ( f'### WARNING\n### You are about to be timed out in the guild "{ctx.guild.name}" ' - f'for {duration} with the reason "{reason}".\n' + f'for {duration_readable} with the reason "{reason}".\n' "as soon as you confirm this, **you cannot cancel it or remove it early**. "scripts/db/fix_sequences.py (1)
125-136: Consider using proper identifier quoting for defense-in-depth.While
sequence_name,table_name, andcolumn_nameoriginate from trusted system catalogs, PostgreSQL identifiers can contain special characters, spaces, or reserved words. Usingquote_ident()in the SQL or SQLAlchemy's escaping mechanisms would make this more robust.♻️ Suggested improvement using PostgreSQL's quote_ident()
# Get current sequence value current_seq_result = await session.execute( - text(f"SELECT last_value, is_called FROM {sequence_name}"), + text(f"SELECT last_value, is_called FROM {sequence_name}"), # sequence_name is already schema-qualified ) current_seq_row = current_seq_result.fetchone() current_seq_value = current_seq_row[0] if current_seq_row else 0 is_called = current_seq_row[1] if current_seq_row else False # Get max ID from table (table and column are safe identifiers) + # For additional safety with edge-case identifiers, consider: + # text(f"SELECT COALESCE(MAX(quote_ident('{column_name}')), 0) FROM quote_ident('{table_name}')") max_id_result = await session.execute( text(f"SELECT COALESCE(MAX({column_name}), 0) FROM {table_name}"), )Alternatively, you could build the query using PostgreSQL's
format()function with%Iplaceholders for identifiers.src/tux/modules/moderation/jail.py (1)
183-189: Signature change looks good, butnoqa PLR0912indicates complexity.The addition of
flags: JailFlagsaligns with other moderation commands in the codebase. However, thenoqa PLR0912suppression indicates the method has too many branches. Consider extracting validation logic into helper methods to reduce complexity.src/tux/modules/moderation/unjail.py (1)
45-48: Docstring usesOptional[discord.Role]instead ofdiscord.Role | None.Per coding guidelines, prefer
Type | Nonesyntax. The identical method injail.py(line 56) correctly usesdiscord.Role | None.📝 Suggested fix
Returns ------- - Optional[discord.Role] + discord.Role | None The jail role, or None if not found.src/tux/database/models/models.py (1)
698-721: Potentially redundant indexidx_case_guild_number.Line 721 already declares
UniqueConstraint("guild_id", "case_number", name="uq_case_guild_case_number"), which implicitly creates a unique index on those columns in PostgreSQL. The explicitidx_case_guild_numbernon-unique index on the same columns is therefore redundant and adds maintenance overhead without query benefit.Consider removing
idx_case_guild_numbersince the unique constraint already provides the same lookup performance.♻️ Proposed fix
Index("idx_case_processed", "case_processed"), - # Composite index for case lookup by guild and case number (common query pattern) - Index("idx_case_guild_number", "guild_id", "case_number"), # Composite index for expired tempban queries (guild_id, case_type, case_status, case_expires_at) Index(src/tux/database/migrations/versions/2026_01_23_0138-0b3288704dea_add_case_perf_indexes.py (1)
11-14: Unused importsqlmodel.The
sqlmodelimport on line 13 is not used in this migration file.♻️ Proposed fix
from alembic import op import sqlalchemy as sa -import sqlmodelsrc/tux/modules/moderation/slowmode.py (1)
308-312: Fragile string manipulation for message formatting.Line 311 splits on
'is'to reuse part of_format_slowmode_message(). This works but creates a brittle dependency on the exact message format. Consider extracting a separate method that returns only the duration description, or restructuring to avoid parsing the formatted output.♻️ Example improvement
+ `@staticmethod` + def _format_duration(delay: int) -> str: + """Format delay into a human-readable duration string.""" + if delay == 0: + return "disabled" + if delay == 1: + return "1 second" + if delay < 60: + return f"{delay} seconds" + if delay == 60: + return "1 minute" + minutes, seconds = divmod(delay, 60) + if seconds == 0: + return f"{minutes} minutes" + minute_suffix = "s" if minutes > 1 else "" + second_suffix = "s" if seconds > 1 else "" + return f"{minutes} minute{minute_suffix} and {seconds} second{second_suffix}" + `@staticmethod` def _format_slowmode_message(delay: int, channel_mention: str) -> str: - # ... existing implementation + duration = Slowmode._format_duration(delay) + if delay == 0: + return f"Slowmode is disabled in {channel_mention}." + return f"The slowmode in {channel_mention} is {duration}."Then in
_set_slowmode:if delay_seconds == 0: message = f"Slowmode has been disabled in {channel.mention}." else: - prefix = "Slowmode set to" - message = f"{prefix} {self._format_slowmode_message(delay_seconds, channel.mention).split('is')[1].strip()}" + message = f"Slowmode set to {self._format_duration(delay_seconds)} in {channel.mention}."src/tux/modules/info/info.py (1)
337-377: Interaction guard is correctly implemented; consider adding cooldown.The
if ctx.interaction:guard on line 358 correctly addresses the previous review concern about prefix command support.Per coding guidelines, consider adding a cooldown to prevent abuse:
💡 Optional cooldown decorator
`@commands.hybrid_group`( name="info", aliases=["i"], ) `@commands.guild_only`() +@commands.cooldown(1, 5, commands.BucketType.user) async def info(
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (35)
scripts/db/fix_sequences.pysrc/tux/core/decorators.pysrc/tux/core/http_config.pysrc/tux/database/controllers/guild_config.pysrc/tux/database/migrations/versions/2026_01_23_0138-0b3288704dea_add_case_perf_indexes.pysrc/tux/database/models/models.pysrc/tux/modules/features/starboard.pysrc/tux/modules/fun/xkcd.pysrc/tux/modules/info/info.pysrc/tux/modules/moderation/ban.pysrc/tux/modules/moderation/cases.pysrc/tux/modules/moderation/clearafk.pysrc/tux/modules/moderation/jail.pysrc/tux/modules/moderation/kick.pysrc/tux/modules/moderation/pollban.pysrc/tux/modules/moderation/pollunban.pysrc/tux/modules/moderation/slowmode.pysrc/tux/modules/moderation/snippetban.pysrc/tux/modules/moderation/snippetunban.pysrc/tux/modules/moderation/tempban.pysrc/tux/modules/moderation/timeout.pysrc/tux/modules/moderation/unban.pysrc/tux/modules/moderation/unjail.pysrc/tux/modules/moderation/untimeout.pysrc/tux/modules/moderation/warn.pysrc/tux/modules/utility/remindme.pysrc/tux/modules/utility/self_timeout.pysrc/tux/services/handlers/error/cog.pysrc/tux/services/handlers/event.pysrc/tux/services/moderation/communication_service.pysrc/tux/services/moderation/execution_service.pysrc/tux/services/moderation/moderation_coordinator.pysrc/tux/shared/__init__.pysrc/tux/shared/cache.pysrc/tux/ui/views/config/dashboard.py
🚧 Files skipped from review as they are similar to previous changes (7)
- src/tux/modules/moderation/ban.py
- src/tux/modules/moderation/pollban.py
- src/tux/modules/moderation/warn.py
- src/tux/modules/fun/xkcd.py
- src/tux/modules/utility/remindme.py
- src/tux/modules/moderation/snippetunban.py
- src/tux/modules/moderation/snippetban.py
🧰 Additional context used
📓 Path-based instructions (9)
**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
**/*.py: Use strict type hints withType | Nonesyntax instead ofOptional[Type]in Python
Use NumPy docstring format for documenting Python functions and classes
Prefer absolute imports, with relative imports allowed only within the same module
Organize imports in order: stdlib → third-party → local, with imports at the top of the file unless absolutely necessary
Use 88 character line length for Python code
Use snake_case for functions and variables, PascalCase for classes, UPPER_CASE for constants in Python
Ensure all type hints are complete for function signatures
Add docstrings for all public APIs
Keep Python files to a maximum of 1600 lines
Use async/await for I/O operations instead of blocking calls
Use custom exceptions for business logic errors
Log with context when handling errors
Do not store secrets in code, use environment variables for configuration
Validate all user inputs in Python code
One class or function per file when possible
**/*.py: Follow input validation patterns fromsecurity/validation.mdc
Follow error patterns fromerror-handling/patterns.mdc
Follow logging patterns using loguru fromerror-handling/logging.mdc
Follow Sentry integration patterns fromerror-handling/sentry.mdc
Follow user-facing error message patterns fromerror-handling/user-feedback.mdc
Follow Discord.py Components V2 rules fromui/cv2.mdc
Files:
src/tux/modules/moderation/pollunban.pysrc/tux/modules/moderation/unjail.pysrc/tux/modules/moderation/cases.pysrc/tux/services/handlers/event.pysrc/tux/modules/moderation/untimeout.pysrc/tux/modules/features/starboard.pysrc/tux/ui/views/config/dashboard.pysrc/tux/services/moderation/communication_service.pysrc/tux/modules/moderation/tempban.pysrc/tux/services/moderation/execution_service.pysrc/tux/database/models/models.pysrc/tux/modules/moderation/slowmode.pysrc/tux/shared/__init__.pysrc/tux/core/decorators.pysrc/tux/services/handlers/error/cog.pysrc/tux/database/controllers/guild_config.pyscripts/db/fix_sequences.pysrc/tux/core/http_config.pysrc/tux/modules/utility/self_timeout.pysrc/tux/modules/moderation/timeout.pysrc/tux/services/moderation/moderation_coordinator.pysrc/tux/shared/cache.pysrc/tux/database/migrations/versions/2026_01_23_0138-0b3288704dea_add_case_perf_indexes.pysrc/tux/modules/moderation/clearafk.pysrc/tux/modules/moderation/unban.pysrc/tux/modules/moderation/jail.pysrc/tux/modules/moderation/kick.pysrc/tux/modules/info/info.py
src/tux/modules/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
src/tux/modules/**/*.py: Use hybrid commands (slash and traditional) for Discord bot commands
Implement role-based permissions for Discord commands
Implement cooldowns and rate limiting for Discord commands
Files:
src/tux/modules/moderation/pollunban.pysrc/tux/modules/moderation/unjail.pysrc/tux/modules/moderation/cases.pysrc/tux/modules/moderation/untimeout.pysrc/tux/modules/features/starboard.pysrc/tux/modules/moderation/tempban.pysrc/tux/modules/moderation/slowmode.pysrc/tux/modules/utility/self_timeout.pysrc/tux/modules/moderation/timeout.pysrc/tux/modules/moderation/clearafk.pysrc/tux/modules/moderation/unban.pysrc/tux/modules/moderation/jail.pysrc/tux/modules/moderation/kick.pysrc/tux/modules/info/info.py
src/tux/services/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
src/tux/services/**/*.py: Use dependency injection in service classes
Keep service classes stateless where possible and use async/await for I/O
Use caching for frequently accessed data
Files:
src/tux/services/handlers/event.pysrc/tux/services/moderation/communication_service.pysrc/tux/services/moderation/execution_service.pysrc/tux/services/handlers/error/cog.pysrc/tux/services/moderation/moderation_coordinator.py
**/*event*.py
📄 CodeRabbit inference engine (.cursor/rules/rules.mdc)
Follow Discord event handler patterns from
modules/events.mdc
Files:
src/tux/services/handlers/event.py
src/tux/ui/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Use rich embeds for Discord message formatting
Files:
src/tux/ui/views/config/dashboard.py
**/*service*.py
📄 CodeRabbit inference engine (.cursor/rules/rules.mdc)
Follow DatabaseService patterns from
database/services.mdc
Files:
src/tux/services/moderation/communication_service.pysrc/tux/services/moderation/execution_service.py
src/tux/database/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
src/tux/database/**/*.py: Use SQLModel for type-safe ORM operations
Use Pydantic for data validation in database models
Use transactions for multi-step database operations
Implement model-level validation in database models
Optimize database queries for performance
Files:
src/tux/database/models/models.pysrc/tux/database/controllers/guild_config.pysrc/tux/database/migrations/versions/2026_01_23_0138-0b3288704dea_add_case_perf_indexes.py
**/*models.py
📄 CodeRabbit inference engine (.cursor/rules/rules.mdc)
Follow SQLModel database model patterns from
database/models.mdc
Files:
src/tux/database/models/models.py
src/tux/database/migrations/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Use Alembic for database migrations
Files:
src/tux/database/migrations/versions/2026_01_23_0138-0b3288704dea_add_case_perf_indexes.py
🧠 Learnings (12)
📚 Learning: 2026-01-12T20:42:11.193Z
Learnt from: CR
Repo: allthingslinux/tux PR: 0
File: .cursor/rules/rules.mdc:0-0
Timestamp: 2026-01-12T20:42:11.193Z
Learning: Applies to **/*interaction*.py : Follow interaction response patterns from `modules/interactions.mdc`
Applied to files:
src/tux/modules/moderation/pollunban.pysrc/tux/modules/moderation/cases.pysrc/tux/modules/moderation/untimeout.py
📚 Learning: 2025-12-30T22:45:12.307Z
Learnt from: CR
Repo: allthingslinux/tux PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-30T22:45:12.307Z
Learning: Applies to src/tux/ui/**/*.py : Use rich embeds for Discord message formatting
Applied to files:
src/tux/modules/features/starboard.py
📚 Learning: 2025-12-30T22:45:12.307Z
Learnt from: CR
Repo: allthingslinux/tux PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-30T22:45:12.307Z
Learning: Applies to src/tux/modules/**/*.py : Use hybrid commands (slash and traditional) for Discord bot commands
Applied to files:
src/tux/modules/features/starboard.py
📚 Learning: 2025-12-30T22:45:12.307Z
Learnt from: CR
Repo: allthingslinux/tux PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-30T22:45:12.307Z
Learning: Applies to src/tux/modules/**/*.py : Implement cooldowns and rate limiting for Discord commands
Applied to files:
src/tux/modules/moderation/slowmode.pysrc/tux/core/http_config.pysrc/tux/modules/utility/self_timeout.pysrc/tux/modules/moderation/timeout.pysrc/tux/modules/info/info.py
📚 Learning: 2025-12-30T22:45:12.307Z
Learnt from: CR
Repo: allthingslinux/tux PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-30T22:45:12.307Z
Learning: Applies to src/tux/services/**/*.py : Use caching for frequently accessed data
Applied to files:
src/tux/shared/__init__.py
📚 Learning: 2025-12-30T22:45:12.307Z
Learnt from: CR
Repo: allthingslinux/tux PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-30T22:45:12.307Z
Learning: Applies to src/tux/modules/**/*.py : Implement role-based permissions for Discord commands
Applied to files:
src/tux/core/decorators.pysrc/tux/modules/info/info.py
📚 Learning: 2025-12-30T22:45:12.307Z
Learnt from: CR
Repo: allthingslinux/tux PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-30T22:45:12.307Z
Learning: Applies to **/*.py : Log with context when handling errors
Applied to files:
src/tux/services/handlers/error/cog.py
📚 Learning: 2026-01-12T20:42:11.193Z
Learnt from: CR
Repo: allthingslinux/tux PR: 0
File: .cursor/rules/rules.mdc:0-0
Timestamp: 2026-01-12T20:42:11.193Z
Learning: Applies to **/*.py : Follow logging patterns using loguru from `error-handling/logging.mdc`
Applied to files:
src/tux/services/handlers/error/cog.py
📚 Learning: 2026-01-12T20:42:11.193Z
Learnt from: CR
Repo: allthingslinux/tux PR: 0
File: .cursor/rules/rules.mdc:0-0
Timestamp: 2026-01-12T20:42:11.193Z
Learning: Applies to **/*.py : Follow error patterns from `error-handling/patterns.mdc`
Applied to files:
src/tux/services/handlers/error/cog.py
📚 Learning: 2026-01-12T20:42:11.193Z
Learnt from: CR
Repo: allthingslinux/tux PR: 0
File: .cursor/rules/rules.mdc:0-0
Timestamp: 2026-01-12T20:42:11.193Z
Learning: Applies to **/*.py : Follow user-facing error message patterns from `error-handling/user-feedback.mdc`
Applied to files:
src/tux/services/handlers/error/cog.py
📚 Learning: 2025-12-30T22:45:12.307Z
Learnt from: CR
Repo: allthingslinux/tux PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-30T22:45:12.307Z
Learning: Applies to **/*.py : Use custom exceptions for business logic errors
Applied to files:
src/tux/services/handlers/error/cog.py
📚 Learning: 2025-12-30T22:45:12.307Z
Learnt from: CR
Repo: allthingslinux/tux PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-30T22:45:12.307Z
Learning: Applies to src/tux/database/**/*.py : Optimize database queries for performance
Applied to files:
src/tux/database/migrations/versions/2026_01_23_0138-0b3288704dea_add_case_perf_indexes.py
🧬 Code graph analysis (12)
src/tux/modules/moderation/pollunban.py (1)
src/tux/modules/moderation/__init__.py (1)
is_pollbanned(135-154)
src/tux/modules/moderation/cases.py (2)
src/tux/database/controllers/__init__.py (2)
case(145-149)guild(110-114)src/tux/database/controllers/case.py (1)
get_case_by_number(343-354)
src/tux/modules/features/starboard.py (1)
src/tux/ui/embeds.py (1)
EmbedCreator(38-235)
src/tux/shared/__init__.py (1)
src/tux/shared/cache.py (1)
TTLCache(19-167)
src/tux/services/handlers/error/cog.py (1)
src/tux/services/handlers/error/config.py (1)
ErrorHandlerConfig(38-60)
src/tux/database/controllers/guild_config.py (2)
src/tux/database/models/models.py (1)
GuildConfig(174-323)src/tux/shared/cache.py (1)
GuildConfigCacheManager(170-246)
src/tux/core/http_config.py (1)
src/tux/core/bot.py (1)
Tux(46-495)
src/tux/modules/utility/self_timeout.py (3)
src/tux/ui/views/confirmation.py (1)
ConfirmationDanger(92-107)src/tux/modules/utility/__init__.py (2)
add_afk(40-64)del_afk(67-80)src/tux/shared/functions.py (2)
convert_to_seconds(125-190)seconds_to_human_readable(193-222)
src/tux/services/moderation/moderation_coordinator.py (4)
src/tux/database/controllers/case.py (2)
update_mod_log_message_id(211-231)create_case(80-198)src/tux/services/moderation/case_service.py (2)
update_mod_log_message_id(131-154)create_case(36-77)src/tux/services/moderation/communication_service.py (1)
send_dm(41-89)src/tux/database/models/models.py (1)
Case(569-726)
src/tux/modules/moderation/clearafk.py (1)
src/tux/database/controllers/afk.py (1)
is_afk(142-151)
src/tux/modules/moderation/jail.py (2)
src/tux/modules/moderation/unjail.py (1)
get_jail_role(36-51)src/tux/modules/moderation/__init__.py (1)
is_jailed(111-133)
src/tux/modules/info/info.py (1)
src/tux/core/converters.py (1)
get_user_safe(179-209)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Seer Code Review
- GitHub Check: Run All Tests (3.13.11)
🔇 Additional comments (90)
src/tux/core/decorators.py (3)
104-113: LGTM! Good refactor to consolidate command name extraction.Extracting
command_nameonce at the start and using it consistently throughout the permission flow improves maintainability. The fallback tofunc.__name__ensures logging works even in edge cases before theValueErroris raised at line 115.
139-141: LGTM! Better audit trail for permission bypasses.Including
command_namein the bypass log message improves traceability when debugging permission issues.
146-148: LGTM! Consistent logging pattern.Matches the logging pattern used for bot owner/sysadmin bypass, maintaining consistency across permission bypass scenarios.
src/tux/modules/utility/self_timeout.py (4)
34-51: LGTM!The helper correctly handles both interaction and prefix command contexts, with ephemeral appropriately applied only to the interaction branch.
53-93: LGTM!Clean validation logic with appropriate bounds checking and debug logging. The walrus operator usage at the call site (line 276) is idiomatic.
95-133: LGTM!The confirmation dialog helper properly handles both command contexts and includes robust exception handling for message deletion. Past review concerns have been addressed.
177-221: LGTM!The timeout application and AFK status setting logic is well-structured. The
assert member.guild is not Noneon line 209 is acceptable here since guild validation occurs in the calling command context.scripts/db/fix_sequences.py (12)
1-28: LGTM!Module docstring clearly explains purpose, and imports are correctly organized following the stdlib → third-party → local convention with complete type annotations.
30-51: LGTM!The SQL query correctly discovers serial-backed sequences using
pg_get_serial_sequence(), and the Discord snowflake threshold is appropriate for filtering externally-provided IDs.
53-64: LGTM!Clean dataclass definition with clear field names and types for representing a sequence fix plan.
66-98: LGTM!The function correctly preserves schema-qualified sequence names, addressing the previous review concern about
search_pathdependency.
153-172: LGTM!The
setval()usage follows correct PostgreSQL syntax. The commit per reset is appropriate for a maintenance CLI to ensure each fix is persisted independently.
175-205: LGTM!Pure function with clear filtering logic. The
max(status["max_id"], 1)correctly handles empty tables by ensuring the sequence starts at 1.
208-271: LGTM!The lambda pattern with default arguments correctly captures loop variables to avoid late binding issues. The redundant condition checks (lines 245, 254) before
plan_sequence_fixare intentional for providing user feedback on skipped sequences.
274-313: LGTM!Clean separation of dry-run vs actual application logic. The lambda pattern correctly captures loop variables.
316-342: LGTM!The dry-run summary now correctly reports "Would fix N sequence(s)" when sequences need fixing, addressing the previous review concern about misleading messages.
345-383: LGTM!Clean orchestration with proper resource cleanup in the
finallyblock. The exception handling is appropriate for an admin maintenance CLI tool.
386-412: LGTM!Standard Typer CLI pattern with clear help text and informative user messaging before execution.
415-416: LGTM!Standard script entry point pattern.
src/tux/modules/moderation/tempban.py (1)
57-60: LGTM! Early defer pattern is correctly implemented.The pattern correctly checks for
ctx.interactionbefore deferring, ensuring prefix commands are unaffected. Ephemeral deferral is appropriate for moderation commands to keep channel activity minimal.The
moderate_usermethod in the base class properly handles the deferred state through theCommunicationService.send_embed()method, which explicitly usesctx.interaction.followup.send()for slash commands andctx.send()for prefix commands—exactly the interaction-aware pattern needed.src/tux/modules/moderation/clearafk.py (1)
61-63: Interaction deferral and follow-ups look consistent.Also applies to: 66-71, 87-91
src/tux/services/handlers/event.py (3)
34-38: LGTM!The early-exit path correctly marks
first_readyto prevent expensive startup checks on reconnects, even when setup hasn't completed. The guard and comment are clear.
78-84: LGTM!The first-ready marking after successful guild registration is well-placed, with appropriate debug logging for observability. The comment accurately describes the intent.
86-92: LGTM!Properly ensures
first_readyis set and waiters are unblocked even on failure, preventing hangs and expensive retry checks. The exception is correctly logged and re-raised.src/tux/core/http_config.py (4)
26-35: LGTM!The
TYPE_CHECKINGguard correctly addresses the circular import withbot.py, and import ordering follows the coding guidelines (stdlib → third-party → local).
37-77: LGTM!The helper function is well-designed with keyword-only arguments for optional parameters, proper exception handling for read-only attributes, and complete NumPy-style documentation.
137-181: LGTM!The attribute configuration attempts are appropriately defensive. The logging levels correctly distinguish between successful configurations (info) and expected failures for constructor-only attributes (debug). The
seconds_suffixparameter is correctly applied to time-based values for clearer log output.
103-135: The timing concern is already addressed in the code.The session may not exist at
setup_hook()time—this is a valid concern and is explicitly acknowledged in the warning message ("setup_hook() may be running before login()..."). However, the function already handles this gracefully with defensive checks and early returns. The docstring documents this as a best-effort approach, and the implementation cannot reliably be moved to run afterlogin()sincesetup_hook()is called as part of the login process itself.The current implementation is appropriate: it attempts configuration when possible but fails safely with informative logging when the session isn't available yet.
src/tux/services/handlers/error/cog.py (2)
128-129: LGTM — passing source context improves diagnostics.
252-255: LGTM — catch-all logging prevents silent failures.src/tux/modules/moderation/timeout.py (1)
66-116: LGTM!The interaction handling is well-implemented with consistent patterns:
- Early defer acknowledges the interaction before async work
- All error/status messages correctly route through
followup.sendfor interactions andctx.sendfor prefix commands- The
noqa: PLR0912suppression is acceptable given the necessary validation branchessrc/tux/modules/moderation/untimeout.py (1)
64-77: LGTM!The interaction handling follows the same consistent pattern as the timeout command—early defer and proper followup routing. Implementation is clean and correct.
src/tux/database/migrations/versions/2026_01_23_0138-0b3288704dea_add_case_perf_indexes.py (1)
23-47: LGTM!The migration correctly creates and drops the indexes with proper partial index conditions. The upgrade/downgrade operations are reversible and align with the model definitions.
Note: If the
idx_case_guild_numberindex is deemed redundant (per the models.py review), this migration would need to be updated accordingly.src/tux/modules/moderation/slowmode.py (2)
119-159: LGTM! Good caching strategy for channel resolution.The
_resolve_channelmethod efficiently prioritizes cached lookups (viaget_channel/get_thread) before falling back to the converter, avoiding unnecessary API calls. The use ofsuppressfor error handling is clean.
180-202: LGTM! Centralized response handling.The
_send_responsehelper provides a clean abstraction for handling both slash and prefix command responses, reducing code duplication across the module.src/tux/database/models/models.py (1)
701-708: No action needed. TheTEMPBANenum value is correctly defined as"TEMPBAN"insrc/tux/database/models/enums.pyand matches the string literal used in thepostgresql_whereclause. The partial index condition will correctly filter on tempban cases.src/tux/modules/info/info.py (5)
117-167: Well-structured response helper with comprehensive path coverage.The
_send_responsemethod cleanly handles all interaction vs. prefix command scenarios. The logic correctly:
- Checks if response is already done before choosing followup vs. direct response
- Handles empty payload edge case
- Falls back appropriately for prefix commands
169-206: Banner helpers properly address previous review concerns.The
_get_member_bannermethod correctly usesget_user_safeto fetch the user safely, avoiding themember.userattribute issue. The_get_user_bannerstatic method uses defensivegetattraccess. Both implementations are clean.
208-268: Converter resolution logic is well-structured.The method correctly iterates through converters, handles the
@everyonerole edge case, and returns a clear boolean result. The inline converter list building addresses previous review suggestions.
270-307: Guild ID resolution is clean with no unreachable code.The refactored
_try_guild_idmethod uses early returns properly, addressing the previous static analysis concern about unreachable code. The 15-20 digit validation for Discord snowflakes is appropriate.
379-423: Consistent use of_send_responseacross all display methods.All
_show_*_infomethods now route through the centralized_send_responsehelper, reducing duplication and ensuring consistent behavior for both interaction and prefix contexts.src/tux/ui/views/config/dashboard.py (1)
2339-2364: Documentation comment accurately describes caching behavior.The added comment on line 2359 correctly notes that cache invalidation is handled by
GuildConfigController.update_config. This improves code clarity without changing behavior.src/tux/shared/__init__.py (1)
1-11: Clean public API exposure of TTLCache.The re-export pattern is appropriate for shared utilities. The
TTLCacheclass (fromcache.py) provides a useful thread-safe caching mechanism with TTL support.src/tux/modules/moderation/kick.py (1)
59-61: Early defer with interaction guard is correctly implemented.The pattern
if ctx.interaction: await ctx.defer(ephemeral=True)correctly acknowledges slash command interactions before async work while preserving prefix command compatibility.src/tux/modules/moderation/pollunban.py (1)
62-75: Interaction-aware response handling is correctly implemented.The early defer with guard (lines 62-64) and conditional followup vs. reply (lines 68-74) correctly handle both slash and prefix command contexts. The ephemeral flag ensures moderator privacy for slash commands.
src/tux/modules/moderation/cases.py (10)
150-153: Consistent early defer pattern across case commands.The early defer with interaction guard is correctly applied to the main
casescommand group.
180-183: LGTM - view subcommand defer.
208-211: LGTM - search subcommand defer.
241-262: Interaction-aware error handling in modify command.The case-not-found and no-valid-changes error paths correctly use
interaction.followup.sendwhen an interaction exists, with appropriate fallbacks toctx.send.
299-311: LGTM - _view_all_cases interaction handling.
313-339: LGTM - _view_single_case interaction handling.
369-385: LGTM - _view_cases_with_flags interaction handling.
416-435: LGTM - _update_case failure path handling.
587-643: LGTM - _send_case_embed interaction handling.Both the error case (lines 617-621) and success case (lines 640-643) correctly use interaction followup when available.
663-673: LGTM - _handle_case_list_response empty case handling.src/tux/database/controllers/guild_config.py (1)
550-571: Batch log-channel fetch helper looks goodClean, single-query access pattern that aligns with the cache usage in services.
src/tux/modules/features/starboard.py (6)
45-62: Unified embed send helper is cleanCentralizes interaction vs prefix handling neatly.
64-86: Emoji validation helper is clearConcise and reusable validation path.
88-110: Threshold validation helper is straightforwardGood guardrail for minimum values.
112-140: Channel permission check helper is tidyKeeps permission validation in one place.
250-320: Setup flow now consistent with interaction deferralEarly defer + centralized validation/readable response handling is solid.
337-384: Removal flow uses unified response handlingConsistent send path and error embed behavior.
src/tux/services/moderation/communication_service.py (4)
38-40: Shared guild-config cache wiring looks goodKeeps cache access centralized and reusable.
198-229: Interaction-aware send path is consistentClear split between followup vs prefix send.
238-272: Cache-backed log channel lookup is efficientNice single-query fetch and cache fill on misses.
274-284: Explicit cache invalidation helper is handyGood encapsulation for targeted invalidation.
src/tux/shared/cache.py (12)
34-48: TTLCache initialization is straightforwardDefaults and state setup are clear.
49-76: Expiration-on-access logic looks goodSimple and predictable cleanup on reads.
78-98: Eviction and TTL assignment are clearFIFO eviction with TTL is easy to reason about.
100-116: Invalidate supports single-key and full clearGood dual-path invalidation.
118-145: get_or_fetch utility is conciseClean helper for cache fill behavior.
146-163: Size calculation with expiry cleanup is fineEnsures size reflects live entries.
165-167: Clear delegating to invalidate is fineSmall and consistent API.
182-187: Singleton initialization looks goodEncapsulates cache creation neatly.
189-204: Cache keying for guild config is cleanSimple and consistent key format.
206-228: Guild config cache set is clearStores audit/mod IDs in a simple payload.
230-241: Per-guild invalidation helper is solidClear path for targeted cache resets.
243-246: Clear-all helper is straightforwardGood complement to per-key invalidation.
src/tux/services/moderation/execution_service.py (6)
34-68: LRU-ready circuit state wiring looks goodOrderedDict + config wiring is clean.
114-118: Reduced retry logging is sensibleKeeps logs useful without noise.
180-182: Cleanup hook before circuit check is sensibleEnsures stale entries are pruned early.
196-233: Cleanup/eviction logic is clearGood balance between time-based and size-based pruning.
243-250: LRU ordering on success is goodKeeps the most relevant entries fresh.
263-270: LRU ordering on failure is goodConsistent MRU updates for failure paths.
src/tux/services/moderation/moderation_coordinator.py (6)
153-282: Parallel case creation and embed sending is well-structuredThe orchestration reads clearly and keeps independent work concurrent.
375-387: Post-action DM timeout handling is clearIncreased timeout and explicit logging are sensible.
396-440: Async case creation helper is cleanGood separation for parallel execution.
442-496: Shared base embed builder reduces duplicationKeeps response and mod-log formatting aligned.
498-513: Response embed helper is straightforwardClear send path and logging.
524-533: Expiry field addition is correctNice touch for temporal cases in mod logs.
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@src/tux/services/moderation/moderation_coordinator.py`:
- Around line 242-279: The asyncio.gather call that awaits response_task and
mod_log_task can raise and abort the flow; change the await to use
asyncio.gather(..., return_exceptions=True) and then inspect the results so you
log any exceptions from the response or mod-log send (referencing response_task,
mod_log_task, _send_response_embed and _send_mod_log_embed), treat exceptions
separately from successful results, only use mod_log_message and call
_case_service.update_mod_log_message_id when the mod-log send succeeded (i.e.
result is not an Exception and has an id), and log failures instead of letting
them propagate so the rest of the method continues.
♻️ Duplicate comments (1)
src/tux/modules/moderation/unjail.py (1)
36-57: Duplicate_respondhelper - see comment injail.py.This is the same helper duplicated from
jail.py. Move toModerationCogBaseas suggested in the other file's review.
🧹 Nitpick comments (10)
src/tux/modules/moderation/jail.py (1)
45-66: Extract_respondhelper toModerationCogBaseto eliminate duplication.This helper is duplicated verbatim in both
jail.pyandunjail.py. Since both cogs inherit fromModerationCogBase, move this method to the base class to follow DRY principles.♻️ Suggested refactor
Move the
_respondmethod tosrc/tux/modules/moderation/__init__.py(ModerationCogBase):# In ModerationCogBase class async def _respond( self, ctx: commands.Context[Tux], message: str, *, ephemeral: bool = True, ) -> None: """Send a response message, handling both slash and prefix commands.""" if ctx.interaction: await ctx.interaction.followup.send(message, ephemeral=ephemeral) else: await ctx.reply(message, mention_author=False)Then remove the duplicated method from both
jail.pyandunjail.py.src/tux/database/controllers/guild_config.py (2)
86-89: Remove redundant logging statement.
GuildConfigCacheManager.invalidate()already logs a debug message:"Invalidated guild config cache for guild {guild_id}". The additional log statement here creates duplicate entries for the same event.♻️ Suggested fix
if result and any( field in updates for field in ( "audit_log_id", "mod_log_id", "join_log_id", "private_log_id", "report_log_id", "dev_log_id", ) ): GuildConfigCacheManager().invalidate(guild_id) - logger.debug( - f"Invalidated guild config cache for guild {guild_id} after config update", - ) return result
93-102: Consider invalidating cache on config deletion.When a guild config is deleted, any cached entry for that guild becomes stale. While the TTL will eventually expire the entry, explicitly invalidating ensures immediate consistency if the guild rejoins or the config is recreated.
♻️ Suggested fix
async def delete_config(self, guild_id: int) -> bool: """ Delete guild configuration. Returns ------- bool True if deleted successfully, False otherwise. """ - return await self.delete_by_id(guild_id) + result = await self.delete_by_id(guild_id) + if result: + GuildConfigCacheManager().invalidate(guild_id) + return resultsrc/tux/modules/moderation/clearafk.py (1)
84-87: Minor typo in comment.Double space in "if the afk status".
✏️ Proposed fix
if ( entry.enforced - ): # untimeout the user if the afk status is a self-timeout + ): # untimeout the user if the afk status is a self-timeout await member.timeout(None, reason="removing self-timeout")src/tux/modules/moderation/slowmode.py (3)
41-47: Consider adding cooldown/rate limiting.Per coding guidelines for modules, Discord commands should implement cooldowns. This command lacks a cooldown decorator, which could allow abuse in high-traffic servers.
♻️ Suggested addition
`@commands.hybrid_command`( name="slowmode", aliases=["sm"], usage="slowmode [channel] [seconds]", ) +@commands.cooldown(1, 5, commands.BucketType.user) `@commands.guild_only`() `@requires_command_permission`()
180-202: Consider addingis_done()check for robustness.This implementation always uses
followup.send(), which works because the interaction is deferred earlier in the command flow. However, the reference pattern ininfo.pychecksctx.interaction.response.is_done()before deciding betweenfollowup.sendandresponse.send_message. This makes the helper more defensive and reusable.♻️ Suggested improvement for consistency
`@staticmethod` async def _send_response( ctx: commands.Context[Tux], content: str, *, ephemeral: bool = True, ) -> None: ... if ctx.interaction: - await ctx.interaction.followup.send(content, ephemeral=ephemeral) + if ctx.interaction.response.is_done(): + await ctx.interaction.followup.send(content, ephemeral=ephemeral) + else: + await ctx.interaction.response.send_message(content, ephemeral=ephemeral) else: await ctx.send(content)
309-312: Fragile string manipulation coupled to formatter output.Line 311 splits on
'is'and takes the second part, relying on_format_slowmode_messagealways including "is" in its output. This implicit coupling is brittle—if the formatter's wording changes, this will break or produce malformed messages.Consider either extracting the delay formatting to a separate reusable helper or building the "set" message directly:
♻️ Suggested simplification
if delay_seconds == 0: message = f"Slowmode has been disabled in {channel.mention}." else: - prefix = "Slowmode set to" - message = f"{prefix} {self._format_slowmode_message(delay_seconds, channel.mention).split('is')[1].strip()}" + message = f"Slowmode has been set to {delay_seconds} seconds in {channel.mention}."src/tux/modules/moderation/unban.py (2)
52-53: Docstring usesOptional[Type]instead ofType | None.Per coding guidelines, prefer
Type | Nonesyntax. The type hint at line 39 correctly usesdiscord.User | None, but the docstring at line 52 usesOptional[discord.User].📝 Fix docstring to match type hint style
- Optional[discord.User] + discord.User | None The user if found, None otherwise.
144-151: Usesend_after_deferhelper to reduce duplication across error responses.The dual-path pattern (interaction followup vs. prefix reply) is repeated at lines 148–151 and 160–163.
BaseCog.send_after_defer()already handles this pattern and should be used instead of manual checks.♻️ Refactor using send_after_defer
- msg = ( - f"Could not find '{username_or_id}' in the ban list. " - "Try using the exact username or ID." - ) - if ctx.interaction: - await ctx.interaction.followup.send(msg, ephemeral=True) - else: - await ctx.reply(msg, mention_author=False) + await self.send_after_defer( + ctx, + f"Could not find '{username_or_id}' in the ban list. " + "Try using the exact username or ID.", + ephemeral=True, + mention_author=False, + )src/tux/services/moderation/moderation_coordinator.py (1)
503-526: Use NumPy docstring format for the new helpers.The new helper docstrings are one‑liners; consider converting them to the standard NumPy format for consistency across this module. As per coding guidelines, ...
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (8)
src/tux/database/controllers/guild_config.pysrc/tux/modules/moderation/clearafk.pysrc/tux/modules/moderation/jail.pysrc/tux/modules/moderation/slowmode.pysrc/tux/modules/moderation/unban.pysrc/tux/modules/moderation/unjail.pysrc/tux/services/handlers/error/cog.pysrc/tux/services/moderation/moderation_coordinator.py
🧰 Additional context used
📓 Path-based instructions (4)
**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
**/*.py: Use strict type hints withType | Nonesyntax instead ofOptional[Type]in Python
Use NumPy docstring format for documenting Python functions and classes
Prefer absolute imports, with relative imports allowed only within the same module
Organize imports in order: stdlib → third-party → local, with imports at the top of the file unless absolutely necessary
Use 88 character line length for Python code
Use snake_case for functions and variables, PascalCase for classes, UPPER_CASE for constants in Python
Ensure all type hints are complete for function signatures
Add docstrings for all public APIs
Keep Python files to a maximum of 1600 lines
Use async/await for I/O operations instead of blocking calls
Use custom exceptions for business logic errors
Log with context when handling errors
Do not store secrets in code, use environment variables for configuration
Validate all user inputs in Python code
One class or function per file when possible
**/*.py: Follow input validation patterns fromsecurity/validation.mdc
Follow error patterns fromerror-handling/patterns.mdc
Follow logging patterns using loguru fromerror-handling/logging.mdc
Follow Sentry integration patterns fromerror-handling/sentry.mdc
Follow user-facing error message patterns fromerror-handling/user-feedback.mdc
Follow Discord.py Components V2 rules fromui/cv2.mdc
Files:
src/tux/modules/moderation/unban.pysrc/tux/modules/moderation/unjail.pysrc/tux/modules/moderation/jail.pysrc/tux/database/controllers/guild_config.pysrc/tux/modules/moderation/slowmode.pysrc/tux/modules/moderation/clearafk.pysrc/tux/services/handlers/error/cog.pysrc/tux/services/moderation/moderation_coordinator.py
src/tux/modules/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
src/tux/modules/**/*.py: Use hybrid commands (slash and traditional) for Discord bot commands
Implement role-based permissions for Discord commands
Implement cooldowns and rate limiting for Discord commands
Files:
src/tux/modules/moderation/unban.pysrc/tux/modules/moderation/unjail.pysrc/tux/modules/moderation/jail.pysrc/tux/modules/moderation/slowmode.pysrc/tux/modules/moderation/clearafk.py
src/tux/database/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
src/tux/database/**/*.py: Use SQLModel for type-safe ORM operations
Use Pydantic for data validation in database models
Use transactions for multi-step database operations
Implement model-level validation in database models
Optimize database queries for performance
Files:
src/tux/database/controllers/guild_config.py
src/tux/services/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
src/tux/services/**/*.py: Use dependency injection in service classes
Keep service classes stateless where possible and use async/await for I/O
Use caching for frequently accessed data
Files:
src/tux/services/handlers/error/cog.pysrc/tux/services/moderation/moderation_coordinator.py
🧠 Learnings (7)
📚 Learning: 2026-01-12T20:42:11.193Z
Learnt from: CR
Repo: allthingslinux/tux PR: 0
File: .cursor/rules/rules.mdc:0-0
Timestamp: 2026-01-12T20:42:11.193Z
Learning: Applies to **/*interaction*.py : Follow interaction response patterns from `modules/interactions.mdc`
Applied to files:
src/tux/modules/moderation/jail.py
📚 Learning: 2025-12-30T22:45:12.307Z
Learnt from: CR
Repo: allthingslinux/tux PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-30T22:45:12.307Z
Learning: Applies to src/tux/modules/**/*.py : Implement cooldowns and rate limiting for Discord commands
Applied to files:
src/tux/modules/moderation/slowmode.py
📚 Learning: 2025-12-30T22:45:12.307Z
Learnt from: CR
Repo: allthingslinux/tux PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-30T22:45:12.307Z
Learning: Applies to **/*.py : Log with context when handling errors
Applied to files:
src/tux/services/handlers/error/cog.py
📚 Learning: 2026-01-12T20:42:11.193Z
Learnt from: CR
Repo: allthingslinux/tux PR: 0
File: .cursor/rules/rules.mdc:0-0
Timestamp: 2026-01-12T20:42:11.193Z
Learning: Applies to **/*.py : Follow logging patterns using loguru from `error-handling/logging.mdc`
Applied to files:
src/tux/services/handlers/error/cog.py
📚 Learning: 2026-01-12T20:42:11.193Z
Learnt from: CR
Repo: allthingslinux/tux PR: 0
File: .cursor/rules/rules.mdc:0-0
Timestamp: 2026-01-12T20:42:11.193Z
Learning: Applies to **/*.py : Follow error patterns from `error-handling/patterns.mdc`
Applied to files:
src/tux/services/handlers/error/cog.py
📚 Learning: 2026-01-12T20:42:11.193Z
Learnt from: CR
Repo: allthingslinux/tux PR: 0
File: .cursor/rules/rules.mdc:0-0
Timestamp: 2026-01-12T20:42:11.193Z
Learning: Applies to **/*.py : Follow user-facing error message patterns from `error-handling/user-feedback.mdc`
Applied to files:
src/tux/services/handlers/error/cog.py
📚 Learning: 2025-12-30T22:45:12.307Z
Learnt from: CR
Repo: allthingslinux/tux PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-30T22:45:12.307Z
Learning: Applies to **/*.py : Use custom exceptions for business logic errors
Applied to files:
src/tux/services/handlers/error/cog.py
🧬 Code graph analysis (7)
src/tux/modules/moderation/unjail.py (1)
src/tux/modules/moderation/jail.py (2)
_respond(45-66)get_jail_role(68-83)
src/tux/modules/moderation/jail.py (3)
src/tux/modules/moderation/unjail.py (2)
_respond(36-57)get_jail_role(59-74)src/tux/core/bot.py (2)
Tux(46-495)is_jailed(193-217)src/tux/modules/moderation/__init__.py (1)
is_jailed(111-133)
src/tux/database/controllers/guild_config.py (2)
src/tux/database/models/models.py (1)
GuildConfig(174-323)src/tux/shared/cache.py (1)
GuildConfigCacheManager(170-246)
src/tux/modules/moderation/slowmode.py (1)
src/tux/modules/info/info.py (2)
_send_response(117-167)info(342-377)
src/tux/modules/moderation/clearafk.py (2)
src/tux/modules/utility/afk.py (1)
afk(50-100)src/tux/database/controllers/afk.py (1)
is_afk(142-151)
src/tux/services/handlers/error/cog.py (1)
src/tux/services/handlers/error/config.py (1)
ErrorHandlerConfig(38-60)
src/tux/services/moderation/moderation_coordinator.py (4)
src/tux/database/controllers/case.py (1)
create_case(80-198)src/tux/services/moderation/case_service.py (1)
create_case(36-77)src/tux/services/moderation/communication_service.py (1)
send_dm(41-89)src/tux/database/models/models.py (1)
Case(569-726)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Run All Tests (3.13.11)
- GitHub Check: Validate
- GitHub Check: Seer Code Review
🔇 Additional comments (25)
src/tux/modules/moderation/jail.py (2)
227-229: LGTM!The conditional deferral logic correctly handles both slash and prefix commands—deferring only when an interaction exists, which avoids errors for prefix commands where
ctx.interactionisNone.
232-246: LGTM!The error messages now route through
_respond, providing consistent handling for both slash and prefix commands. This addresses the previous review feedback about inconsistent response methods.src/tux/modules/moderation/unjail.py (3)
59-74: LGTM!The type annotation update from
Optional[discord.Role]todiscord.Role | Nonealigns with the coding guidelines preference for theType | Nonesyntax.
196-198: LGTM!Conditional deferral correctly handles both command invocation styles, consistent with the pattern in
jail.py.
200-227: LGTM!Error messages consistently use
_respondfor unified slash/prefix handling. The flow correctly validates jail role, jail status, and jail case before proceeding with the unjail operation.src/tux/database/controllers/guild_config.py (3)
552-573: LGTM!Good optimization to fetch both
audit_log_idandmod_log_idin a single database query rather than making two separate calls viaget_config_field. The docstring accurately describes the efficiency benefit.
143-159: LGTM!Good refactor to delegate to
update_configinstead of callingupdate_by_iddirectly. This ensures cache invalidation is handled consistently when log channel fields are updated through this method.
12-16: LGTM!Imports are correctly organized: stdlib (
__future__,typing) → third-party (loguru) → local (tux.database.*,tux.shared.*).src/tux/modules/moderation/clearafk.py (3)
39-58: LGTM!The return type is now correctly
discord.Messageand the docstring accurately states it raises on send failure. This addresses the previous review feedback.
61-73: LGTM!The early defer and interaction-aware response pattern is correctly implemented, consistent with the approach in
afk.pyand other modules in this PR. The assertion for type narrowing onfollowup.sendis appropriate.
89-98: LGTM!The success response follows the same interaction-aware pattern, correctly using
followup.sendfor deferred interactions and falling back toctx.sendfor prefix commands.src/tux/modules/moderation/slowmode.py (5)
78-80: LGTM!Early defer pattern correctly handles slash command interactions before async channel resolution work.
83-93: LGTM!Channel resolution logic cleanly handles both argument patterns (delay-only vs channel+delay) with appropriate fallbacks.
119-159: LGTM!Cache-first resolution pattern efficiently handles IDs and mentions without API calls, with appropriate converter fallback for name-based lookups.
231-260: LGTM!Slowmode retrieval correctly checks channel capability and consistently uses
_send_responsefor all output paths.
325-354: LGTM!Delay parsing handles common time suffixes (s/m/h) correctly with appropriate error handling.
src/tux/services/handlers/error/cog.py (3)
128-129: Nice context propagation into logging.Passing
sourceinto_log_errorimproves diagnosability without changing error flow.
183-233: Contextual logging and safe fallback look solid.Good addition of command/guild/source context and a safe
logger.errorfallback.
253-255: Robust fallback logging for unexpected send failures.
logger.exceptionhere is the right choice to preserve traceback.src/tux/modules/moderation/unban.py (2)
159-163: LGTM!The dual-path response pattern correctly handles both deferred interactions (using followup) and prefix commands (using reply). Consistent with the error handling at lines 144-151.
133-135: The success path properly handles deferred interactions. Thesend_embedmethod in the communication service explicitly checksif ctx.interaction:and usesctx.interaction.followup.send()(line 220-221 of communication_service.py), making the response handling consistent with the error paths. No action needed.Likely an incorrect or invalid review comment.
src/tux/services/moderation/moderation_coordinator.py (4)
153-225: Parallel case creation and expiry handling look solid.Nice split of expiration derivation + async case creation while actions run; this keeps the flow responsive without losing case metadata.
380-399: Post-action DM timeout + cancellation handling is clean.The explicit timeout and CancelledError handling improve resilience and user feedback.
401-446: Async case creation helper is well-factored.Clear separation of concerns and logging make the parallel path easier to reason about.
529-538: Expiration field in mod-log embed is a nice UX win.Clear, readable display of remaining time for temp actions.
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
Pull Request
Description
Provide a clear summary of your changes and reference any related issues. Include the motivation behind these changes and list any new dependencies if applicable.
If your PR is related to an issue, please include the issue number below:
Related Issue: Closes #
Type of Change:
Guidelines
My code follows the style guidelines of this project (formatted with Ruff)
I have performed a self-review of my own code
I have commented my code, particularly in hard-to-understand areas
I have made corresponding changes to the documentation if needed
My changes generate no new warnings
I have tested this change
Any dependent changes have been merged and published in downstream modules
I have added all appropriate labels to this PR
I have followed all of these guidelines.
How Has This Been Tested? (if applicable)
Please describe how you tested your code. e.g describe what commands you ran, what arguments, and any config stuff (if applicable)
Screenshots (if applicable)
Please add screenshots to help explain your changes.
Additional Information
Please add any other information that is important to this PR.
Summary by Sourcery
Improve interaction handling, permissions, and performance across multiple bot modules while introducing configurable Discord intents and sequence repair tooling.
New Features:
Enhancements:
Build:
Deployment:
Documentation:
Chores: