File size: 7,455 Bytes
80d4bc1
 
 
 
 
 
 
 
 
1b99e9c
52048a9
0d830e5
80d4bc1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d16c049
 
 
 
 
 
 
52048a9
 
 
 
80d4bc1
 
d16c049
80d4bc1
 
 
 
1b99e9c
80d4bc1
 
1b99e9c
 
 
 
 
80d4bc1
 
1b99e9c
 
 
 
80d4bc1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52048a9
 
 
80d4bc1
 
 
 
 
 
4d6ec14
 
1c7e8ea
0d830e5
1c7e8ea
4d6ec14
 
 
 
 
2650048
80d4bc1
9c3af50
 
 
 
 
 
 
 
 
80d4bc1
 
 
 
 
 
 
 
 
 
 
 
9c3af50
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80d4bc1
 
 
 
 
 
 
 
 
 
9c3af50
80d4bc1
 
 
 
 
 
 
 
 
 
 
9c3af50
80d4bc1
 
9c3af50
 
 
 
80d4bc1
 
 
9c3af50
80d4bc1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
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<string, any>;
  state: Record<string, any>;
  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<BotContext>(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<string, any>) => {
  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}` };
  }
};