first commit

This commit is contained in:
Michaël
2025-12-25 15:08:20 -03:00
commit f62d7b15e2
53 changed files with 4453 additions and 0 deletions

1
.env.example Normal file
View File

@@ -0,0 +1 @@
BOT_TOKEN=your_bot_token_here

5
.gitignore vendored Normal file
View File

@@ -0,0 +1,5 @@
node_modules/
.env
*.log
.DS_Store

View File

View File

@@ -0,0 +1 @@
BOT_TOKEN=your_bot_token_here

View File

@@ -0,0 +1 @@
BOT_TOKEN=8531569553:AAFT-SvBHGCDnF_8dvwyEiLRA1ome-p-ttc

View File

@@ -0,0 +1,2 @@
#BOT_TOKEN=8531569553:AAFT-SvBHGCDnF_8dvwyEiLRA1ome-p-ttc
BOT_TOKEN=8566687126:AAGw-zhiTml3qZyXfdEkF0Jag5MTCqhO1BU

View File

@@ -0,0 +1 @@
BOT_TOKEN=8531569553:AAFT-SvBHGCDnF_8dvwyEiLRA1ome-p-ttc

View File

@@ -0,0 +1,2 @@
#BOT_TOKEN=8531569553:AAFT-SvBHGCDnF_8dvwyEiLRA1ome-p-ttc
BOT_TOKEN=8566687126:AAGw-zhiTml3qZyXfdEkF0Jag5MTCqhO1BU

View File

@@ -0,0 +1,62 @@
# Keyboard Reset Bot
A minimal Telegram bot that removes reply keyboard buttons in Telegram group chats by sending a keyboard reset message.
## Features
- Works only in group chats and supergroups
- Single command: `/resetkeyboard`
- Admin-only authorization
- Automatically removes its confirmation message after 7 seconds
- Stateless (no database, no data storage)
## Setup
1. **Get a Bot Token**
- Talk to [@BotFather](https://t.me/botfather) on Telegram
- Create a new bot with `/newbot`
- Copy the bot token
2. **Install Dependencies**
```bash
npm install
```
3. **Configure Environment**
- Copy `.env.example` to `.env`
- Add your bot token:
```
BOT_TOKEN=your_bot_token_here
```
4. **Run the Bot**
```bash
npm start
```
## Usage
1. Add the bot to your Telegram group
2. Grant the bot "Read messages" permission (and optionally "Delete messages" for cleanup)
3. An admin can use `/resetkeyboard` to remove all reply keyboards in the group
## Requirements
- Node.js 14+ (ES modules support)
- Bot permissions: "Read messages" (required), "Delete messages" (optional)
## How It Works
When an admin sends `/resetkeyboard` in a group:
1. The bot verifies the user is an administrator
2. Sends a message with `ReplyKeyboardRemove` (selective: false)
3. This resets reply keyboards for all users who receive the message
4. The bot deletes its own message after 7 seconds
## Notes
- The bot ignores private chats
- Only group administrators can use the command
- The bot is stateless and does not store any data
- If another bot sends a keyboard after reset, it will appear again (expected behavior)

View File

@@ -0,0 +1,62 @@
# Keyboard Reset Bot
A minimal Telegram bot that removes reply keyboard buttons in Telegram group chats by sending a keyboard reset message.
## Features
- Works only in group chats and supergroups
- Single command: `/resetkeyboard`
- Admin-only authorization
- Automatically removes its confirmation message after 7 seconds
- Stateless (no database, no data storage)
## Setup
1. **Get a Bot Token**
- Talk to [@BotFather](https://t.me/botfather) on Telegram
- Create a new bot with `/newbot`
- Copy the bot token
2. **Install Dependencies**
```bash
npm install
```
3. **Configure Environment**
- Copy `.env.example` to `.env`
- Add your bot token:
```
BOT_TOKEN=your_bot_token_here
```
4. **Run the Bot**
```bash
npm start
```
## Usage
1. Add the bot to your Telegram group
2. Grant the bot "Read messages" permission (and optionally "Delete messages" for cleanup)
3. An admin can use `/resetkeyboard` to remove all reply keyboards in the group
## Requirements
- Node.js 14+ (ES modules support)
- Bot permissions: "Read messages" (required), "Delete messages" (optional)
## How It Works
When an admin sends `/resetkeyboard` in a group:
1. The bot verifies the user is an administrator
2. Sends a message with `ReplyKeyboardRemove` (selective: false)
3. This resets reply keyboards for all users who receive the message
4. The bot deletes its own message after 7 seconds
## Notes
- The bot ignores private chats
- Only group administrators can use the command
- The bot is stateless and does not store any data
- If another bot sends a keyboard after reset, it will appear again (expected behavior)

View File

View File

@@ -0,0 +1,128 @@
BOT NAME
Keyboard Reset Bot (working name)
PURPOSE
A minimal Telegram bot whose only responsibility is to remove reply keyboard buttons in Telegram group chats by sending a keyboard reset message.
This bot does not manage data, users, state, or configuration beyond a single slash command.
CORE FUNCTIONAL REQUIREMENTS
Supported chats
• Group chats
• Supergroups
The bot must ignore private chats.
If used in a private chat, it should reply once with:
“This bot only works in groups.”
Command
Single slash command:
/resetkeyboard
No aliases. No parameters.
Authorization
Only group administrators may trigger the command.
Authorization rules:
• Check the user who sent /resetkeyboard
• If the user is an administrator or creator → allow
• Otherwise → ignore or reply with:
“Only group admins can use this command.”
No role persistence. Authorization is checked per command invocation.
Keyboard removal behavior
When triggered by an authorized user in a group:
The bot sends one normal message to the group with:
• reply_markup = ReplyKeyboardRemove
• selective = false
This message must:
• Be visible (not silent)
• Not be inline
• Not target a specific user
This resets the reply keyboard for all users who receive the message.
Message content
Message text should be short and neutral, for example:
“Keyboard reset.”
No emojis.
No markdown.
No mentions.
Message lifecycle
Optional but recommended:
• The bot deletes its own confirmation message after 510 seconds
• Do NOT delete immediately (clients need time to process the keyboard reset)
If deletion fails (permissions, race condition), the bot must silently continue.
What the bot must NOT do
The bot must NOT:
• Store data
• Track users
• Use a database
• React to normal messages
• Remove inline keyboards
• Delete other bots messages
• Re-send keyboards
• Perform scheduled actions
This is a stateless utility bot.
EDGE CASES AND EXPECTED BEHAVIOR
• If another bot sends a keyboard after this bot runs, that keyboard will appear again. This is expected.
• If a user does not receive the message (offline/network), their keyboard may persist until the next reset.
• This is the only technically correct way to reset keyboards in Telegram.
IMPLEMENTATION CONSTRAINTS
Update handling
Either polling or webhook is acceptable.
Polling is preferred for simplicity.
Libraries
Any official or widely used Telegram library is acceptable, such as:
• python-telegram-bot
• aiogram
• Telegraf (Node.js)
• Raw Bot API (HTTP)
No unofficial wrappers.
Permissions required
The bot must be granted:
• “Read messages”
• “Delete messages” (optional, only for cleanup)
No admin rights beyond this are required.
LOGGING AND ERROR HANDLING
• Log startup success
• Log command usage with chat ID and user ID
• Log authorization failures at debug level
• Fail silently on Telegram API errors (do not spam the group)
SUCCESS CRITERIA
The bot is considered correct if:
• An admin sends /resetkeyboard in a group
• All visible reply keyboards disappear for users in that group
• The bot does nothing else

View File

@@ -0,0 +1,86 @@
import { Telegraf, Markup } 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);
}
const bot = new Telegraf(BOT_TOKEN);
// Log startup success
console.log('Keyboard Reset Bot started successfully');
// 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 received - 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.log(`Authorization failed - Chat ID: ${chatId}, User ID: ${userId}`);
await ctx.reply('Only group admins can use this command.');
return;
}
// Send keyboard reset message
const sentMessage = await ctx.reply('Keyboard reset.', {
reply_markup: Markup.removeKeyboard()
});
// Log successful reset
console.log(`Keyboard reset successful - Chat ID: ${chatId}, User ID: ${userId}`);
// Delete the confirmation message after 7 seconds
setTimeout(async () => {
try {
await ctx.deleteMessage(sentMessage.message_id);
} catch (error) {
// Silently continue if deletion fails (permissions, race condition, etc.)
// This is expected behavior - do not log or spam
}
}, 7000);
} catch (error) {
// Fail silently on Telegram API errors (do not spam the group)
// Only log to console for debugging
console.error('Error processing command:', error.message);
}
});
// Handle errors
bot.catch((err, ctx) => {
console.error('Bot error:', err);
});
// Start polling
bot.launch().then(() => {
console.log('Bot is polling for updates...');
}).catch((error) => {
console.error('Failed to start bot:', error);
process.exit(1);
});
// Enable graceful stop
process.once('SIGINT', () => bot.stop('SIGINT'));
process.once('SIGTERM', () => bot.stop('SIGTERM'));

