Add help system, deployment docs, and improve setup
Introduces a new interactive help command with button navigation, adds a detailed DEPLOYMENT.md guide, and improves server setup validation and error handling. Updates command registration to include all 9 games, adds version reporting, enhances Docker deployment with a multi-platform script, and removes local .env files from the repo. Also refactors bot startup for better diagnostics and graceful shutdown.
This commit is contained in:
140
index.js
140
index.js
@@ -1,6 +1,7 @@
|
||||
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
|
||||
@@ -20,38 +21,155 @@ const logger = winston.createLogger({
|
||||
]
|
||||
});
|
||||
|
||||
// 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
|
||||
const bot = new Bot(process.env.DISCORD_TOKEN, supabase, logger);
|
||||
bot.start().catch(error => {
|
||||
console.error('Failed to start bot:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
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 () => {
|
||||
console.log('Received SIGINT. Shutting down...');
|
||||
logger.info('📥 Received SIGINT. Shutting down gracefully...');
|
||||
try {
|
||||
await bot.stop();
|
||||
if (bot) {
|
||||
await bot.stop();
|
||||
}
|
||||
logger.info('✅ Bot shutdown completed');
|
||||
process.exit(0);
|
||||
} catch (error) {
|
||||
console.error('Error during shutdown:', error);
|
||||
logger.error('❌ Error during shutdown:', {
|
||||
message: error.message,
|
||||
stack: error.stack
|
||||
});
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
|
||||
process.on('SIGTERM', async () => {
|
||||
console.log('Received SIGTERM. Shutting down...');
|
||||
logger.info('📥 Received SIGTERM. Shutting down gracefully...');
|
||||
try {
|
||||
await bot.stop();
|
||||
if (bot) {
|
||||
await bot.stop();
|
||||
}
|
||||
logger.info('✅ Bot shutdown completed');
|
||||
process.exit(0);
|
||||
} catch (error) {
|
||||
console.error('Error during shutdown:', error);
|
||||
logger.error('❌ Error during shutdown:', {
|
||||
message: error.message,
|
||||
stack: error.stack
|
||||
});
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user