using System.Net.Http.Headers; using System.Net.Http.Json; using Microsoft.Extensions.Options; namespace ROLAC.API.Services.Notifications; /// Sends text messages and replies via the Line Messaging API REST endpoints. public sealed class LineMessageChannel : IMessageChannel { private const string PushUrl = "https://api.line.me/v2/bot/message/push"; private const string ReplyUrl = "https://api.line.me/v2/bot/message/reply"; private readonly HttpClient _http; private readonly LineOptions _options; public LineMessageChannel(HttpClient http, IOptions options) { _http = http; _options = options.Value; } public Task PushToUserAsync(string externalId, string text, CancellationToken ct = default) => PostAsync(PushUrl, new { to = externalId, messages = new[] { new { type = "text", text } } }, ct); public Task PushToGroupAsync(string externalId, string text, CancellationToken ct = default) => PostAsync(PushUrl, new { to = externalId, messages = new[] { new { type = "text", text } } }, ct); public Task ReplyAsync(string replyToken, string text, CancellationToken ct = default) => PostAsync(ReplyUrl, new { replyToken, messages = new[] { new { type = "text", text } } }, ct); private async Task PostAsync(string url, object payload, CancellationToken ct) { try { using var request = new HttpRequestMessage(HttpMethod.Post, url) { Content = JsonContent.Create(payload), }; request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", _options.ChannelAccessToken); using var response = await _http.SendAsync(request, ct); if (response.IsSuccessStatusCode) return new MessageSendResult(true, null); var body = await response.Content.ReadAsStringAsync(ct); return new MessageSendResult(false, $"{(int)response.StatusCode}: {body}"); } catch (Exception ex) { return new MessageSendResult(false, ex.Message); } } }