View File

@@ -0,0 +1,85 @@
import { Telegraf, Markup } 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);
}
const bot = new Telegraf(BOT_TOKEN);
// Log startup success
console.log('Keyboard Reset Bot started successfully');
// 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 received - 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.log(`Authorization failed - Chat ID: ${chatId}, User ID: ${userId}`);
await ctx.reply('Only group admins can use this command.');
return;
}
// Send keyboard reset message
const sentMessage = await ctx.reply('Keyboard reset.', {
reply_markup: Markup.removeKeyboard()
});
// Log successful reset
console.log(`Keyboard reset successful - Chat ID: ${chatId}, User ID: ${userId}`);
// Delete the confirmation message after 7 seconds
setTimeout(async() => {
try {
await ctx.deleteMessage(sentMessage.message_id);
} catch (error) {
// Silently continue if deletion fails (permissions, race condition, etc.)
// This is expected behavior - do not log or spam
}
}, 7000);
} catch (error) {
// Fail silently on Telegram API errors (do not spam the group)
// Only log to console for debugging
console.error('Error processing command:', error.message);
}
});
// Handle errors
bot.catch((err, ctx) => {
console.error('Bot error:', err);
});
// Start polling
bot.launch().then(() => {
console.log('Bot is polling for updates...');
}).catch((error) => {
console.error('Failed to start bot:', error);
process.exit(1);
});
// Enable graceful stop
process.once('SIGINT', () => bot.stop('SIGINT'));
process.once('SIGTERM', () => bot.stop('SIGTERM'));

View File

@@ -0,0 +1,97 @@
import { Telegraf, Markup } 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);
}
const bot = new Telegraf(BOT_TOKEN);
// Log startup success
console.log('Keyboard Reset Bot started successfully');
// Debug: Log all incoming updates to see if bot is receiving messages
bot.use(async (ctx, next) => {
console.log('Update received:', {
updateType: ctx.updateType,
chatType: ctx.chat?.type,
chatId: ctx.chat?.id,
fromId: ctx.from?.id,
text: ctx.message?.text || ctx.update.message?.text || 'N/A'
});
return next();
});
// 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 received - 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.log(`Authorization failed - Chat ID: ${chatId}, User ID: ${userId}`);
await ctx.reply('Only group admins can use this command.');
return;
}
// Send keyboard reset message
const sentMessage = await ctx.reply('Keyboard reset.', {
reply_markup: Markup.removeKeyboard()
});
// Log successful reset
console.log(`Keyboard reset successful - Chat ID: ${chatId}, User ID: ${userId}`);
// Delete the confirmation message after 7 seconds
setTimeout(async() => {
try {
await ctx.deleteMessage(sentMessage.message_id);
} catch (error) {
// Silently continue if deletion fails (permissions, race condition, etc.)
// This is expected behavior - do not log or spam
}
}, 7000);
} catch (error) {
// Fail silently on Telegram API errors (do not spam the group)
// Only log to console for debugging
console.error('Error processing command:', error.message);
}
});
// Handle errors
bot.catch((err, ctx) => {
console.error('Bot error:', err);
});
// Start polling
bot.launch().then(() => {
console.log('Bot is polling for updates...');
}).catch((error) => {
console.error('Failed to start bot:', error);
process.exit(1);
});
// Enable graceful stop
process.once('SIGINT', () => bot.stop('SIGINT'));
process.once('SIGTERM', () => bot.stop('SIGTERM'));

View File

@@ -0,0 +1,107 @@
import { Telegraf, Markup } 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);
}
const bot = new Telegraf(BOT_TOKEN);
// Log startup success
console.log('Keyboard Reset Bot started successfully');
// Debug: Log all incoming updates to see if bot is receiving messages
bot.use(async (ctx, next) => {
console.log('Update received:', {
updateType: ctx.updateType,
chatType: ctx.chat?.type,
chatId: ctx.chat?.id,
fromId: ctx.from?.id,
text: ctx.message?.text || ctx.update.message?.text || 'N/A'
});
return next();
});
// 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 received - 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.log(`Authorization failed - Chat ID: ${chatId}, User ID: ${userId}`);
await ctx.reply('Only group admins can use this command.');
return;
}
// Send keyboard reset message
const sentMessage = await ctx.reply('Keyboard reset.', {
reply_markup: Markup.removeKeyboard()
});
// Log successful reset
console.log(`Keyboard reset successful - Chat ID: ${chatId}, User ID: ${userId}`);
// Delete the confirmation message after 7 seconds
setTimeout(async() => {
try {
await ctx.deleteMessage(sentMessage.message_id);
} catch (error) {
// Silently continue if deletion fails (permissions, race condition, etc.)
// This is expected behavior - do not log or spam
}
}, 7000);
} catch (error) {
// Log errors for debugging
console.error('Error processing command:', error);
console.error('Error details:', {
message: error.message,
code: error.code,
response: error.response
});
// Try to reply with error (but don't spam if it fails)
try {
await ctx.reply('An error occurred while processing the command.');
} catch (replyError) {
// Silently continue if reply also fails
}
}
});
// Handle errors
bot.catch((err, ctx) => {
console.error('Bot error:', err);
});
// Start polling
bot.launch().then(() => {
console.log('Bot is polling for updates...');
}).catch((error) => {
console.error('Failed to start bot:', error);
process.exit(1);
});
// Enable graceful stop
process.once('SIGINT', () => bot.stop('SIGINT'));
process.once('SIGTERM', () => bot.stop('SIGTERM'));

