Deploy Bot commited on
Commit
8d9e872
Β·
1 Parent(s): c7b99fb

Fix_Invalid_Trigger_Error_In_Match_Function

Browse files
Files changed (1) hide show
  1. src/bot.js +175 -186
src/bot.js CHANGED
@@ -206,8 +206,12 @@ bot.action('change_lang', (ctx) => {
206
 
207
  // User Interactions
208
  // User Interactions
209
- const locales = require('./locales');
210
- const match = (key) => [locales.uz[key], locales.ru[key], locales.en[key]];
 
 
 
 
211
 
212
  bot.hears(match('btn_catalog'), (ctx) => userController.showCategories(ctx));
213
  bot.hears(match('btn_cart'), (ctx) => userController.showCart(ctx));
@@ -221,194 +225,179 @@ bot.hears("πŸ‘¨β€πŸ’Ό Admin Panel", (ctx) => {
221
 
222
  bot.hears(match('btn_contact'), (ctx) => {
223
  ctx.reply(ctx.i18n.contact_info, Markup.inlineKeyboard([
224
- [Markup.button.url("πŸ“¦ Mahsulotlar bo'yicha Admin", "https://t.me/isfandiyor_3")],
225
- [Markup.button.url("πŸ€– Bot bo'yicha Admin", "https://t.me/IBROHM_7")]
226
- ]));
227
- });
228
-
229
- bot.hears(match('btn_channel'), (ctx) => {
230
- ctx.reply(ctx.i18n.btn_channel, Markup.inlineKeyboard([
231
- [Markup.button.url("πŸ“’ Kanalga o'tish", "https://t.me/Pc_Store_Market")]
232
- ]));
233
- });
234
-
235
- bot.hears(match('btn_group'), (ctx) => {
236
- ctx.reply(ctx.i18n.btn_group, Markup.inlineKeyboard([
237
- [Markup.button.url("πŸ‘₯ Guruhga o'tish", "https://t.me/Pc_Store_Market1")]
238
- ]));
239
- });
240
-
241
- bot.hears(match('btn_invite'), (ctx) => userController.inviteFriends(ctx));
242
- bot.hears(match('btn_settings'), (ctx) => userController.settings(ctx));
243
- bot.hears(match('btn_back'), (ctx) => userController.start(ctx));
244
-
245
- // Language Change Button Handler
246
- bot.hears(match('btn_lang'), (ctx) => {
247
- ctx.reply("πŸ‡ΊπŸ‡Ώ Iltimos, tilni tanlang:\nπŸ‡·πŸ‡Ί ΠŸΠΎΠΆΠ°Π»ΡƒΠΉΡΡ‚Π°, Π²Ρ‹Π±Π΅Ρ€ΠΈΡ‚Π΅ язык:\nπŸ‡¬πŸ‡§ Please select a language:", Markup.inlineKeyboard([
248
- [Markup.button.callback("πŸ‡ΊπŸ‡Ώ O'zbekcha", "set_lang_uz")],
249
- [Markup.button.callback("πŸ‡·πŸ‡Ί Русский", "set_lang_ru")],
250
- [Markup.button.callback("πŸ‡¬πŸ‡§ English", "set_lang_en")]
251
- ]));
252
- });
253
-
254
- // Handle /start with Payload
255
- bot.start((ctx) => {
256
- // Check for payload
257
- const payload = ctx.startPayload; // Telegraf extracts this automatically "start 123" -> "123"
258
-
259
- // Register User logic here (or ensure it's done) - Middlewares usually trigger first, ensuring user exists.
260
- // Pass payload to controller
261
- if (payload) {
262
- userController.handleReferral(ctx, payload);
263
- }
264
-
265
- const user = ctx.from;
266
- const welcomeText = `πŸ‘‹ <b>Assalomu alaykum, ${user.first_name}!</b>\n\nπŸ’» <b>PC Store</b> botiga xush kelibsiz!\nSifati va halolligi kafolatlangan texnikalar makoni.\n\nπŸ‘‡ <i>Quyidagi bo'limlardan birini tanlang:</i>`;
267
- userController.start(ctx, welcomeText);
268
- });
269
-
270
- bot.hears("πŸ”Ž Qidiruv", (ctx) => userController.startSearch(ctx));
271
- bot.hears("πŸ“¦ Buyurtmalarim", (ctx) => userController.showOrderHistory(ctx));
272
- bot.hears("βš™οΈ Sozlamalar", (ctx) => userController.settings(ctx));
273
-
274
- bot.action("set_name", (ctx) => {
275
- ctx.deleteMessage();
276
- userController.changeName(ctx);
277
- });
278
-
279
-
280
- // Handle Category Selection
281
- bot.action(/cat_(.+)/, async (ctx) => {
282
- const catId = ctx.match[1];
283
- const Category = require('./models/Category');
284
- const userController = require('./controllers/userController');
285
-
286
- // Check if this category has subcategories
287
- const subCount = await Category.countDocuments({ parent: catId });
288
-
289
- if (subCount > 0) {
290
- // Show Subcategories
291
- return userController.showSubCategories(ctx, catId);
292
- } else {
293
- // Show Products (Leaf Category)
294
- return userController.showProducts(ctx, catId);
295
- }
296
- });
297
-
298
- // Carousel Navigation
299
- // Carousel Navigation (New)
300
- bot.action(/br_(.+)_(.+)_(.+)/, (ctx) => {
301
- // pattern: br_catId_prodIndex_mediaIndex
302
- const catId = "cat_" + ctx.match[1];
303
- const prodIndex = parseInt(ctx.match[2]);
304
- const mediaIndex = parseInt(ctx.match[3]);
305
- userController.browseCategory(ctx, catId, prodIndex, mediaIndex);
306
- });
307
-
308
- // Backward compatibility or redirect
309
- bot.action(/browse_(.+)_(.+)/, (ctx) => {
310
- const catId = "cat_" + ctx.match[1];
311
- const index = parseInt(ctx.match[2]);
312
- userController.browseCategory(ctx, catId, index, 0);
313
- });
314
-
315
- bot.action(/rate_ask_(.+)/, (ctx) => userController.askRating(ctx, ctx.match[1]));
316
- bot.action(/rate_save_(.+)_(.+)/, (ctx) => userController.saveRating(ctx, ctx.match[1], ctx.match[2]));
317
-
318
- bot.action("back_to_cats", (ctx) => {
319
- ctx.deleteMessage();
320
- userController.showCategories(ctx);
321
- });
322
-
323
- bot.action("noop", (ctx) => ctx.answerCbQuery()); // Do nothing for page counter
324
-
325
- bot.action(/prod_(.+)/, (ctx) => {
326
- ctx.answerCbQuery();
327
- userController.showProduct(ctx, ctx.match[1]);
328
- });
329
-
330
- bot.action(/add_cart_(.+)/, (ctx) => {
331
- userController.addToCart(ctx, ctx.match[1]);
332
- });
333
-
334
- bot.action("clear_cart", (ctx) => userController.clearCart(ctx));
335
- bot.action(/remove_item_(.+)/, (ctx) => userController.removeItem(ctx, parseInt(ctx.match[1])));
336
-
337
- bot.action("checkout", (ctx) => {
338
- ctx.answerCbQuery();
339
- ctx.deleteMessage(); // Clear cart message
340
- ctx.scene.enter('CHECKOUT_SCENE');
341
- });
342
-
343
- bot.action("my_orders_list", (ctx) => {
344
- ctx.deleteMessage();
345
- userController.showOrderHistory(ctx);
346
- });
347
-
348
- bot.action("back_to_menu", (ctx) => {
349
- ctx.deleteMessage();
350
- ctx.reply("Asosiy menyu:", Markup.keyboard(userController.getMenuButtons(ctx)).resize());
351
- // Wait, getMenuButtons is not exported or defined nicely. userController.start(ctx) sends the menu.
352
- // Let's just call userController.start(ctx);
353
- userController.start(ctx);
354
- });
355
-
356
- bot.action(/my_order_(.+)/, (ctx) => userController.showOrderDetails(ctx, ctx.match[1]));
357
-
358
- // Handle Text (Search & Settings)
359
- // This MUST be the last text handler
360
- bot.on('text', async (ctx, next) => {
361
- // 1. Check Search
362
- let isHandled = await userController.handleSearch(ctx);
363
- if (isHandled) return;
364
 
365
- // 2. Check Name Change
366
- isHandled = await userController.handleNameChange(ctx);
367
- if (isHandled) return;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
368
 
369
- return next();
370
- });
371
 
 
 
 
 
 
 
372
 
373
- // Launch with Retry Logic and DNS Check
374
- // const dns = require('dns'); // Already imported at the top
 
375
 
376
- const launchBot = async () => {
377
- try {
378
- // Clear any stuck webhooks
379
- await bot.telegram.deleteWebhook({ drop_pending_updates: true });
380
- console.log('πŸ”„ Webhook tozalandi...');
381
-
382
- await bot.launch({
383
- dropPendingUpdates: true
384
- });
385
- console.log('βœ… Bot muvaffaqiyatli ishga tushdi!');
386
- } catch (err) {
387
- console.error('Botni ishga tushirishda xatolik:', err);
388
- if (err.description && err.description.includes('Conflict')) {
389
- console.warn("⚠️ DIQQAT: Botni boshqa joyda (masalan, kompyuteringizda terminalda) o'chirishingiz kerak! Serverda ikkita bot bitta token bilan ishlayapti.");
 
 
 
 
 
 
 
 
 
 
390
  }
391
- console.log('5 soniyadan keyin qayta urunib ko\'ramiz...');
392
- setTimeout(launchBot, 5000); // Retry after 5 seconds
393
- }
394
- };
395
-
396
- launchBot();
397
-
398
- // Enable graceful stop
399
- process.once('SIGINT', () => bot.stop('SIGINT'));
400
- process.once('SIGTERM', () => bot.stop('SIGTERM'));
401
-
402
- // Add HTTP Server for Hugging Face Spaces (Health Check)
403
- const http = require('http');
404
- const PORT = process.env.PORT || 7860;
405
- http.createServer((req, res) => {
406
- res.writeHead(200, { 'Content-Type': 'text/plain' });
407
- res.write('Bot is running!');
408
- res.end();
409
- }).listen(PORT, () => {
410
- console.log(`Server listening on port ${PORT}`);
411
- });
412
-
413
- module.exports = bot;
414
 
 
206
 
207
  // User Interactions
208
  // User Interactions
209
+ // Match Helper to get keywords from all languages
210
+ const match = (key) => {
211
+ const locales = require('./locales');
212
+ const triggers = Object.values(locales).map(l => l[key]).filter(v => v); // Filter out undefined/null
213
+ return triggers.length > 0 ? triggers : [new RegExp(`^${key}$`)]; // Fallback if empty (shouldn't happen)
214
+ };
215
 
216
  bot.hears(match('btn_catalog'), (ctx) => userController.showCategories(ctx));
217
  bot.hears(match('btn_cart'), (ctx) => userController.showCart(ctx));
 
225
 
226
  bot.hears(match('btn_contact'), (ctx) => {
227
  ctx.reply(ctx.i18n.contact_info, Markup.inlineKeyboard([
228
+ bot.hears(match('btn_invite'), (ctx) => userController.inviteFriends(ctx));
229
+ bot.hears(match('btn_settings'), (ctx) => userController.settings(ctx));
230
+ bot.hears(match('btn_back'), (ctx) => userController.start(ctx));
231
+
232
+ // Language Change Button Handler
233
+ // We need to ensure 'btn_lang' exists in ALL locales or filter(Boolean) handles it.
234
+ // In locales.js we added 'btn_lang' to all 3 languages.
235
+ bot.hears(match('btn_lang'), (ctx) => {
236
+ ctx.reply("πŸ‡ΊπŸ‡Ώ Iltimos, tilni tanlang:\nπŸ‡·πŸ‡Ί ΠŸΠΎΠΆΠ°Π»ΡƒΠΉΡΡ‚Π°, Π²Ρ‹Π±Π΅Ρ€ΠΈΡ‚Π΅ язык:\nπŸ‡¬πŸ‡§ Please select a language:", Markup.inlineKeyboard([
237
+ [Markup.button.callback("πŸ‡ΊπŸ‡Ώ O'zbekcha", "set_lang_uz")],
238
+ [Markup.button.callback("πŸ‡·πŸ‡Ί Русский", "set_lang_ru")],
239
+ [Markup.button.callback("πŸ‡¬πŸ‡§ English", "set_lang_en")]
240
+ ]));
241
+ });
242
+
243
+ // Handle /start with Payload
244
+ bot.start((ctx) => {
245
+ // Check for payload
246
+ const payload = ctx.startPayload; // Telegraf extracts this automatically "start 123" -> "123"
247
+
248
+ // Register User logic here (or ensure it's done) - Middlewares usually trigger first, ensuring user exists.
249
+ // Pass payload to controller
250
+ if (payload) {
251
+ userController.handleReferral(ctx, payload);
252
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
253
 
254
+ const user = ctx.from;
255
+ const welcomeText = `πŸ‘‹ <b>Assalomu alaykum, ${user.first_name}!</b>\n\nπŸ’» <b>PC Store</b> botiga xush kelibsiz!\nSifati va halolligi kafolatlangan texnikalar makoni.\n\nπŸ‘‡ <i>Quyidagi bo'limlardan birini tanlang:</i>`;
256
+ userController.start(ctx, welcomeText);
257
+ });
258
+
259
+ bot.hears("πŸ”Ž Qidiruv", (ctx) => userController.startSearch(ctx));
260
+ bot.hears("πŸ“¦ Buyurtmalarim", (ctx) => userController.showOrderHistory(ctx));
261
+ bot.hears("βš™οΈ Sozlamalar", (ctx) => userController.settings(ctx));
262
+
263
+ bot.action("set_name", (ctx) => {
264
+ ctx.deleteMessage();
265
+ userController.changeName(ctx);
266
+ });
267
+
268
+
269
+ // Handle Category Selection
270
+ bot.action(/cat_(.+)/, async (ctx) => {
271
+ const catId = ctx.match[1];
272
+ const Category = require('./models/Category');
273
+ const userController = require('./controllers/userController');
274
+
275
+ // Check if this category has subcategories
276
+ const subCount = await Category.countDocuments({ parent: catId });
277
+
278
+ if (subCount > 0) {
279
+ // Show Subcategories
280
+ return userController.showSubCategories(ctx, catId);
281
+ } else {
282
+ // Show Products (Leaf Category)
283
+ return userController.showProducts(ctx, catId);
284
+ }
285
+ });
286
+
287
+ // Carousel Navigation
288
+ // Carousel Navigation (New)
289
+ bot.action(/br_(.+)_(.+)_(.+)/, (ctx) => {
290
+ // pattern: br_catId_prodIndex_mediaIndex
291
+ const catId = "cat_" + ctx.match[1];
292
+ const prodIndex = parseInt(ctx.match[2]);
293
+ const mediaIndex = parseInt(ctx.match[3]);
294
+ userController.browseCategory(ctx, catId, prodIndex, mediaIndex);
295
+ });
296
+
297
+ // Backward compatibility or redirect
298
+ bot.action(/browse_(.+)_(.+)/, (ctx) => {
299
+ const catId = "cat_" + ctx.match[1];
300
+ const index = parseInt(ctx.match[2]);
301
+ userController.browseCategory(ctx, catId, index, 0);
302
+ });
303
+
304
+ bot.action(/rate_ask_(.+)/, (ctx) => userController.askRating(ctx, ctx.match[1]));
305
+ bot.action(/rate_save_(.+)_(.+)/, (ctx) => userController.saveRating(ctx, ctx.match[1], ctx.match[2]));
306
+
307
+ bot.action("back_to_cats", (ctx) => {
308
+ ctx.deleteMessage();
309
+ userController.showCategories(ctx);
310
+ });
311
+
312
+ bot.action("noop", (ctx) => ctx.answerCbQuery()); // Do nothing for page counter
313
+
314
+ bot.action(/prod_(.+)/, (ctx) => {
315
+ ctx.answerCbQuery();
316
+ userController.showProduct(ctx, ctx.match[1]);
317
+ });
318
+
319
+ bot.action(/add_cart_(.+)/, (ctx) => {
320
+ userController.addToCart(ctx, ctx.match[1]);
321
+ });
322
+
323
+ bot.action("clear_cart", (ctx) => userController.clearCart(ctx));
324
+ bot.action(/remove_item_(.+)/, (ctx) => userController.removeItem(ctx, parseInt(ctx.match[1])));
325
+
326
+ bot.action("checkout", (ctx) => {
327
+ ctx.answerCbQuery();
328
+ ctx.deleteMessage(); // Clear cart message
329
+ ctx.scene.enter('CHECKOUT_SCENE');
330
+ });
331
+
332
+ bot.action("my_orders_list", (ctx) => {
333
+ ctx.deleteMessage();
334
+ userController.showOrderHistory(ctx);
335
+ });
336
+
337
+ bot.action("back_to_menu", (ctx) => {
338
+ ctx.deleteMessage();
339
+ ctx.reply("Asosiy menyu:", Markup.keyboard(userController.getMenuButtons(ctx)).resize());
340
+ // Wait, getMenuButtons is not exported or defined nicely. userController.start(ctx) sends the menu.
341
+ // Let's just call userController.start(ctx);
342
+ userController.start(ctx);
343
+ });
344
 
345
+ bot.action(/my_order_(.+)/, (ctx) => userController.showOrderDetails(ctx, ctx.match[1]));
 
346
 
347
+ // Handle Text (Search & Settings)
348
+ // This MUST be the last text handler
349
+ bot.on('text', async (ctx, next) => {
350
+ // 1. Check Search
351
+ let isHandled = await userController.handleSearch(ctx);
352
+ if (isHandled) return;
353
 
354
+ // 2. Check Name Change
355
+ isHandled = await userController.handleNameChange(ctx);
356
+ if (isHandled) return;
357
 
358
+ return next();
359
+ });
360
+
361
+
362
+ // Launch with Retry Logic and DNS Check
363
+ // const dns = require('dns'); // Already imported at the top
364
+
365
+ const launchBot = async () => {
366
+ try {
367
+ // Clear any stuck webhooks
368
+ await bot.telegram.deleteWebhook({ drop_pending_updates: true });
369
+ console.log('πŸ”„ Webhook tozalandi...');
370
+
371
+ await bot.launch({
372
+ dropPendingUpdates: true
373
+ });
374
+ console.log('βœ… Bot muvaffaqiyatli ishga tushdi!');
375
+ } catch (err) {
376
+ console.error('Botni ishga tushirishda xatolik:', err);
377
+ if (err.description && err.description.includes('Conflict')) {
378
+ console.warn("⚠️ DIQQAT: Botni boshqa joyda (masalan, kompyuteringizda terminalda) o'chirishingiz kerak! Serverda ikkita bot bitta token bilan ishlayapti.");
379
+ }
380
+ console.log('5 soniyadan keyin qayta urunib ko\'ramiz...');
381
+ setTimeout(launchBot, 5000); // Retry after 5 seconds
382
  }
383
+ };
384
+
385
+ launchBot();
386
+
387
+ // Enable graceful stop
388
+ process.once('SIGINT', () => bot.stop('SIGINT'));
389
+ process.once('SIGTERM', () => bot.stop('SIGTERM'));
390
+
391
+ // Add HTTP Server for Hugging Face Spaces (Health Check)
392
+ const http = require('http');
393
+ const PORT = process.env.PORT || 7860;
394
+ http.createServer((req, res) => {
395
+ res.writeHead(200, { 'Content-Type': 'text/plain' });
396
+ res.write('Bot is running!');
397
+ res.end();
398
+ }).listen(PORT, () => {
399
+ console.log(`Server listening on port ${PORT}`);
400
+ });
401
+
402
+ module.exports = bot;
 
 
 
403