import { Telegraf } from "telegraf"; import { telegrafBots } from "../models"; import { setupCommandHandlers } from "./handlers/commandHandlers"; import { setupCallbackHandlers } from "./handlers/index"; import { BotContext } from "./types/botTypes"; import { supabase } from "../db/supabase"; import { createLogger } from "../utils/logger"; import { messageManager } from "./utils/messageManager"; import { handleLanguageSelection, handleLanguageChange } from "./handlers/languageHandlers"; import { getBotIdFromToken, saveBotTokenMapping, isValidBotToken } from "../utils/botUtils"; import { groupCheckMiddleware } from "./middleware/groupCheckMiddleware"; // import { balanceUpdateService } from "./services/BalanceUpdateService"; const logger = createLogger('BotManager'); export const BotCommands: { command: string; description: string }[] = [ { command: 'start', description: 'بدء البوت' }, { command: 'help', description: 'يعرض قائمة المساعدة' }, { command: 'about', description: 'معلومات عن البوت' }, { command: 'contact', description: 'تواصل معنا' }, { command: 'balance', description: 'رصيدي' }, { command: 'change_language', description: 'تغيير اللغة / Change language' }, ]; // Add this interface to match your database schema export interface BotData { id: string; name: string; user_id: string; bot_token: string; is_active: boolean; currency: string; profit_type: 'fix' | 'percentage'; profit_value_percentage: number; profit_value_fix: number; last_activity: string | null; version: string; // API Keys and External Service Configuration fivesim_api_key: string; paypal_client_id: string; paypal_client_secret: string; crypto_wallet_address: string; admin_contact: string; // Group Join Settings join_group_required: boolean; group_channel_username: string; settings: Record; state: Record; suffix_email: string; created_at: string; updated_at: string; } // Update the initializeBot function to use our utilities export const initializeBot = async (botToken: string, botData?: BotData) => { try { // Validate bot token if (!isValidBotToken(botToken)) { throw new Error('Invalid bot token format'); } const bot = new Telegraf(botToken); // Extract and save bot ID mapping const botId = getBotIdFromToken(botToken); saveBotTokenMapping(botToken, botId); // Set bot ID and load messages await messageManager.loadMessages(); // Set language based on bot settings or default to Arabic messageManager.setLanguage(botData?.settings?.language || 'en'); // Add bot data to context for use in handlers bot.context.botData = botData || null; // Setup middleware to track activity bot.use(async (ctx, next) => { if (botData?.id) { // Update last_activity in database await supabase .from('bots') .update({ last_activity: new Date().toISOString() }) .eq('id', botData.id); } return next(); }); // Add group check middleware bot.use(groupCheckMiddleware); // Setup command handlers setupCommandHandlers(bot); // Setup callback handlers setupCallbackHandlers(bot); // Initialize balance update service and ensure it's properly set up try { // balanceUpdateService.setBot(bot); logger.info('Balance update service initialized successfully'); } catch (error: any) { logger.error(`Failed to initialize balance update service: ${error.message}`); // Continue initialization even if balance service fails } // Set bot commands try { await bot.telegram.setMyCommands(BotCommands, { scope: { type: 'default' } }); logger.info('Bot commands set successfully'); } catch (error: any) { logger.error(`Failed to set bot commands: ${error.message}`); // Continue initialization even if setting commands fails } return { success: true, message: botData?.name ? `Bot "${botData.name}" initialized successfully` : "Bot initialized successfully", bot }; } catch (error: any) { logger.error(`Failed to initialize bot: ${error.message}`); return { success: false, message: `Failed to initialize bot: ${error.message}` }; } }; // Utility function to update bot status in database const updateBotStatus = async (botId: string, isActive: boolean, error?: string) => { try { await supabase .from('bots') .update({ is_active: isActive, last_activity: new Date().toISOString(), state: { status: isActive ? 'running' : 'error', startedAt: isActive ? new Date().toISOString() : undefined, error: error } }) .eq('id', botId); } catch (error: any) { logger.error(`Error updating bot status: ${error.message}`); } }; export const stopBot = async (botId: string) => { try { // Get bot token from database const { data: botData, error } = await supabase .from('bots') .select('bot_token') .eq('id', botId) .single(); if (error || !botData) { await updateBotStatus(botId, false, "Bot not found in database"); return { success: false, message: "Bot not found in database" }; } const botToken = botData.bot_token; const bot = telegrafBots.get(botToken); if (bot) { await bot.stop(); telegrafBots.delete(botToken); // Update database await updateBotStatus(botId, false); return { success: true, message: "Bot stopped successfully" }; } // Bot instance not found await updateBotStatus(botId, false, "Bot instance not found"); return { success: false, message: "Bot instance not found" }; } catch (error: any) { logger.error(`Error stopping bot: ${error.message}`); await updateBotStatus(botId, false, error.message); return { success: false, message: `Failed to stop bot: ${error.message}` }; } }; // New function to update bot settings export const updateBotSettings = async (botId: string, settings: Record) => { try { // Get bot data from database const { data: botData, error } = await supabase .from('bots') .select('bot_token, settings') .eq('id', botId) .single(); if (error || !botData) { return { success: false, message: "Bot not found in database" }; } // Merge existing settings with new ones const updatedSettings = { ...(botData.settings || {}), ...settings }; // Update database await supabase .from('bots') .update({ settings: updatedSettings, updated_at: new Date().toISOString() }) .eq('id', botId); // Update running bot if it exists const bot = telegrafBots.get(botData.bot_token); if (bot && bot.context) { bot.context.botData = { ...(bot.context.botData || {}), settings: updatedSettings }; } return { success: true, message: "Bot settings updated successfully" }; } catch (error: any) { logger.error(`Error updating bot settings: ${error.message}`); return { success: false, message: `Failed to update bot settings: ${error.message}` }; } };