View File

@@ -0,0 +1,107 @@
import { Telegraf, Markup } 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);
}
const bot = new Telegraf(BOT_TOKEN);
// Log startup success
console.log('Keyboard Reset Bot started successfully');
// Debug: Log all incoming updates to see if bot is receiving messages
bot.use(async (ctx, next) => {
console.log('Update received:', {
updateType: ctx.updateType,
chatType: ctx.chat?.type,
chatId: ctx.chat?.id,
fromId: ctx.from?.id,
text: ctx.message?.text || ctx.update.message?.text || 'N/A'
});
return next();
});
// 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 received - 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.log(`Authorization failed - Chat ID: ${chatId}, User ID: ${userId}`);
await ctx.reply('Only group admins can use this command.');
return;
}
// Send keyboard reset message
const sentMessage = await ctx.reply('Keyboard reset.', {
reply_markup: Markup.removeKeyboard()
});
// Log successful reset
console.log(`Keyboard reset successful - Chat ID: ${chatId}, User ID: ${userId}`);
// Delete the confirmation message after 7 seconds
setTimeout(async() => {
try {
await ctx.deleteMessage(sentMessage.message_id);
} catch (error) {
// Silently continue if deletion fails (permissions, race condition, etc.)
// This is expected behavior - do not log or spam
}
}, 7000);
} catch (error) {
// Log errors for debugging
console.error('Error processing command:', error);
console.error('Error details:', {
message: error.message,
code: error.code,
response: error.response
});
// Try to reply with error (but don't spam if it fails)
try {
await ctx.reply('An error occurred while processing the command.');
} catch (replyError) {
// Silently continue if reply also fails
}
}
});
// Handle errors
bot.catch((err, ctx) => {
console.error('Bot error:', err);
});
// Start polling
bot.launch().then(() => {
console.log('Bot is polling for updates...');
}).catch((error) => {
console.error('Failed to start bot:', error);
process.exit(1);
});
// Enable graceful stop
process.once('SIGINT', () => bot.stop('SIGINT'));
process.once('SIGTERM', () => bot.stop('SIGTERM'));

View File

@@ -0,0 +1,107 @@
import { Telegraf, Markup } 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);
}
const bot = new Telegraf(BOT_TOKEN);
// Log startup success
console.log('Keyboard Reset Bot started successfully');
// Debug: Log all incoming updates to see if bot is receiving messages
bot.use(async(ctx, next) => {
console.log('Update received:', {
updateType: ctx.updateType,
chatType: ctx.chat ? .type,
chatId: ctx.chat ? .id,
fromId: ctx.from ? .id,
text: ctx.message ? .text || ctx.update.message ? .text || 'N/A'
});
return next();
});
// 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 received - 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.log(`Authorization failed - Chat ID: ${chatId}, User ID: ${userId}`);
await ctx.reply('Only group admins can use this command.');
return;
}
// Send keyboard reset message
const sentMessage = await ctx.reply('Keyboard reset.', {
reply_markup: Markup.removeKeyboard()
});
// Log successful reset
console.log(`Keyboard reset successful - Chat ID: ${chatId}, User ID: ${userId}`);
// Delete the confirmation message after 7 seconds
setTimeout(async() => {
try {
await ctx.deleteMessage(sentMessage.message_id);
} catch (error) {
// Silently continue if deletion fails (permissions, race condition, etc.)
// This is expected behavior - do not log or spam
}
}, 7000);
} catch (error) {
// Log errors for debugging
console.error('Error processing command:', error);
console.error('Error details:', {
message: error.message,
code: error.code,
response: error.response
});
// Try to reply with error (but don't spam if it fails)
try {
await ctx.reply('An error occurred while processing the command.');
} catch (replyError) {
// Silently continue if reply also fails
}
}
});
// Handle errors
bot.catch((err, ctx) => {
console.error('Bot error:', err);
});
// Start polling
bot.launch().then(() => {
console.log('Bot is polling for updates...');
}).catch((error) => {
console.error('Failed to start bot:', error);
process.exit(1);
});
// Enable graceful stop
process.once('SIGINT', () => bot.stop('SIGINT'));
process.once('SIGTERM', () => bot.stop('SIGTERM'));

View File

@@ -0,0 +1,107 @@
import { Telegraf, Markup } 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);
}
const bot = new Telegraf(BOT_TOKEN);
// Log startup success
console.log('Keyboard Reset Bot started successfully');
// Debug: Log all incoming updates to see if bot is receiving messages
bot.use(async(ctx, next) => {
console.log('Update received:', {
updateType: ctx.updateType,
chatType: ctx.chat ? .type,
chatId: ctx.chat ? .id,
fromId: ctx.from ? .id,
text: ctx.message ? .text || ctx.update.message ? .text || 'N/A'
});
return next();
});
// 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 received - 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.log(`Authorization failed - Chat ID: ${chatId}, User ID: ${userId}`);
await ctx.reply('Only group admins can use this command.');
return;
}
// Send keyboard reset message
const sentMessage = await ctx.reply('Keyboard reset.', {
reply_markup: Markup.removeKeyboard()
});
// Log successful reset
console.log(`Keyboard reset successful - Chat ID: ${chatId}, User ID: ${userId}`);
// Delete the confirmation message after 7 seconds
setTimeout(async() => {
try {
await ctx.deleteMessage(sentMessage.message_id);
} catch (error) {
// Silently continue if deletion fails (permissions, race condition, etc.)
// This is expected behavior - do not log or spam
}
}, 7000);
} catch (error) {
// Log errors for debugging
console.error('Error processing command:', error);
console.error('Error details:', {
message: error.message,
code: error.code,
response: error.response
});
// Try to reply with error (but don't spam if it fails)
try {
await ctx.reply('An error occurred while processing the command.');
} catch (replyError) {
// Silently continue if reply also fails
}
}
});
// Handle errors
bot.catch((err, ctx) => {
console.error('Bot error:', err);
});
// Start polling
bot.launch().then(() => {
console.log('Bot is polling for updates...');
}).catch((error) => {
console.error('Failed to start bot:', error);
process.exit(1);
});
// Enable graceful stop
process.once('SIGINT', () => bot.stop('SIGINT'));
process.once('SIGTERM', () => bot.stop('SIGTERM'));

View File

