import { Telegraf } from 'telegraf'; import dotenv from 'dotenv'; dotenv.config(); const BOT_TOKEN = process.env.BOT_TOKEN; if (!BOT_TOKEN) { console.error('Error: BOT_TOKEN environment variable is not set'); process.exit(1); } console.log('Keyboard Reset Bot initializing...'); const bot = new Telegraf(BOT_TOKEN); // Debug middleware - log all incoming updates bot.use(async(ctx, next) => { console.log('Update received:', { type: ctx.updateType, chat: ctx.chat ? .type, text: ctx.message ? .text }); return next(); }); // Handle /start command (for private DM) bot.command('start', async(ctx) => { const chatType = ctx.chat.type; if (chatType === 'private') { await ctx.reply( 'Keyboard Reset Bot\n\n' + 'This bot removes reply keyboard buttons in group chats.\n\n' + 'How to use:\n' + '1. Add this bot to a group\n' + '2. Use /resetkeyboard in the group (admins only)\n\n' + 'The bot will send a message that clears all reply keyboards for users in the group.' ); } else { // In groups, just acknowledge briefly await ctx.reply('Use /resetkeyboard to clear reply keyboards (admins only).'); } }); // Handle /resetkeyboard command bot.command('resetkeyboard', async(ctx) => { const chatId = ctx.chat.id; const userId = ctx.from.id; const chatType = ctx.chat.type; // Log command usage console.log(`Command /resetkeyboard - Chat ID: ${chatId}, User ID: ${userId}, Chat Type: ${chatType}`); // Check if chat is a group or supergroup if (chatType !== 'group' && chatType !== 'supergroup') { await ctx.reply('This bot only works in groups.'); return; } try { // Check if user is an administrator const member = await ctx.getChatMember(userId); const isAdmin = member.status === 'administrator' || member.status === 'creator'; if (!isAdmin) { // Log authorization failure at debug level console.debug(`Authorization failed - Chat ID: ${chatId}, User ID: ${userId}`); await ctx.reply('Only group admins can use this command.'); return; } // Send keyboard reset message with ReplyKeyboardRemove // selective: false ensures it removes keyboard for ALL users const sentMessage = await ctx.reply('Keyboard reset.', { reply_markup: { remove_keyboard: true, selective: false } }); // Log successful reset console.log(`Keyboard reset successful - Chat ID: ${chatId}, User ID: ${userId}`); // Delete the confirmation message after 7 seconds // This gives clients time to process the keyboard reset setTimeout(async() => { try { await ctx.deleteMessage(sentMessage.message_id); } catch (error) { // Silently continue if deletion fails (permissions, race condition, etc.) } }, 7000); } catch (error) { // Fail silently on Telegram API errors (do not spam the group) console.error(`Error processing command - Chat ID: ${chatId}, User ID: ${userId}:`, error.message); } }); // Handle errors globally bot.catch((err, ctx) => { console.error('Bot error:', err.message); }); // Start polling console.log('Starting bot polling...'); bot.launch() .then(() => { console.log('Keyboard Reset Bot started successfully!'); console.log('Bot is now polling for updates...'); }) .catch((error) => { console.error('Failed to start bot:', error.message); process.exit(1); }); // Enable graceful stop process.once('SIGINT', () => bot.stop('SIGINT')); process.once('SIGTERM', () => bot.stop('SIGTERM'));