namespace TaxBaik.Web.Services; using System.Net.Http.Json; /// /// Telegram Bot 알림 서비스 /// 중요 로깅 및 오류를 Telegram으로 전송 /// public interface ITelegramNotificationService { Task SendMessageAsync(string message, CancellationToken ct = default); Task SendErrorAsync(string title, string details, CancellationToken ct = default); Task SendInfoAsync(string title, string message, CancellationToken ct = default); Task SendInquiryNotificationAsync(string message, CancellationToken ct = default); Task SendSystemNotificationAsync(string message, CancellationToken ct = default); Task SendReportAsync(string reportTitle, string reportContent, CancellationToken ct = default); } public class TelegramNotificationService : ITelegramNotificationService { private readonly HttpClient _httpClient; private readonly ILogger _logger; private readonly string _botToken; private readonly string _defaultChatId; private readonly string _inquiryChatId; private readonly string _systemChatId; private const string TelegramApiUrl = "https://api.telegram.org"; public TelegramNotificationService( HttpClient httpClient, ILogger logger, IConfiguration config) { _httpClient = httpClient; _logger = logger; _botToken = config["Telegram:BotToken"] ?? ""; _defaultChatId = config["Telegram:ChatId"] ?? "-5434691215"; _inquiryChatId = config["Telegram:InquiryChatId"] ?? _defaultChatId; _systemChatId = config["Telegram:SystemChatId"] ?? "-5585148480"; } public async Task SendMessageAsync(string message, CancellationToken ct = default) { if (string.IsNullOrEmpty(_botToken) || string.IsNullOrEmpty(_defaultChatId)) { _logger.LogWarning("Telegram credentials not configured"); return; } await SendToChat(_defaultChatId, message, ct); } public async Task SendInquiryNotificationAsync(string message, CancellationToken ct = default) => await SendToChat(_inquiryChatId, $"📋 문의 사항\n\n{message}", ct); public async Task SendSystemNotificationAsync(string message, CancellationToken ct = default) => await SendToChat(_systemChatId, $"🔧 시스템 알림\n\n{message}", ct); private async Task SendToChat(string chatId, string message, CancellationToken ct) { if (string.IsNullOrEmpty(_botToken) || string.IsNullOrEmpty(chatId)) { _logger.LogWarning("Telegram credentials not configured for chatId {ChatId}", chatId); return; } try { var url = $"{TelegramApiUrl}/bot{_botToken}/sendMessage"; var payload = new { chat_id = chatId, text = message, parse_mode = "HTML" }; var response = await _httpClient.PostAsJsonAsync(url, payload, cancellationToken: ct); if (!response.IsSuccessStatusCode) { _logger.LogError("Failed to send Telegram message to {ChatId}: {StatusCode}", chatId, response.StatusCode); } } catch (Exception ex) { _logger.LogError(ex, "Error sending Telegram message to {ChatId}", chatId); } } public async Task SendErrorAsync(string title, string details, CancellationToken ct = default) { var message = $"❌ {title}\n\n{details}\n\n{DateTime.UtcNow:yyyy-MM-dd HH:mm:ss} UTC"; await SendToChat(_systemChatId, message, ct); } public async Task SendInfoAsync(string title, string message, CancellationToken ct = default) { var text = $"ℹ️ {title}\n\n{message}\n\n{DateTime.UtcNow:yyyy-MM-dd HH:mm:ss} UTC"; await SendMessageAsync(text, ct); } public async Task SendReportAsync(string reportTitle, string reportContent, CancellationToken ct = default) { var text = $"📊 {reportTitle}\n\n{reportContent}\n\n{DateTime.UtcNow:yyyy-MM-dd HH:mm:ss} UTC"; await SendToChat(_systemChatId, text, ct); } }