@@ -0,0 +1,107 @@
import { Telegraf, Markup } 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);
}
const bot = new Telegraf(BOT_TOKEN);
// Log startup success
console.log('Keyboard Reset Bot started successfully');
// Debug: Log all incoming updates to see if bot is receiving messages
bot.use(async (ctx, next) => {
console.log('Update received:', {
updateType: ctx.updateType,
chatType: ctx.chat?.type,
chatId: ctx.chat?.id,
fromId: ctx.from?.id,
text: ctx.message?.text || ctx.update.message?.text || 'N/A'
});
return next();
});
// 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 received - 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.log(`Authorization failed - Chat ID: ${chatId}, User ID: ${userId}`);
await ctx.reply('Only group admins can use this command.');
return;
}
// Send keyboard reset message
const sentMessage = await ctx.reply('Keyboard reset.', {
reply_markup: Markup.removeKeyboard()
});
// Log successful reset
console.log(`Keyboard reset successful - Chat ID: ${chatId}, User ID: ${userId}`);
// Delete the confirmation message after 7 seconds
setTimeout(async() => {
try {
await ctx.deleteMessage(sentMessage.message_id);
} catch (error) {
// Silently continue if deletion fails (permissions, race condition, etc.)
// This is expected behavior - do not log or spam
}
}, 7000);
} catch (error) {
// Log errors for debugging
console.error('Error processing command:', error);
console.error('Error details:', {
message: error.message,
code: error.code,
response: error.response
});
// Try to reply with error (but don't spam if it fails)
try {
await ctx.reply('An error occurred while processing the command.');
} catch (replyError) {
// Silently continue if reply also fails
}
}
});
// Handle errors
bot.catch((err, ctx) => {
console.error('Bot error:', err);
});
// Start polling
bot.launch().then(() => {
console.log('Bot is polling for updates...');
}).catch((error) => {
console.error('Failed to start bot:', error);
process.exit(1);
});
// Enable graceful stop
process.once('SIGINT', () => bot.stop('SIGINT'));
process.once('SIGTERM', () => bot.stop('SIGTERM'));

View File

@@ -0,0 +1,107 @@
import { Telegraf, Markup } 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);
}
const bot = new Telegraf(BOT_TOKEN);
// Log startup success
console.log('Keyboard Reset Bot started successfully');
// Debug: Log all incoming updates to see if bot is receiving messages
bot.use(async (ctx, next) => {
console.log('Update received:', {
updateType: ctx.updateType,
chatType: ctx.chat?.type,
chatId: ctx.chat?.id,
fromId: ctx.from?.id,
text: ctx.message?.text || ctx.update.message?.text || 'N/A'
});
return next();
});
// 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 received - 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.log(`Authorization failed - Chat ID: ${chatId}, User ID: ${userId}`);
await ctx.reply('Only group admins can use this command.');
return;
}
// Send keyboard reset message
const sentMessage = await ctx.reply('Keyboard reset.', {
reply_markup: Markup.removeKeyboard()
});
// Log successful reset
console.log(`Keyboard reset successful - Chat ID: ${chatId}, User ID: ${userId}`);
// Delete the confirmation message after 7 seconds
setTimeout(async () => {
try {
await ctx.deleteMessage(sentMessage.message_id);
} catch (error) {
// Silently continue if deletion fails (permissions, race condition, etc.)
// This is expected behavior - do not log or spam
}
}, 7000);
} catch (error) {
// Log errors for debugging
console.error('Error processing command:', error);
console.error('Error details:', {
message: error.message,
code: error.code,
response: error.response
});
// Try to reply with error (but don't spam if it fails)
try {
await ctx.reply('An error occurred while processing the command.');
} catch (replyError) {
// Silently continue if reply also fails
}
}
});
// Handle errors
bot.catch((err, ctx) => {
console.error('Bot error:', err);
});
// Start polling
bot.launch().then(() => {
console.log('Bot is polling for updates...');
}).catch((error) => {
console.error('Failed to start bot:', error);
process.exit(1);
});
// Enable graceful stop
process.once('SIGINT', () => bot.stop('SIGINT'));
process.once('SIGTERM', () => bot.stop('SIGTERM'));

View File

@@ -0,0 +1,107 @@
import { Telegraf, Markup } 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);
}
const bot = new Telegraf(BOT_TOKEN);
// Log startup success
console.log('Keyboard Reset Bot started successfully');
// Debug: Log all incoming updates to see if bot is receiving messages
bot.use(async(ctx, next) => {
console.log('Update received:', {
updateType: ctx.updateType,
chatType: ctx.chat ? .type,
chatId: ctx.chat ? .id,
fromId: ctx.from ? .id,
text: ctx.message ? .text || ctx.update.message ? .text || 'N/A'
});
return next();
});
// 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 received - 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.log(`Authorization failed - Chat ID: ${chatId}, User ID: ${userId}`);
await ctx.reply('Only group admins can use this command.');
return;
}
// Send keyboard reset message
const sentMessage = await ctx.reply('Keyboard reset.', {
reply_markup: Markup.removeKeyboard()
});
// Log successful reset
console.log(`Keyboard reset successful - Chat ID: ${chatId}, User ID: ${userId}`);
// Delete the confirmation message after 7 seconds
setTimeout(async() => {
try {
await ctx.deleteMessage(sentMessage.message_id);
} catch (error) {
// Silently continue if deletion fails (permissions, race condition, etc.)
// This is expected behavior - do not log or spam
}
}, 7000);
} catch (error) {
// Log errors for debugging
console.error('Error processing command:', error);
console.error('Error details:', {
message: error.message,
code: error.code,
response: error.response
});
// Try to reply with error (but don't spam if it fails)
try {
await ctx.reply('An error occurred while processing the command.');
} catch (replyError) {
// Silently continue if reply also fails
}
}
});
// Handle errors
bot.catch((err, ctx) => {
console.error('Bot error:', err);
});
// Start polling
bot.launch().then(() => {
console.log('Bot is polling for updates...');
}).catch((error) => {
console.error('Failed to start bot:', error);
process.exit(1);
});
// Enable graceful stop
process.once('SIGINT', () => bot.stop('SIGINT'));
process.once('SIGTERM', () => bot.stop('SIGTERM'));

View File

@@ -0,0 +1,107 @@
import { Telegraf, Markup } 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);
}
const bot = new Telegraf(BOT_TOKEN);
// Log startup success
console.log('Keyboard Reset Bot started successfully');
// Debug: Log all incoming updates to see if bot is receiving messages
bot.use(async (ctx, next) => {
console.log('Update received:', {
updateType: ctx.updateType,
chatType: ctx.chat?.type,
chatId: ctx.chat?.id,
fromId: ctx.from?.id,
text: ctx.message?.text || ctx.update.message?.text || 'N/A'
});
return next();
});
// 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 received - 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.log(`Authorization failed - Chat ID: ${chatId}, User ID: ${userId}`);
await ctx.reply('Only group admins can use this command.');
return;
}
// Send keyboard reset message
const sentMessage = await ctx.reply('Keyboard reset.', {
reply_markup: Markup.removeKeyboard()
});
// Log successful reset
console.log(`Keyboard reset successful - Chat ID: ${chatId}, User ID: ${userId}`);
// Delete the confirmation message after 7 seconds
setTimeout(async() => {
try {
await ctx.deleteMessage(sentMessage.message_id);
} catch (error) {
// Silently continue if deletion fails (permissions, race condition, etc.)
// This is expected behavior - do not log or spam
}
}, 7000);
} catch (error) {
// Log errors for debugging
console.error('Error processing command:', error);
console.error('Error details:', {
message: error.message,
code: error.code,
response: error.response
});
// Try to reply with error (but don't spam if it fails)
try {
await ctx.reply('An error occurred while processing the command.');
} catch (replyError) {
// Silently continue if reply also fails
}
}
});
// Handle errors
bot.catch((err, ctx) => {
console.error('Bot error:', err);
});
// Start polling
bot.launch().then(() => {
console.log('Bot is polling for updates...');
}).catch((error) => {
console.error('Failed to start bot:', error);
process.exit(1);
});
// Enable graceful stop
process.once('SIGINT', () => bot.stop('SIGINT'));
process.once('SIGTERM', () => bot.stop('SIGTERM'));

