- delete public/js/notifications.js (521 LOC) - remove notifications/patterns/surge/chat/priority/bosscord/accountinfo/threads UI sections - remove 3 /api/notifications/* proxy routes from server.js - untrack settings-site backup files from git - ~926 LOC removed from settings-site
Broccolini Bot
A Node.js Discord bot that unifies Gmail, Discord, and MongoDB for support ticketing. Incoming emails become Discord ticket channels; staff messages in those channels are sent back to customers via Gmail. Discord-originated tickets (panels, context menu) live entirely in Discord. State is stored in MongoDB via Mongoose.
Built for game-server hosting support (Indifferent Broccoli), with game detection from email content, tiered escalation, optional per-staff notification channels (reply alerts with cooldown + unclaimed-ticket digests), saved responses, /tag categorization, claimer emoji in channel names (STAFF_EMOJIS), and automation (auto-close, reminders, auto-unclaim, claim timeout).
Jump to: Features · Quick start · Configuration · Staff notifications · Broccolini settings page · Commands · Project layout
Table of contents
- Features
- Architecture
- Prerequisites
- Quick start
- Installation
- Configuration
- Staff notification channels & reply alerts
- Broccolini settings page
- Running the bot (test and Docker)
- Discord commands
- Ticket UI (buttons & modals)
- Tag & response system
- Panel system
- Channel renames & moves (rate limits)
- Project structure
- Database collections
- HTTP: healthcheck & optional API
- Gmail OAuth refresh token
- Documentation in
docs/ - Development & CI
- Troubleshooting
- References
- License
Features
Email → Discord
- Polls Gmail about every 30 seconds for new unread primary mail (
gmail-poll.js). - Creates a Discord text channel (or thread, per guild settings) per email ticket, with overflow category support when a category is full.
- Detects game from subject/body using
GAME_LISTand built-in aliases inconfig.js. - Posts welcome + action buttons (Close, Claim, Escalate / De-escalate where applicable).
Discord → Gmail
- For email-sourced tickets, staff messages in the ticket channel are forwarded to the customer via Gmail (threaded).
- Discord-only tickets (
gmailThreadIdprefixdiscord-/discord-msg-) do not use Gmail for replies; conversation stays in Discord.
Ticket management
- Claim / Unclaim via buttons (not slash commands); optional claim overwrite, claim timeout, and auto-unclaim.
- Priority (
low/normal/medium/high) with configurable emojis and/priority. - Escalation: tier 2 and tier 3 categories (separate IDs for email vs Discord where configured); slash
/escalateand in-channel buttons. - De-escalation one step at a time (
/deescalateor button). - Close with confirmation; force-close for admins.
- Transcripts posted to a configured channel; closure email for email tickets.
- Auto-close, inactivity reminders, auto-unclaim (all optional via env).
Staff notifications & alerts (optional)
- Per-staff notification channels:
/notification addcreates a dedicated text channel per staff member underSTAFF_NOTIFICATION_CATEGORY_IDand stores it inStaffNotification(MongoDB). When a non-staff user replies in a ticket claimed by someone with a notification channel, the bot posts an alert there (subject to per-ticket cooldown via/notification setor admin/staffnotification). - Unclaimed digests: a background job runs every 30 minutes and, if
UNCLAIMED_REMINDER_THRESHOLDSis set, posts unclaimed ticket digests to those same channels when tickets cross age thresholds. - DM reply alerts:
/notifydmtoggles optional DM alerts to the claimer on customer reply (separate from the notification channel); stored inStaffSettings. - Staff threads (optional): when
STAFF_THREAD_ENABLEDis true, each ticket channel can get a private staff-only thread namedSTAFF_THREAD_NAME; on claim, the claimer can be added to that thread, and (optionally) all members ofSTAFF_THREAD_ROLE_IDare auto-added. - Pins (optional):
PIN_INITIAL_MESSAGE_ENABLEDandPIN_ESCALATION_MESSAGE_ENABLEDenable auto-pinning of the ticket welcome message and escalation messages;PIN_SUPPRESS_SYSTEM_MESSAGEhides the default “X pinned a message” system notice. - Chat monitoring & surge detection: see Patterns, surge & chat alerts for automatic alerts about busy chats, surging games, backlogs, and no-staff situations.
See Staff notification channels and Patterns, surge & chat alerts for details.
Note: Older docs referred to per-staffer mirror channels driven by STAFF_CATEGORIES. In current config.js that map is deprecated and always empty, and createStaffChannel is not called from the claim flow—staffChannelId on tickets is effectively unused. Reply alerts use StaffNotification channels instead, and staff discussion happens in optional staff threads.
Extras
/panel: “Open ticket” UI (modal collects email, game, description)./tag: ticket category dropdown;/response: saved templates with variable substitution./setup: setup wizard for guild defaults./accountinfo: website account lookup (email or Discord user)./stats,/search,/backup,/export,/email-routing.- Context menus: create ticket from message; view user tickets.
- Optional REST API under
/apiwhen the relevant API key env vars are set (see.env.example).
Architecture
┌─────────────────────────────────────────────────────────────────┐
│ BROCCOLINI BOT │
├─────────────────────────────────────────────────────────────────┤
│ Gmail (inbox) ──► gmail-poll.js ──► Discord ticket channels │
│ │ ▲ │
│ ▼ │ │
│ services/gmail.js ◄── handlers/messages.js │
│ services/tickets.js handlers/buttons.js │
│ services/channelQueue.js │
│ services/staffNotifications.js │
│ │ │
│ ▼ │
│ MongoDB (Mongoose) ◄── models.js │
│ │
│ Express: GET / → "Active" ; optional /api → routes/ │
└─────────────────────────────────────────────────────────────────┘
Typical email ticket lifecycle
- New unread mail → poll creates Discord channel +
Ticketdocument. - Staff reply in channel → message handler sends Gmail reply (email tickets only).
- Close confirmed → transcript, optional closure email, channel delete; DB marked closed.
Prerequisites
| Requirement | Notes |
|---|---|
| Node.js | 18+; Docker image uses 20 (Dockerfile). |
| npm | npm install locally; npm ci --omit=dev in Docker. |
| MongoDB | Self-hosted; MONGODB_URI required at startup. |
| Discord application | Bot token, application ID; intents: Message Content, Server Members; also Guilds + Guild Messages. |
| Google Cloud | Gmail API enabled; OAuth2 client ID/secret + refresh token for the support mailbox. |
Quick start
git clone <your-repo-url>
cd broccolini-bot
npm install
cp .env.example .env
- Fill Discord (
DISCORD_TOKENorDISCORD_BOT_TOKEN,DISCORD_APPLICATION_ID,DISCORD_GUILD_ID, categories,ROLE_ID_TO_PING, transcript/log channels). - Fill MongoDB (
MONGODB_URI). - Fill Google OAuth (
GOOGLE_CLIENT_ID,GOOGLE_CLIENT_SECRET,REFRESH_TOKEN,MY_EMAIL) — usenode get-refresh-token.jsonce if needed. - Run
npm start. - In Discord, use
/setupor verify categories and roles manually.
Restart after any .env change. After changing slash command definitions, restart so registerCommands() re-registers with Discord.
Installation
Same as quick start. Optional:
- Test env: copy
.env.test.example→.env.test. On Unix shells:npm run start:test(setsENV_FILE). On Windows PowerShell:$env:ENV_FILE='.env.test'; node broccolini-discord.js(or setENV_FILEin the environment your process manager uses).npm run test-mongodb:testhas the sameENV_FILEpattern. - 1Password CLI:
npm run start:1p/start:test:1pinject secrets (see docs/setup/1PASSWORD.md).
Do not commit .env or .env.test. AI/agents should not edit production .env without explicit approval; see ENV_AND_SECURITY.md.
Configuration
Configuration is environment variables only, loaded in config.js as CONFIG. Names below match .env.example unless noted.
Discord (core)
| Variable | Required | Description |
|---|---|---|
DISCORD_TOKEN |
Yes* | Bot token (*or DISCORD_BOT_TOKEN, first non-empty wins after trim). |
DISCORD_APPLICATION_ID |
Yes | Used as CLIENT_ID for REST command registration. |
DISCORD_GUILD_ID |
Yes | Guild where slash commands are registered. |
TICKET_CATEGORY_ID |
Yes | Default category for email tickets (startup validates this). |
DISCORD_TICKET_CATEGORY_ID |
No | Category for Discord panel/context tickets (falls back to TICKET_CATEGORY_ID). |
EMAIL_THREAD_CHANNEL_ID / DISCORD_THREAD_CHANNEL_ID |
No | Parent text channels for thread-style tickets, when used. |
EMAIL_TICKET_OVERFLOW_CATEGORY_IDS |
No | Comma-separated extra categories when the main is full (50 channels). |
DISCORD_TICKET_OVERFLOW_CATEGORY_IDS |
No | Same for Discord ticket category. |
ROLE_ID_TO_PING |
Yes | Support role pinged on new tickets; alias ROLE_TO_PING_ID in code. |
ADDITIONAL_STAFF_ROLES |
No | Extra role IDs treated as staff for commands. |
BLACKLISTED_ROLES |
No | Roles blocked from opening tickets. |
TRANSCRIPT_CHANNEL_ID |
No | Where transcripts are posted on close. |
LOGGING_CHANNEL_ID |
No | Ticket lifecycle logs. |
DEBUGGING_CHANNEL_ID |
No | Optional error/debug forwarding. |
BACKUP_EXPORT_CHANNEL_ID |
No | Target for /backup and /export. |
ACCOUNT_INFO_CHANNEL_ID |
No | Account info flows. |
Escalation categories
| Variable | Description |
|---|---|
EMAIL_ESCALATED_CATEGORY_ID |
Legacy fallback; alias ESCALATED_CATEGORY_ID. |
DISCORD_ESCALATED_CATEGORY_ID |
Discord fallback tier-2–style bucket. |
DISCORD_ESCALATED2_CHANNEL_ID |
Tier 2 placement for Discord tickets (or + fallback category). |
EMAIL_ESCALATED2_CHANNEL_ID |
Tier 2 for email tickets (env name says CHANNEL for legacy reasons). |
DISCORD_ESCALATED3_CHANNEL_ID |
Tier 3 Discord. |
EMAIL_ESCALATED3_CHANNEL_ID |
Tier 3 email. |
Slash /escalate and buttons require the appropriate tier IDs for non-thread channels (threads skip category moves).
Staff notifications, claimer display, admin
| Variable | Description |
|---|---|
STAFF_NOTIFICATION_CATEGORY_ID |
Category where /notification add creates per-staffer notification channels. |
STAFF_EMOJIS |
Comma-separated discordUserId:emoji pairs; used in channel name when a ticket is claimed. |
CLAIMER_EMOJI_FALLBACK |
Emoji if the claimer has no STAFF_EMOJIS entry. |
ADMIN_ID |
Discord user ID allowed to use /staffnotification (override cooldown for another member). |
UNCLAIMED_REMINDER_THRESHOLDS |
Comma-separated hours (e.g. 1,2,4); drives unclaimed ticket alerts into notification channels. |
Logging & observability
| Variable | Description |
|---|---|
GMAIL_LOG_CHANNEL_ID |
Channel for Gmail poll activity logs. |
AUTOMATION_LOG_CHANNEL_ID |
Channel for auto-close/auto-unclaim/reminder logs. |
RENAME_LOG_CHANNEL_ID |
Channel for channel rename queue logs. |
SECURITY_LOG_CHANNEL_ID |
Channel for security/audit logs. |
SYSTEM_LOG_CHANNEL_ID |
Channel for bot lifecycle logs (startup, shutdown, DB events). |
Pattern detection & surge/chat alerts
Core behaviour is configured via .env.example; high level:
- Pattern detection (
patternStore.js,patternChecker.js):USER_PATTERNS_CHANNEL_ID,GAME_PATTERNS_CHANNEL_ID,TAG_PATTERNS_CHANNEL_ID,ESCALATION_PATTERNS_CHANNEL_ID,STAFF_PATTERNS_CHANNEL_ID,COMBINED_PATTERNS_CHANNEL_IDselect where pattern embeds are posted.- Threshold envs like
PATTERN_USER_TICKET_THRESHOLD,PATTERN_GAME_TICKET_THRESHOLD,PATTERN_UNCLAIMED_HOURS,PATTERN_ESCALATION_THRESHOLD,PATTERN_RAPID_CLOSE_SECONDStune when alerts fire. - Windows (
today,week,month) reset automatically via scheduled timers inpatternStore.scheduleResets().
- Surge detection (
surgeChecker.js):ALL_STAFF_CHANNEL_IDis the primary surge-alert channel;SURGE_ROLE_IDis pinged when set.SURGE_TICKET_COUNT/SURGE_TICKET_WINDOW_MINUTES,SURGE_GAME_TICKET_COUNT/SURGE_GAME_TICKET_WINDOW_MINUTES,SURGE_STALE_*,SURGE_NEEDS_RESPONSE_*,SURGE_UNCLAIMED_*,SURGE_TIER3_UNCLAIMED_MINUTES,SURGE_COOLDOWN_MINUTEScontrol volume/backlog alerts.SURGE_NO_STAFF_OPEN_TICKET_THRESHOLD,SURGE_NO_STAFF_COOLDOWN_MINUTES,STAFF_IDS, andSTAFF_DND_COUNTS_AS_AVAILABLEdrive “no staff available” alerts (presence-based with message activity fallback).
- Chat monitoring (
chatAlertChecker.js):CHAT_ALERT_CHANNEL_IDSlists channels to monitor.CHAT_ALERT_MESSAGE_COUNT,CHAT_ALERT_HOURS_WITHOUT_RESPONSE,CHAT_ALERT_COOLDOWN_MINUTESconfigure when to send chat-attention alerts toALL_STAFF_CHAT_ALERT_CHANNEL_ID.
Google / Gmail
| Variable | Required | Description |
|---|---|---|
GOOGLE_CLIENT_ID |
Yes | OAuth2 client ID. |
GOOGLE_CLIENT_SECRET |
Yes | OAuth2 secret. |
REFRESH_TOKEN |
Yes | Long-lived refresh for the inbox account. |
MY_EMAIL |
Yes | Canonical support address (lowercased in config). |
MongoDB
| Variable | Required |
|---|---|
MONGODB_URI |
Yes |
Test: npm run test-mongodb (optionally with ENV_FILE / .env.test as above).
Server & optional HTTP API
| Variable | Default | Description |
|---|---|---|
DISCORD_ONLY_PORT |
5000 |
Express listen port (CONFIG.PORT). |
HEALTHCHECK_HOST |
(all interfaces) | e.g. 127.0.0.1 for local-only bind. |
Additional variables for mounting /api (API key, CORS, etc.) are listed in .env.example if you use that integration.
Messaging & branding
See .env.example for defaults: ESCALATION_MESSAGE ({support_name}), TICKET_WELCOME_MESSAGE, TICKET_CLAIMED_MESSAGE / TICKET_UNCLAIMED_MESSAGE ({staff_mention}, {staff_name}), DISCORD_CLOSE_MESSAGE, DISCORD_TRANSCRIPT_MESSAGE ({channel_name}, {email}, {date_opened}, {date_closed}), EMAIL_SIGNATURE (\n → <br>), embed color hex vars, button labels/emojis, SUPPORT_NAME, LOGO_URL.
Automation & limits
- Auto-close:
AUTO_CLOSE_ENABLED,AUTO_CLOSE_AFTER_HOURS,AUTO_CLOSE_MESSAGE. - Reminders:
REMINDER_ENABLED,REMINDER_AFTER_HOURS,REMINDER_MESSAGE({ping},{hours}). - Limits:
GLOBAL_TICKET_LIMIT,TICKET_LIMIT_PER_CATEGORY,RATE_LIMIT_TICKETS_PER_USER,RATE_LIMIT_WINDOW_MINUTES. - Claim:
ALLOW_CLAIM_OVERWRITE,AUTO_UNCLAIM_*,CLAIM_TIMEOUT_ENABLED,CLAIM_TIMEOUT_HOURS. - Priority:
PRIORITY_ENABLED,DEFAULT_PRIORITY,PRIORITY_*_EMOJI.
Game list
GAME_LIST=comma,separated,names — used for detection/normalization in email handling (plus aliases in config.js).
Thread-style tickets (legacy)
USE_THREADS, THREAD_PARENT_CHANNEL (see .env.example) — optional legacy paths; primary behavior is also governed by GuildSettings.emailRouting (/email-routing: thread | category).
Staff notification channels & reply alerts
When STAFF_NOTIFICATION_CATEGORY_ID is set:
/notification add(with a target member) creates a channel under that category and savesuserId→channelId+ default cooldown inStaffNotification./notification set hours:(1–6) updates the cooldown between reply alerts for that user’s claimed tickets (same ticket keys offgmailThreadId)./staffnotification(admin,ADMIN_ID) sets cooldown for another staff member.- On messageCreate, if the ticket has a
claimerIdand the author is not detected as havingROLE_ID_TO_PING,notifyStaffOfReplymay post in the claimer’s notification channel (respecting cooldown). - Every 30 minutes,
notifyAllStaffUnclaimedevaluates open tickets withclaimedBy: nullagainstUNCLAIMED_REMINDER_THRESHOLDSand posts to all configured notification channels (tracks sent thresholds on the ticket inunclaimedReminderssent).
/notifydm toggles StaffSettings.notifyDm for the invoking user; when enabled, claimers can also receive a DM on customer reply (in addition to any notification channel).
Broccolini settings page
The repo includes an optional Broccolini settings web UI under settings-site/ for configuring the bot without editing .env directly.
- Runs as a small Express app (
settings-site/server.js) onSETTINGS_PORTand talks to the bot’s internal API onINTERNAL_API_PORTusingINTERNAL_API_SECRET. - Serves a password-protected dashboard (
SETTINGS_ADMIN_PASSWORD) where you can adjust Discord channels, categories, Gmail credentials, ticket behavior, surge alerts, pattern thresholds, appearance, staff options, and advanced settings. - Changes are sent to the bot’s internal
/internal/configendpoints and can be saved as pending, applied immediately, or saved and paired with an immediate or scheduled restart.
To use it, run node settings-site/server.js alongside the bot (or via Docker), set the SETTINGS_* and INTERNAL_API_* variables as in .env.example, and put it behind HTTPS with your preferred reverse proxy.
Running the bot (test and Docker)
npm start
# or
node broccolini-discord.js
Test / alternate env file: see Installation for ENV_FILE on Windows vs Unix.
npm run test-mongodb
Docker (see Dockerfile):
docker build -t broccolini-bot .
docker run --env-file .env -p 5000:5000 broccolini-bot
Ensure MONGODB_URI and Discord token are available inside the container. A sample docker-compose.yml exists—adjust ports and env_file for your host (do not copy production-specific bind addresses into new deployments without review).
Discord commands
Most commands require staff (ROLE_ID_TO_PING or ADDITIONAL_STAFF_ROLES). /help is available more broadly per registration.
| Command | Description |
|---|---|
/setup |
Guild setup wizard (panel, role, category, transcript channel, etc.). |
/panel |
Post a ticket Open button in a channel (optional type: thread / category / both; custom title/description). |
/email-routing |
Choose whether new email tickets create threads vs category channels (GuildSettings in DB). |
/escalate |
Required: level (Tier 2 or Tier 3), action (unclaim clears claimedBy + claimerId after escalation, keep preserves claim). |
/deescalate |
Step down one tier (tier 3 → 2 → normal). |
/notifydm |
setting: on / off — DM when a non-staff user replies in a ticket you claimed. |
/notification |
Subcommands: set (cooldown hours), add (create notification channel for a member). |
/staffnotification |
Admin only (ADMIN_ID); override another member’s notification cooldown. |
/add, /remove |
Add/remove user overwrites on the current ticket channel. |
/transfer |
Set claimedBy to another staff member (must have staff role). |
/move |
Move channel to another category (direct setParent). |
/force-close |
Close without button confirmation (still archives transcript best-effort). |
/topic |
Set Discord channel topic. |
/priority |
low / normal / medium / high. |
/tag |
Set ticket tag category from dropdown (choices from TICKET_TAGS in config.js). |
/response |
Subcommands: send, create, edit, delete, list (saved responses). |
/accountinfo |
Subcommands: email, discord. |
/search |
Search tickets by email, subject, or number. |
/stats |
Bot analytics snapshot. |
/backup, /export |
Post exports to BACKUP_EXPORT_CHANNEL_ID. |
/help |
In-bot command summary embed. |
Context menus
- Create Ticket From Message — opens a ticket prefilled from a message.
- View User Tickets — lists recent tickets for a user (by sender tag match).
Ticket UI (buttons & modals)
- Open ticket (panel): modal fields are account email, game, description.
- In ticket channels: Close, Claim/Unclaim, Escalate (tier choice), De-escalate as built in
utils/ticketComponents.js/handlers/buttons.js. - Email routing and tag delete confirmations use additional button custom IDs.
Tag & response system
/tag
Sets ticketTag from the fixed list in config.js (TICKET_TAGS). Channel naming may incorporate tag/priority emojis via ticket naming logic.
/response
Templates support variables such as {ticket.user}, {ticket.email}, {ticket.number}, {ticket.subject}, {staff.name}, {staff.mention}, {server.name}, {date}, {time} (see utils.js / handler docs).
Panel system
- Run
/paneltargeting a channel (and optional style: thread-only, category-only, or both buttons). - User clicks Open ticket → modal → bot creates thread or channel per configuration.
- Welcome embeds + action row are posted;
TicketstoresdiscordThreadId,ticketNumber, etc.
Channel renames & moves (rate limits)
Discord allows two renames per 10 minutes per channel. The bot serializes renames/moves through services/channelQueue.js (p-queue). If rename is blocked, staff see a message with a relative time to retry.
Project structure
broccolini-bot/
├── broccolini-discord.js # Entry: Discord client, Express, Gmail poll interval, jobs
├── config.js # Env → CONFIG (game lists, TICKET_TAGS, STAFF_EMOJIS map, …)
├── db-connection.js # Mongo connect + require models
├── models.js # Mongoose schemas (Ticket, Tag, StaffSettings, StaffNotification, …)
├── utils.js # Email/game helpers, template variables
├── utils/ticketComponents.js # Action row builders
├── gmail-poll.js # Ingest Gmail → Discord ticket creation
├── get-refresh-token.js # One-shot OAuth refresh token helper
├── commands/register.js # Slash + context menu registration (discord.js v14)
├── handlers/
│ ├── buttons.js # Claim/close/modals/escalate buttons, ticket create modal
│ ├── commands.js # Slash handlers, runEscalation/runDeescalation
│ ├── messages.js # Staff ↔ Gmail relay; notifydm; notification alerts
│ ├── accountinfo.js
│ ├── analytics.js
│ └── setup.js
├── services/
│ ├── gmail.js
│ ├── tickets.js # Auto-close, reminders, auto-unclaim, naming helpers
│ ├── channelQueue.js # enqueueRename / enqueueMove
│ ├── staffChannel.js # Legacy mirror helpers (unused in current claim flow)
│ ├── staffNotifications.js # Reply alerts + unclaimed reminders
│ ├── staffSettings.js # notifydm prefs
│ ├── guildSettings.js
│ └── debugLog.js
├── routes/ # Optional Express `/api` routes
├── api/ # Bot client accessor for HTTP layer
├── scripts/ # Maintenance / one-off utilities
├── docs/ # Deeper guides (setup, security, MongoDB, API notes)
├── Dockerfile
├── docker-compose.yml
├── package.json
└── .env.example / .env.test.example
Database collections
| Model / collection | Role |
|---|---|
| Ticket | Gmail thread id, Discord channel/thread id, status, priority, claim (claimedBy display label, claimerId), legacy staffChannelId, escalation tier, welcomeMessageId, ticketTag, unclaimedReminderssent, etc. |
| TicketCounter | Per-sender local counters (legacy paths). |
| Transcript | Links closed tickets to transcript message IDs. |
| Tag | Saved response name + content. |
| GuildSettings | e.g. emailRouting: thread | category. |
| StaffSettings | Per-user notifyDm (+ guildId, updatedAt). |
| StaffNotification | Per-user channelId, cooldownHours for reply/unclaimed alerts. |
| CloseRequest | Pending close workflow if used. |
| User, Host, DashboardMetrics, ErrorLog | Shared / website-era schemas in the same models.js file. |
HTTP: healthcheck & optional API
GET /→ plain textActive(intended for load balancers / DockerHEALTHCHECK)./api/*is registered only after the bot isreadyand the optional HTTP API is enabled via env (see.env.example). JSON body parsing is enabled; auth uses a Bearer token from configuration. Route definitions live underroutes/in this repo.
Gmail OAuth refresh token
node get-refresh-token.js
Requires GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET in .env, and redirect URI http://localhost:3000/oauth2callback registered on the Google OAuth client. Paste the printed refresh token into .env as REFRESH_TOKEN.
Documentation in docs/
Index: docs/README.md. Highlights:
| Doc | Topic |
|---|---|
| ENV_AND_SECURITY.md | Secrets, test env, agent rules |
| MONGODB_SETUP.md | Database |
| QUICKSTART.md | First-time orientation |
| PROJECT_STRUCTURE.md | Layout (may overlap this README) |
| 1PASSWORD.md | 1Password CLI for npm run start:1p |
Development & CI
This repo includes .gitlab-ci.yml with GitLab SAST and secret detection templates. Adjust or extend stages in GitLab as needed for your fork.
Troubleshooting
| Symptom | Checks |
|---|---|
| Commands missing | Correct DISCORD_APPLICATION_ID + DISCORD_GUILD_ID; restart bot; Discord can take time to sync. |
| Gmail not ingesting | REFRESH_TOKEN, API enablement, inbox auth; regenerate token if revoked. |
| MongoDB errors | MONGODB_URI, npm run test-mongodb. |
| Channels not creating | Bot Manage Channels in ticket categories; category not full (50) unless overflow set. |
| Modal / button no response | Intents + permissions; bot online; check DEBUGGING_CHANNEL_ID / console. |
| Renames “too quickly” | Discord rename cooldown; wait for channel queue / timestamp in bot message. |
| Test script env on Windows | npm run start:test sets ENV_FILE Unix-style; use PowerShell ENV_FILE + node if the script fails. |
References
| Technology | Link |
|---|---|
| discord.js v14 | discord.js guide |
| Google APIs (Gmail) | googleapis Node |
| Mongoose | mongoosejs.com |
| Express | expressjs.com |
License
ISC