import axios from 'axios'; interface TelegramMessage { chatId: string; text: string; latitude?: number; longitude?: number; buttons?: Array<{ text: string; url: string }>; } interface GeofenceNotificationParams { chatId: string; deviceName: string; geofenceName: string; eventType: 'enter' | 'exit'; latitude: number; longitude: number; timestamp: string; mapUrl?: string; dashboardUrl?: string; } class TelegramService { private botToken: string; private baseUrl: string; constructor() { this.botToken = process.env.TELEGRAM_BOT_TOKEN || ''; if (!this.botToken) { console.warn('[TelegramService] No TELEGRAM_BOT_TOKEN configured'); } this.baseUrl = `https://api.telegram.org/bot${this.botToken}`; } /** * Check if Telegram is configured */ isConfigured(): boolean { return !!this.botToken; } /** * Send text message with optional inline buttons */ async sendMessage(params: TelegramMessage): Promise { if (!this.isConfigured()) { throw new Error('Telegram bot token not configured'); } const { chatId, text, buttons } = params; const payload: any = { chat_id: chatId, text: text, parse_mode: 'HTML', }; // Add inline buttons if provided if (buttons && buttons.length > 0) { payload.reply_markup = { inline_keyboard: [ buttons.map(btn => ({ text: btn.text, url: btn.url, })), ], }; } const response = await axios.post(`${this.baseUrl}/sendMessage`, payload); if (!response.data.ok) { throw new Error(`Telegram API error: ${response.data.description}`); } } /** * Send location pin on map */ async sendLocation( chatId: string, latitude: number, longitude: number ): Promise { if (!this.isConfigured()) { throw new Error('Telegram bot token not configured'); } const response = await axios.post(`${this.baseUrl}/sendLocation`, { chat_id: chatId, latitude, longitude, }); if (!response.data.ok) { throw new Error(`Telegram API error: ${response.data.description}`); } } /** * Send geofence notification (complete with text + location + buttons) */ async sendGeofenceNotification( params: GeofenceNotificationParams ): Promise { const { chatId, deviceName, geofenceName, eventType, latitude, longitude, timestamp, mapUrl, dashboardUrl, } = params; // Format message const emoji = eventType === 'enter' ? '🟒' : 'πŸ”΄'; const action = eventType === 'enter' ? 'BETRETEN' : 'VERLASSEN'; const verb = eventType === 'enter' ? 'betreten' : 'verlassen'; const formattedDate = new Date(timestamp).toLocaleString('de-DE', { dateStyle: 'short', timeStyle: 'short', }); const text = ` ${emoji} Geofence ${action} πŸ“± Device: ${deviceName} πŸ“ Geofence: ${geofenceName} πŸ• Zeit: ${formattedDate} πŸ“Š Ereignis: Hat ${geofenceName} ${verb} `.trim(); // Prepare inline buttons const buttons = []; if (mapUrl) { buttons.push({ text: 'πŸ—ΊοΈ Auf Karte zeigen', url: mapUrl }); } if (dashboardUrl) { buttons.push({ text: 'πŸ“Š Dashboard ΓΆffnen', url: dashboardUrl }); } // Send text message with buttons await this.sendMessage({ chatId, text, buttons }); // Send location pin await this.sendLocation(chatId, latitude, longitude); } /** * Test connection by sending a simple message */ async testConnection(chatId: string): Promise { try { await this.sendMessage({ chatId, text: 'βœ… Telegram Connection Test\n\nDie Verbindung funktioniert!', }); return true; } catch (error) { console.error('[TelegramService] Test failed:', error); return false; } } } export const telegramService = new TelegramService();