View File

@@ -0,0 +1,107 @@
import { Telegraf, Markup } 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);
}
const bot = new Telegraf(BOT_TOKEN);
// Log startup success
console.log('Keyboard Reset Bot started successfully');
// Debug: Log all incoming updates to see if bot is receiving messages
bot.use(async (ctx, next) => {
console.log('Update received:', {
updateType: ctx.updateType,
chatType: ctx.chat?.type,
chatId: ctx.chat?.id,
fromId: ctx.from?.id,
text: ctx.message?.text || ctx.update.message?.text || 'N/A'
});
return next();
});
// 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 received - 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.log(`Authorization failed - Chat ID: ${chatId}, User ID: ${userId}`);
await ctx.reply('Only group admins can use this command.');
return;
}
// Send keyboard reset message
const sentMessage = await ctx.reply('Keyboard reset.', {
reply_markup: Markup.removeKeyboard()
});
// Log successful reset
console.log(`Keyboard reset successful - Chat ID: ${chatId}, User ID: ${userId}`);
// Delete the confirmation message after 7 seconds
setTimeout(async() => {
try {
await ctx.deleteMessage(sentMessage.message_id);
} catch (error) {
// Silently continue if deletion fails (permissions, race condition, etc.)
// This is expected behavior - do not log or spam
}
}, 7000);
} catch (error) {
// Log errors for debugging
console.error('Error processing command:', error);
console.error('Error details:', {
message: error.message,
code: error.code,
response: error.response
});
// Try to reply with error (but don't spam if it fails)
try {
await ctx.reply('An error occurred while processing the command.');
} catch (replyError) {
// Silently continue if reply also fails
}
}
});
// Handle errors
bot.catch((err, ctx) => {
console.error('Bot error:', err);
});
// Start polling
bot.launch().then(() => {
console.log('Bot is polling for updates...');
}).catch((error) => {
console.error('Failed to start bot:', error);
process.exit(1);
});
// Enable graceful stop
process.once('SIGINT', () => bot.stop('SIGINT'));
process.once('SIGTERM', () => bot.stop('SIGTERM'));

View File

@@ -0,0 +1,107 @@
import { Telegraf, Markup } 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);
}
const bot = new Telegraf(BOT_TOKEN);
// Log startup success
console.log('Keyboard Reset Bot started successfully');
// Debug: Log all incoming updates to see if bot is receiving messages
bot.use(async (ctx, next) => {
console.log('Update received:', {
updateType: ctx.updateType,
chatType: ctx.chat?.type,
chatId: ctx.chat?.id,
fromId: ctx.from?.id,
text: ctx.message?.text || ctx.update.message?.text || 'N/A'
});
return next();
});
// 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 received - 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.log(`Authorization failed - Chat ID: ${chatId}, User ID: ${userId}`);
await ctx.reply('Only group admins can use this command.');
return;
}
// Send keyboard reset message
const sentMessage = await ctx.reply('Keyboard reset.', {
reply_markup: Markup.removeKeyboard()
});
// Log successful reset
console.log(`Keyboard reset successful - Chat ID: ${chatId}, User ID: ${userId}`);
// Delete the confirmation message after 7 seconds
setTimeout(async () => {
try {
await ctx.deleteMessage(sentMessage.message_id);
} catch (error) {
// Silently continue if deletion fails (permissions, race condition, etc.)
// This is expected behavior - do not log or spam
}
}, 7000);
} catch (error) {
// Log errors for debugging
console.error('Error processing command:', error);
console.error('Error details:', {
message: error.message,
code: error.code,
response: error.response
});
// Try to reply with error (but don't spam if it fails)
try {
await ctx.reply('An error occurred while processing the command.');
} catch (replyError) {
// Silently continue if reply also fails
}
}
});
// Handle errors
bot.catch((err, ctx) => {
console.error('Bot error:', err);
});
// Start polling
bot.launch().then(() => {
console.log('Bot is polling for updates...');
}).catch((error) => {
console.error('Failed to start bot:', error);
process.exit(1);
});
// Enable graceful stop
process.once('SIGINT', () => bot.stop('SIGINT'));
process.once('SIGTERM', () => bot.stop('SIGTERM'));

View File

@@ -0,0 +1,107 @@
import { Telegraf, Markup } 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);
}
const bot = new Telegraf(BOT_TOKEN);
// Log startup success
console.log('Keyboard Reset Bot started successfully');
// Debug: Log all incoming updates to see if bot is receiving messages
bot.use(async(ctx, next) => {
console.log('Update received:', {
updateType: ctx.updateType,
chatType: ctx.chat ? .type,
chatId: ctx.chat ? .id,
fromId: ctx.from ? .id,
text: ctx.message ? .text || ctx.update.message ? .text || 'N/A'
});
return next();
});
// 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 received - 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.log(`Authorization failed - Chat ID: ${chatId}, User ID: ${userId}`);
await ctx.reply('Only group admins can use this command.');
return;
}
// Send keyboard reset message
const sentMessage = await ctx.reply('Keyboard reset.', {
reply_markup: Markup.removeKeyboard()
});
// Log successful reset
console.log(`Keyboard reset successful - Chat ID: ${chatId}, User ID: ${userId}`);
// Delete the confirmation message after 7 seconds
setTimeout(async() => {
try {
await ctx.deleteMessage(sentMessage.message_id);
} catch (error) {
// Silently continue if deletion fails (permissions, race condition, etc.)
// This is expected behavior - do not log or spam
}
}, 7000);
} catch (error) {
// Log errors for debugging
console.error('Error processing command:', error);
console.error('Error details:', {
message: error.message,
code: error.code,
response: error.response
});
// Try to reply with error (but don't spam if it fails)
try {
await ctx.reply('An error occurred while processing the command.');
} catch (replyError) {
// Silently continue if reply also fails
}
}
});
// Handle errors
bot.catch((err, ctx) => {
console.error('Bot error:', err);
});
// Start polling
bot.launch().then(() => {
console.log('Bot is polling for updates...');
}).catch((error) => {
console.error('Failed to start bot:', error);
process.exit(1);
});
// Enable graceful stop
process.once('SIGINT', () => bot.stop('SIGINT'));
process.once('SIGTERM', () => bot.stop('SIGTERM'));

View File

