feat: Add Telegram bot with group support

- Full Telegram bot implementation for Lightning Jackpot
- Commands: /start, /buy, /tickets, /wins, /address, /jackpot, /help
- Lightning invoice generation with QR codes
- Payment polling and confirmation notifications
- User state management (Redis/in-memory fallback)
- Group support with admin settings panel
- Configurable draw announcements and reminders
- Centralized messages for easy i18n
- Docker configuration included
This commit is contained in:
Michilis
2025-11-27 23:10:25 +00:00
parent d3bf8080b6
commit f743a6749c
29 changed files with 7616 additions and 1 deletions

View File

@@ -0,0 +1,68 @@
import TelegramBot from 'node-telegram-bot-api';
import { stateManager } from '../services/state';
import { logger, logUserAction } from '../services/logger';
import { getMainMenuKeyboard, getCancelKeyboard } from '../utils/keyboards';
import { messages } from '../messages';
/**
* Handle /start command
*/
export async function handleStart(bot: TelegramBot, msg: TelegramBot.Message): Promise<void> {
const chatId = msg.chat.id;
const userId = msg.from?.id;
if (!userId) {
await bot.sendMessage(chatId, messages.errors.userNotIdentified);
return;
}
logUserAction(userId, 'Started bot', {
username: msg.from?.username,
firstName: msg.from?.first_name,
});
try {
// Check if user exists
let user = await stateManager.getUser(userId);
if (!user) {
// Create new user
user = await stateManager.createUser(
userId,
msg.from?.username,
msg.from?.first_name,
msg.from?.last_name
);
}
// Welcome message
await bot.sendMessage(chatId, messages.start.welcome, { parse_mode: 'Markdown' });
// Check if lightning address is set
if (!user.lightningAddress) {
await bot.sendMessage(chatId, messages.start.needAddress, {
parse_mode: 'Markdown',
reply_markup: getCancelKeyboard(),
});
await stateManager.updateUserState(userId, 'awaiting_lightning_address');
} else {
// Show main menu
await bot.sendMessage(
chatId,
messages.start.addressSet(user.lightningAddress),
{
parse_mode: 'Markdown',
reply_markup: getMainMenuKeyboard(),
}
);
await stateManager.updateUserState(userId, 'idle');
}
} catch (error) {
logger.error('Error in handleStart', { error, userId });
await bot.sendMessage(chatId, messages.errors.startAgain);
}
}
export default handleStart;