Spaces:
Running
Running
Deploy bot fixes: menus and search order
Browse files- bot/bot.js +65 -6
bot/bot.js
CHANGED
|
@@ -104,9 +104,9 @@ const getMainMenu = () => {
|
|
| 104 |
return Markup.inlineKeyboard([
|
| 105 |
[Markup.button.callback('β Yangi tovar', 'action_addproduct'), Markup.button.callback('π¦ Tovarlar', 'action_products_0')],
|
| 106 |
[Markup.button.callback('π Kategoriyalar', 'action_categories'), Markup.button.callback('π Qidirish', 'action_search')],
|
| 107 |
-
[Markup.button.callback('π Buyurtmalar', 'action_orders_0'), Markup.button.callback('
|
| 108 |
-
[Markup.button.callback('
|
| 109 |
-
[Markup.button.callback('π’ Push Xabar
|
| 110 |
[Markup.button.callback('β Yordam', 'action_help')]
|
| 111 |
]);
|
| 112 |
};
|
|
@@ -214,6 +214,7 @@ if (process.env.BOT_TOKEN && process.env.BOT_TOKEN !== 'YOUR_TELEGRAM_BOT_TOKEN'
|
|
| 214 |
if (!isAdmin(ctx)) return;
|
| 215 |
const cId = ctx.match[1];
|
| 216 |
await ctx.answerCbQuery();
|
|
|
|
| 217 |
ctx.reply('β οΈ *Kategoriyani o\'chirmoqchimisiz?*\nUnga tegishli tovarlar o\'chmaydi, lekin kategoriyasi bo\'sh bo\'lib qoladi.', {
|
| 218 |
parse_mode: 'Markdown',
|
| 219 |
...Markup.inlineKeyboard([[Markup.button.callback('β
Ha, o\'chirish', `delcat_${cId}`), Markup.button.callback('β Yo\'q', 'action_categories')]])
|
|
@@ -357,6 +358,7 @@ if (process.env.BOT_TOKEN && process.env.BOT_TOKEN !== 'YOUR_TELEGRAM_BOT_TOKEN'
|
|
| 357 |
|
| 358 |
bot.action(/del_confirm_(.*)/, async (ctx) => {
|
| 359 |
if (!isAdmin(ctx)) return;
|
|
|
|
| 360 |
ctx.reply('β οΈ *O\'chirmoqchimisiz?*', { parse_mode: 'Markdown', ...Markup.inlineKeyboard([[Markup.button.callback('β
Ha', `del_product_${ctx.match[1]}`), Markup.button.callback('β Yo\'q', 'action_home')]]) });
|
| 361 |
});
|
| 362 |
bot.action(/del_product_(.*)/, async (ctx) => {
|
|
@@ -453,6 +455,13 @@ if (process.env.BOT_TOKEN && process.env.BOT_TOKEN !== 'YOUR_TELEGRAM_BOT_TOKEN'
|
|
| 453 |
ctx.reply('π *Qidirish*\n\nTovar nomini yozib yuboring (Masalan: "Kastiyum"):', { parse_mode: 'Markdown' });
|
| 454 |
});
|
| 455 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 456 |
bot.action('action_export_excel', async (ctx) => {
|
| 457 |
if (!isAdmin(ctx)) return;
|
| 458 |
try {
|
|
@@ -546,13 +555,15 @@ if (process.env.BOT_TOKEN && process.env.BOT_TOKEN !== 'YOUR_TELEGRAM_BOT_TOKEN'
|
|
| 546 |
} catch(e) { ctx.answerCbQuery('Xato: ' + e.message); }
|
| 547 |
});
|
| 548 |
|
| 549 |
-
// πΈ Banner ko'rish (rasmli preview)
|
| 550 |
-
bot.action(/
|
| 551 |
if (!isAdmin(ctx)) return;
|
| 552 |
try {
|
| 553 |
-
const
|
|
|
|
| 554 |
if (!banner) return ctx.answerCbQuery('Banner topilmadi');
|
| 555 |
await ctx.answerCbQuery();
|
|
|
|
| 556 |
|
| 557 |
const titleStr = banner.title || '(Nomi yo\'q)';
|
| 558 |
const subtitleStr = banner.subtitle || 'β';
|
|
@@ -741,6 +752,7 @@ if (process.env.BOT_TOKEN && process.env.BOT_TOKEN !== 'YOUR_TELEGRAM_BOT_TOKEN'
|
|
| 741 |
bot.action(/banner_del_confirm_(.+)/, async (ctx) => {
|
| 742 |
if (!isAdmin(ctx)) return;
|
| 743 |
ctx.answerCbQuery();
|
|
|
|
| 744 |
ctx.reply('β οΈ *Bannerni o\'chirmoqchimisiz?*\n\nBu amalni ortga qaytarib bo\'lmaydi.', {
|
| 745 |
parse_mode: 'Markdown',
|
| 746 |
...Markup.inlineKeyboard([
|
|
@@ -943,6 +955,53 @@ if (process.env.BOT_TOKEN && process.env.BOT_TOKEN !== 'YOUR_TELEGRAM_BOT_TOKEN'
|
|
| 943 |
delete appState[userId]; return;
|
| 944 |
}
|
| 945 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 946 |
// Mahsulot edit
|
| 947 |
if (state.step === 'editing_price') {
|
| 948 |
const num = Number(text);
|
|
|
|
| 104 |
return Markup.inlineKeyboard([
|
| 105 |
[Markup.button.callback('β Yangi tovar', 'action_addproduct'), Markup.button.callback('π¦ Tovarlar', 'action_products_0')],
|
| 106 |
[Markup.button.callback('π Kategoriyalar', 'action_categories'), Markup.button.callback('π Qidirish', 'action_search')],
|
| 107 |
+
[Markup.button.callback('π Barcha Buyurtmalar', 'action_orders_0'), Markup.button.callback('π Turniket (Chek O\'qish)', 'action_search_order')],
|
| 108 |
+
[Markup.button.callback('π Statistika', 'action_stats'), Markup.button.callback('π Reklamalar', 'action_banners')],
|
| 109 |
+
[Markup.button.callback('π₯ Excel yuklash', 'action_export_excel'), Markup.button.callback('π’ Push Xabar', 'action_send_push')],
|
| 110 |
[Markup.button.callback('β Yordam', 'action_help')]
|
| 111 |
]);
|
| 112 |
};
|
|
|
|
| 214 |
if (!isAdmin(ctx)) return;
|
| 215 |
const cId = ctx.match[1];
|
| 216 |
await ctx.answerCbQuery();
|
| 217 |
+
try { await ctx.deleteMessage(); } catch(e){}
|
| 218 |
ctx.reply('β οΈ *Kategoriyani o\'chirmoqchimisiz?*\nUnga tegishli tovarlar o\'chmaydi, lekin kategoriyasi bo\'sh bo\'lib qoladi.', {
|
| 219 |
parse_mode: 'Markdown',
|
| 220 |
...Markup.inlineKeyboard([[Markup.button.callback('β
Ha, o\'chirish', `delcat_${cId}`), Markup.button.callback('β Yo\'q', 'action_categories')]])
|
|
|
|
| 358 |
|
| 359 |
bot.action(/del_confirm_(.*)/, async (ctx) => {
|
| 360 |
if (!isAdmin(ctx)) return;
|
| 361 |
+
try { await ctx.deleteMessage(); } catch(e){}
|
| 362 |
ctx.reply('β οΈ *O\'chirmoqchimisiz?*', { parse_mode: 'Markdown', ...Markup.inlineKeyboard([[Markup.button.callback('β
Ha', `del_product_${ctx.match[1]}`), Markup.button.callback('β Yo\'q', 'action_home')]]) });
|
| 363 |
});
|
| 364 |
bot.action(/del_product_(.*)/, async (ctx) => {
|
|
|
|
| 455 |
ctx.reply('π *Qidirish*\n\nTovar nomini yozib yuboring (Masalan: "Kastiyum"):', { parse_mode: 'Markdown' });
|
| 456 |
});
|
| 457 |
|
| 458 |
+
bot.action('action_search_order', (ctx) => {
|
| 459 |
+
if (!isAdmin(ctx)) return;
|
| 460 |
+
appState[ctx.from.id] = { step: 'searching_order' };
|
| 461 |
+
ctx.answerCbQuery();
|
| 462 |
+
ctx.reply('π *Turniket (Chek O\'qish)*\n\nMijoz ko\'rsatgan QR Koddagi 24 xonali ID raqamini yuboring:', { parse_mode: 'Markdown' });
|
| 463 |
+
});
|
| 464 |
+
|
| 465 |
bot.action('action_export_excel', async (ctx) => {
|
| 466 |
if (!isAdmin(ctx)) return;
|
| 467 |
try {
|
|
|
|
| 555 |
} catch(e) { ctx.answerCbQuery('Xato: ' + e.message); }
|
| 556 |
});
|
| 557 |
|
| 558 |
+
// πΈ Banner ko'rish yoki tahrirlash (rasmli preview)
|
| 559 |
+
bot.action(/banner_(view|edit)_(.+)/, async (ctx) => {
|
| 560 |
if (!isAdmin(ctx)) return;
|
| 561 |
try {
|
| 562 |
+
const bannerId = ctx.match[2];
|
| 563 |
+
const banner = await Banner.findById(bannerId);
|
| 564 |
if (!banner) return ctx.answerCbQuery('Banner topilmadi');
|
| 565 |
await ctx.answerCbQuery();
|
| 566 |
+
try { await ctx.deleteMessage(); } catch(e){}
|
| 567 |
|
| 568 |
const titleStr = banner.title || '(Nomi yo\'q)';
|
| 569 |
const subtitleStr = banner.subtitle || 'β';
|
|
|
|
| 752 |
bot.action(/banner_del_confirm_(.+)/, async (ctx) => {
|
| 753 |
if (!isAdmin(ctx)) return;
|
| 754 |
ctx.answerCbQuery();
|
| 755 |
+
try { await ctx.deleteMessage(); } catch(e){}
|
| 756 |
ctx.reply('β οΈ *Bannerni o\'chirmoqchimisiz?*\n\nBu amalni ortga qaytarib bo\'lmaydi.', {
|
| 757 |
parse_mode: 'Markdown',
|
| 758 |
...Markup.inlineKeyboard([
|
|
|
|
| 955 |
delete appState[userId]; return;
|
| 956 |
}
|
| 957 |
|
| 958 |
+
// ββββββ B2C Kassir Qidiruv (Variant 2) ββββββ
|
| 959 |
+
if (state.step === 'searching_order') {
|
| 960 |
+
try {
|
| 961 |
+
const searchTxt = text.trim();
|
| 962 |
+
let order = null;
|
| 963 |
+
|
| 964 |
+
// Mongoose ObjectId orqali qidirish (24 hex characters)
|
| 965 |
+
if (/^[0-9a-fA-F]{24}$/.test(searchTxt)) {
|
| 966 |
+
order = await Order.findById(searchTxt);
|
| 967 |
+
}
|
| 968 |
+
// Agar qisqa qidiruv bo'lsa
|
| 969 |
+
if (!order) {
|
| 970 |
+
const match = await Order.find({ _id: { $regex: searchTxt, $options: 'i' } }).limit(1);
|
| 971 |
+
if (match && match.length > 0) order = match[0];
|
| 972 |
+
}
|
| 973 |
+
|
| 974 |
+
if (!order) {
|
| 975 |
+
ctx.reply('β Buyurtma topilmadi. Raqamni tekshirib qayta yuboring:', { reply_markup: { force_reply: true } });
|
| 976 |
+
return; // Return so they can try again without dropping state
|
| 977 |
+
}
|
| 978 |
+
|
| 979 |
+
let productsText = "";
|
| 980 |
+
order.products.forEach(p => {
|
| 981 |
+
productsText += `β ${p.name} (${p.quantity} ta) x ${formatPrice(p.price)}\n`;
|
| 982 |
+
});
|
| 983 |
+
|
| 984 |
+
const statusEmoji = order.status === 'Kutilmoqda' ? 'β³' : order.status === 'Yetkazildi' ? 'β
' : 'π';
|
| 985 |
+
const msg = `π§Ύ *TOPILDI β ID:* \`${order._id}\`\n${thinLine}\n` +
|
| 986 |
+
`π€ Mijoz: *${order.customerName}*\nπ Tel: ${order.phone}\n\nπ *Tovarlar:*\n${productsText}\n` +
|
| 987 |
+
`π° *Jami summa:* ${formatPrice(order.totalAmount)} so'm\n\n` +
|
| 988 |
+
`Hozirgi holati: ${statusEmoji} ${order.status}\n\n` +
|
| 989 |
+
`π³ *XARIDOR TO'LOV QILDIMI?*`;
|
| 990 |
+
|
| 991 |
+
const buttons = [
|
| 992 |
+
[Markup.button.callback('β
Pul Olindi (Yopish)', `order_status_deliver_${order._id}`)],
|
| 993 |
+
[Markup.button.callback('β Bekor Qilish', `order_status_cancel_${order._id}`)],
|
| 994 |
+
[Markup.button.callback('π Menyu', 'action_home')]
|
| 995 |
+
];
|
| 996 |
+
|
| 997 |
+
ctx.reply(msg, { parse_mode: 'Markdown', ...Markup.inlineKeyboard(buttons) });
|
| 998 |
+
} catch (e) {
|
| 999 |
+
ctx.reply('Xatolik yuz berdi: ' + e.message, getMainMenu());
|
| 1000 |
+
}
|
| 1001 |
+
delete appState[userId]; return;
|
| 1002 |
+
}
|
| 1003 |
+
|
| 1004 |
+
|
| 1005 |
// Mahsulot edit
|
| 1006 |
if (state.step === 'editing_price') {
|
| 1007 |
const num = Number(text);
|