Files
broccolini-bot/config.js
root 519788c633 Initial commit
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-10 08:22:19 -06:00

169 lines
8.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Bridge configuration and game lists.
* Load dotenv so env is available when this module is required first.
* dotenv-expand resolves ${NGROK_URL} etc. in .env.
*/
const dotenv = require('dotenv');
const dotenvExpand = require('dotenv-expand');
dotenvExpand.expand(dotenv.config({ debug: true }));
const ZAMMAD = {
URL: process.env.ZAMMAD_URL,
TOKEN: process.env.ZAMMAD_TOKEN,
EMAIL_GROUP: process.env.ZAMMAD_EMAIL_GROUP || 'Email Users',
DISCORD_GROUP: process.env.ZAMMAD_DISCORD_GROUP || 'Discord Users'
};
const CONFIG = {
DISCORD_TOKEN: process.env.DISCORD_TOKEN,
DISCORD_GUILD_ID: process.env.DISCORD_GUILD_ID || null,
TICKET_CATEGORY_ID: process.env.TICKET_CATEGORY_ID,
EMAIL_TICKET_OVERFLOW_CATEGORY_IDS: (process.env.EMAIL_TICKET_OVERFLOW_CATEGORY_IDS || '')
.split(',')
.map(s => s.trim())
.filter(Boolean),
DISCORD_TICKET_CATEGORY_ID: process.env.DISCORD_TICKET_CATEGORY_ID || process.env.TICKET_CATEGORY_ID,
DISCORD_TICKET_OVERFLOW_CATEGORY_IDS: (process.env.DISCORD_TICKET_OVERFLOW_CATEGORY_IDS || '')
.split(',')
.map(s => s.trim())
.filter(Boolean),
ROLE_ID_TO_PING: process.env.ROLE_ID_TO_PING,
ROLE_TO_PING_ID: process.env.ROLE_ID_TO_PING || process.env.ROLE_TO_PING_ID,
TRANSCRIPT_CHAN: process.env.TRANSCRIPT_CHANNEL_ID,
LOG_CHAN: process.env.LOGGING_CHANNEL_ID,
DEBUGGING_CHANNEL_ID: process.env.DEBUGGING_CHANNEL_ID || null,
BACKUP_EXPORT_CHANNEL_ID: process.env.BACKUP_EXPORT_CHANNEL_ID || null,
ACCOUNT_INFO_CHANNEL_ID: process.env.ACCOUNT_INFO_CHANNEL_ID || null,
CLIENT_ID: process.env.DISCORD_APPLICATION_ID,
CLIENT_SECRET: process.env.GOOGLE_CLIENT_SECRET,
REFRESH_TOKEN: process.env.REFRESH_TOKEN,
MY_EMAIL: (process.env.MY_EMAIL || '').toLowerCase(),
LOGO_URL: process.env.LOGO_URL,
SUPPORT_NAME: process.env.SUPPORT_NAME || 'Support',
PORT: process.env.DISCORD_ONLY_PORT || 5000,
SIGNATURE: (process.env.EMAIL_SIGNATURE || '').trim().replace(/\\n/g, '<br>'),
GAME_LIST: process.env.GAME_LIST || '',
DISCORD_THREAD_CHANNEL_ID: process.env.DISCORD_THREAD_CHANNEL_ID || null,
EMAIL_THREAD_CHANNEL_ID: process.env.EMAIL_THREAD_CHANNEL_ID || null,
EMAIL_ESCALATED_CATEGORY_ID: process.env.EMAIL_ESCALATED_CATEGORY_ID || process.env.ESCALATED_CATEGORY_ID,
DISCORD_ESCALATED_CATEGORY_ID: process.env.DISCORD_ESCALATED_CATEGORY_ID,
EMAIL_ESCALATED2_CHANNEL_ID: process.env.EMAIL_ESCALATED2_CHANNEL_ID || null,
DISCORD_ESCALATED2_CHANNEL_ID: process.env.DISCORD_ESCALATED2_CHANNEL_ID || null,
EMAIL_ESCALATED3_CHANNEL_ID: process.env.EMAIL_ESCALATED3_CHANNEL_ID || null,
DISCORD_ESCALATED3_CHANNEL_ID: process.env.DISCORD_ESCALATED3_CHANNEL_ID || null,
ESCALATION_MESSAGE: process.env.ESCALATION_MESSAGE || 'This email ticket has been escalated.',
TICKET_CLOSE_SUBJECT_PREFIX: process.env.TICKET_CLOSE_SUBJECT_PREFIX || '[Resolved]',
TICKET_CLOSE_MESSAGE: process.env.TICKET_CLOSE_MESSAGE || 'This ticket has been marked as resolved. If you would like to re-open this issue, please reply to this email.',
TICKET_CLOSE_SIGNATURE: process.env.TICKET_CLOSE_SIGNATURE || 'Thank you for using Indifferent Broccoli.',
AUTO_CLOSE_ENABLED: process.env.AUTO_CLOSE_ENABLED === 'true',
AUTO_CLOSE_AFTER_HOURS: parseInt(process.env.AUTO_CLOSE_AFTER_HOURS) || 72,
AUTO_CLOSE_MESSAGE: process.env.AUTO_CLOSE_MESSAGE || 'This ticket has been automatically closed due to inactivity.',
GLOBAL_TICKET_LIMIT: parseInt(process.env.GLOBAL_TICKET_LIMIT) || 5,
TICKET_LIMIT_PER_CATEGORY: parseInt(process.env.TICKET_LIMIT_PER_CATEGORY) || 3,
RATE_LIMIT_TICKETS_PER_USER: parseInt(process.env.RATE_LIMIT_TICKETS_PER_USER) || 0,
RATE_LIMIT_WINDOW_MINUTES: parseInt(process.env.RATE_LIMIT_WINDOW_MINUTES) || 60,
BLACKLISTED_ROLES: (process.env.BLACKLISTED_ROLES || '').split(',').map(r => r.trim()).filter(Boolean),
ADDITIONAL_STAFF_ROLES: (process.env.ADDITIONAL_STAFF_ROLES || '').split(',').map(r => r.trim()).filter(Boolean),
TICKET_WELCOME_MESSAGE: process.env.TICKET_WELCOME_MESSAGE || 'Thank you for contacting support! A team member will assist you shortly.',
TICKET_CLAIMED_MESSAGE: process.env.TICKET_CLAIMED_MESSAGE || 'This ticket has been claimed by {staff_name}.',
TICKET_UNCLAIMED_MESSAGE: process.env.TICKET_UNCLAIMED_MESSAGE || 'This ticket is now available for any staff member.',
REMINDER_ENABLED: process.env.REMINDER_ENABLED === 'true',
REMINDER_AFTER_HOURS: parseInt(process.env.REMINDER_AFTER_HOURS) || 24,
REMINDER_MESSAGE: process.env.REMINDER_MESSAGE || 'This ticket has been inactive for {hours} hours. Please provide an update or close the ticket.',
PRIORITY_ENABLED: process.env.PRIORITY_ENABLED === 'true',
DEFAULT_PRIORITY: process.env.DEFAULT_PRIORITY || 'normal',
PRIORITY_HIGH_EMOJI: process.env.PRIORITY_HIGH_EMOJI || '🔴',
PRIORITY_MEDIUM_EMOJI: process.env.PRIORITY_MEDIUM_EMOJI || '🟡',
PRIORITY_LOW_EMOJI: process.env.PRIORITY_LOW_EMOJI || '🟢',
CLAIM_TIMEOUT_ENABLED: process.env.CLAIM_TIMEOUT_ENABLED === 'true',
CLAIM_TIMEOUT_HOURS: parseInt(process.env.CLAIM_TIMEOUT_HOURS) || 48,
AUTO_UNCLAIM_ENABLED: process.env.AUTO_UNCLAIM_ENABLED === 'true',
AUTO_UNCLAIM_AFTER_HOURS: parseInt(process.env.AUTO_UNCLAIM_AFTER_HOURS) || 24,
ALLOW_CLAIM_OVERWRITE: process.env.ALLOW_CLAIM_OVERWRITE === 'true',
USE_THREADS: process.env.USE_THREADS === 'true',
THREAD_PARENT_CHANNEL: process.env.THREAD_PARENT_CHANNEL || process.env.EMAIL_THREAD_CHANNEL_ID || null,
BUTTON_LABEL_CLOSE: process.env.BUTTON_LABEL_CLOSE || 'Close Ticket',
BUTTON_LABEL_CLAIM: process.env.BUTTON_LABEL_CLAIM || 'Claim',
BUTTON_LABEL_UNCLAIM: process.env.BUTTON_LABEL_UNCLAIM || 'Unclaim',
BUTTON_EMOJI_CLOSE: process.env.BUTTON_EMOJI_CLOSE || '🔒',
BUTTON_EMOJI_CLAIM: process.env.BUTTON_EMOJI_CLAIM || '📌',
BUTTON_EMOJI_UNCLAIM: process.env.BUTTON_EMOJI_UNCLAIM || '🔓',
EMBED_COLOR_OPEN: parseInt(process.env.EMBED_COLOR_OPEN) || 0x00FF00,
EMBED_COLOR_CLOSED: parseInt(process.env.EMBED_COLOR_CLOSED) || 0xFF0000,
EMBED_COLOR_CLAIMED: parseInt(process.env.EMBED_COLOR_CLAIMED) || 0xFFFF00,
EMBED_COLOR_ESCALATED: parseInt(process.env.EMBED_COLOR_ESCALATED) || 0xFF6600,
EMBED_COLOR_INFO: parseInt(process.env.EMBED_COLOR_INFO) || 0x1e2124
};
/** Ticket category tags for /tag set [emoji] [label] in dropdown; priority emoji always first in channel name, then tag emoji. */
const TICKET_TAGS = [
{ value: 'server-down', emoji: '⬇️', name: 'Server Down' },
{ value: 'stuck-restarting', emoji: '⏳', name: 'Stuck Restarting' },
{ value: 'cant-connect', emoji: '📵', name: "Can't Connect" },
{ value: 'server-lag', emoji: '🐌', name: 'Server Lag' },
{ value: 'billing', emoji: '💳', name: 'Billing' },
{ value: 'refund-request', emoji: '💸', name: 'Refund Request' },
{ value: 'mod-help', emoji: '🔧', name: 'Mod Help' },
{ value: 'backup-restore', emoji: '💾', name: 'Backup Restore' },
{ value: 'world-save', emoji: '🌍', name: 'World / Save' },
{ value: 'server-config', emoji: '⚙️', name: 'Server Config' }
];
const GAME_NAMES = (CONFIG.GAME_LIST || '')
.split(',')
.map(g => g.trim())
.filter(Boolean);
const GAME_ALIASES = {
'7D2D': '7 Days to Die',
'7 days': '7 Days to Die',
PZ: 'Project Zomboid',
zomboid: 'Project Zomboid',
MC: 'Minecraft',
Ark: 'ARK: Survival Evolved',
SOTF: 'Sons of the Forest',
CS2: 'Counter-Strike 2'
};
const GAME_NAME_TO_KEY = {
'Project Zomboid': 'project_zomboid',
'Satisfactory': 'satisfactory',
'Palworld': 'palworld',
'Minecraft': 'minecraft',
'Valheim': 'valheim',
'Enshrouded': 'enshrouded',
'7 Days to Die': '7_days_to_die',
'Hytale': 'hytale',
'ICARUS': 'icarus',
'Abiotic Factor': 'abiotic_factor',
'ARK: Survival Evolved': 'ark_survival_evolved',
'Conan Exiles': 'conan_exiles',
'Core Keeper': 'core_keeper',
'Counter-Strike 2': 'counter_strike_2',
'DayZ': 'dayz',
'ECO': 'eco',
'Factorio': 'factorio',
'FiveM': 'fivem',
'The Front': 'the_front',
"Garry's Mod": 'garrys_mod',
'Necesse': 'necesse',
'Rust': 'rust',
'Sons of the Forest': 'sons_of_the_forest',
'Soulmask': 'soulmask',
'Star Rupture': 'star_rupture',
'Terraria': 'terraria',
'VEIN': 'vein',
'Vintage Story': 'vintage_story',
'Voyagers of Nera': 'voyagers_of_nera',
'V Rising': 'v_rising'
};
module.exports = {
CONFIG,
ZAMMAD,
TICKET_TAGS,
GAME_NAMES,
GAME_ALIASES,
GAME_NAME_TO_KEY
};