Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ LOG_URL=https://logviewername.herokuapp.com/
GUILD_ID=1234567890
OWNERS=Owner1ID,Owner2ID,Owner3ID
CONNECTION_URI=mongodb+srv://mongodburi
DISABLE_AUTOUPDATES=true
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* text=auto
2 changes: 1 addition & 1 deletion .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -1 +1 @@
patreon: kyber
buy_me_a_coffee: modmaildev
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ body:
- Heroku
- Systemd
- PM2
- Patreon
- Buy Me A Coffee / Patreon
- Other
validations:
required: true
Expand Down
97 changes: 97 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,103 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
This project mostly adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html);
however, insignificant breaking changes do not guarantee a major version bump, see the reasoning [here](https://github.com/modmail-dev/modmail/issues/319). If you're a plugin developer, note the "BREAKING" section.

# v4.2.1

### Added

**New Configuration Options:**
* `unsnooze_history_limit`: Limits the number of messages replayed when unsnoozing (genesis message and notes are always shown).
* `snooze_behavior`: Choose between `delete` (legacy) or `move` behavior for snoozing.
* `snoozed_category_id`: Target category for `move` snoozing; required when `snooze_behavior` is `move`.
* `snooze_store_attachments`: When enabled, image attachments are stored as base64 when snoozing with delete behavior, allowing them to be re-uploaded on unsnooze.
* `snooze_attachment_max_bytes`: Maximum size per attachment to store as base64 (default: 4 MiB).
* `thread_creation_menu_timeout`: Timeout duration for user interaction with the menu (default: 30 seconds).
* `thread_creation_menu_close_on_timeout`: Silently abort thread creation if user doesn't select an option.
* `thread_creation_menu_anonymous_menu`: Anonymize the initial menu prompt relayed to staff.
* `thread_creation_menu_embed_text`: Text shown in the embed above the selection dropdown.
* `thread_creation_menu_dropdown_placeholder`: Placeholder text in the dropdown before selection.
* `thread_creation_menu_selection_log`: Log the chosen menu option in the newly created thread channel.
* `thread_creation_menu_precreate_channel`: Create thread channel immediately upon first DM even if menu is enabled.
* `thread_creation_menu_embed_title`: Optional title for the thread-creation menu embed.
* `thread_creation_menu_embed_footer`: Optional footer text for the menu embed.
* `thread_creation_menu_embed_footer_icon_url`: Optional URL for the footer icon.
* `thread_creation_menu_embed_thumbnail_url`: Optional thumbnail image URL.
* `thread_creation_menu_embed_image_url`: Optional large hero image URL for the menu embed.
* `thread_creation_menu_embed_large_image`: Promote thumbnail to large hero image if no separate image URL is set.
* `thread_creation_menu_embed_color`: Color for the menu embed's side strip.

**Thread-Creation Menu Feature:**
* Full thread-creation menu system with interactive select menus:
* `?threadmenu toggle`: Enable/disable the menu globally.
* `?threadmenu show`: List current top-level options.
* `?threadmenu option add`: Interactive wizard to create an option.
* `?threadmenu option edit/remove/show`: Manage or inspect existing options.
* `?threadmenu submenu create/delete/list/show`: Manage submenus (nested menu levels).
* `?threadmenu submenu option add/edit/remove`: Manage options inside submenus.
* `?threadmenu dump_config`: Export current configuration to a file.
* `?threadmenu load_config`: Import configuration from a file.
* `?threadmenu reset`: Reset all thread-creation menu settings to defaults.
* Per-option category targeting: Each menu option can specify a target category where threads are created.
* Submenu support: Create up to 25 main-level options, each with up to 24 nested options.
* Optional selection logging: Log which menu option was chosen in the newly created thread channel.
* Anonymous menu support: Hide original prompt author context from staff when menu is anonymized.
* Category fallback: If an option's category is invalid/missing, creation falls back to `main_category_id`.

**Snooze Enhancements:**
* Attachment persistence for delete-behavior snoozing: Image attachments can now be stored as base64 data.
* Enhanced unsnooze functionality with configurable message replay limits.
* Auto-unsnooze task continuously monitors and automatically unsnoozes threads when duration expires.

### Changed
- Renamed `max_snooze_time` to `snooze_default_duration` (accepts seconds or human-readable time like "7 days").
- When `snooze_behavior` is set to `move`, the snoozed category now has a hard limit of 49 channels. New snoozes are blocked once it’s full until space is freed.
- When switching `snooze_behavior` to `move` via `?config set`, the bot reminds admins to set `snoozed_category_id` if it’s missing.
- Thread-creation menu options and submenu options now support per-option `category` targeting.
- Category selection in menu option wizards allows specifying ID, name, or mention format.
- Snoozed thread restoration now respects `unsnooze_history_limit` (if set) to replay only the last N messages.
- Enhanced auto-unsnooze task monitors and automatically unsnoozes threads when their snooze duration expires.
- Snoozed threads can now be moved to a dedicated category instead of being deleted (via `snooze_behavior: move`).

### Fixed

- Corrected behavior when snooze channel count reaches the 49-channel limit in move-based snoozing.
- Improved category resolution in threadmenu wizards (handles ID, name, and mention formats reliably).
- Enhanced thread state restoration after unsnoozing to properly re-add all recipients.


# v4.2.0

Upgraded discord.py to version 2.6.3, added support for CV2.
Forwarded messages now properly show in threads, rather than showing as an empty embed.

### Fixed
- Make Modmail keep working when typing is disabled due to an outage caused by Discord.
- Resolved an issue where forwarded messages appeared as empty embeds.
- Fixed internal message handling and restoration processes.
- Eliminated duplicate logs and notes.
- Addressed inconsistent use of `logkey` after ticket restoration.
- Fixed issues with identifying the user who sent internal messages.
- Solved an ancient bug where closing with words like `evening` wouldn't work.
- Fixed the command from being included in the reply in rare conditions.

### Added
Commands:
* `snooze`: Initiates a snooze action.
* `snoozed`: Displays snoozed items.
* `unsnooze`: Reverses the snooze action.
* `clearsnoozed`: Clears all snoozed items.

Configuration Options:
* `max_snooze_time`: Sets the maximum duration for snooze.
* `snooze_title`: Customizes the title for snooze notifications.
* `snooze_text`: Customizes the text for snooze notifications.
* `unsnooze_text`: Customizes the text for unsnooze notifications.
* `unsnooze_notify_channel`: Specifies the channel for unsnooze notifications.
* `thread_min_characters`: Minimum number of characters required.
* `thread_min_characters_title`: Title shown when the message is too short.
* `thread_min_characters_response`: Response shown to the user if their message is too short.
* `thread_min_characters_footer`: Footer displaying the minimum required characters.

# v4.1.2

### Fixed
Expand Down
21 changes: 13 additions & 8 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,29 @@ verify_ssl = true
bandit = ">=1.7.5"
black = "==23.11.0"
pylint = "==3.0.2"
typing-extensions = "==4.8.0"
tomli = "==2.2.1"

[packages]
aiohttp = "==3.9.0"
aiohttp = "==3.13.2"
async-timeout = {version = "==5.0.1", markers = "python_version < '3.11'"}
typing-extensions = "==4.15.0"
colorama = "==0.4.6"
"discord.py" = {version = "==2.3.2", extras = ["speed"]}
"discord.py" = {version = "==2.6.3", extras = ["speed"]}
emoji = "==2.8.0"
isodate = "==0.6.1"
motor = "==3.3.2"
natural = "==0.2.0" # Why is this needed?
motor = "==3.7.1"
natural = "==0.2.0"
packaging = "==23.2"
parsedatetime = "==2.6"
pymongo = {extras = ["srv"], version = "*"} # Required by motor
dnspython = "==2.8.0"
pymongo = "==4.15.3"
python-dateutil = "==2.8.2"
python-dotenv = "==1.0.0"
uvloop = {version = ">=0.19.0", markers = "sys_platform != 'win32'"}
lottie = {version = "==0.7.0", extras = ["pdf"]}
uvloop = {version = "==0.22.1", markers = "sys_platform != 'win32'"}
lottie = {version = "==0.7.2", extras = ["pdf"]}
setuptools = "==80.9.0"
requests = "==2.31.0"
orjson = "==3.11.4"

[scripts]
bot = "python bot.py"
Loading