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:
444
telegram_bot/src/messages/index.ts
Normal file
444
telegram_bot/src/messages/index.ts
Normal file
@@ -0,0 +1,444 @@
|
||||
/**
|
||||
* All Telegram bot messages centralized for easy management and future i18n support
|
||||
*/
|
||||
|
||||
export const messages = {
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// ERRORS
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
errors: {
|
||||
userNotIdentified: '❌ Could not identify user.',
|
||||
startFirst: '❌ Please start the bot first with /start',
|
||||
generic: '❌ An error occurred. Please try again.',
|
||||
startAgain: '❌ An error occurred. Please try again with /start',
|
||||
systemUnavailable: '❌ The lottery system is temporarily unavailable. Please try again soon.',
|
||||
invoiceCreationFailed: '❌ Failed to create invoice. Please try again.',
|
||||
fetchTicketsFailed: '❌ Failed to fetch tickets. Please try again.',
|
||||
fetchWinsFailed: '❌ Failed to fetch wins. Please try again.',
|
||||
ticketNotFound: '❌ Ticket not found.',
|
||||
fetchTicketDetailsFailed: '❌ Failed to fetch ticket details.',
|
||||
checkStatusFailed: '❌ Failed to check status',
|
||||
noPendingPurchase: '❌ No pending purchase. Please start again with /buy',
|
||||
setAddressFirst: '❌ Please set your Lightning Address first.',
|
||||
},
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// START / ONBOARDING
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
start: {
|
||||
welcome: `⚡🎉 *Welcome to Lightning Jackpot!* 🎉⚡
|
||||
|
||||
You can buy Bitcoin Lightning lottery tickets, and if you win, your prize is paid instantly to your Lightning Address!
|
||||
|
||||
🎯 *How it works:*
|
||||
1️⃣ Set your Lightning Address (where you'll receive winnings)
|
||||
2️⃣ Buy tickets with Lightning
|
||||
3️⃣ Wait for the draw
|
||||
4️⃣ If you win, prize is sent instantly!`,
|
||||
|
||||
needAddress: `Before you can play, I need your Lightning Address to send any winnings.
|
||||
|
||||
*Example:* \`yourname@getalby.com\`
|
||||
|
||||
Please send your Lightning Address now:`,
|
||||
|
||||
addressSet: (address: string) =>
|
||||
`✅ Your payout address is set to: \`${address}\`
|
||||
|
||||
Use the menu below to get started! Good luck! 🍀`,
|
||||
|
||||
welcomeUnknown: '👋 Welcome! Please use /start to begin.',
|
||||
},
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// LIGHTNING ADDRESS
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
address: {
|
||||
currentAddress: (address: string) =>
|
||||
`⚡ *Your Current Payout Address:*
|
||||
\`${address}\`
|
||||
|
||||
Send me your new Lightning Address to update it:`,
|
||||
|
||||
noAddressSet: `⚡ You don't have a Lightning Address set yet.
|
||||
|
||||
Send me your Lightning Address now:
|
||||
|
||||
*Example:* \`yourname@getalby.com\``,
|
||||
|
||||
invalidFormat: `❌ That doesn't look like a valid Lightning Address.
|
||||
|
||||
*Format:* \`username@domain.com\`
|
||||
*Example:* \`satoshi@getalby.com\`
|
||||
|
||||
Please try again:`,
|
||||
|
||||
firstTimeSuccess: (address: string) =>
|
||||
`✅ *Perfect!* I'll use \`${address}\` to send any winnings.
|
||||
|
||||
You're all set! Use the menu below to buy tickets and check your results. Good luck! 🍀`,
|
||||
|
||||
updateSuccess: (address: string) =>
|
||||
`✅ *Lightning Address updated!*
|
||||
|
||||
New address: \`${address}\`
|
||||
|
||||
⚠️ *Note:* Previous ticket purchases will still use their original addresses.`,
|
||||
|
||||
saveFailed: '❌ An error occurred saving your address. Please try again.',
|
||||
|
||||
needAddressFirst: `❌ I don't have your Lightning Address yet!
|
||||
|
||||
Please send your Lightning Address first:
|
||||
|
||||
*Example:* \`yourname@getalby.com\``,
|
||||
},
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// BUY TICKETS
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
buy: {
|
||||
noActiveJackpot: `😔 *No Active Jackpot*
|
||||
|
||||
There's no lottery cycle available right now. Please check back soon!`,
|
||||
|
||||
jackpotInfo: (
|
||||
potSats: string,
|
||||
ticketPrice: string,
|
||||
drawTime: string,
|
||||
timeLeft: string
|
||||
) =>
|
||||
`🎰 *Next Jackpot Info*
|
||||
|
||||
💰 *Prize Pool:* ${potSats} sats
|
||||
🎟 *Ticket Price:* ${ticketPrice} sats each
|
||||
⏰ *Draw at:* ${drawTime}
|
||||
⏳ *Time left:* ${timeLeft}
|
||||
|
||||
How many tickets do you want to buy?`,
|
||||
|
||||
customAmountPrompt: (maxTickets: number) =>
|
||||
`🔢 *Custom Amount*
|
||||
|
||||
Enter the number of tickets you want to buy (1-${maxTickets}):`,
|
||||
|
||||
invalidNumber: (maxTickets: number) =>
|
||||
`❌ Please enter a valid number (1-${maxTickets}):`,
|
||||
|
||||
tooManyTickets: (maxTickets: number) =>
|
||||
`❌ Maximum ${maxTickets} tickets per purchase.
|
||||
|
||||
Please enter a smaller number:`,
|
||||
|
||||
confirmPurchase: (
|
||||
ticketCount: number,
|
||||
ticketPrice: string,
|
||||
totalAmount: string,
|
||||
drawTime: string
|
||||
) =>
|
||||
`📋 *Confirm Purchase*
|
||||
|
||||
🎟 *Tickets:* ${ticketCount}
|
||||
💰 *Price:* ${ticketPrice} sats each
|
||||
💵 *Total:* ${totalAmount} sats
|
||||
|
||||
⏰ *Draw:* ${drawTime}
|
||||
|
||||
Confirm this purchase?`,
|
||||
|
||||
creatingInvoice: 'Creating invoice...',
|
||||
|
||||
invoiceCreated: '💸 *Pay this Lightning invoice to complete your purchase:*',
|
||||
|
||||
invoiceCaption: (
|
||||
ticketCount: number,
|
||||
totalAmount: string,
|
||||
paymentRequest: string,
|
||||
expiryMinutes: number
|
||||
) =>
|
||||
`🎟 *${ticketCount} ticket${ticketCount > 1 ? 's' : ''}*
|
||||
💰 *Amount:* ${totalAmount} sats
|
||||
|
||||
\`${paymentRequest}\`
|
||||
|
||||
⏳ This invoice expires in ${expiryMinutes} minutes.
|
||||
I'll notify you when payment is received!`,
|
||||
|
||||
paymentReceived: (ticketNumbers: string, drawTime: string) =>
|
||||
`🎉 *Payment Received!*
|
||||
|
||||
Your tickets have been issued!
|
||||
|
||||
*Your Ticket Numbers:*
|
||||
${ticketNumbers}
|
||||
|
||||
*Draw Time:* ${drawTime}
|
||||
|
||||
Good luck! 🍀 I'll notify you after the draw!`,
|
||||
|
||||
invoiceExpired: `❌ *Invoice Expired*
|
||||
|
||||
No payment was received in time. No tickets were issued.
|
||||
|
||||
Use /buy to try again.`,
|
||||
|
||||
invoiceExpiredShort: `❌ *Invoice Expired*
|
||||
|
||||
This invoice has expired. No tickets were issued.
|
||||
|
||||
Use /buy to try again.`,
|
||||
|
||||
jackpotUnavailable: '❌ Jackpot is no longer available.',
|
||||
},
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// TICKETS
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
tickets: {
|
||||
header: `🧾 *Your Recent Purchases*\n\n`,
|
||||
|
||||
empty: `🧾 *Your Tickets*
|
||||
|
||||
You haven't purchased any tickets yet!
|
||||
|
||||
Use /buy to get started! 🎟`,
|
||||
|
||||
notFound: `🧾 *Your Tickets*
|
||||
|
||||
No ticket purchases found. Purchase history may have expired.
|
||||
|
||||
Use /buy to get new tickets! 🎟`,
|
||||
|
||||
tapForDetails: `\nTap a ticket below for details:`,
|
||||
|
||||
statusPending: 'Pending',
|
||||
statusExpired: 'Expired',
|
||||
statusActive: 'Active',
|
||||
statusWon: 'Won!',
|
||||
statusLost: 'Lost',
|
||||
|
||||
// Ticket detail view
|
||||
detailHeader: '🎫 *Ticket Details*',
|
||||
|
||||
detailAwaitingPayment: '⏳ *Status:* Awaiting Payment',
|
||||
detailExpired: '❌ *Status:* Invoice Expired (No tickets issued)',
|
||||
detailActive: '🎟 *Status:* Active - Draw Pending',
|
||||
detailWinner: (prizeSats: string, payoutStatus: string) =>
|
||||
`🏆 *Status:* WINNER!
|
||||
💰 *Prize:* ${prizeSats} sats
|
||||
📤 *Payout:* ${payoutStatus}`,
|
||||
detailLost: (winningTicketId: string) =>
|
||||
`😔 *Status:* Did not win this round
|
||||
🎯 *Winning Ticket:* #${winningTicketId}`,
|
||||
|
||||
detailFormat: (
|
||||
purchaseId: string,
|
||||
ticketCount: number,
|
||||
ticketNumbers: string,
|
||||
amountSats: string,
|
||||
drawDate: string,
|
||||
statusSection: string
|
||||
) =>
|
||||
`🎫 *Ticket Details*
|
||||
|
||||
📋 *Purchase ID:* \`${purchaseId}...\`
|
||||
🎟 *Tickets:* ${ticketCount}
|
||||
🔢 *Numbers:* ${ticketNumbers}
|
||||
💰 *Amount Paid:* ${amountSats} sats
|
||||
📅 *Draw:* ${drawDate}
|
||||
|
||||
${statusSection}`,
|
||||
|
||||
// Status check responses
|
||||
checkStatusPending: '⏳ Still waiting for payment...',
|
||||
checkStatusConfirmed: '✅ Payment confirmed! Tickets issued. Waiting for draw...',
|
||||
checkStatusWon: '🏆 YOU WON! Check your Lightning wallet!',
|
||||
checkStatusLost: '😔 Draw completed. Better luck next time!',
|
||||
checkStatusExpired: '❌ Invoice expired. No tickets were issued.',
|
||||
checkStatusProcessing: '⏳ Processing...',
|
||||
},
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// WINS
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
wins: {
|
||||
empty: `🏆 *Your Wins*
|
||||
|
||||
You haven't purchased any tickets yet, so no wins to show!
|
||||
|
||||
Use /buy to get started! 🎟`,
|
||||
|
||||
noWinsYet: `🏆 *Your Wins*
|
||||
|
||||
You haven't won any jackpots yet. Keep playing!
|
||||
|
||||
Use /buy to get more tickets! 🎟🍀`,
|
||||
|
||||
header: (totalWinnings: string, paidWinnings: string) =>
|
||||
`🏆 *Your Wins*
|
||||
|
||||
💰 *Total Winnings:* ${totalWinnings} sats
|
||||
✅ *Paid:* ${paidWinnings} sats
|
||||
|
||||
*Win History:*
|
||||
`,
|
||||
},
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// HELP
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
help: {
|
||||
message: `⚡🎰 *Lightning Jackpot Bot* 🎰⚡
|
||||
|
||||
This is the Lightning Jackpot lottery bot! Buy tickets with Bitcoin Lightning, and if you win, your prize is paid instantly!
|
||||
|
||||
*How It Works:*
|
||||
1️⃣ Set your Lightning Address (where winnings go)
|
||||
2️⃣ Buy tickets using the menu
|
||||
3️⃣ Pay the Lightning invoice
|
||||
4️⃣ Wait for the draw
|
||||
5️⃣ If you win, sats are sent to your address instantly!
|
||||
|
||||
*Commands:*
|
||||
• /buy — Buy lottery tickets
|
||||
• /tickets — View your tickets
|
||||
• /wins — View your past wins
|
||||
• /address — Update Lightning Address
|
||||
• /menu — Show main menu
|
||||
• /help — Show this help
|
||||
|
||||
*Tips:*
|
||||
🎟 Each ticket is one chance to win
|
||||
💰 Prize pool grows with each ticket sold
|
||||
⚡ Winnings are paid instantly via Lightning
|
||||
🔔 You'll be notified after every draw
|
||||
|
||||
Good luck! 🍀`,
|
||||
},
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// MENU
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
menu: {
|
||||
header: `🎰 *Lightning Jackpot Menu*
|
||||
|
||||
What would you like to do?`,
|
||||
|
||||
cancelled: '❌ Cancelled.',
|
||||
whatToDo: 'What would you like to do?',
|
||||
didNotUnderstand:
|
||||
"I didn't understand that. Use the menu below or type /help for available commands.",
|
||||
},
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// DRAW NOTIFICATIONS
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
notifications: {
|
||||
winner: (
|
||||
prizeSats: string,
|
||||
winningTicket: string,
|
||||
payoutStatus: string
|
||||
) =>
|
||||
`🎉 *YOU WON THE LIGHTNING JACKPOT!* 🎉
|
||||
|
||||
💰 *Prize:* ${prizeSats} sats
|
||||
🎟 *Winning Ticket:* #${winningTicket}
|
||||
📤 *Payout Status:* ${payoutStatus}
|
||||
|
||||
Congratulations! 🥳`,
|
||||
|
||||
loser: (winningTicket: string, prizeSats: string) =>
|
||||
`The draw has finished!
|
||||
Your tickets did not win this time.
|
||||
|
||||
🎟 *Winning Ticket:* #${winningTicket}
|
||||
💰 *Prize:* ${prizeSats} sats
|
||||
|
||||
Good luck next round! 🍀`,
|
||||
|
||||
drawAnnouncement: (
|
||||
winnerName: string,
|
||||
winningTicket: string,
|
||||
prizeSats: string,
|
||||
totalTickets: number
|
||||
) =>
|
||||
`🎰 *JACKPOT DRAW COMPLETE!* 🎰
|
||||
|
||||
🏆 *Winner:* ${winnerName}
|
||||
🎟 *Winning Ticket:* #${winningTicket}
|
||||
💰 *Prize:* ${prizeSats} sats
|
||||
📊 *Total Tickets:* ${totalTickets}
|
||||
|
||||
Congratulations to the winner! ⚡
|
||||
|
||||
Use /buy to enter the next draw! 🍀`,
|
||||
|
||||
drawReminder: (potSats: string, drawTime: string, timeLeft: string) =>
|
||||
`⏰ *Draw Reminder!*
|
||||
|
||||
🎰 The next Lightning Jackpot draw is coming up!
|
||||
|
||||
💰 *Current Prize Pool:* ${potSats} sats
|
||||
🕐 *Draw Time:* ${drawTime}
|
||||
⏳ *Time Left:* ${timeLeft}
|
||||
|
||||
Don't miss your chance to win! Use /buy to get your tickets! 🎟`,
|
||||
},
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// GROUPS
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
groups: {
|
||||
welcome: (groupName: string) =>
|
||||
`⚡🎰 *Lightning Jackpot Bot Added!* 🎰⚡
|
||||
|
||||
Hello *${groupName}*! I'm the Lightning Jackpot lottery bot.
|
||||
|
||||
I can announce lottery draws and remind you when jackpots are coming up!
|
||||
|
||||
*Group Admin Commands:*
|
||||
• /settings — Configure bot settings for this group
|
||||
|
||||
*User Commands:*
|
||||
• /buy — Buy lottery tickets (in DM)
|
||||
• /jackpot — View current jackpot info
|
||||
• /help — Get help
|
||||
|
||||
To buy tickets, message me directly @LightningLottoBot! 🎟`,
|
||||
|
||||
privateChat: '❌ This command only works in groups. Use /menu to see available commands.',
|
||||
|
||||
adminOnly: '⚠️ Only group administrators can change these settings.',
|
||||
|
||||
settingsOverview: (settings: {
|
||||
groupTitle: string;
|
||||
enabled: boolean;
|
||||
drawAnnouncements: boolean;
|
||||
reminders: boolean;
|
||||
ticketPurchaseAllowed: boolean;
|
||||
}) =>
|
||||
`⚙️ *Group Settings*
|
||||
|
||||
📍 *Group:* ${settings.groupTitle}
|
||||
|
||||
*Current Configuration:*
|
||||
${settings.enabled ? '✅' : '❌'} Bot Enabled
|
||||
${settings.drawAnnouncements ? '✅' : '❌'} Draw Announcements
|
||||
${settings.reminders ? '✅' : '❌'} Draw Reminders
|
||||
${settings.ticketPurchaseAllowed ? '✅' : '❌'} Ticket Purchases in Group
|
||||
|
||||
Tap a button below to toggle settings:`,
|
||||
|
||||
settingUpdated: (setting: string, enabled: boolean) =>
|
||||
`✅ *${setting}* has been ${enabled ? 'enabled' : 'disabled'}.`,
|
||||
|
||||
botDisabled: 'The Lightning Jackpot bot is currently disabled for this group.',
|
||||
|
||||
purchasesDisabled: `🎟 Ticket purchases are disabled in this group for privacy.
|
||||
|
||||
Please message me directly to buy tickets: @LightningLottoBot`,
|
||||
},
|
||||
};
|
||||
|
||||
export default messages;
|
||||
|
||||
Reference in New Issue
Block a user