using System.Net; using WebPush; namespace ROLAC.API.Services.Notifications; /// /// Sends one encrypted Web Push message via the WebPush library, signing with the VAPID keys from /// the notification settings. Translates a "subscription gone" (404/410) response into /// so the caller prunes the dead subscription. /// public sealed class WebPushSender : IWebPushSender { private readonly INotificationSettingsService _settings; private readonly WebPushClient _client = new(); public WebPushSender(INotificationSettingsService settings) => _settings = settings; public async Task SendAsync( WebPushTarget target, string payloadJson, CancellationToken ct = default) { var options = _settings.GetWebPush(); if (string.IsNullOrWhiteSpace(options.PublicKey) || string.IsNullOrWhiteSpace(options.PrivateKey)) return new WebPushSendResult(Success: false, IsExpired: false, Error: "Web Push is not configured (missing VAPID keys)."); var subject = string.IsNullOrWhiteSpace(options.Subject) ? "mailto:admin@rolac.local" : options.Subject; var vapid = new VapidDetails(subject, options.PublicKey, options.PrivateKey); var subscription = new PushSubscription(target.Endpoint, target.P256dh, target.Auth); try { await _client.SendNotificationAsync(subscription, payloadJson, vapid, ct); return new WebPushSendResult(Success: true, IsExpired: false, Error: null); } catch (WebPushException ex) { var expired = ex.StatusCode is HttpStatusCode.NotFound or HttpStatusCode.Gone; return new WebPushSendResult(Success: false, IsExpired: expired, Error: ex.Message); } } }