Files
gott/Endpoints/TelegramEndpoint.cs
T
Meleki 011b26c37f feat(telegram): Zugriffskontrolle mit Chat-ID-Whitelist
- TelegramService: IsChatIdAllowed() prüft Owner + Whitelist
- /start von unbekannter ChatId: Zugriff verweigert + ChatId angezeigt
- Owner wird bei Zugriffsanfrage benachrichtigt (Username + ChatId)
- Alle Commands/Messages prüfen Whitelist vor Verarbeitung
- Neues Feld telegram_allowed_chat_ids in sessions-Tabelle
- Frontend: Input für erlaubte Chat-IDs in Session-Telegram-Settings
- API: allowedChatIds in Save/Get durchgereicht
2026-03-06 13:04:02 +01:00

165 lines
6.1 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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 Session (von Telegram aufgerufen – keine Cookie-Auth!)
app.MapPost("/api/telegram/webhook/{sessionId}", HandleWebhook);
// Session Telegram-Config speichern
app.MapPut("/api/sessions/{sessionId}/telegram", HandleSaveTelegram);
// Session Telegram-Config abrufen
app.MapGet("/api/sessions/{sessionId}/telegram", HandleGetTelegram);
// Webhook registrieren (pro Session)
app.MapPost("/api/sessions/{sessionId}/telegram/register-webhook", HandleRegisterWebhook);
// Webhook-Info (pro Session)
app.MapGet("/api/sessions/{sessionId}/telegram/webhook-info", HandleWebhookInfo);
// Webhook löschen (pro Session)
app.MapDelete("/api/sessions/{sessionId}/telegram/webhook", HandleDeleteWebhook);
}
private static async Task HandleWebhook(string sessionId, HttpRequest req, HttpResponse res, TelegramService telegram, DatabaseService db)
{
var session = await db.GetSession(sessionId);
if (session == null || string.IsNullOrEmpty(session.TelegramBotToken))
{
res.StatusCode = 404;
return;
}
// Secret-Token prüfen
var secret = req.Headers["X-Telegram-Bot-Api-Secret-Token"].ToString();
if (!string.IsNullOrEmpty(session.TelegramWebhookSecret) && secret != session.TelegramWebhookSecret)
{
res.StatusCode = 403;
return;
}
try
{
var body = await JsonSerializer.DeserializeAsync<JsonElement>(req.Body);
// Fire-and-forget – Telegram erwartet schnelle 200 OK Antwort
_ = Task.Run(async () =>
{
try { await telegram.HandleUpdate(body, session); }
catch (Exception ex) { Console.Error.WriteLine($"[Telegram] Fehler für Session {sessionId}: {ex.Message}"); }
});
}
catch
{
// Malformed JSON – ignorieren
}
res.StatusCode = 200;
}
private static async Task HandleSaveTelegram(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<JsonElement>(req.Body);
var botToken = body.TryGetProperty("botToken", out var t) ? t.GetString() : null;
var webhookSecret = body.TryGetProperty("webhookSecret", out var s) ? s.GetString() : null;
var allowedChatIds = body.TryGetProperty("allowedChatIds", out var a) ? a.GetString() : session.TelegramAllowedChatIds;
await db.UpdateSessionTelegram(sessionId, botToken, webhookSecret, session.TelegramChatId, allowedChatIds);
await res.WriteAsJsonAsync(new { ok = true });
}
private static async Task HandleGetTelegram(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
{
botToken = session.TelegramBotToken ?? "",
webhookSecret = session.TelegramWebhookSecret ?? "",
chatId = session.TelegramChatId ?? "",
allowedChatIds = session.TelegramAllowedChatIds ?? "",
configured = !string.IsNullOrEmpty(session.TelegramBotToken)
});
}
private static async Task HandleRegisterWebhook(string sessionId, HttpRequest req, HttpResponse res, DatabaseService db, TelegramService telegram)
{
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<JsonElement>(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(), sessionId);
res.ContentType = "application/json";
await res.WriteAsync(result);
}
private static async Task HandleWebhookInfo(string sessionId, HttpRequest req, HttpResponse res, DatabaseService db, TelegramService telegram)
{
var userId = req.HttpContext.GetUserId();
var session = await db.GetSession(sessionId);
if (session == null || session.UserId != userId)
{
res.StatusCode = 404;
return;
}
var result = await telegram.GetWebhookInfo(sessionId);
res.ContentType = "application/json";
await res.WriteAsync(result);
}
private static async Task HandleDeleteWebhook(string sessionId, HttpRequest req, HttpResponse res, DatabaseService db, TelegramService telegram)
{
var userId = req.HttpContext.GetUserId();
var session = await db.GetSession(sessionId);
if (session == null || session.UserId != userId)
{
res.StatusCode = 404;
return;
}
var result = await telegram.DeleteWebhook(sessionId);
res.ContentType = "application/json";
await res.WriteAsync(result);
}
}