# ============================================================================= # 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://broccoli_bot:CHANGE_ME@localhost:27017/broccoli_db?authSource=broccoli_db) # 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 TRANSCRIPT_DM_TO_CREATOR=false # DM the transcript file to the ticket creator on close (Discord-origin tickets only) # --- 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