audit
This commit is contained in:
90
config.js
90
config.js
@@ -70,6 +70,11 @@ const DEFAULT_NOTIFICATION_THRESHOLDS = {
|
||||
chat_time: ['30m', '1h', '2h', '4h']
|
||||
};
|
||||
|
||||
function toInt(v, fallback) {
|
||||
const n = parseInt(v, 10);
|
||||
return Number.isFinite(n) ? n : fallback;
|
||||
}
|
||||
|
||||
function parseThresholdString(str) {
|
||||
const value = String(str || '').trim();
|
||||
if (!value) return NaN;
|
||||
@@ -136,7 +141,7 @@ const CONFIG = {
|
||||
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,
|
||||
PORT: toInt(process.env.DISCORD_ONLY_PORT, 5000),
|
||||
HEALTHCHECK_HOST: process.env.HEALTHCHECK_HOST || null, // null = listen on all interfaces; set to 127.0.0.1 for local-only
|
||||
SIGNATURE: (process.env.EMAIL_SIGNATURE || '').trim().replace(/\\n/g, '<br>'),
|
||||
GAME_LIST: process.env.GAME_LIST || '',
|
||||
@@ -157,19 +162,19 @@ const CONFIG = {
|
||||
DISCORD_TRANSCRIPT_MESSAGE: process.env.DISCORD_TRANSCRIPT_MESSAGE || 'Your ticket **{channel_name}** has been closed. Here is your transcript. If you still need assistance, please open a new ticket.',
|
||||
DISCORD_AUTO_CLOSE_MESSAGE: process.env.DISCORD_AUTO_CLOSE_MESSAGE || 'This ticket was closed due to inactivity. If you still need assistance, please open a new ticket.',
|
||||
AUTO_CLOSE_ENABLED: process.env.AUTO_CLOSE_ENABLED === 'true',
|
||||
AUTO_CLOSE_AFTER_HOURS: parseInt(process.env.AUTO_CLOSE_AFTER_HOURS) || 72,
|
||||
AUTO_CLOSE_AFTER_HOURS: toInt(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,
|
||||
GLOBAL_TICKET_LIMIT: toInt(process.env.GLOBAL_TICKET_LIMIT, 5),
|
||||
TICKET_LIMIT_PER_CATEGORY: toInt(process.env.TICKET_LIMIT_PER_CATEGORY, 3),
|
||||
RATE_LIMIT_TICKETS_PER_USER: toInt(process.env.RATE_LIMIT_TICKETS_PER_USER, 0),
|
||||
RATE_LIMIT_WINDOW_MINUTES: toInt(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 || "We got your ticket. We'll be with you as soon as possible. Feel free to add any additional information to your ticket.",
|
||||
TICKET_CLAIMED_MESSAGE: process.env.TICKET_CLAIMED_MESSAGE || 'Ticket claimed by {staff_mention} 🚀',
|
||||
TICKET_UNCLAIMED_MESSAGE: process.env.TICKET_UNCLAIMED_MESSAGE || 'Ticket unclaimed by {staff_mention} ☀️',
|
||||
REMINDER_ENABLED: process.env.REMINDER_ENABLED === 'true',
|
||||
REMINDER_AFTER_HOURS: parseInt(process.env.REMINDER_AFTER_HOURS) || 24,
|
||||
REMINDER_AFTER_HOURS: toInt(process.env.REMINDER_AFTER_HOURS, 24),
|
||||
REMINDER_MESSAGE: process.env.REMINDER_MESSAGE || 'Hey {ping}! 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',
|
||||
@@ -177,9 +182,9 @@ const CONFIG = {
|
||||
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,
|
||||
CLAIM_TIMEOUT_HOURS: toInt(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,
|
||||
AUTO_UNCLAIM_AFTER_HOURS: toInt(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,
|
||||
@@ -189,11 +194,11 @@ const CONFIG = {
|
||||
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,
|
||||
EMBED_COLOR_OPEN: toInt(process.env.EMBED_COLOR_OPEN, 0x00FF00),
|
||||
EMBED_COLOR_CLOSED: toInt(process.env.EMBED_COLOR_CLOSED, 0xFF0000),
|
||||
EMBED_COLOR_CLAIMED: toInt(process.env.EMBED_COLOR_CLAIMED, 0xFFFF00),
|
||||
EMBED_COLOR_ESCALATED: toInt(process.env.EMBED_COLOR_ESCALATED, 0xFF6600),
|
||||
EMBED_COLOR_INFO: toInt(process.env.EMBED_COLOR_INFO, 0x1e2124),
|
||||
STAFF_CATEGORIES: new Map(), // deprecated – kept for staffChannel.js compat
|
||||
STAFF_EMOJIS: (() => {
|
||||
const raw = process.env.STAFF_EMOJIS;
|
||||
@@ -213,8 +218,8 @@ const CONFIG = {
|
||||
CLAIMER_EMOJI_FALLBACK: process.env.CLAIMER_EMOJI_FALLBACK || '🎫',
|
||||
ADMIN_ID: process.env.ADMIN_ID || null,
|
||||
STAFF_NOTIFICATION_CATEGORY_ID: process.env.STAFF_NOTIFICATION_CATEGORY_ID || null,
|
||||
FORCE_CLOSE_TIMER: parseInt(process.env.FORCE_CLOSE_TIMER_SECONDS) || 60,
|
||||
GMAIL_POLL_INTERVAL_MS: parseInt(process.env.GMAIL_POLL_INTERVAL_SECONDS || '30') * 1000,
|
||||
FORCE_CLOSE_TIMER: toInt(process.env.FORCE_CLOSE_TIMER_SECONDS, 60),
|
||||
GMAIL_POLL_INTERVAL_MS: toInt(process.env.GMAIL_POLL_INTERVAL_SECONDS, 30) * 1000,
|
||||
GMAIL_LOG_CHANNEL_ID: process.env.GMAIL_LOG_CHANNEL_ID || null,
|
||||
AUTOMATION_LOG_CHANNEL_ID: process.env.AUTOMATION_LOG_CHANNEL_ID || null,
|
||||
RENAME_LOG_CHANNEL_ID: process.env.RENAME_LOG_CHANNEL_ID || null,
|
||||
@@ -226,35 +231,35 @@ const CONFIG = {
|
||||
ESCALATION_PATTERNS_CHANNEL_ID: process.env.ESCALATION_PATTERNS_CHANNEL_ID || null,
|
||||
STAFF_PATTERNS_CHANNEL_ID: process.env.STAFF_PATTERNS_CHANNEL_ID || null,
|
||||
COMBINED_PATTERNS_CHANNEL_ID: process.env.COMBINED_PATTERNS_CHANNEL_ID || null,
|
||||
PATTERN_USER_TICKET_THRESHOLD: parseInt(process.env.PATTERN_USER_TICKET_THRESHOLD) || 3,
|
||||
PATTERN_GAME_TICKET_THRESHOLD: parseInt(process.env.PATTERN_GAME_TICKET_THRESHOLD) || 10,
|
||||
PATTERN_STAFF_STALE_PING_THRESHOLD: parseInt(process.env.PATTERN_STAFF_STALE_PING_THRESHOLD) || 5,
|
||||
PATTERN_ESCALATION_THRESHOLD: parseInt(process.env.PATTERN_ESCALATION_THRESHOLD) || 3,
|
||||
PATTERN_RAPID_CLOSE_SECONDS: parseInt(process.env.PATTERN_RAPID_CLOSE_SECONDS) || 120,
|
||||
PATTERN_UNCLAIMED_HOURS: parseInt(process.env.PATTERN_UNCLAIMED_HOURS) || 4,
|
||||
PATTERN_CHECK_INTERVAL_MINUTES: parseInt(process.env.PATTERN_CHECK_INTERVAL_MINUTES) || 30,
|
||||
PATTERN_USER_TICKET_THRESHOLD: toInt(process.env.PATTERN_USER_TICKET_THRESHOLD, 3),
|
||||
PATTERN_GAME_TICKET_THRESHOLD: toInt(process.env.PATTERN_GAME_TICKET_THRESHOLD, 10),
|
||||
PATTERN_STAFF_STALE_PING_THRESHOLD: toInt(process.env.PATTERN_STAFF_STALE_PING_THRESHOLD, 5),
|
||||
PATTERN_ESCALATION_THRESHOLD: toInt(process.env.PATTERN_ESCALATION_THRESHOLD, 3),
|
||||
PATTERN_RAPID_CLOSE_SECONDS: toInt(process.env.PATTERN_RAPID_CLOSE_SECONDS, 120),
|
||||
PATTERN_UNCLAIMED_HOURS: toInt(process.env.PATTERN_UNCLAIMED_HOURS, 4),
|
||||
PATTERN_CHECK_INTERVAL_MINUTES: toInt(process.env.PATTERN_CHECK_INTERVAL_MINUTES, 30),
|
||||
ALL_STAFF_CHANNEL_ID: process.env.ALL_STAFF_CHANNEL_ID || null,
|
||||
ALL_STAFF_CHAT_ALERT_CHANNEL_ID: process.env.ALL_STAFF_CHAT_ALERT_CHANNEL_ID || null,
|
||||
SURGE_ROLE_ID: process.env.SURGE_ROLE_ID || null,
|
||||
SURGE_TICKET_COUNT: parseInt(process.env.SURGE_TICKET_COUNT) || 10,
|
||||
SURGE_TICKET_WINDOW_MINUTES: parseInt(process.env.SURGE_TICKET_WINDOW_MINUTES) || 30,
|
||||
SURGE_GAME_TICKET_COUNT: parseInt(process.env.SURGE_GAME_TICKET_COUNT) || 5,
|
||||
SURGE_GAME_TICKET_WINDOW_MINUTES: parseInt(process.env.SURGE_GAME_TICKET_WINDOW_MINUTES) || 30,
|
||||
SURGE_STALE_COUNT: parseInt(process.env.SURGE_STALE_COUNT) || 8,
|
||||
SURGE_STALE_HOURS: parseInt(process.env.SURGE_STALE_HOURS) || 2,
|
||||
SURGE_NEEDS_RESPONSE_COUNT: parseInt(process.env.SURGE_NEEDS_RESPONSE_COUNT) || 5,
|
||||
SURGE_NEEDS_RESPONSE_HOURS: parseInt(process.env.SURGE_NEEDS_RESPONSE_HOURS) || 1,
|
||||
SURGE_UNCLAIMED_COUNT: parseInt(process.env.SURGE_UNCLAIMED_COUNT) || 5,
|
||||
SURGE_UNCLAIMED_MINUTES: parseInt(process.env.SURGE_UNCLAIMED_MINUTES) || 30,
|
||||
SURGE_TIER3_UNCLAIMED_MINUTES: parseInt(process.env.SURGE_TIER3_UNCLAIMED_MINUTES) || 15,
|
||||
SURGE_COOLDOWN_MINUTES: parseInt(process.env.SURGE_COOLDOWN_MINUTES) || 60,
|
||||
SURGE_TICKET_COUNT: toInt(process.env.SURGE_TICKET_COUNT, 10),
|
||||
SURGE_TICKET_WINDOW_MINUTES: toInt(process.env.SURGE_TICKET_WINDOW_MINUTES, 30),
|
||||
SURGE_GAME_TICKET_COUNT: toInt(process.env.SURGE_GAME_TICKET_COUNT, 5),
|
||||
SURGE_GAME_TICKET_WINDOW_MINUTES: toInt(process.env.SURGE_GAME_TICKET_WINDOW_MINUTES, 30),
|
||||
SURGE_STALE_COUNT: toInt(process.env.SURGE_STALE_COUNT, 8),
|
||||
SURGE_STALE_HOURS: toInt(process.env.SURGE_STALE_HOURS, 2),
|
||||
SURGE_NEEDS_RESPONSE_COUNT: toInt(process.env.SURGE_NEEDS_RESPONSE_COUNT, 5),
|
||||
SURGE_NEEDS_RESPONSE_HOURS: toInt(process.env.SURGE_NEEDS_RESPONSE_HOURS, 1),
|
||||
SURGE_UNCLAIMED_COUNT: toInt(process.env.SURGE_UNCLAIMED_COUNT, 5),
|
||||
SURGE_UNCLAIMED_MINUTES: toInt(process.env.SURGE_UNCLAIMED_MINUTES, 30),
|
||||
SURGE_TIER3_UNCLAIMED_MINUTES: toInt(process.env.SURGE_TIER3_UNCLAIMED_MINUTES, 15),
|
||||
SURGE_COOLDOWN_MINUTES: toInt(process.env.SURGE_COOLDOWN_MINUTES, 60),
|
||||
CHAT_ALERT_CHANNEL_IDS: (process.env.CHAT_ALERT_CHANNEL_IDS || '').split(',').filter(Boolean),
|
||||
CHAT_ALERT_MESSAGE_COUNT: parseInt(process.env.CHAT_ALERT_MESSAGE_COUNT) || 5,
|
||||
CHAT_ALERT_HOURS_WITHOUT_RESPONSE: parseInt(process.env.CHAT_ALERT_HOURS_WITHOUT_RESPONSE) || 2,
|
||||
CHAT_ALERT_COOLDOWN_MINUTES: parseInt(process.env.CHAT_ALERT_COOLDOWN_MINUTES) || 60,
|
||||
CHAT_ALERT_MESSAGE_COUNT: toInt(process.env.CHAT_ALERT_MESSAGE_COUNT, 5),
|
||||
CHAT_ALERT_HOURS_WITHOUT_RESPONSE: toInt(process.env.CHAT_ALERT_HOURS_WITHOUT_RESPONSE, 2),
|
||||
CHAT_ALERT_COOLDOWN_MINUTES: toInt(process.env.CHAT_ALERT_COOLDOWN_MINUTES, 60),
|
||||
STAFF_IDS: (process.env.STAFF_IDS || '').split(',').map(s => s.trim()).filter(Boolean),
|
||||
SURGE_NO_STAFF_COOLDOWN_MINUTES: parseInt(process.env.SURGE_NO_STAFF_COOLDOWN_MINUTES) || 30,
|
||||
SURGE_NO_STAFF_OPEN_TICKET_THRESHOLD: parseInt(process.env.SURGE_NO_STAFF_OPEN_TICKET_THRESHOLD) || 3,
|
||||
SURGE_NO_STAFF_COOLDOWN_MINUTES: toInt(process.env.SURGE_NO_STAFF_COOLDOWN_MINUTES, 30),
|
||||
SURGE_NO_STAFF_OPEN_TICKET_THRESHOLD: toInt(process.env.SURGE_NO_STAFF_OPEN_TICKET_THRESHOLD, 3),
|
||||
STAFF_DND_COUNTS_AS_AVAILABLE: process.env.STAFF_DND_COUNTS_AS_AVAILABLE === 'true',
|
||||
STAFF_THREAD_ENABLED: process.env.STAFF_THREAD_ENABLED === 'true',
|
||||
STAFF_THREAD_NAME: process.env.STAFF_THREAD_NAME || 'Staff Discussion',
|
||||
@@ -262,11 +267,12 @@ const CONFIG = {
|
||||
STAFF_THREAD_ROLE_ID: process.env.STAFF_THREAD_ROLE_ID || process.env.ROLE_ID_TO_PING || null,
|
||||
PIN_INITIAL_MESSAGE_ENABLED: process.env.PIN_INITIAL_MESSAGE_ENABLED === 'true',
|
||||
PIN_ESCALATION_MESSAGE_ENABLED: process.env.PIN_ESCALATION_MESSAGE_ENABLED === 'true',
|
||||
TRANSCRIPT_DM_TO_CREATOR: process.env.TRANSCRIPT_DM_TO_CREATOR === 'true',
|
||||
PIN_SUPPRESS_SYSTEM_MESSAGE: process.env.PIN_SUPPRESS_SYSTEM_MESSAGE === 'true',
|
||||
SETTINGS_PORT: parseInt(process.env.SETTINGS_PORT) || 12752,
|
||||
SETTINGS_PORT: toInt(process.env.SETTINGS_PORT, 12752),
|
||||
SETTINGS_ADMIN_PASSWORD: process.env.SETTINGS_ADMIN_PASSWORD || null,
|
||||
SETTINGS_DOMAIN: process.env.SETTINGS_DOMAIN || 'tickets.indifferentketchup.com',
|
||||
INTERNAL_API_PORT: parseInt(process.env.INTERNAL_API_PORT) || 12753,
|
||||
INTERNAL_API_PORT: toInt(process.env.INTERNAL_API_PORT, 12753),
|
||||
INTERNAL_API_SECRET: process.env.INTERNAL_API_SECRET || null,
|
||||
NOTIFICATION_THRESHOLDS: parseNotificationThresholdsJson(process.env.NOTIFICATION_THRESHOLDS_JSON),
|
||||
UNCLAIMED_REMINDER_THRESHOLDS: (process.env.UNCLAIMED_REMINDER_THRESHOLDS || '1,2,4')
|
||||
|
||||
Reference in New Issue
Block a user