first commit
This commit is contained in:
1
.env.example
Normal file
1
.env.example
Normal file
@@ -0,0 +1 @@
|
|||||||
|
BOT_TOKEN=your_bot_token_here
|
||||||
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
node_modules/
|
||||||
|
.env
|
||||||
|
*.log
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
0
.history/.env_20251216201616
Normal file
0
.history/.env_20251216201616
Normal file
1
.history/.env_20251216201624
Normal file
1
.history/.env_20251216201624
Normal file
@@ -0,0 +1 @@
|
|||||||
|
BOT_TOKEN=your_bot_token_here
|
||||||
1
.history/.env_20251216201746
Normal file
1
.history/.env_20251216201746
Normal file
@@ -0,0 +1 @@
|
|||||||
|
BOT_TOKEN=8531569553:AAFT-SvBHGCDnF_8dvwyEiLRA1ome-p-ttc
|
||||||
2
.history/.env_20251216205724
Normal file
2
.history/.env_20251216205724
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
#BOT_TOKEN=8531569553:AAFT-SvBHGCDnF_8dvwyEiLRA1ome-p-ttc
|
||||||
|
BOT_TOKEN=8566687126:AAGw-zhiTml3qZyXfdEkF0Jag5MTCqhO1BU
|
||||||
1
.history/.env_20251216210105
Normal file
1
.history/.env_20251216210105
Normal file
@@ -0,0 +1 @@
|
|||||||
|
BOT_TOKEN=8531569553:AAFT-SvBHGCDnF_8dvwyEiLRA1ome-p-ttc
|
||||||
2
.history/.env_20251217082418
Normal file
2
.history/.env_20251217082418
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
#BOT_TOKEN=8531569553:AAFT-SvBHGCDnF_8dvwyEiLRA1ome-p-ttc
|
||||||
|
BOT_TOKEN=8566687126:AAGw-zhiTml3qZyXfdEkF0Jag5MTCqhO1BU
|
||||||
62
.history/README_20251216201331.md
Normal file
62
.history/README_20251216201331.md
Normal 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)
|
||||||
|
|
||||||
62
.history/README_20251216201351.md
Normal file
62
.history/README_20251216201351.md
Normal 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)
|
||||||
|
|
||||||
0
.history/about_20251216204253.md
Normal file
0
.history/about_20251216204253.md
Normal file
128
.history/about_20251216204256.md
Normal file
128
.history/about_20251216204256.md
Normal 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 5–10 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
|
||||||
86
.history/bot_20251216201350.js
Normal file
86
.history/bot_20251216201350.js
Normal 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'));
|
||||||
|
|
||||||
85
.history/bot_20251216201358.js
Normal file
85
.history/bot_20251216201358.js
Normal 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'));
|
||||||
97
.history/bot_20251216201948.js
Normal file
97
.history/bot_20251216201948.js
Normal 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'));
|
||||||
107
.history/bot_20251216201952.js
Normal file
107
.history/bot_20251216201952.js
Normal 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'));
|
||||||
107
.history/bot_20251216201956.js
Normal file
107
.history/bot_20251216201956.js
Normal 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'));
|
||||||
107
.history/bot_20251216202004.js
Normal file
107
.history/bot_20251216202004.js
Normal 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'));
|
||||||
107
.history/bot_20251216202006.js
Normal file
107
.history/bot_20251216202006.js
Normal 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'));
|
||||||
107
.history/bot_20251216202021.js
Normal file
107
.history/bot_20251216202021.js
Normal 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'));
|
||||||
107
.history/bot_20251216202022.js
Normal file
107
.history/bot_20251216202022.js
Normal 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'));
|
||||||
107
.history/bot_20251216202030.js
Normal file
107
.history/bot_20251216202030.js
Normal 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'));
|
||||||
107
.history/bot_20251216202045.js
Normal file
107
.history/bot_20251216202045.js
Normal 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'));
|
||||||
107
.history/bot_20251216202046.js
Normal file
107
.history/bot_20251216202046.js
Normal 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'));
|
||||||
107
.history/bot_20251216202047.js
Normal file
107
.history/bot_20251216202047.js
Normal 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'));
|
||||||
107
.history/bot_20251216202053.js
Normal file
107
.history/bot_20251216202053.js
Normal 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'));
|
||||||
107
.history/bot_20251216202108.js
Normal file
107
.history/bot_20251216202108.js
Normal 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'));
|
||||||
107
.history/bot_20251216202110.js
Normal file
107
.history/bot_20251216202110.js
Normal 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'));
|
||||||
107
.history/bot_20251216202111.js
Normal file
107
.history/bot_20251216202111.js
Normal 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'));
|
||||||
107
.history/bot_20251216202116.js
Normal file
107
.history/bot_20251216202116.js
Normal 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'));
|
||||||
89
.history/bot_20251216204344.js
Normal file
89
.history/bot_20251216204344.js
Normal 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'));
|
||||||
89
.history/bot_20251216204356.js
Normal file
89
.history/bot_20251216204356.js
Normal 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'));
|
||||||
89
.history/bot_20251216204358.js
Normal file
89
.history/bot_20251216204358.js
Normal 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'));
|
||||||
120
.history/bot_20251216204824.js
Normal file
120
.history/bot_20251216204824.js
Normal 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'));
|
||||||
120
.history/bot_20251216204836.js
Normal file
120
.history/bot_20251216204836.js
Normal 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'));
|
||||||
120
.history/bot_20251216204928.js
Normal file
120
.history/bot_20251216204928.js
Normal 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'));
|
||||||
120
.history/bot_20251216204946.js
Normal file
120
.history/bot_20251216204946.js
Normal 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'));
|
||||||
120
.history/bot_20251216204950.js
Normal file
120
.history/bot_20251216204950.js
Normal 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'));
|
||||||
120
.history/bot_20251216205010.js
Normal file
120
.history/bot_20251216205010.js
Normal 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'));
|
||||||
120
.history/bot_20251216205016.js
Normal file
120
.history/bot_20251216205016.js
Normal 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'));
|
||||||
120
.history/bot_20251216205023.js
Normal file
120
.history/bot_20251216205023.js
Normal 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'));
|
||||||
120
.history/bot_20251216205028.js
Normal file
120
.history/bot_20251216205028.js
Normal 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'));
|
||||||
122
.history/bot_20251216205056.js
Normal file
122
.history/bot_20251216205056.js
Normal 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'));
|
||||||
122
.history/bot_20251216205100.js
Normal file
122
.history/bot_20251216205100.js
Normal 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'));
|
||||||
122
.history/bot_20251216205103.js
Normal file
122
.history/bot_20251216205103.js
Normal 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'));
|
||||||
23
.history/package_20251216201322.json
Normal file
23
.history/package_20251216201322.json
Normal 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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
22
.history/package_20251216201351.json
Normal file
22
.history/package_20251216201351.json
Normal 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"
|
||||||
|
}
|
||||||
|
}
|
||||||
22
.history/package_20251216202006.json
Normal file
22
.history/package_20251216202006.json
Normal 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
62
README.md
Normal 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
128
about.md
Normal 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 5–10 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
122
bot.js
Normal 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
201
package-lock.json
generated
Normal 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
22
package.json
Normal 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"
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user