204 lines
12 KiB
Plaintext
204 lines
12 KiB
Plaintext
# =============================================================================
|
||
# Broccolini Bot – Example environment (no secrets)
|
||
# Copy to .env and fill in real values. See README for full docs.
|
||
# =============================================================================
|
||
# Test env: set ENV_FILE=.env.test to load .env.test instead (see docs/setup/ENV_AND_SECURITY.md).
|
||
|
||
# --- Discord: Core ---
|
||
DISCORD_TOKEN= # Bot token from Discord Developer Portal
|
||
DISCORD_APPLICATION_ID= # Application (client) ID
|
||
DISCORD_GUILD_ID= # Server (guild) ID where the bot runs
|
||
|
||
# --- Discord: Channel & category IDs ---
|
||
# Ticket creation: set one or both; /panel and /email-routing choose behavior
|
||
DISCORD_TICKET_CATEGORY_ID= # Category for Discord-originated ticket channels
|
||
TICKET_CATEGORY_ID= # Category for email-originated ticket channels
|
||
DISCORD_THREAD_CHANNEL_ID= # Text channel for Discord ticket threads (optional)
|
||
EMAIL_THREAD_CHANNEL_ID= # Text channel for email ticket threads (optional)
|
||
|
||
# Category display names (primary must match the category name in Discord; overflow folders are created as "{name} (Overflow 1)", etc.)
|
||
TICKET_CATEGORY_NAME=Open Tickets
|
||
TICKET_T2_CATEGORY_NAME=Tier 2 Escalated Tickets
|
||
TICKET_T3_CATEGORY_NAME=Tier 3 Escalated Tickets
|
||
|
||
# Escalation categories (tier 2 and tier 3)
|
||
DISCORD_ESCALATED_CATEGORY_ID= # Fallback escalation category (Discord)
|
||
EMAIL_ESCALATED_CATEGORY_ID= # Fallback escalation category (email); legacy alias: ESCALATED_CATEGORY_ID
|
||
DISCORD_ESCALATED2_CHANNEL_ID= # Tier 2 escalation category/channel (Discord)
|
||
DISCORD_ESCALATED3_CHANNEL_ID= # Tier 3 escalation category/channel (Discord)
|
||
EMAIL_ESCALATED2_CHANNEL_ID= # Tier 2 escalation category ID (email tickets; env name says CHANNEL for legacy reasons)
|
||
EMAIL_ESCALATED3_CHANNEL_ID= # Tier 3 escalation category ID (email tickets; same naming note as tier 2)
|
||
|
||
# Logging, transcripts, and utility
|
||
ROLE_ID_TO_PING= # Role ID to ping on new tickets (config also accepts ROLE_TO_PING_ID as alias)
|
||
TRANSCRIPT_CHANNEL_ID= # Channel for ticket transcripts on close
|
||
LOGGING_CHANNEL_ID= # Channel for lifecycle log messages
|
||
DEBUGGING_CHANNEL_ID= # Channel for error logs (escalate, poll, etc.); optional
|
||
BACKUP_EXPORT_CHANNEL_ID= # Channel where /backup and /export post .txt files; optional
|
||
ACCOUNT_INFO_CHANNEL_ID= # Channel for account info lookups; optional
|
||
DISCORD_CHANNEL_ID= # General Discord channel (if used)
|
||
|
||
# --- Discord: Ticket copy & buttons ---
|
||
# ESCALATION_MESSAGE: use {support_name} for SUPPORT_NAME
|
||
ESCALATION_MESSAGE= # e.g. Your ticket has been escalated.\n\nA senior {support_name} will be here to assist as soon as possible.
|
||
BUTTON_LABEL_CLOSE=Close Ticket
|
||
BUTTON_LABEL_CLAIM=Claim
|
||
BUTTON_LABEL_UNCLAIM=Unclaim
|
||
BUTTON_EMOJI_CLOSE=🔒
|
||
BUTTON_EMOJI_CLAIM=📌
|
||
BUTTON_EMOJI_UNCLAIM=🔓
|
||
|
||
# --- Google / Gmail ---
|
||
GOOGLE_CLIENT_ID= # OAuth2 Client ID from Google Cloud Console
|
||
GOOGLE_CLIENT_SECRET= # OAuth2 Client Secret
|
||
REFRESH_TOKEN= # OAuth2 refresh token for the support inbox
|
||
MY_EMAIL= # Support inbox email address
|
||
|
||
# --- Server & URLs ---
|
||
NGROK_URL= # Public URL (optional); run ngrok outside this repo
|
||
DISCORD_ONLY_PORT=5000 # Port for healthcheck / Discord-only server
|
||
# HEALTHCHECK_HOST= # Optional; bind address for health server (default: all interfaces; use 127.0.0.1 for local-only)
|
||
|
||
# --- bOSScord (support cockpit) ---
|
||
# Set BOSSCORD_API_KEY to enable /api (ticket list, thread, send message). Use same key in bOSScord app login.
|
||
# BOSSCORD_API_KEY= # e.g. from: openssl rand -hex 32
|
||
# BOSSCORD_CORS_ORIGIN=* # Optional; default * (set to bOSScord origin in production)
|
||
|
||
# --- Database ---
|
||
MONGODB_URI= # MongoDB connection string (e.g. mongodb+srv://user:pass@cluster/dbname)
|
||
# MONGODB_DATABASE= # Optional; DB name usually in MONGODB_URI path (not read by app currently)
|
||
|
||
# --- Branding & copy ---
|
||
SUPPORT_NAME=Support
|
||
LOGO_URL= # URL of logo shown in embeds (optional)
|
||
EMAIL_SIGNATURE= # HTML signature for outgoing emails (use \n for line breaks)
|
||
TICKET_CLOSE_SUBJECT_PREFIX=[Resolved]
|
||
# Email tickets only (closure email body):
|
||
TICKET_CLOSE_MESSAGE= # Body of closure email to customer
|
||
TICKET_CLOSE_SIGNATURE= # Signature on closure email
|
||
# Discord ticket closure (in-channel before transcript, transcript post, and auto-close):
|
||
DISCORD_CLOSE_MESSAGE= # Message in ticket channel before transcript (e.g. ... If you still need assistance, please open a new ticket.)
|
||
DISCORD_TRANSCRIPT_MESSAGE= # When posting transcript / DM to user. Use {channel_name}, {email}, {date_opened}, {date_closed}
|
||
DISCORD_AUTO_CLOSE_MESSAGE= # Message in ticket when auto-closed (e.g. ... If you still need assistance, please open a new ticket.)
|
||
|
||
# --- Ticket limits & permissions ---
|
||
GLOBAL_TICKET_LIMIT=5 # Max concurrent open tickets globally
|
||
TICKET_LIMIT_PER_CATEGORY=3 # Max tickets per category
|
||
RATE_LIMIT_TICKETS_PER_USER=0 # Max tickets per user per window (0 = disabled)
|
||
RATE_LIMIT_WINDOW_MINUTES=60 # Window in minutes for per-user rate limit
|
||
BLACKLISTED_ROLES= # Comma-separated role IDs that cannot open tickets
|
||
ADDITIONAL_STAFF_ROLES= # Comma-separated role IDs with staff permissions
|
||
|
||
# --- Auto-close ---
|
||
AUTO_CLOSE_ENABLED=false
|
||
AUTO_CLOSE_AFTER_HOURS=72
|
||
AUTO_CLOSE_MESSAGE= # Message when ticket is auto-closed
|
||
|
||
# --- Reminders ---
|
||
REMINDER_ENABLED=false
|
||
REMINDER_AFTER_HOURS=24
|
||
# REMINDER_MESSAGE: use {ping} (claimer mention or role ping), {hours}
|
||
REMINDER_MESSAGE= # e.g. Hey {ping}! This ticket has been inactive for {hours} hours. Please provide an update or close the ticket.
|
||
TICKET_WELCOME_MESSAGE= # Message in welcome embed when ticket channel is created
|
||
# TICKET_CLAIMED_MESSAGE / TICKET_UNCLAIMED_MESSAGE: use {staff_mention}, {staff_name}
|
||
TICKET_CLAIMED_MESSAGE= # e.g. Ticket claimed by {staff_mention} 🚀
|
||
TICKET_UNCLAIMED_MESSAGE= # e.g. Ticket unclaimed by {staff_mention} ☀️
|
||
|
||
# --- Priority (low, normal, medium, high; default: normal) ---
|
||
PRIORITY_ENABLED=false
|
||
DEFAULT_PRIORITY=normal
|
||
PRIORITY_HIGH_EMOJI=🔴
|
||
PRIORITY_MEDIUM_EMOJI=🟡
|
||
PRIORITY_LOW_EMOJI=🟢
|
||
|
||
# --- Claiming ---
|
||
CLAIM_TIMEOUT_ENABLED=false
|
||
CLAIM_TIMEOUT_HOURS=48
|
||
AUTO_UNCLAIM_ENABLED=false
|
||
AUTO_UNCLAIM_AFTER_HOURS=24
|
||
ALLOW_CLAIM_OVERWRITE=false
|
||
STAFF_EMOJIS=224692549225283584:🍅 # userId:emoji pairs, comma-separated
|
||
CLAIMER_EMOJI_FALLBACK=🎫 # fallback if claimer has no entry in STAFF_EMOJIS
|
||
ADMIN_ID= # Discord user ID of the bot admin (for /staffnotification)
|
||
STAFF_NOTIFICATION_CATEGORY_ID= # Category for staff notification channels (created by /notification add)
|
||
UNCLAIMED_REMINDER_THRESHOLDS=1,2,4 # Comma-separated hour thresholds for unclaimed ticket alerts
|
||
FORCE_CLOSE_TIMER_SECONDS=60 # Seconds to wait before force-closing a ticket (default 60)
|
||
GMAIL_POLL_INTERVAL_SECONDS=30 # Gmail poll interval in seconds (default 30)
|
||
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 ---
|
||
USER_PATTERNS_CHANNEL_ID= # Channel for repeat-user pattern alerts
|
||
GAME_PATTERNS_CHANNEL_ID= # Channel for game-specific pattern alerts
|
||
TAG_PATTERNS_CHANNEL_ID= # Channel for ticket tag pattern alerts
|
||
ESCALATION_PATTERNS_CHANNEL_ID= # Channel for escalation pattern alerts
|
||
STAFF_PATTERNS_CHANNEL_ID= # Channel for staff workload pattern alerts
|
||
COMBINED_PATTERNS_CHANNEL_ID= # Channel for combined/cross-cutting pattern alerts
|
||
PATTERN_USER_TICKET_THRESHOLD=3 # Tickets per user before alerting
|
||
PATTERN_GAME_TICKET_THRESHOLD=10 # Tickets per game before alerting
|
||
PATTERN_STAFF_STALE_PING_THRESHOLD=5 # Stale pings before alerting
|
||
PATTERN_ESCALATION_THRESHOLD=3 # Escalations before alerting
|
||
PATTERN_RAPID_CLOSE_SECONDS=120 # Seconds; closes faster than this are flagged
|
||
PATTERN_UNCLAIMED_HOURS=4 # Hours unclaimed before flagging
|
||
PATTERN_CHECK_INTERVAL_MINUTES=30 # Minutes between pattern check runs
|
||
|
||
# --- Surge & chat alerts ---
|
||
ALL_STAFF_CHANNEL_ID= # Channel for staff surge alerts
|
||
ALL_STAFF_CHAT_ALERT_CHANNEL_ID= # Channel for chat monitoring alerts
|
||
SURGE_ROLE_ID= # Role to ping on surge alerts
|
||
SURGE_TICKET_COUNT=10 # Ticket count to trigger surge
|
||
SURGE_TICKET_WINDOW_MINUTES=30 # Window for ticket surge
|
||
SURGE_GAME_TICKET_COUNT=5 # Per-game ticket count for surge
|
||
SURGE_GAME_TICKET_WINDOW_MINUTES=30 # Window for game surge
|
||
SURGE_STALE_COUNT=8 # Stale tickets to trigger alert
|
||
SURGE_STALE_HOURS=2 # Hours before ticket is stale
|
||
SURGE_NEEDS_RESPONSE_COUNT=5 # Tickets awaiting response to trigger alert
|
||
SURGE_NEEDS_RESPONSE_HOURS=1 # Hours awaiting response
|
||
SURGE_UNCLAIMED_COUNT=5 # Unclaimed tickets for surge alert
|
||
SURGE_UNCLAIMED_MINUTES=30 # Minutes unclaimed before counting
|
||
SURGE_TIER3_UNCLAIMED_MINUTES=15 # Minutes before tier 3 unclaimed alert
|
||
SURGE_COOLDOWN_MINUTES=60 # Cooldown between surge alerts
|
||
CHAT_ALERT_CHANNEL_IDS= # Comma-separated channel IDs to monitor
|
||
CHAT_ALERT_MESSAGE_COUNT=5 # Unresponded messages to trigger alert
|
||
CHAT_ALERT_HOURS_WITHOUT_RESPONSE=2 # Hours without staff response to alert
|
||
CHAT_ALERT_COOLDOWN_MINUTES=60 # Cooldown between chat alerts
|
||
STAFF_IDS= # Comma-separated Discord user IDs of all staff members
|
||
SURGE_NO_STAFF_COOLDOWN_MINUTES=30 # Cooldown between zero-staff alerts
|
||
SURGE_NO_STAFF_OPEN_TICKET_THRESHOLD=3 # Min open tickets before alerting
|
||
STAFF_DND_COUNTS_AS_AVAILABLE=false # Whether DND status counts as available
|
||
|
||
# --- Staff threads ---
|
||
STAFF_THREAD_ENABLED=false # Create a private staff thread on each ticket channel
|
||
STAFF_THREAD_NAME=Staff Discussion # Name of the private thread
|
||
STAFF_THREAD_AUTO_ADD_ROLE=false # Auto-add all members of STAFF_THREAD_ROLE_ID to thread on creation
|
||
STAFF_THREAD_ROLE_ID= # Role whose members are added to the thread (defaults to ROLE_ID_TO_PING)
|
||
|
||
# --- Message pinning ---
|
||
PIN_INITIAL_MESSAGE_ENABLED=false # Auto-pin the welcome message on ticket creation
|
||
PIN_ESCALATION_MESSAGE_ENABLED=false # Auto-pin escalation messages
|
||
PIN_SUPPRESS_SYSTEM_MESSAGE=false # Delete the "X pinned a message" system message after pinning
|
||
|
||
# --- Settings site & internal API ---
|
||
SETTINGS_PORT=12752 # Port for the settings web UI
|
||
SETTINGS_ADMIN_PASSWORD= # Password to access the settings UI
|
||
SETTINGS_DOMAIN=tickets.indifferentketchup.com # Domain for the settings site (update when domain changes)
|
||
INTERNAL_API_PORT=12753 # Internal port for bot<->settings IPC (not exposed externally)
|
||
INTERNAL_API_SECRET= # Shared secret between bot and settings site (generate a random string)
|
||
|
||
# --- Thread-style tickets (legacy) ---
|
||
USE_THREADS=false
|
||
THREAD_PARENT_CHANNEL=
|
||
|
||
# --- Game list (comma-separated; used for detection and tags) ---
|
||
GAME_LIST=Project Zomboid, Minecraft, ...
|
||
|
||
# --- Embed colors (hex with 0x prefix) ---
|
||
EMBED_COLOR_OPEN=0x00FF00
|
||
EMBED_COLOR_CLOSED=0xFF0000
|
||
EMBED_COLOR_CLAIMED=0xFFFF00
|
||
EMBED_COLOR_ESCALATED=0xFF6600
|
||
EMBED_COLOR_INFO=0x1e2124
|