Docs/Plugins

Tickets plugin

Support ticket panels, categories, staff claiming, escalation, and transcripts. Panels, categories, and their behavior are configured entirely from the dashboard; Discord commands handle day-to-day ticket management.

#How it works

  1. From the dashboard, build one or more panels — a message (plain text and/or an embed) posted to a channel, showing one or more categories as buttons (max 5) or a select menu (max 25).
  2. A member opens a ticket by clicking a category. If the category has form questions configured, they answer those first in a modal; the answers are included in the ticket.
  3. Dreamliner creates a private channel or thread (per the category's mode) named from naming_pattern, posts the welcome message, and optionally pings ping_role_ids (then deletes that ping message).
  4. Staff (from the category's support_role_ids, or the plugin-wide staff_role_ids when empty) claim, assign, reply, and manage the ticket. An escalation ladder can ping a role, alert another channel, bump priority, or auto-close a ticket after a set number of minutes without a staff reply.
  5. Closing a ticket generates a transcript, which is posted to transcript_channel_id (falling back to default_transcript_channel_id) and/or DMed to the opener, and can request feedback (a rating) if enabled.

#Configuration

yaml
plugins:
  tickets:
    enabled: true
    config:
      staff_role_ids: []
      log_channel_id: ""
      default_transcript_channel_id: ""
      dm_transcript_on_close: true
      feedback_enabled: false
      max_open_tickets_per_user: 1
      blacklist_notify: true
      panels: []

#Plugin-wide settings

FieldDescription
staff_role_idsSupport staff roles, used as the fallback when a category has no support_role_ids of its own.
log_channel_idChannel for ticket open/claim/close event logs.
default_transcript_channel_idDefault transcript channel when a category has no override.
dm_transcript_on_closeDM the opener their transcript when the ticket closes.
feedback_enabledPlugin-wide default: DM the opener a rating request after close.
max_open_tickets_per_userDefault limit on how many tickets one member may have open at once.
blacklist_notifyTell blacklisted members why their ticket attempt was blocked.
panelsTicket panels for this server — build and edit these from the dashboard, not by hand.

#Panel fields

FieldDescription
nameDashboard-only label for this panel.
enabledTurn this panel on or off without deleting it.
channel_idChannel the panel message is posted in.
stylebuttons (max 5 categories) or select (max 25 categories).
content / embedThe panel message's optional text and embed.
categoriesThe panel's categories (see below), 1-25.

#Category fields

FieldDescription
label / description / emoji / button_styleHow the category appears on the panel.
category_channel_idDiscord channel category new ticket channels are created under.
modeOpen tickets as a private channel or a private thread.
naming_patternChannel/thread name pattern. Supports {number}, {username}, {category}.
welcome_messageMessage posted in the new ticket. Supports {user}, {guild}, {category}, plus each question's answer as {answer_1}, {answer_2}, ...
support_role_ids / ping_role_idsRoles that can see/reply, and roles pinged (then unpinned) when a ticket opens.
form_questionsUp to 5 questions asked in a modal before the ticket opens.
max_open_per_userPer-user open-ticket limit for this category. 0 disables new tickets. Empty uses the plugin-wide limit.
auto_close_hoursAuto-close after this many hours of opener inactivity. 0 disables.
escalationSLA ladder — up to 10 steps, each firing after N minutes of staff silence (see below).
close_permissionWho may close tickets from this category: opener, staff, or either.
require_close_reasonRequire a reason when closing a ticket.
transcript_channel_idTranscript channel override for this category.
feedback_enabledPer-category override for the plugin-wide feedback setting.

#Escalation steps

FieldDescription
after_minutesTrigger this step after this many minutes without a staff reply (or since the ticket opened, if staff never replied).
actionping_role, notify_channel, set_priority, or close.
role_id / channel_id / priorityUsed by the matching action type.
messageOptional note appended to the ping/alert.

Escalation re-arms whenever staff reply again.

#Commands

CommandPermissionDescription
/ticket new—Open a ticket (only when the server has exactly one panel with exactly one category and no form questions — otherwise use the panel buttons/menu)
/ticket close [reason]close_permission on the category (opener/staff/either)Close the ticket in this channel
/ticket claim / unclaimcan_claimClaim or unclaim the ticket in this channel
/ticket assign <user> / unassigncan_assignAssign or unassign the ticket to another member
/ticket status set <status>can_set_statusSet the ticket's status (Open, In Progress, Awaiting Response, Awaiting Further Information, On Hold)
/ticket add <user> / remove <user>can_add_remove_membersAdd or remove a member from the ticket
/ticket rename <name>can_manage_panelsRename the ticket's channel
/ticket priority <level>can_claimSet the ticket's priority (low/medium/high/urgent)
/ticket transcript—DM yourself the ticket's latest transcript (posts to the log channel instead if your DMs are closed)
/ticket stats [member] [days]can_view_statsTicket handler performance stats — closed count, average resolution time, average first-response time
/ticket blacklist <target> [reason]can_blacklistBlock a member from opening tickets
/ticket ai stopManage Server, a support role of the category, or can_control_aiStop the AI Responder in this ticket so staff can take over
/ticket ai resumeManage Server, a support role of the category, or can_control_aiHand the ticket back to the AI Responder
/ticket ai usage—Today's AI replies against the server's daily limit

Also available: can_reopen (reopen closed tickets), can_view_all (view any ticket, not just ones you're part of), and can_delete (permanently delete tickets) — used by the dashboard's ticket view rather than a dedicated slash command.

Grant these to a Dreamliner Role on the dashboard's Roles page (or /permissions role grant) — see permissions.md.

#AI Responder

An optional first line of support (ai_responder in the Tickets config, edited on Support → Tickets → AI Responder). When it's on, new tickets in the chosen categories (or every category) are answered by the AI first; staff are only pinged when it hands the ticket over.

  • What it knows: read live for every reply and never stored: server info (name, description, rules channel, public channels, roles, ticket categories), the member (join date, account age, roles), their recent tickets and, if turned on, their recent moderation cases (never who issued them). On top of that it uses the server's knowledge base: FAQs and notes written on the dashboard, facts kept by Autotrain, and approved lessons learned from staff. The 500 most relevant entries are searched per question.
  • Hand-off: it hands the ticket to staff when the member asks (or presses Talk to staff), on sensitive topics (bans and appeals, payments and refunds, account access, harassment and safety reports, reports against members), on the server's own topics, when it isn't sure, after the per-ticket reply limit, or when the daily limit runs out. The hand-off posts a short summary for staff and pings the category's ping roles (or its support roles). Once staff reply in the ticket the AI stops on its own; /ticket ai resume hands it back.
  • Learning from staff: when a ticket staff answered is closed, the AI extracts up to three reusable lessons from the transcript. They wait in Needs review until approved (or are used straight away if Use lessons without review is on).
  • Autotrain: reads recent messages (up to 300 per channel) in up to 10 chosen channels on a schedule (every 6 hours or more) and keeps short facts, updating or removing the ones it kept before. The messages themselves are not stored.
  • Limits: 20 AI replies a day per server, or 1,000 with Dreamliner One. Each reply counts once; the greeting and hand-offs don't. Learning and Autotrain have their own smaller daily budget (15, or 300 with One). Limits reset at midnight UTC.
  • Model: gpt-4.1-mini by default; set OPENAI_TICKET_MODEL to change it. Replies are checked before posting: pings are removed, links are only kept for Discord, Dreamliner, and sites found in the server's own knowledge, and replies are cut to the configured length.

#Dashboard

Support → Tickets is where panels and categories are built and edited, where the View Tickets page shows every open/closed ticket with claim, assign, status, and delete actions, and where the AI Responder page sets up the AI, its knowledge base, Autotrain, and a test chat.

#Requirements

  • The bot needs Manage Channels (create ticket channels) and, for thread-mode categories, permission to create private threads.
  • category_channel_id must be set on every category so ticket channels have somewhere to be created.

#Setup

  1. Open the dashboard's Support → Tickets page and create a panel: pick a channel, a style (buttons or select), and an embed/message.
  2. Add at least one category: set its ticket-channel category, naming pattern, welcome message, support roles, and optionally form questions and an escalation ladder.
  3. Save — Dreamliner posts (or reposts) the panel message.
  4. Grant the staff-facing permissions above to your support roles.