@@ -0,0 +1,107 @@
import { Telegraf, Markup } 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);
}
const bot = new Telegraf(BOT_TOKEN);
// Log startup success
console.log('Keyboard Reset Bot started successfully');
// Debug: Log all incoming updates to see if bot is receiving messages
bot.use(async (ctx, next) => {
console.log('Update received:', {
updateType: ctx.updateType,
chatType: ctx.chat?.type,
chatId: ctx.chat?.id,
fromId: ctx.from?.id,
text: ctx.message?.text || ctx.update.message?.text || 'N/A'
});
return next();
});
// 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 received - 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.log(`Authorization failed - Chat ID: ${chatId}, User ID: ${userId}`);
await ctx.reply('Only group admins can use this command.');
return;
}
// Send keyboard reset message
const sentMessage = await ctx.reply('Keyboard reset.', {
reply_markup: Markup.removeKeyboard()
});
// Log successful reset
console.log(`Keyboard reset successful - Chat ID: ${chatId}, User ID: ${userId}`);
// Delete the confirmation message after 7 seconds
setTimeout(async() => {
try {
await ctx.deleteMessage(sentMessage.message_id);
} catch (error) {
// Silently continue if deletion fails (permissions, race condition, etc.)
// This is expected behavior - do not log or spam
}
}, 7000);
} catch (error) {
// Log errors for debugging
console.error('Error processing command:', error);
console.error('Error details:', {
message: error.message,
code: error.code,
response: error.response
});
// Try to reply with error (but don't spam if it fails)
try {
await ctx.reply('An error occurred while processing the command.');
} catch (replyError) {
// Silently continue if reply also fails
}
}
});
// Handle errors
bot.catch((err, ctx) => {
console.error('Bot error:', err);
});
// Start polling
bot.launch().then(() => {
console.log('Bot is polling for updates...');
}).catch((error) => {
console.error('Failed to start bot:', error);
process.exit(1);
});
// Enable graceful stop
process.once('SIGINT', () => bot.stop('SIGINT'));
process.once('SIGTERM', () => bot.stop('SIGTERM'));

View File

@@ -0,0 +1,107 @@
import { Telegraf, Markup } 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);
}
const bot = new Telegraf(BOT_TOKEN);
// Log startup success
console.log('Keyboard Reset Bot started successfully');
// Debug: Log all incoming updates to see if bot is receiving messages
bot.use(async (ctx, next) => {
console.log('Update received:', {
updateType: ctx.updateType,
chatType: ctx.chat?.type,
chatId: ctx.chat?.id,
fromId: ctx.from?.id,
text: ctx.message?.text || ctx.update.message?.text || 'N/A'
});
return next();
});
// 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 received - 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.log(`Authorization failed - Chat ID: ${chatId}, User ID: ${userId}`);
await ctx.reply('Only group admins can use this command.');
return;
}
// Send keyboard reset message
const sentMessage = await ctx.reply('Keyboard reset.', {
reply_markup: Markup.removeKeyboard()
});
// Log successful reset
console.log(`Keyboard reset successful - Chat ID: ${chatId}, User ID: ${userId}`);
// Delete the confirmation message after 7 seconds
setTimeout(async() => {
try {
await ctx.deleteMessage(sentMessage.message_id);
} catch (error) {
// Silently continue if deletion fails (permissions, race condition, etc.)
// This is expected behavior - do not log or spam
}
}, 7000);
} catch (error) {
// Log errors for debugging
console.error('Error processing command:', error);
console.error('Error details:', {
message: error.message,
code: error.code,
response: error.response
});
// Try to reply with error (but don't spam if it fails)
try {
await ctx.reply('An error occurred while processing the command.');
} catch (replyError) {
// Silently continue if reply also fails
}
}
});
// Handle errors
bot.catch((err, ctx) => {
console.error('Bot error:', err);
});
// Start polling
bot.launch().then(() => {
console.log('Bot is polling for updates...');
}).catch((error) => {
console.error('Failed to start bot:', error);
process.exit(1);
});
// Enable graceful stop
process.once('SIGINT', () => bot.stop('SIGINT'));
process.once('SIGTERM', () => bot.stop('SIGTERM'));

View File

@@ -0,0 +1,107 @@
import { Telegraf, Markup } 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);
}
const bot = new Telegraf(BOT_TOKEN);
// Log startup success
console.log('Keyboard Reset Bot started successfully');
// Debug: Log all incoming updates to see if bot is receiving messages
bot.use(async (ctx, next) => {
console.log('Update received:', {
updateType: ctx.updateType,
chatType: ctx.chat?.type,
chatId: ctx.chat?.id,
fromId: ctx.from?.id,
text: ctx.message?.text || ctx.update.message?.text || 'N/A'
});
return next();
});
// 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 received - 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.log(`Authorization failed - Chat ID: ${chatId}, User ID: ${userId}`);
await ctx.reply('Only group admins can use this command.');
return;
}
// Send keyboard reset message
const sentMessage = await ctx.reply('Keyboard reset.', {
reply_markup: Markup.removeKeyboard()
});
// Log successful reset
console.log(`Keyboard reset successful - Chat ID: ${chatId}, User ID: ${userId}`);
// Delete the confirmation message after 7 seconds
setTimeout(async () => {
try {
await ctx.deleteMessage(sentMessage.message_id);
} catch (error) {
// Silently continue if deletion fails (permissions, race condition, etc.)
// This is expected behavior - do not log or spam
}
}, 7000);
} catch (error) {
// Log errors for debugging
console.error('Error processing command:', error);
console.error('Error details:', {
message: error.message,
code: error.code,
response: error.response
});
// Try to reply with error (but don't spam if it fails)
try {
await ctx.reply('An error occurred while processing the command.');
} catch (replyError) {
// Silently continue if reply also fails
}
}
});
// Handle errors
bot.catch((err, ctx) => {
console.error('Bot error:', err);
});
// Start polling
bot.launch().then(() => {
console.log('Bot is polling for updates...');
}).catch((error) => {
console.error('Failed to start bot:', error);
process.exit(1);
});
// Enable graceful stop
process.once('SIGINT', () => bot.stop('SIGINT'));
process.once('SIGTERM', () => bot.stop('SIGTERM'));

View File

@@ -0,0 +1,107 @@
import { Telegraf, Markup } 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);
}
const bot = new Telegraf(BOT_TOKEN);
// Log startup success
console.log('Keyboard Reset Bot started successfully');
// Debug: Log all incoming updates to see if bot is receiving messages
bot.use(async(ctx, next) => {
console.log('Update received:', {
updateType: ctx.updateType,
chatType: ctx.chat ? .type,
chatId: ctx.chat ? .id,
fromId: ctx.from ? .id,
text: ctx.message ? .text || ctx.update.message ? .text || 'N/A'
});
return next();
});
// 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 received - 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.log(`Authorization failed - Chat ID: ${chatId}, User ID: ${userId}`);
await ctx.reply('Only group admins can use this command.');
return;
}
// Send keyboard reset message
const sentMessage = await ctx.reply('Keyboard reset.', {
reply_markup: Markup.removeKeyboard()
});
// Log successful reset
console.log(`Keyboard reset successful - Chat ID: ${chatId}, User ID: ${userId}`);
// Delete the confirmation message after 7 seconds
setTimeout(async() => {
try {
await ctx.deleteMessage(sentMessage.message_id);
} catch (error) {
// Silently continue if deletion fails (permissions, race condition, etc.)
// This is expected behavior - do not log or spam
}
}, 7000);
} catch (error) {
// Log errors for debugging
console.error('Error processing command:', error);
console.error('Error details:', {
message: error.message,
code: error.code,
response: error.response
});
// Try to reply with error (but don't spam if it fails)
try {
await ctx.reply('An error occurred while processing the command.');
} catch (replyError) {
// Silently continue if reply also fails
}
}
});
// Handle errors
bot.catch((err, ctx) => {
console.error('Bot error:', err);
});
// Start polling
bot.launch().then(() => {
console.log('Bot is polling for updates...');
}).catch((error) => {
console.error('Failed to start bot:', error);
process.exit(1);
});
// Enable graceful stop
process.once('SIGINT', () => bot.stop('SIGINT'));
process.once('SIGTERM', () => bot.stop('SIGTERM'));

