[backend/masto-client] Catch GracefulExceptions correctly in push handler
This commit is contained in:
parent
fa75409923
commit
d4e8d7a6f6
1 changed files with 75 additions and 77 deletions
|
@ -38,9 +38,10 @@ public class PushService(
|
||||||
await using var scope = scopeFactory.CreateAsyncScope();
|
await using var scope = scopeFactory.CreateAsyncScope();
|
||||||
await using var db = scope.ServiceProvider.GetRequiredService<DatabaseContext>();
|
await using var db = scope.ServiceProvider.GetRequiredService<DatabaseContext>();
|
||||||
|
|
||||||
|
var type = NotificationEntity.EncodeType(notification.Type);
|
||||||
var subscriptions = await db.PushSubscriptions.Where(p => p.User == notification.Notifiee)
|
var subscriptions = await db.PushSubscriptions.Where(p => p.User == notification.Notifiee)
|
||||||
.Include(pushSubscription => pushSubscription.OauthToken)
|
.Include(pushSubscription => pushSubscription.OauthToken)
|
||||||
.Where(p => p.Types.Contains(NotificationEntity.EncodeType(notification.Type)))
|
.Where(p => p.Types.Contains(type))
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
if (subscriptions.Count == 0)
|
if (subscriptions.Count == 0)
|
||||||
|
@ -58,91 +59,88 @@ public class PushService(
|
||||||
await db.Followings.AnyAsync(p => p.Follower == notification.Notifier &&
|
await db.Followings.AnyAsync(p => p.Follower == notification.Notifier &&
|
||||||
p.Followee == notification.Notifiee);
|
p.Followee == notification.Notifiee);
|
||||||
|
|
||||||
try
|
var renderer = scope.ServiceProvider.GetRequiredService<NotificationRenderer>();
|
||||||
|
var rendered = await renderer.RenderAsync(notification, notification.Notifiee);
|
||||||
|
var name = rendered.Notifier.DisplayName;
|
||||||
|
var subject = rendered.Type switch
|
||||||
{
|
{
|
||||||
var renderer = scope.ServiceProvider.GetRequiredService<NotificationRenderer>();
|
"favourite" => $"{name} favorited your post",
|
||||||
var rendered = await renderer.RenderAsync(notification, notification.Notifiee);
|
"follow" => $"{name} is now following you",
|
||||||
var name = rendered.Notifier.DisplayName;
|
"follow_request" => $"Pending follower: {name}",
|
||||||
var subject = rendered.Type switch
|
"mention" => $"You were mentioned by {name}",
|
||||||
|
"poll" => $"A poll by {name} has ended",
|
||||||
|
"reblog" => $"{name} boosted your post",
|
||||||
|
"status" => $"{name} just posted",
|
||||||
|
"update" => $"{name} edited a post",
|
||||||
|
_ => $"New notification from {name}"
|
||||||
|
};
|
||||||
|
|
||||||
|
var body = "";
|
||||||
|
|
||||||
|
if (notification.Note != null)
|
||||||
|
body = notification.Note.Cw ?? notification.Note.Text ?? "";
|
||||||
|
|
||||||
|
body = body.Trim().Truncate(140).TrimEnd();
|
||||||
|
if (body.Length > 137)
|
||||||
|
body = body.Truncate(137).TrimEnd() + "...";
|
||||||
|
|
||||||
|
var meta = scope.ServiceProvider.GetRequiredService<MetaService>();
|
||||||
|
var (priv, pub) = await meta.GetMany(MetaEntity.VapidPrivateKey, MetaEntity.VapidPublicKey);
|
||||||
|
|
||||||
|
var client = new WebPushClient(httpClient);
|
||||||
|
client.SetVapidDetails(new VapidDetails($"https://{config.Value.WebDomain}", pub, priv));
|
||||||
|
|
||||||
|
var matchingSubscriptions =
|
||||||
|
from subscription in subscriptions
|
||||||
|
where subscription.Policy != PushSubscription.PushPolicy.Followed || followed
|
||||||
|
where subscription.Policy != PushSubscription.PushPolicy.Follower || follower
|
||||||
|
where subscription.Policy != PushSubscription.PushPolicy.None || isSelf
|
||||||
|
select subscription;
|
||||||
|
|
||||||
|
foreach (var subscription in matchingSubscriptions)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
"favourite" => $"{name} favorited your post",
|
var res = new PushSchemas.PushNotification
|
||||||
"follow" => $"{name} is now following you",
|
{
|
||||||
"follow_request" => $"Pending follower: {name}",
|
AccessToken = subscription.OauthToken.Token,
|
||||||
"mention" => $"You were mentioned by {name}",
|
NotificationType = rendered.Type,
|
||||||
"poll" => $"A poll by {name} has ended",
|
NotificationId = long.Parse(rendered.Id),
|
||||||
"reblog" => $"{name} boosted your post",
|
IconUrl = rendered.Notifier.AvatarUrl,
|
||||||
"status" => $"{name} just posted",
|
Title = subject,
|
||||||
"update" => $"{name} edited a post",
|
Body = body
|
||||||
_ => $"New notification from {name}"
|
};
|
||||||
};
|
|
||||||
|
|
||||||
var body = "";
|
var sub = new WebPushSubscription
|
||||||
|
{
|
||||||
|
Endpoint = subscription.Endpoint,
|
||||||
|
P256DH = subscription.PublicKey,
|
||||||
|
Auth = subscription.AuthSecret,
|
||||||
|
PushMode = PushMode.AesGcm
|
||||||
|
};
|
||||||
|
|
||||||
if (notification.Note != null)
|
await client.SendNotificationAsync(sub, JsonSerializer.Serialize(res));
|
||||||
body = notification.Note.Cw ?? notification.Note.Text ?? "";
|
}
|
||||||
|
catch (Exception e)
|
||||||
body = body.Trim().Truncate(140).TrimEnd();
|
|
||||||
if (body.Length > 137)
|
|
||||||
body = body.Truncate(137).TrimEnd() + "...";
|
|
||||||
|
|
||||||
var meta = scope.ServiceProvider.GetRequiredService<MetaService>();
|
|
||||||
var (priv, pub) = await meta.GetMany(MetaEntity.VapidPrivateKey, MetaEntity.VapidPublicKey);
|
|
||||||
|
|
||||||
var client = new WebPushClient(httpClient);
|
|
||||||
client.SetVapidDetails(new VapidDetails($"https://{config.Value.WebDomain}", pub, priv));
|
|
||||||
|
|
||||||
var matchingSubscriptions =
|
|
||||||
from subscription in subscriptions
|
|
||||||
where subscription.Policy != PushSubscription.PushPolicy.Followed || followed
|
|
||||||
where subscription.Policy != PushSubscription.PushPolicy.Follower || follower
|
|
||||||
where subscription.Policy != PushSubscription.PushPolicy.None || isSelf
|
|
||||||
select subscription;
|
|
||||||
|
|
||||||
foreach (var subscription in matchingSubscriptions)
|
|
||||||
{
|
{
|
||||||
try
|
switch (e)
|
||||||
{
|
{
|
||||||
var res = new PushSchemas.PushNotification
|
case WebPushException { StatusCode: HttpStatusCode.Gone }:
|
||||||
{
|
await db.PushSubscriptions.Where(p => p.Id == subscription.Id).ExecuteDeleteAsync();
|
||||||
AccessToken = subscription.OauthToken.Token,
|
break;
|
||||||
NotificationType = rendered.Type,
|
case WebPushException we:
|
||||||
NotificationId = long.Parse(rendered.Id),
|
logger.LogDebug("Push notification delivery failed: {e}", we.Message);
|
||||||
IconUrl = rendered.Notifier.AvatarUrl,
|
break;
|
||||||
Title = subject,
|
default:
|
||||||
Body = body
|
logger.LogDebug("Push notification delivery threw exception: {e}", e);
|
||||||
};
|
break;
|
||||||
|
|
||||||
var sub = new WebPushSubscription
|
|
||||||
{
|
|
||||||
Endpoint = subscription.Endpoint,
|
|
||||||
P256DH = subscription.PublicKey,
|
|
||||||
Auth = subscription.AuthSecret,
|
|
||||||
PushMode = PushMode.AesGcm
|
|
||||||
};
|
|
||||||
|
|
||||||
await client.SendNotificationAsync(sub, JsonSerializer.Serialize(res));
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
switch (e)
|
|
||||||
{
|
|
||||||
case WebPushException { StatusCode: HttpStatusCode.Gone }:
|
|
||||||
await db.PushSubscriptions.Where(p => p.Id == subscription.Id).ExecuteDeleteAsync();
|
|
||||||
break;
|
|
||||||
case WebPushException we:
|
|
||||||
logger.LogDebug("Push notification delivery failed: {e}", we.Message);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
logger.LogDebug("Push notification delivery threw exception: {e}", e);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (GracefulException)
|
}
|
||||||
{
|
catch (GracefulException)
|
||||||
// Unsupported notification type
|
{
|
||||||
}
|
// Unsupported notification type
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Reference in a new issue