const winston = require('winston'); const { createClient } = require('@supabase/supabase-js'); const Bot = require('./src/Bot'); const packageInfo = require('./package.json'); require('dotenv').config(); // Initialize logger const logger = winston.createLogger({ level: 'debug', format: winston.format.combine( winston.format.timestamp(), winston.format.json() ), transports: [ new winston.transports.Console({ format: winston.format.combine( winston.format.colorize(), winston.format.simple() ) }) ] }); // Display startup banner with version info logger.info('๐Ÿค– ===== VRBattles Discord Bot Starting ===== ๐Ÿค–'); logger.info(`๐Ÿ“ฆ Version: ${packageInfo.version}`); logger.info(`๐Ÿ“ Name: ${packageInfo.name}`); logger.info(`๐Ÿ“… Started: ${new Date().toISOString()}`); logger.info(`๐ŸŒ Environment: ${process.env.NODE_ENV || 'development'}`); logger.info(`๐Ÿง Platform: ${process.platform} ${process.arch}`); logger.info(`โšก Node.js: ${process.version}`); // Check required environment variables const requiredEnvVars = ['DISCORD_TOKEN', 'SUPABASE_URL', 'SUPABASE_KEY']; const missingEnvVars = requiredEnvVars.filter(varName => !process.env[varName]); if (missingEnvVars.length > 0) { logger.error(`โŒ Missing required environment variables: ${missingEnvVars.join(', ')}`); process.exit(1); } logger.info('โœ… Environment variables validated'); // Initialize Supabase client logger.info('๐Ÿ”— Initializing Supabase connection...'); const supabase = createClient( process.env.SUPABASE_URL, process.env.SUPABASE_KEY ); // Initialize bot variable at module level let bot = null; // Initialize and start bot async function startBot() { try { // Test Supabase connection logger.info('๐Ÿงช Testing Supabase connection...'); // Test 1: Read access to games table const { data: games, error } = await supabase .from('games') .select('id, name, active') .eq('active', true) .limit(3); if (error) { logger.error('โŒ Supabase read test failed:', { message: error.message, details: error.details, hint: error.hint, code: error.code }); process.exit(1); } logger.info(`โœ… Supabase read access OK - Found ${games.length} active games`); logger.info(`๐Ÿ“‹ Sample games: ${games.map(g => g.name).join(', ')}`); // Test 2: Write access to servers table (dry run) logger.info('๐Ÿงช Testing database write permissions...'); const testGuildId = 'test_connection_' + Date.now(); try { // Try to insert a test record const { data: testServer, error: insertError } = await supabase .from('servers') .insert([{ discord_server_id: testGuildId, server_name: 'Connection Test Server', active: false // Mark as inactive so it doesn't interfere }]) .select() .single(); if (insertError) { logger.error('โŒ Database write test failed:', { message: insertError.message, details: error.details, hint: insertError.hint, code: insertError.code }); logger.error('๐Ÿ’ก This suggests a database permissions issue. Check row-level security policies.'); process.exit(1); } // Clean up test record if (testServer?.id) { await supabase .from('servers') .delete() .eq('id', testServer.id); } logger.info('โœ… Database write access OK'); } catch (writeError) { logger.error('โŒ Database write test exception:', { message: writeError.message, stack: writeError.stack }); process.exit(1); } // Initialize and start bot logger.info('๐Ÿš€ Starting Discord bot...'); bot = new Bot(process.env.DISCORD_TOKEN, supabase, logger); await bot.start(); return bot; } catch (error) { logger.error('โŒ Failed to start bot:', { message: error.message, stack: error.stack, name: error.name }); process.exit(1); } } startBot(); // Handle process termination process.on('SIGINT', async () => { logger.info('๐Ÿ“ฅ Received SIGINT. Shutting down gracefully...'); try { if (bot) { await bot.stop(); } logger.info('โœ… Bot shutdown completed'); process.exit(0); } catch (error) { logger.error('โŒ Error during shutdown:', { message: error.message, stack: error.stack }); process.exit(1); } }); process.on('SIGTERM', async () => { logger.info('๐Ÿ“ฅ Received SIGTERM. Shutting down gracefully...'); try { if (bot) { await bot.stop(); } logger.info('โœ… Bot shutdown completed'); process.exit(0); } catch (error) { logger.error('โŒ Error during shutdown:', { message: error.message, stack: error.stack }); process.exit(1); } });