Disable keyboard buttons completely in group chats

- Added getReplyMarkupForChat utility to explicitly remove keyboards in groups
- Updated all group chat messages to remove keyboards
- Prevents keyboards from being re-enabled when users press buttons
- Ensures keyboards are disabled for all users in group chats
This commit is contained in:
Michilis
2025-12-25 18:03:16 +00:00
parent ff9c1f1dcf
commit d1ce0f0bef
5 changed files with 104 additions and 58 deletions

View File

@@ -10,6 +10,7 @@ import {
getViewTicketKeyboard,
getMainMenuKeyboard,
getCancelKeyboard,
getReplyMarkupForChat,
} from '../utils/keyboards';
import { formatSats, formatDate, formatTimeUntil } from '../utils/format';
import { PendingPurchaseData, AwaitingPaymentData } from '../types';
@@ -71,7 +72,9 @@ export async function handleBuyCommand(
if (!user.lightningAddress) {
await bot.sendMessage(chatId, messages.address.needAddressFirst, {
parse_mode: 'Markdown',
reply_markup: getCancelKeyboard(),
reply_markup: isGroupChat(chatId)
? getReplyMarkupForChat(chatId)
: getCancelKeyboard(),
});
await stateManager.updateUserState(userId, 'awaiting_lightning_address');
return;
@@ -81,7 +84,10 @@ export async function handleBuyCommand(
const jackpot = await apiClient.getNextJackpot();
if (!jackpot) {
await bot.sendMessage(chatId, messages.buy.noActiveJackpot, { parse_mode: 'Markdown' });
await bot.sendMessage(chatId, messages.buy.noActiveJackpot, {
parse_mode: 'Markdown',
reply_markup: getReplyMarkupForChat(chatId),
});
return;
}
@@ -96,7 +102,9 @@ export async function handleBuyCommand(
await bot.sendMessage(chatId, message, {
parse_mode: 'Markdown',
reply_markup: getTicketAmountKeyboard(),
reply_markup: isGroupChat(chatId)
? getReplyMarkupForChat(chatId)
: getTicketAmountKeyboard(),
});
// Store jackpot info in state for later use
@@ -195,7 +203,11 @@ export async function handleCustomTicketAmount(
await bot.sendMessage(
chatId,
messages.buy.invalidNumber(config.bot.maxTicketsPerPurchase),
{ reply_markup: getCancelKeyboard() }
{
reply_markup: isGroupChat(chatId)
? getReplyMarkupForChat(chatId)
: getCancelKeyboard(),
}
);
return true;
}
@@ -204,7 +216,11 @@ export async function handleCustomTicketAmount(
await bot.sendMessage(
chatId,
messages.buy.tooManyTickets(config.bot.maxTicketsPerPurchase),
{ reply_markup: getCancelKeyboard() }
{
reply_markup: isGroupChat(chatId)
? getReplyMarkupForChat(chatId)
: getCancelKeyboard(),
}
);
return true;
}
@@ -359,8 +375,7 @@ export async function handlePurchaseConfirmation(
} catch (error) {
logger.error('Error in handlePurchaseConfirmation', { error, userId });
await bot.sendMessage(chatId, messages.errors.invoiceCreationFailed, {
// Only show reply keyboard in private chats, not in groups
...(isGroupChat(chatId) ? {} : { reply_markup: getMainMenuKeyboard() }),
reply_markup: getReplyMarkupForChat(chatId, getMainMenuKeyboard()),
});
await stateManager.clearUserStateData(userId);
}
@@ -421,8 +436,7 @@ async function pollPaymentStatus(
await bot.sendMessage(chatId, messages.buy.invoiceExpired, {
parse_mode: 'Markdown',
// Only show reply keyboard in private chats, not in groups
...(isGroupChat(chatId) ? {} : { reply_markup: getMainMenuKeyboard() }),
reply_markup: getReplyMarkupForChat(chatId, getMainMenuKeyboard()),
});
await stateManager.clearUserStateData(userId);
return;
@@ -476,8 +490,7 @@ async function pollPaymentStatus(
await bot.sendMessage(chatId, messages.buy.invoiceExpiredShort, {
parse_mode: 'Markdown',
// Only show reply keyboard in private chats, not in groups
...(isGroupChat(chatId) ? {} : { reply_markup: getMainMenuKeyboard() }),
reply_markup: getReplyMarkupForChat(chatId, getMainMenuKeyboard()),
});
await stateManager.clearUserStateData(userId);
return;

View File

@@ -2,6 +2,7 @@ import TelegramBot from 'node-telegram-bot-api';
import { groupStateManager } from '../services/groupState';
import { logger, logUserAction } from '../services/logger';
import { messages } from '../messages';
import { getReplyMarkupForChat } from '../utils/keyboards';
import {
GroupSettings,
REMINDER_PRESETS,
@@ -52,6 +53,7 @@ export async function handleBotAddedToGroup(
await bot.sendMessage(chatId, messages.groups.welcome(chatTitle), {
parse_mode: 'Markdown',
reply_markup: getReplyMarkupForChat(chatId),
});
} catch (error) {
logger.error('Failed to register group', { error, chatId });
@@ -97,7 +99,9 @@ export async function handleGroupSettings(
// Check if user is admin
const isAdmin = await isGroupAdmin(bot, chatId, userId);
if (!isAdmin) {
await bot.sendMessage(chatId, messages.groups.adminOnly);
await bot.sendMessage(chatId, messages.groups.adminOnly, {
reply_markup: getReplyMarkupForChat(chatId),
});
return;
}
@@ -117,7 +121,9 @@ export async function handleGroupSettings(
const currentSettings = settings || await groupStateManager.getGroup(chatId);
if (!currentSettings) {
await bot.sendMessage(chatId, messages.errors.generic);
await bot.sendMessage(chatId, messages.errors.generic, {
reply_markup: getReplyMarkupForChat(chatId),
});
return;
}
@@ -138,19 +144,27 @@ export async function handleGroupSettings(
// Notify in the group that settings were sent to DM
await bot.sendMessage(
chatId,
`⚙️ @${msg.from?.username || 'Admin'}, I've sent the group settings to your DMs!`
`⚙️ @${msg.from?.username || 'Admin'}, I've sent the group settings to your DMs!`,
{
reply_markup: getReplyMarkupForChat(chatId),
}
);
} catch (dmError) {
// If DM fails (user hasn't started the bot), prompt them to start it
logger.warn('Failed to send settings DM', { error: dmError, userId });
await bot.sendMessage(
chatId,
`⚙️ @${msg.from?.username || 'Admin'}, please start a private chat with me first (@LightningLottoBot) so I can send you the settings.`
`⚙️ @${msg.from?.username || 'Admin'}, please start a private chat with me first (@LightningLottoBot) so I can send you the settings.`,
{
reply_markup: getReplyMarkupForChat(chatId),
}
);
}
} catch (error) {
logger.error('Error in handleGroupSettings', { error, chatId });
await bot.sendMessage(chatId, messages.errors.generic);
await bot.sendMessage(chatId, messages.errors.generic, {
reply_markup: getReplyMarkupForChat(chatId),
});
}
}
@@ -583,7 +597,10 @@ export async function broadcastDrawAnnouncement(
for (const group of groups) {
try {
await bot.sendMessage(group.groupId, announcement, { parse_mode: 'Markdown' });
await bot.sendMessage(group.groupId, announcement, {
parse_mode: 'Markdown',
reply_markup: getReplyMarkupForChat(group.groupId),
});
sent++;
} catch (error) {
logger.error('Failed to send announcement to group', {
@@ -613,7 +630,10 @@ export async function broadcastDrawReminder(
for (const group of groups) {
try {
await bot.sendMessage(group.groupId, reminder, { parse_mode: 'Markdown' });
await bot.sendMessage(group.groupId, reminder, {
parse_mode: 'Markdown',
reply_markup: getReplyMarkupForChat(group.groupId),
});
sent++;
} catch (error) {
logger.error('Failed to send reminder to group', {

View File

@@ -1,6 +1,6 @@
import TelegramBot from 'node-telegram-bot-api';
import { logUserAction } from '../services/logger';
import { getMainMenuKeyboard } from '../utils/keyboards';
import { getMainMenuKeyboard, getReplyMarkupForChat } from '../utils/keyboards';
import { messages } from '../messages';
/**
@@ -22,6 +22,7 @@ export async function handleHelpCommand(
// Show group-specific help with admin commands
await bot.sendMessage(chatId, messages.help.groupMessage, {
parse_mode: 'Markdown',
reply_markup: getReplyMarkupForChat(chatId),
});
} else {
// Show user help in DM