|
|
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"; |
|
|
|
|
|
|
|
|
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' }, |
|
|
]; |
|
|
|
|
|
|
|
|
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; |
|
|
|
|
|
|
|
|
fivesim_api_key: string; |
|
|
paypal_client_id: string; |
|
|
paypal_client_secret: string; |
|
|
crypto_wallet_address: string; |
|
|
admin_contact: string; |
|
|
|
|
|
|
|
|
join_group_required: boolean; |
|
|
group_channel_username: string; |
|
|
|
|
|
settings: Record<string, any>; |
|
|
state: Record<string, any>; |
|
|
suffix_email: string; |
|
|
created_at: string; |
|
|
updated_at: string; |
|
|
} |
|
|
|
|
|
|
|
|
export const initializeBot = async (botToken: string, botData?: BotData) => { |
|
|
try { |
|
|
|
|
|
if (!isValidBotToken(botToken)) { |
|
|
throw new Error('Invalid bot token format'); |
|
|
} |
|
|
|
|
|
const bot = new Telegraf<BotContext>(botToken); |
|
|
|
|
|
|
|
|
const botId = getBotIdFromToken(botToken); |
|
|
saveBotTokenMapping(botToken, botId); |
|
|
|
|
|
|
|
|
await messageManager.loadMessages(); |
|
|
|
|
|
|
|
|
messageManager.setLanguage(botData?.settings?.language || 'en'); |
|
|
|
|
|
|
|
|
bot.context.botData = botData || null; |
|
|
|
|
|
|
|
|
bot.use(async (ctx, next) => { |
|
|
if (botData?.id) { |
|
|
|
|
|
await supabase |
|
|
.from('bots') |
|
|
.update({ |
|
|
last_activity: new Date().toISOString() |
|
|
}) |
|
|
.eq('id', botData.id); |
|
|
} |
|
|
return next(); |
|
|
}); |
|
|
|
|
|
|
|
|
bot.use(groupCheckMiddleware); |
|
|
|
|
|
|
|
|
setupCommandHandlers(bot); |
|
|
|
|
|
|
|
|
setupCallbackHandlers(bot); |
|
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
|
|
|
|
logger.info('Balance update service initialized successfully'); |
|
|
} catch (error: any) { |
|
|
logger.error(`Failed to initialize balance update service: ${error.message}`); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
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}`); |
|
|
|
|
|
} |
|
|
|
|
|
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}` }; |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
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 { |
|
|
|
|
|
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); |
|
|
|
|
|
|
|
|
await updateBotStatus(botId, false); |
|
|
return { success: true, message: "Bot stopped successfully" }; |
|
|
} |
|
|
|
|
|
|
|
|
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}` }; |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
export const updateBotSettings = async (botId: string, settings: Record<string, any>) => { |
|
|
try { |
|
|
|
|
|
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" }; |
|
|
} |
|
|
|
|
|
|
|
|
const updatedSettings = { ...(botData.settings || {}), ...settings }; |
|
|
|
|
|
|
|
|
await supabase |
|
|
.from('bots') |
|
|
.update({ |
|
|
settings: updatedSettings, |
|
|
updated_at: new Date().toISOString() |
|
|
}) |
|
|
.eq('id', botId); |
|
|
|
|
|
|
|
|
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}` }; |
|
|
} |
|
|
}; |
|
|
|
|
|
|