View File

@@ -0,0 +1,89 @@
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);
}
const bot = new Telegraf(BOT_TOKEN);
// Log startup success
console.log('Keyboard Reset Bot starting...');
// 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
bot.launch().then(() => {
console.log('Keyboard Reset Bot started successfully');
console.log('Bot is 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'));

View File

@@ -0,0 +1,89 @@
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);
}
const bot = new Telegraf(BOT_TOKEN);
// Log startup success
console.log('Keyboard Reset Bot starting...');
// 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
bot.launch().then(() => {
console.log('Keyboard Reset Bot started successfully');
console.log('Bot is 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'));

View File

@@ -0,0 +1,89 @@
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);
}
const bot = new Telegraf(BOT_TOKEN);
// Log startup success
console.log('Keyboard Reset Bot starting...');
// 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
bot.launch().then(() => {
console.log('Keyboard Reset Bot started successfully');
console.log('Bot is 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'));

View File

@@ -0,0 +1,120 @@
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'));

View File

@@ -0,0 +1,120 @@
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'));

View File

@@ -0,0 +1,120 @@
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'));

View File

@@ -0,0 +1,120 @@
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'));

View File

@@ -0,0 +1,120 @@
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'));

View File

@@ -0,0 +1,120 @@
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'));

View File

@@ -0,0 +1,120 @@
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'));

View File

@@ -0,0 +1,120 @@
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'));

View File

@@ -0,0 +1,120 @@
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'));

View File

@@ -0,0 +1,122 @@
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) => {
const chatType = ctx.chat ? ctx.chat.type : undefined;
const messageText = ctx.message ? ctx.message.text : undefined;
console.log('Update received:', {
type: ctx.updateType,
chat: chatType,
text: messageText
});
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'));

View File

@@ -0,0 +1,122 @@
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) => {
const chatType = ctx.chat ? ctx.chat.type : undefined;
const messageText = ctx.message ? ctx.message.text : undefined;
console.log('Update received:', {
type: ctx.updateType,
chat: chatType,
text: messageText
});
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'));

View File

@@ -0,0 +1,122 @@
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) => {
const chatType = ctx.chat ? ctx.chat.type : undefined;
const messageText = ctx.message ? ctx.message.text : undefined;
console.log('Update received:', {
type: ctx.updateType,
chat: chatType,
text: messageText
});
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'));

View File

@@ -0,0 +1,23 @@
{
"name": "keyboard-reset-bot",
"version": "1.0.0",
"description": "A minimal Telegram bot that removes reply keyboard buttons in group chats",
"main": "bot.js",
"type": "module",
"scripts": {
"start": "node bot.js"
},
"keywords": [
"telegram",
"bot",
"keyboard",
"reset"
],
"author": "",
"license": "MIT",
"dependencies": {
"telegraf": "^4.15.0",
"dotenv": "^16.3.1"
}
}

View File

@@ -0,0 +1,22 @@
{
"name": "keyboard-reset-bot",
"version": "1.0.0",
"description": "A minimal Telegram bot that removes reply keyboard buttons in group chats",
"main": "bot.js",
"type": "module",
"scripts": {
"start": "node bot.js"
},
"keywords": [
"telegram",
"bot",
"keyboard",
"reset"
],
"author": "",
"license": "MIT",
"dependencies": {
"telegraf": "^4.15.0",
"dotenv": "^16.3.1"
}
}

View File

@@ -0,0 +1,22 @@
{
"name": "keyboard-reset-bot",
"version": "1.0.0",
"description": "A minimal Telegram bot that removes reply keyboard buttons in group chats",
"main": "bot.js",
"type": "module",
"scripts": {
"start": "node bot.js"
},
"keywords": [
"telegram",
"bot",
"keyboard",
"reset"
],
"author": "",
"license": "MIT",
"dependencies": {
"telegraf": "^4.15.0",
"dotenv": "^16.3.1"
}
}

62
README.md Normal file
View File

@@ -0,0 +1,62 @@
# Keyboard Reset Bot
A minimal Telegram bot that removes reply keyboard buttons in Telegram group chats by sending a keyboard reset message.
## Features
- Works only in group chats and supergroups
- Single command: `/resetkeyboard`
- Admin-only authorization
- Automatically removes its confirmation message after 7 seconds
- Stateless (no database, no data storage)
## Setup
1. **Get a Bot Token**
- Talk to [@BotFather](https://t.me/botfather) on Telegram
- Create a new bot with `/newbot`
- Copy the bot token
2. **Install Dependencies**
```bash
npm install
```
3. **Configure Environment**
- Copy `.env.example` to `.env`
- Add your bot token:
```
BOT_TOKEN=your_bot_token_here
```
4. **Run the Bot**
```bash
npm start
```
## Usage
1. Add the bot to your Telegram group
2. Grant the bot "Read messages" permission (and optionally "Delete messages" for cleanup)
3. An admin can use `/resetkeyboard` to remove all reply keyboards in the group
## Requirements
- Node.js 14+ (ES modules support)
- Bot permissions: "Read messages" (required), "Delete messages" (optional)
## How It Works
When an admin sends `/resetkeyboard` in a group:
1. The bot verifies the user is an administrator
2. Sends a message with `ReplyKeyboardRemove` (selective: false)
3. This resets reply keyboards for all users who receive the message
4. The bot deletes its own message after 7 seconds
## Notes
- The bot ignores private chats
- Only group administrators can use the command
- The bot is stateless and does not store any data
- If another bot sends a keyboard after reset, it will appear again (expected behavior)

128
about.md Normal file
View File

@@ -0,0 +1,128 @@
BOT NAME
Keyboard Reset Bot (working name)
PURPOSE
A minimal Telegram bot whose only responsibility is to remove reply keyboard buttons in Telegram group chats by sending a keyboard reset message.
This bot does not manage data, users, state, or configuration beyond a single slash command.
CORE FUNCTIONAL REQUIREMENTS
Supported chats
• Group chats
• Supergroups
The bot must ignore private chats.
If used in a private chat, it should reply once with:
“This bot only works in groups.”
Command
Single slash command:
/resetkeyboard
No aliases. No parameters.
Authorization
Only group administrators may trigger the command.
Authorization rules:
• Check the user who sent /resetkeyboard
• If the user is an administrator or creator → allow
• Otherwise → ignore or reply with:
“Only group admins can use this command.”
No role persistence. Authorization is checked per command invocation.
Keyboard removal behavior
When triggered by an authorized user in a group:
The bot sends one normal message to the group with:
• reply_markup = ReplyKeyboardRemove
• selective = false
This message must:
• Be visible (not silent)
• Not be inline
• Not target a specific user
This resets the reply keyboard for all users who receive the message.
Message content
Message text should be short and neutral, for example:
“Keyboard reset.”
No emojis.
No markdown.
No mentions.
Message lifecycle
Optional but recommended:
• The bot deletes its own confirmation message after 510 seconds
• Do NOT delete immediately (clients need time to process the keyboard reset)
If deletion fails (permissions, race condition), the bot must silently continue.
What the bot must NOT do
The bot must NOT:
• Store data
• Track users
• Use a database
• React to normal messages
• Remove inline keyboards
• Delete other bots messages
• Re-send keyboards
• Perform scheduled actions
This is a stateless utility bot.
EDGE CASES AND EXPECTED BEHAVIOR
• If another bot sends a keyboard after this bot runs, that keyboard will appear again. This is expected.
• If a user does not receive the message (offline/network), their keyboard may persist until the next reset.
• This is the only technically correct way to reset keyboards in Telegram.
IMPLEMENTATION CONSTRAINTS
Update handling
Either polling or webhook is acceptable.
Polling is preferred for simplicity.
Libraries
Any official or widely used Telegram library is acceptable, such as:
• python-telegram-bot
• aiogram
• Telegraf (Node.js)
• Raw Bot API (HTTP)
No unofficial wrappers.
Permissions required
The bot must be granted:
• “Read messages”
• “Delete messages” (optional, only for cleanup)
No admin rights beyond this are required.
LOGGING AND ERROR HANDLING
• Log startup success
• Log command usage with chat ID and user ID
• Log authorization failures at debug level
• Fail silently on Telegram API errors (do not spam the group)
SUCCESS CRITERIA
The bot is considered correct if:
• An admin sends /resetkeyboard in a group
• All visible reply keyboards disappear for users in that group
• The bot does nothing else

122
bot.js Normal file
View File

@@ -0,0 +1,122 @@
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) => {
const chatType = ctx.chat ? ctx.chat.type : undefined;
const messageText = ctx.message ? ctx.message.text : undefined;
console.log('Update received:', {
type: ctx.updateType,
chat: chatType,
text: messageText
});
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'));

201
package-lock.json generated Normal file
View File

@@ -0,0 +1,201 @@
{
"name": "keyboard-reset-bot",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "keyboard-reset-bot",
"version": "1.0.0",
"license": "MIT",
"dependencies": {
"dotenv": "^16.3.1",
"telegraf": "^4.15.0"
}
},
"node_modules/@telegraf/types": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/@telegraf/types/-/types-7.1.0.tgz",
"integrity": "sha512-kGevOIbpMcIlCDeorKGpwZmdH7kHbqlk/Yj6dEpJMKEQw5lk0KVQY0OLXaCswy8GqlIVLd5625OB+rAntP9xVw==",
"license": "MIT"
},
"node_modules/abort-controller": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
"integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
"license": "MIT",
"dependencies": {
"event-target-shim": "^5.0.0"
},
"engines": {
"node": ">=6.5"
}
},
"node_modules/buffer-alloc": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz",
"integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==",
"license": "MIT",
"dependencies": {
"buffer-alloc-unsafe": "^1.1.0",
"buffer-fill": "^1.0.0"
}
},
"node_modules/buffer-alloc-unsafe": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz",
"integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==",
"license": "MIT"
},
"node_modules/buffer-fill": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz",
"integrity": "sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==",
"license": "MIT"
},
"node_modules/debug": {
"version": "4.4.3",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
"license": "MIT",
"dependencies": {
"ms": "^2.1.3"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/dotenv": {
"version": "16.6.1",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz",
"integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==",
"license": "BSD-2-Clause",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://dotenvx.com"
}
},
"node_modules/event-target-shim": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
"integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==",
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/mri": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
"integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==",
"license": "MIT",
"engines": {
"node": ">=4"
}
},
"node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"license": "MIT"
},
"node_modules/node-fetch": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
"integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
"license": "MIT",
"dependencies": {
"whatwg-url": "^5.0.0"
},
"engines": {
"node": "4.x || >=6.0.0"
},
"peerDependencies": {
"encoding": "^0.1.0"
},
"peerDependenciesMeta": {
"encoding": {
"optional": true
}
}
},
"node_modules/p-timeout": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-4.1.0.tgz",
"integrity": "sha512-+/wmHtzJuWii1sXn3HCuH/FTwGhrp4tmJTxSKJbfS+vkipci6osxXM5mY0jUiRzWKMTgUT8l7HFbeSwZAynqHw==",
"license": "MIT",
"engines": {
"node": ">=10"
}
},
"node_modules/safe-compare": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/safe-compare/-/safe-compare-1.1.4.tgz",
"integrity": "sha512-b9wZ986HHCo/HbKrRpBJb2kqXMK9CEWIE1egeEvZsYn69ay3kdfl9nG3RyOcR+jInTDf7a86WQ1d4VJX7goSSQ==",
"license": "MIT",
"dependencies": {
"buffer-alloc": "^1.2.0"
}
},
"node_modules/sandwich-stream": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/sandwich-stream/-/sandwich-stream-2.0.2.tgz",
"integrity": "sha512-jLYV0DORrzY3xaz/S9ydJL6Iz7essZeAfnAavsJ+zsJGZ1MOnsS52yRjU3uF3pJa/lla7+wisp//fxOwOH8SKQ==",
"license": "Apache-2.0",
"engines": {
"node": ">= 0.10"
}
},
"node_modules/telegraf": {
"version": "4.16.3",
"resolved": "https://registry.npmjs.org/telegraf/-/telegraf-4.16.3.tgz",
"integrity": "sha512-yjEu2NwkHlXu0OARWoNhJlIjX09dRktiMQFsM678BAH/PEPVwctzL67+tvXqLCRQQvm3SDtki2saGO9hLlz68w==",
"license": "MIT",
"dependencies": {
"@telegraf/types": "^7.1.0",
"abort-controller": "^3.0.0",
"debug": "^4.3.4",
"mri": "^1.2.0",
"node-fetch": "^2.7.0",
"p-timeout": "^4.1.0",
"safe-compare": "^1.1.4",
"sandwich-stream": "^2.0.2"
},
"bin": {
"telegraf": "lib/cli.mjs"
},
"engines": {
"node": "^12.20.0 || >=14.13.1"
}
},
"node_modules/tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
"license": "MIT"
},
"node_modules/webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
"license": "BSD-2-Clause"
},
"node_modules/whatwg-url": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
"license": "MIT",
"dependencies": {
"tr46": "~0.0.3",
"webidl-conversions": "^3.0.0"
}
}
}
}

22
package.json Normal file
View File

@@ -0,0 +1,22 @@
{
"name": "keyboard-reset-bot",
"version": "1.0.0",
"description": "A minimal Telegram bot that removes reply keyboard buttons in group chats",
"main": "bot.js",
"type": "module",
"scripts": {
"start": "node bot.js"
},
"keywords": [
"telegram",
"bot",
"keyboard",
"reset"
],
"author": "",
"license": "MIT",
"dependencies": {
"telegraf": "^4.15.0",
"dotenv": "^16.3.1"
}
}