41 lines
1.8 KiB
C#
41 lines
1.8 KiB
C#
using System.Net;
|
|
using WebPush;
|
|
|
|
namespace ROLAC.API.Services.Notifications;
|
|
|
|
/// <summary>
|
|
/// 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
|
|
/// <see cref="WebPushSendResult.IsExpired"/> so the caller prunes the dead subscription.
|
|
/// </summary>
|
|
public sealed class WebPushSender : IWebPushSender
|
|
{
|
|
private readonly INotificationSettingsService _settings;
|
|
private readonly WebPushClient _client = new();
|
|
|
|
public WebPushSender(INotificationSettingsService settings) => _settings = settings;
|
|
|
|
public async Task<WebPushSendResult> 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);
|
|
}
|
|
}
|
|
}
|