using System; using System.Text.Json; using System.Threading.Tasks; using Gott.Extensions; using Gott.Services; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing; namespace Gott.Endpoints; public static class TelegramEndpoint { public static void MapTelegramEndpoints(this IEndpointRouteBuilder app) { // Webhook pro Bot (von Telegram aufgerufen – keine Cookie-Auth!) app.MapPost("/api/telegram/webhook/{botId}", HandleWebhook); // ── Telegram Bot CRUD ── app.MapGet("/api/telegram/bots", HandleGetBots); app.MapGet("/api/telegram/bots/available", HandleGetAvailableBots); app.MapPost("/api/telegram/bots", HandleCreateBot); app.MapGet("/api/telegram/bots/{botId}", HandleGetBot); app.MapPut("/api/telegram/bots/{botId}", HandleUpdateBot); app.MapDelete("/api/telegram/bots/{botId}", HandleDeleteBot); // ── Webhook-Verwaltung (pro Bot) ── app.MapPost("/api/telegram/bots/{botId}/register-webhook", HandleRegisterWebhook); app.MapGet("/api/telegram/bots/{botId}/webhook-info", HandleWebhookInfo); app.MapDelete("/api/telegram/bots/{botId}/webhook", HandleDeleteWebhook); // ── Session Telegram-Config ── app.MapGet("/api/sessions/{sessionId}/telegram", HandleGetSessionTelegram); app.MapPut("/api/sessions/{sessionId}/telegram", HandleSaveSessionTelegram); } // ── Webhook Handler ── private static async Task HandleWebhook(string botId, HttpRequest req, HttpResponse res, TelegramService telegram, DatabaseService db) { var bot = await db.GetTelegramBot(botId); if (bot == null) { res.StatusCode = 404; return; } // Secret-Token prüfen var secret = req.Headers["X-Telegram-Bot-Api-Secret-Token"].ToString(); if (!string.IsNullOrEmpty(bot.WebhookSecret) && secret != bot.WebhookSecret) { res.StatusCode = 403; return; } try { var body = await JsonSerializer.DeserializeAsync(req.Body); _ = Task.Run(async () => { try { await telegram.HandleUpdate(body, bot); } catch (Exception ex) { Console.Error.WriteLine($"[Telegram] Fehler für Bot {bot.Name}: {ex.Message}"); } }); } catch { // Malformed JSON – ignorieren } res.StatusCode = 200; } // ── Bot CRUD ── private static async Task HandleGetBots(HttpRequest req, HttpResponse res, DatabaseService db) { var userId = req.HttpContext.GetUserId(); var bots = await db.GetTelegramBots(userId); var result = new System.Collections.Generic.List(); foreach (var bot in bots) { var sessionCount = await db.GetTelegramBotSessionCount(bot.BotId); result.Add(new { botId = bot.BotId, name = bot.Name, botToken = bot.BotToken, webhookSecret = bot.WebhookSecret, isPublic = bot.IsPublic, sessionCount, createdAt = bot.CreatedAt, updatedAt = bot.UpdatedAt }); } await res.WriteAsJsonAsync(result); } private static async Task HandleGetBot(string botId, HttpRequest req, HttpResponse res, DatabaseService db) { var userId = req.HttpContext.GetUserId(); var bot = await db.GetTelegramBot(botId); if (bot == null || bot.UserId != userId) { res.StatusCode = 404; await res.WriteAsJsonAsync(new { error = "Bot nicht gefunden" }); return; } var sessionCount = await db.GetTelegramBotSessionCount(bot.BotId); await res.WriteAsJsonAsync(new { botId = bot.BotId, name = bot.Name, botToken = bot.BotToken, webhookSecret = bot.WebhookSecret, isPublic = bot.IsPublic, sessionCount, createdAt = bot.CreatedAt, updatedAt = bot.UpdatedAt }); } private static async Task HandleCreateBot(HttpRequest req, HttpResponse res, DatabaseService db) { var userId = req.HttpContext.GetUserId(); var body = await JsonSerializer.DeserializeAsync(req.Body); var name = body.TryGetProperty("name", out var n) ? n.GetString()?.Trim() : null; var botToken = body.TryGetProperty("botToken", out var t) ? t.GetString()?.Trim() : null; if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(botToken)) { res.StatusCode = 400; await res.WriteAsJsonAsync(new { error = "Name und Bot-Token sind erforderlich" }); return; } var bot = await db.CreateTelegramBot(userId, name, botToken); await res.WriteAsJsonAsync(new { botId = bot.BotId, name = bot.Name, botToken = bot.BotToken, webhookSecret = bot.WebhookSecret, createdAt = bot.CreatedAt }); } private static async Task HandleUpdateBot(string botId, HttpRequest req, HttpResponse res, DatabaseService db) { var userId = req.HttpContext.GetUserId(); var bot = await db.GetTelegramBot(botId); if (bot == null || bot.UserId != userId) { res.StatusCode = 404; await res.WriteAsJsonAsync(new { error = "Bot nicht gefunden" }); return; } var body = await JsonSerializer.DeserializeAsync(req.Body); var name = body.TryGetProperty("name", out var n) ? n.GetString()?.Trim() : bot.Name; var botToken = body.TryGetProperty("botToken", out var t) ? t.GetString()?.Trim() : bot.BotToken; var isPublic = body.TryGetProperty("isPublic", out var p) ? p.GetBoolean() : bot.IsPublic; await db.UpdateTelegramBot(botId, name, botToken, isPublic); await res.WriteAsJsonAsync(new { ok = true }); } private static async Task HandleDeleteBot(string botId, HttpRequest req, HttpResponse res, DatabaseService db, TelegramService telegram) { var userId = req.HttpContext.GetUserId(); var bot = await db.GetTelegramBot(botId); if (bot == null || bot.UserId != userId) { res.StatusCode = 404; await res.WriteAsJsonAsync(new { error = "Bot nicht gefunden" }); return; } // Webhook bei Telegram löschen try { await telegram.DeleteWebhook(bot); } catch { /* ignore */ } await db.DeleteTelegramBot(botId); await res.WriteAsJsonAsync(new { ok = true }); } // ── Webhook-Verwaltung ── private static async Task HandleRegisterWebhook(string botId, HttpRequest req, HttpResponse res, DatabaseService db, TelegramService telegram) { var userId = req.HttpContext.GetUserId(); var bot = await db.GetTelegramBot(botId); if (bot == null || bot.UserId != userId) { res.StatusCode = 404; await res.WriteAsJsonAsync(new { error = "Bot nicht gefunden" }); return; } var body = await JsonSerializer.DeserializeAsync(req.Body); if (!body.TryGetProperty("baseUrl", out var urlEl)) { res.StatusCode = 400; await res.WriteAsJsonAsync(new { error = "baseUrl required" }); return; } var result = await telegram.RegisterWebhook(urlEl.GetString(), bot); res.ContentType = "application/json"; await res.WriteAsync(result); } private static async Task HandleWebhookInfo(string botId, HttpRequest req, HttpResponse res, DatabaseService db, TelegramService telegram) { var userId = req.HttpContext.GetUserId(); var bot = await db.GetTelegramBot(botId); if (bot == null || bot.UserId != userId) { res.StatusCode = 404; return; } var result = await telegram.GetWebhookInfo(bot); res.ContentType = "application/json"; await res.WriteAsync(result); } private static async Task HandleDeleteWebhook(string botId, HttpRequest req, HttpResponse res, DatabaseService db, TelegramService telegram) { var userId = req.HttpContext.GetUserId(); var bot = await db.GetTelegramBot(botId); if (bot == null || bot.UserId != userId) { res.StatusCode = 404; return; } var result = await telegram.DeleteWebhook(bot); res.ContentType = "application/json"; await res.WriteAsync(result); } // ── Verfügbare Bots (eigene + public) ── private static async Task HandleGetAvailableBots(HttpRequest req, HttpResponse res, DatabaseService db) { var userId = req.HttpContext.GetUserId(); var bots = await db.GetAvailableTelegramBots(userId); var result = new System.Collections.Generic.List(); foreach (var bot in bots) { var isOwner = bot.UserId == userId; result.Add(new { botId = bot.BotId, name = bot.Name, isOwner, isPublic = bot.IsPublic, createdAt = bot.CreatedAt, // Token nur für eigene Bots anzeigen botToken = isOwner ? bot.BotToken : null }); } await res.WriteAsJsonAsync(result); } // ── Session Telegram-Config ── private static async Task HandleGetSessionTelegram(string sessionId, HttpRequest req, HttpResponse res, DatabaseService db) { var userId = req.HttpContext.GetUserId(); var session = await db.GetSession(sessionId); if (session == null || session.UserId != userId) { res.StatusCode = 404; await res.WriteAsJsonAsync(new { error = "Session nicht gefunden" }); return; } await res.WriteAsJsonAsync(new { telegramBotId = session.TelegramBotId ?? "", chatId = session.TelegramChatId ?? "", configured = !string.IsNullOrEmpty(session.TelegramBotId) }); } private static async Task HandleSaveSessionTelegram(string sessionId, HttpRequest req, HttpResponse res, DatabaseService db) { var userId = req.HttpContext.GetUserId(); var session = await db.GetSession(sessionId); if (session == null || session.UserId != userId) { res.StatusCode = 404; await res.WriteAsJsonAsync(new { error = "Session nicht gefunden" }); return; } var body = await JsonSerializer.DeserializeAsync(req.Body); var botId = body.TryGetProperty("telegramBotId", out var b) ? b.GetString() : null; var chatId = body.TryGetProperty("chatId", out var c) ? c.GetString() : session.TelegramChatId; // Bot-Zuordnung setzen if (botId != null) { await db.SetSessionTelegramBot(sessionId, string.IsNullOrEmpty(botId) ? null : botId); } // Chat-ID aktualisieren (leerer String → NULL) await db.UpdateSessionTelegramChat(sessionId, string.IsNullOrEmpty(chatId) ? null : chatId); await res.WriteAsJsonAsync(new { ok = true }); } }