A secure, bilingual support workflow for Discord communities. TicketBot turns a public support panel into private, permission-scoped ticket channels with staff access, duplicate prevention, notifications, and auditable closure.
Try the interactive workflow → · Leia em português
Community support in public channels leaks context and becomes difficult to triage. TicketBot gives members one clear entry point and gives staff an isolated channel per request, without requiring a separate dashboard or database.
- interaction-driven workflow using slash commands, buttons, and modals;
- private Discord permission overwrites for requester and support role;
- one active ticket per member plus an in-process creation lock;
- deterministic sequential channel naming across restarts;
- PT-BR and EN-US panels and support notices;
- optional Discord webhook notifications and event log channel;
- administrator authorization at command registration and runtime boundaries;
- destructive actions restricted to canonical
ticket-00000channels; - reconnect backoff for gateway/session failures;
- dependency audit, behavioral tests, public-boundary gate, and full-history Gitleaks.
Admin publishes panel
→ member opens ticket
→ bot creates private channel
→ support conversation
→ admin closes canonical ticket channel
The public demo simulates this lifecycle without a Discord token or real server.
git clone https://github.com/lippdev/ticketbot.git
cd ticketbot
npm ci
cp .env.example .env
# Add DISCORD_TOKEN and, ideally, DISCORD_GUILD_ID
npm startCreate the bot in the Discord Developer Portal. Never commit its token or a webhook URL.
| Variable | Required | Purpose |
|---|---|---|
DISCORD_TOKEN | Yes | Bot credential from Discord Developer Portal |
DISCORD_GUILD_ID | Recommended | Registers commands immediately in one guild |
DISCORD_TICKET_CATEGORY_ID | No | Parent category for ticket channels |
DISCORD_TICKET_SUPPORT_ROLE_ID | No | Staff role granted ticket access |
DISCORD_TICKET_LOG_CHANNEL_ID | No | Ticket event audit channel |
DISCORD_WEBHOOK_URL | No | Ticket-open notification endpoint |
SUPPORT_EMAIL | No | Contact shown in automatic notices |
SUPPORT_HOURS_PT, SUPPORT_HOURS_EN | No | Localized availability text |
BOT_PRESENCE_MESSAGES | No | Pipe-separated rotating activities |
Required intents: Guilds, Guild Messages, and Message Content.
| Command | Access | Purpose |
|---|---|---|
/ticketpanel | Administrator | Configure and publish the PT-BR panel |
/ticketpanel-en | Administrator | Publish the EN-US panel |
/ticketadmin | Administrator | Open controls inside a ticket channel |
Ticket channels deny ViewChannel to @everyone, then grant only the requester and optional support role. Administrative interactions are checked at both Discord command registration and execution time. Channel deletion rejects non-ticket names even for administrators.
State is intentionally in memory. Existing tickets survive restarts as Discord channels and are rediscovered by canonical name/permissions; ephemeral locks, panel edits, and first-reply markers reset. Add persistence only when operating multiple bot processes.
npm ci
npm test
npm run audit:public
npm audit --omit=dev --audit-level=highSee architecture and contributing guide.
Built by Filipe Moreira, full-stack software engineer — GitHub.
MIT