-
-
Notifications
You must be signed in to change notification settings - Fork 4.7k
modmail update QOL #3392
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: development
Are you sure you want to change the base?
modmail update QOL #3392
Conversation
Make Modmail keep working when typing is disabled/outage
Signed-off-by: lorenzo132 <50767078+lorenzo132@users.noreply.github.com>
Corrected wording in the changelog entry regarding command inclusion in replies. Signed-off-by: lorenzo132 <50767078+lorenzo132@users.noreply.github.com>
Forwarded messages now display correctly in threads. Signed-off-by: lorenzo132 <50767078+lorenzo132@users.noreply.github.com>
…r accurasy on high load
Signed-off-by: lorenzo132 <50767078+lorenzo132@users.noreply.github.com>
Signed-off-by: lorenzo132 <50767078+lorenzo132@users.noreply.github.com>
…permissions on auto-created Snoozed Threads and sync perms on move; restore original overwrites on unsnooze; add capacity guard and config docs
…eplay and notifications)
feat(config): `unsnooze_history_limit`: Limits the number of messages replayed when unsnoozing (genesis message and notes are always shown).
|
The above suggested changes requested by sebkuip have been introduced. |
sssmartfridge
left a comment
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.
Looks good overall, seems ready for testing
Update sponsors and bmac links
The logs command can be used anywhere again.
This PR fixes displaying the wrong guild icon in the thread_creation_response embed. When servers having a seperate server setup, the guild icon from the main guild should be displayed instead of the inbox guild.
…permission is missing
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.
Pull request overview
This PR introduces significant quality-of-life improvements to a Modmail bot, addressing race conditions, thread duplication issues, and adding new features like message queueing, configurable snooze behaviors, and an interactive thread-creation menu system.
Key Changes:
- Implements message queueing per user to prevent race conditions during high load
- Adds move-based snooze behavior as an alternative to channel deletion
- Introduces an interactive thread-creation menu with category-specific routing
- Improves command queueing during unsnooze operations to prevent conflicts
Reviewed changes
Copilot reviewed 12 out of 15 changed files in this pull request and generated 16 comments.
Show a summary per file
| File | Description |
|---|---|
| requirements.txt | Updates pymongo (4.15.2→4.9.2) and motor (3.3.2→3.6.1) versions |
| core/utils.py | Adds debug logging for reference preview extraction failures; formatting improvements |
| core/time.py | Code formatting improvements only (multi-line function signatures) |
| core/thread.py | Major refactor: adds snooze move behavior, command queueing, race condition prevention, genesis message handling, and thread-creation menu integration |
| core/paginator.py | Minor formatting fix (spacing around operators) |
| core/models.py | Formatting improvements and enhanced logging configuration |
| core/config_help.json | Adds extensive documentation for new snooze and thread-creation menu options |
| core/config.py | Adds 20+ new configuration options for snooze behavior and thread menus |
| core/clients.py | Formatting improvements only |
| cogs/utility.py | Adds config pagination (15 fields/embed), snooze behavior validation warnings |
| cogs/threadmenu.py | New cog providing interactive thread-creation menu management commands |
| cogs/plugins.py | Formatting improvements only |
| cogs/modmail.py | Updates reply commands to pass content explicitly, adds auto-unsnooze task, scheduled close improvements |
| bot.py | Implements per-user message queue, stale thread detection, adds threadmenu cog |
| CHANGELOG.md | Documents new features and configuration options |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
cogs/threadmenu.py
Outdated
| new_description = None | ||
| if description.lower() == "skip": | ||
| new_description = conf["options"][key]["description"] |
Copilot
AI
Nov 22, 2025
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.
Variable new_description is not used.
| new_description = None | |
| if description.lower() == "skip": | |
| new_description = conf["options"][key]["description"] | |
| if description.lower() == "skip": | |
| description = conf["options"][key]["description"] |
| @@ -1258,7 +1906,7 @@ async def send( | |||
| tag = str(get_top_role(author, self.bot.config["use_hoisted_top_role"])) | |||
Copilot
AI
Nov 22, 2025
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.
Variable tag is not used.
| timeout = 20 | ||
|
|
||
| options = self.bot.config.get("thread_creation_menu_options") or {} | ||
| submenus = self.bot.config.get("thread_creation_menu_submenus") or {} |
Copilot
AI
Nov 22, 2025
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.
Variable submenus is not used.
| submenus = self.bot.config.get("thread_creation_menu_submenus") or {} |
| recipient = thread_data.get("recipient") | ||
| if not recipient or not recipient.get("id"): | ||
| continue | ||
| thread_id = int(recipient.get("id")) |
Copilot
AI
Nov 22, 2025
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.
This assignment to 'thread_id' is unnecessary as it is redefined before this value is used.
| thread_id = int(recipient.get("id")) |
| return False | ||
| # Now safe to access self.snooze_data | ||
|
|
||
| # Cache some fields we need later (before we potentially clear snooze_data) | ||
| snoozed_by = self.snooze_data.get("snoozed_by") |
Copilot
AI
Nov 22, 2025
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.
This assignment to 'snoozed_by' is unnecessary as it is redefined before this value is used.
| snoozed_by = self.snooze_data.get("snoozed_by") |
| except (discord.Forbidden, discord.NotFound): | ||
| pass |
Copilot
AI
Nov 22, 2025
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.
'except' clause does nothing but pass and there is no explanatory comment.
| except (discord.Forbidden, discord.NotFound): | |
| pass | |
| except (discord.Forbidden, discord.NotFound) as e: | |
| logger.debug(f"Failed to delete message (likely already deleted or lacking permissions): {e}") |
| try: | ||
| await ctx.message.delete(delay=5) | ||
| except (discord.Forbidden, discord.NotFound): | ||
| pass |
Copilot
AI
Nov 22, 2025
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.
'except' clause does nothing but pass and there is no explanatory comment.
| pass | |
| logger.debug("Failed to delete message %s due to missing permissions or message not found.", ctx.message.id) |
| regular_messages = regular_messages[-history_limit:] | ||
| limited = True | ||
| except (ValueError, TypeError): | ||
| pass |
Copilot
AI
Nov 22, 2025
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.
'except' clause does nothing but pass and there is no explanatory comment.
| pass | |
| logger.warning( | |
| f"Invalid unsnooze_history_limit config value: {history_limit!r}. No history limit will be applied." | |
| ) |
| if conf.get("embed_color"): | ||
| try: | ||
| await self.bot.config.set("thread_creation_menu_embed_color", conf.get("embed_color")) | ||
| except Exception: |
Copilot
AI
Nov 22, 2025
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.
'except' clause does nothing but pass and there is no explanatory comment.
| avatar_url = getattr(self.bot.user.display_avatar, "url", system_avatar_url) | ||
| else: | ||
| name = str(author) | ||
| avatar_url = avatar_url |
Copilot
AI
Nov 22, 2025
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.
This assignment assigns a variable to itself.
| avatar_url = avatar_url | |
| avatar_url = getattr(author.display_avatar, "url", system_avatar_url) |
fix: raceconditions, thread duplication on unsnooze, message queue for accuracy on highload, escape mentions.
feat: unsnooze_history_limit, command queue during snooze process.