Skip to content
Closed
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
10 changes: 10 additions & 0 deletions .claude/settings.local.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"permissions": {
"allow": [
"Read(//e/Users/TammyShepherd/Documents/Modmail/core/**)",
"Read(//e/Users/TammyShepherd/Documents/Modmail/**)"
],
"deny": [],
"ask": []
}
}
175 changes: 65 additions & 110 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,93 +1,29 @@
#### Modmail
# Plugins
plugins/*
!plugins/registry.json
!plugins/@local

# Config files
config.json
.env

# Data
temp/

### Python
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
target/

# Jupyter Notebook
.ipynb_checkpoints

# IPython
profile_default/
ipython_config.py

# pyenv
.python-version

# celery beat schedule file
celerybeat-schedule

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
Expand All @@ -98,43 +34,62 @@ ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject
#### PyCharm
.idea/

# mkdocs documentation
/site
#### VS Code
.vscode/

# mypy
.mypy_cache/
.dmypy.json
dmypy.json
### Windows
# Windows thumbnail cache files
Thumbs.db
Thumbs.db:encryptable
ehthumbs.db
ehthumbs_vista.db

# Pyre type checker
.pyre/
# Dump file
*.stackdump

# PyCharm
.idea/
# Folder config file
[Dd]esktop.ini

# MacOS
.DS_Store
# Recycle Bin used on file shares
$RECYCLE.BIN/

# VS Code
.vscode/
# Windows Installer files
*.cab
*.msi
*.msix
*.msm
*.msp

# Node
package-lock.json
node_modules/
# Windows shortcuts
*.lnk

# Modmail
plugins/*
!plugins/registry.json
!plugins/@local
config.json
temp/
test.py
stack.yml
.github/workflows/build_docker.yml
### macOS
# General
.DS_Store
.AppleDouble
.LSOverride

# Icon must end with two \r
Icon

# Thumbnails
._*

# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent

# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
8 changes: 6 additions & 2 deletions core/clients.py
Original file line number Diff line number Diff line change
Expand Up @@ -449,8 +449,11 @@ def __init__(self, bot):
logger.critical("A Mongo URI is necessary for the bot to function.")
raise RuntimeError

# Get database name from config, default to "modmail_bot"
db_name = bot.config.get("db_name", convert=False) or "modmail_bot"

try:
db = AsyncIOMotorClient(mongo_uri).modmail_bot
db = AsyncIOMotorClient(mongo_uri)[db_name]
except ConfigurationError as e:
logger.critical(
"Your MongoDB CONNECTION_URI might be copied wrong, try re-copying from the source again. "
Expand Down Expand Up @@ -497,6 +500,7 @@ async def validate_database_connection(self, *, ssl_retry=True):
mongo_uri = self.bot.config["connection_uri"]
if mongo_uri is None:
mongo_uri = self.bot.config["mongo_uri"]
db_name = self.bot.config.get("db_name", convert=False) or "modmail_bot"
for _ in range(3):
logger.warning(
"FAILED TO VERIFY SSL CERTIFICATE, ATTEMPTING TO START WITHOUT SSL (UNSAFE)."
Expand All @@ -506,7 +510,7 @@ async def validate_database_connection(self, *, ssl_retry=True):
'run "Certificate.command" on MacOS, '
'and check certifi is up to date "pip3 install --upgrade certifi".'
)
self.db = AsyncIOMotorClient(mongo_uri, tlsAllowInvalidCertificates=True).modmail_bot
self.db = AsyncIOMotorClient(mongo_uri, tlsAllowInvalidCertificates=True)[db_name]
return await self.validate_database_connection(ssl_retry=False)
if "ServerSelectionTimeoutError" in message:
logger.critical(
Expand Down
3 changes: 3 additions & 0 deletions core/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ class ConfigManager:
"plain_snippets": False,
"require_close_reason": False,
"show_log_url_button": False,
"public_ticket_logs_send_on_close": False,
# group conversations
"private_added_to_group_title": "New Thread (Group)",
"private_added_to_group_response": "{moderator.name} has added you to a Modmail thread.",
Expand Down Expand Up @@ -204,6 +205,7 @@ class ConfigManager:
"mongo_uri": None,
"database_type": "mongodb",
"connection_uri": None, # replace mongo uri in the future
"db_name": "modmail_bot", # configurable database name
"owners": None,
"enable_presence_intent": False,
"registry_plugins_only": False,
Expand Down Expand Up @@ -274,6 +276,7 @@ class ConfigManager:
"anonymous_snippets",
"plain_snippets",
"require_close_reason",
"public_ticket_logs_send_on_close",
"recipient_thread_close",
"thread_show_roles",
"thread_show_account_age",
Expand Down
24 changes: 24 additions & 0 deletions core/config_help.json
Original file line number Diff line number Diff line change
Expand Up @@ -872,6 +872,19 @@
],
"notes": []
},
"public_ticket_logs_send_on_close": {
"default": "No",
"description": "When enabled, automatically appends a link to the log/transcript at the end of the thread close message sent to recipients.",
"examples": [
"`{prefix}config set public_ticket_logs_send_on_close yes`",
"`{prefix}config set public_ticket_logs_send_on_close no`"
],
"notes": [
"This adds a \"View a transcript of this communication [here](log_url)\" link to the close message.",
"The log URL must be properly configured for this to work.",
"See also: `thread_close_response`, `thread_self_close_response`, `log_url`."
]
},
"private_added_to_group_title": {
"default": "New Thread (Group)",
"description": "This is the message embed title sent to the recipient that is just added to a thread.",
Expand Down Expand Up @@ -1125,6 +1138,17 @@
"This configuration can only to be set through `.env` file or environment (config) variables."
]
},
"db_name": {
"default": "modmail_bot",
"description": "The name of the MongoDB database to use. This allows you to customize the database name instead of using the default 'modmail_bot'.",
"examples": [
],
"notes": [
"This configuration can only to be set through `.env` file or environment (config) variables.",
"If not specified, defaults to 'modmail_bot'.",
"Useful for running multiple instances or custom database naming schemes."
]
},
"owners": {
"default": "None, required",
"description": "A list of definite bot owners, use `{prefix}perms add level OWNER @user` to set flexible bot owners.",
Expand Down
4 changes: 4 additions & 0 deletions core/thread.py
Original file line number Diff line number Diff line change
Expand Up @@ -1200,6 +1200,10 @@ async def _close(self, closer, silent=False, delete_channel=True, message=None,
logkey=log_data["key"] if log_data else None,
)

# Append log URL if config is enabled
if self.bot.config.get("public_ticket_logs_send_on_close") and log_url:
message += f" View a transcript of this communication [here]({log_url})."

embed.description = message
footer = self.bot.config["thread_close_footer"]
embed.set_footer(
Expand Down