Spaces:
Paused
Paused
| const { Scenes, Markup } = require('telegraf'); | |
| const User = require('../../models/User'); | |
| const usersScene = new Scenes.WizardScene( | |
| 'admin_users', | |
| // Step 1: Main Menu for User Management | |
| async (ctx) => { | |
| // Inject i18n | |
| if (!ctx.i18n) { | |
| const User = require('../../models/User'); | |
| const locales = require('../../locales'); | |
| const user = await User.findOne({ id: ctx.from.id }); | |
| const lang = (user && user.language) ? user.language : 'uz'; | |
| ctx.i18n = locales[lang] || locales.uz; | |
| } | |
| const i18n = ctx.i18n; | |
| const text = i18n.admin.users_title; | |
| const buttons = [ | |
| [Markup.button.callback(i18n.admin.users_search, "search_id")], | |
| [Markup.button.callback(i18n.admin.users_blocked, "list_blocked")], | |
| [Markup.button.callback(i18n.admin.back, "back_dashboard")] | |
| ]; | |
| if (ctx.callbackQuery) { | |
| await ctx.editMessageText(text, { parse_mode: 'Markdown', ...Markup.inlineKeyboard(buttons) }); | |
| } else { | |
| await ctx.replyWithMarkdown(text, Markup.inlineKeyboard(buttons)); | |
| } | |
| return ctx.wizard.next(); | |
| }, | |
| // Step 2: Handle Selection | |
| async (ctx) => { | |
| // Ensure i18n | |
| if (!ctx.i18n) { const locales = require('../../locales'); ctx.i18n = locales.uz; } | |
| const i18n = ctx.i18n; | |
| if (!ctx.callbackQuery && !ctx.message) return; | |
| const txt = ctx.message ? ctx.message.text : ''; | |
| if (txt === '/start' || txt === i18n.admin.btn_reject || txt === 'β Bekor qilish') { | |
| return ctx.scene.leave(); | |
| } | |
| if (ctx.callbackQuery) { | |
| const data = ctx.callbackQuery.data; | |
| if (data === 'back_dashboard') { | |
| await ctx.scene.leave(); | |
| const adminController = require('../../controllers/adminController'); | |
| return adminController.showDashboard(ctx); | |
| } | |
| if (data === 'search_id') { | |
| await ctx.reply(i18n.admin.users_search_prompt, Markup.keyboard([[i18n.admin.btn_reject]]).resize()); | |
| ctx.wizard.state.action = 'search_id'; | |
| return ctx.wizard.next(); | |
| } | |
| if (data === 'list_blocked') { | |
| const blockedUsers = await User.find({ isBlocked: true }); | |
| if (blockedUsers.length === 0) { | |
| await ctx.answerCbQuery(i18n.admin.users_blocked + ": 0"); | |
| return; | |
| } | |
| let msg = `${i18n.admin.users_blocked}:\n\n`; | |
| blockedUsers.forEach(u => { | |
| msg += `π€ ${u.first_name} (ID: ${u.id})\n`; | |
| }); | |
| await ctx.replyWithMarkdown(msg); | |
| return; | |
| } | |
| } | |
| }, | |
| // Step 3: Input Handler (Search ID) & Action Execution | |
| async (ctx) => { | |
| // Ensure i18n | |
| if (!ctx.i18n) { const locales = require('../../locales'); ctx.i18n = locales.uz; } | |
| const i18n = ctx.i18n; | |
| const txt = ctx.message ? ctx.message.text : ''; | |
| if (txt === i18n.admin.btn_reject || txt === 'β Bekor qilish') { | |
| await ctx.reply(i18n.admin.back, Markup.removeKeyboard()); | |
| return ctx.scene.leave(); | |
| } | |
| if (ctx.wizard.state.action === 'search_id') { | |
| const userId = parseInt(txt); | |
| if (isNaN(userId)) { | |
| await ctx.reply(i18n.admin.error_num || "Error"); | |
| return; | |
| } | |
| const user = await User.findOne({ id: userId }); | |
| if (!user) { | |
| await ctx.reply(i18n.admin.del_fail || "Not found"); | |
| return ctx.scene.leave(); | |
| } | |
| ctx.wizard.state.selectedUser = user; | |
| // Show User Details | |
| const status = user.isBlocked ? i18n.admin.users_blocked : "β Aktiv"; | |
| const info = `${i18n.admin.users_info}\n\n` + | |
| `π ID: \`${user.id}\`\n` + | |
| `π€ ${i18n.name}: ${user.first_name}\n` + | |
| `π ${i18n.phone}: ${user.phone || "Yo'q"}\n` + | |
| `π Status: ${status}\n` + | |
| `π Date: ${user.createdAt.toLocaleDateString()}`; | |
| const buttons = []; | |
| if (user.isBlocked) { | |
| buttons.push([Markup.button.callback(i18n.admin.btn_unban, "unban_user")]); | |
| } else { | |
| buttons.push([Markup.button.callback(i18n.admin.btn_ban, "ban_user")]); | |
| } | |
| buttons.push([Markup.button.callback(i18n.admin.btn_dm, "dm_user")]); | |
| buttons.push([Markup.button.callback(i18n.admin.btn_reject, "cancel")]); | |
| await ctx.replyWithMarkdown(info, Markup.inlineKeyboard(buttons)); | |
| return ctx.wizard.next(); | |
| } | |
| }, | |
| // Step 4: Handle User Actions (Ban/Unban/DM) | |
| async (ctx) => { | |
| // Ensure i18n | |
| const i18n = ctx.i18n || require('../../locales').uz; | |
| if (ctx.callbackQuery) { | |
| const data = ctx.callbackQuery.data; | |
| const user = ctx.wizard.state.selectedUser; | |
| if (data === 'cancel') { | |
| await ctx.deleteMessage(); | |
| await ctx.reply(i18n.admin.back, Markup.removeKeyboard()); | |
| return ctx.scene.leave(); | |
| } | |
| if (data === 'ban_user') { | |
| await User.updateOne({ id: user.id }, { isBlocked: true }); | |
| await ctx.answerCbQuery(i18n.admin.btn_ban); | |
| await ctx.reply(`π« ${user.first_name} blocked.`); | |
| return ctx.scene.leave(); | |
| } | |
| if (data === 'unban_user') { | |
| await User.updateOne({ id: user.id }, { isBlocked: false }); | |
| await ctx.answerCbQuery(i18n.admin.btn_unban); | |
| await ctx.reply(`β ${user.first_name} unblocked.`); | |
| return ctx.scene.leave(); | |
| } | |
| if (data === 'dm_user') { | |
| await ctx.reply(i18n.admin.dm_prompt, Markup.keyboard([[i18n.admin.btn_reject]]).resize()); | |
| ctx.wizard.state.action = 'typing_dm'; | |
| return ctx.wizard.next(); // Go to Step 5 (DM Input) | |
| } | |
| } | |
| }, | |
| // Step 5: Send DM | |
| async (ctx) => { | |
| // Ensure i18n | |
| const i18n = ctx.i18n || require('../../locales').uz; | |
| const txt = ctx.message ? ctx.message.text : ''; | |
| if (txt === i18n.admin.btn_reject || txt === 'β Bekor qilish') { | |
| await ctx.reply(i18n.admin.back, Markup.removeKeyboard()); | |
| return ctx.scene.leave(); | |
| } | |
| const user = ctx.wizard.state.selectedUser; | |
| try { | |
| await ctx.telegram.sendMessage(user.id, `π **Admin:**\n\n${txt}`, { parse_mode: 'Markdown' }); | |
| await ctx.reply(i18n.admin.dm_sent); | |
| } catch (err) { | |
| await ctx.reply(i18n.admin.error); | |
| } | |
| return ctx.scene.leave(); | |
| } | |
| ); | |
| module.exports = usersScene; | |