Skip to content

Configuration

Mathildeuh edited this page Sep 12, 2026 · 2 revisions

Configuration

Everything lives in plugins/SOS-Staff/config.yml, generated on first run. Reload with /sostaff reload after editing - it never disrupts a ticket that's already open, since Discord channel IDs are stored per-ticket in the database rather than recomputed.

commands

commands:
  main: "ticket"
  aliases: ["support", "sos"]

The player-facing command's label and aliases. /sostaff (the staff command) is fixed.

creation-mode

creation-mode: BOTH        # PRESET | FREE_INPUT | BOTH

The default creation flow, overridable per category (below). PRESET shows a list of common issues to pick from; FREE_INPUT prompts the player to type their own description in chat; BOTH offers a "write your own" option alongside the presets. /ticket <reason> skips all of this and creates a ticket directly, in the first configured category.

categories

categories:
  bug:
    display-name: "Bug / Technical issue"
    icon: BOOK
    color: "#5865F2"
    mode: PRESET
    presets: ["Item duplication", "Crash on world load", "Other technical bug"]
    ping-role: "123456789012345678"
  report:
    display-name: "Report a player"
    icon: IRON_SWORD
    color: "#ED4245"
    mode: FREE_INPUT
    prompt-key: "creation.report.prompt"

At least one category is required. Each key (bug, report, ...) is the category's id, used internally and in /ticket new <category>.

  • icon - any Bukkit Material name
  • color - a #RRGGBB hex color, used for the category's menu item and its Discord embeds
  • mode - optional; overrides the global creation-mode for this category only
  • presets - the preset issue descriptions shown in PRESET/BOTH mode
  • ping-role - optional Discord role id pinged in addition to discord.mentions.on-create.roles whenever a ticket in this category is created
  • prompt-key - a lang/*.yml key used as the prompt text in FREE_INPUT mode; falls back to creation.default.prompt if unset

discord

discord:
  token: ""
  category:
    name: "Ticket Support"
    auto-create: true
    archived-category-name: "Archived Tickets"
  channel:
    name-format: "ticket-%id%-%player%"
    topic-format: "Ticket #%id% - %category% - Priority: %priority%"
  permissions:
    staff-roles: ["123456789012345678"]
    hide-from-everyone: true
    creator-can-see: true
  mentions:
    on-create:
      roles: ["123456789012345678"]
      message: "New ticket from **%player%** - %category%"
    on-escalate:
      message: "Ticket #%id% unanswered for %minutes% min"
  on-close:
    action: ARCHIVE
    lock-channel: true
    auto-delete-after-days: 7

See Discord Setup for the bot itself. token is only a fallback - set SOSSTAFF_DISCORD_TOKEN instead and leave this blank. staff-roles is who can see every ticket channel. name-format/topic-format support %id%, %player%, %category%, %priority%.

discord.action-buttons

discord:
  action-buttons:
    heal-player:
      enabled: true
      label: "Heal"
      command: HEAL
      permission: "sosstaff.action.heal-player"
      requires-online: true
    force-reconnect:
      enabled: true
      label: "Force Reconnect"
      command: KICK
      permission: "sosstaff.action.force-reconnect"
      requires-online: true
      confirm: true
      kick-reason: "Reconnection requested by support - %staff%"
    teleport-spawn:
      enabled: false
      label: "TP Spawn"
      command: "tp %player% 0 100 0"
      permission: "sosstaff.action.teleport-spawn"
      requires-online: true

Each entry adds a button to every ticket's Discord embed. command is either one of the reserved internal keys below, or any raw server command (placeholders %player%, %staff%, %ticket_id% are substituted first). permission is checked against the Minecraft account resolved from the Discord clicker's display name (see the note on that below) before the button does anything. requires-online: true grays the button out while the ticket's player is offline. confirm: true asks for a second click before running a disruptive action.

Reserved internal command keys: HEAL, FEED, KICK, FREEZE, UNFREEZE, TELEPORT_TO_PLAYER (bring the clicking staff member to the ticket's player), TELEPORT_PLAYER_TO_STAFF (the reverse).

No Discord-to-Minecraft account link exists. Claiming a ticket is entirely a Discord concept and never needs one. The two teleport actions and the permission check on other action buttons resolve the clicker to a Minecraft account by matching their Discord display name against an online player's username. Teleporting genuinely needs that match (there is no Minecraft character to move otherwise) and fails clearly if it can't find one; every other action button still runs without a match, trusting Discord channel access (discord.permissions.staff-roles) instead of a Bukkit permission check.

escalation

escalation:
  enabled: true
  no-claim-after-minutes: 15

An unclaimed, still-open ticket gets staff pinged again (discord.mentions.on-escalate) once it has been open longer than this, checked once a minute. Claiming or closing it clears the escalation state.

anti-spam

anti-spam:
  max-open-tickets-per-player: 1
  cooldown-after-close-seconds: 30
  bypass-permission: "sosstaff.bypass.antispam"

Counted against any ticket status other than CLOSED/ARCHIVED. A rejected creation points the player at their existing ticket (or tells them how long the cooldown has left) rather than failing silently. bypass-permission skips both checks entirely.

storage

storage:
  type: SQLITE              # SQLITE | MYSQL
  mysql:
    host: "localhost"
    port: 3306
    database: "sosstaff"
    username: ""
    password: ""

Only SQLITE is implemented. Setting MYSQL disables the plugin on startup with a clear error - the mysql block is reserved for that backend once it exists.

gdpr

gdpr:
  transcript-retention-days: 90

/sostaff gdpr erase <player> deletes a specific player's tickets and messages on request; this setting instead purges message content older than the window automatically, once a day, for every ticket regardless of who asked.

update-checker

update-checker:
  enabled: true

A single async, log-only check against Modrinth on startup, comparing the running version to the latest published one. Never blocks startup and never does anything but log.

language

language:
  default: "en_US"
  shipped: ["en_US", "fr_FR", "es_ES", "ru_RU", "de_DE"]
  per-player: false

default must be one of shipped, and is used for every player right now - per-player is reserved for a future feature and currently has no effect either way. Missing keys in any non-en_US file fall back to the en_US (pivot) value automatically.

Clone this wiki locally