mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2025-01-09 16:10:12 +00:00
Use packed notification flags
This commit is contained in:
parent
86c686b5d6
commit
4bbd76abcf
|
@ -56,6 +56,7 @@ type Notification struct {
|
|||
NotificationPendingReply NotificationType = 10 // NotificationPendingReply -- Someone has replied to a status of yours, which requires approval by you.
|
||||
NotificationPendingReblog NotificationType = 11 // NotificationPendingReblog -- Someone has boosted a status of yours, which requires approval by you.
|
||||
NotificationAdminReport NotificationType = 12 // NotificationAdminReport -- someone has submitted a new report to the instance.
|
||||
NotificationTypeNumValues NotificationType = 13 // NotificationTypeNumValues -- 1 + number of max notification type
|
||||
)
|
||||
|
||||
// String returns a stringified, frontend API compatible form of NotificationType.
|
||||
|
|
|
@ -49,19 +49,44 @@ type WebPushSubscription struct {
|
|||
// P256dh is a Base64-encoded Diffie-Hellman public key on the P-256 elliptic curve.
|
||||
P256dh string `bun:",nullzero,notnull"`
|
||||
|
||||
// NotifyFollow and friends control which notifications are delivered to a given subscription.
|
||||
// Corresponds to NotificationType and model.PushSubscriptionAlerts.
|
||||
NotifyFollow *bool `bun:",nullzero,notnull,default:false"`
|
||||
NotifyFollowRequest *bool `bun:",nullzero,notnull,default:false"`
|
||||
NotifyFavourite *bool `bun:",nullzero,notnull,default:false"`
|
||||
NotifyMention *bool `bun:",nullzero,notnull,default:false"`
|
||||
NotifyReblog *bool `bun:",nullzero,notnull,default:false"`
|
||||
NotifyPoll *bool `bun:",nullzero,notnull,default:false"`
|
||||
NotifyStatus *bool `bun:",nullzero,notnull,default:false"`
|
||||
NotifyUpdate *bool `bun:",nullzero,notnull,default:false"`
|
||||
NotifyAdminSignup *bool `bun:",nullzero,notnull,default:false"`
|
||||
NotifyAdminReport *bool `bun:",nullzero,notnull,default:false"`
|
||||
NotifyPendingFavourite *bool `bun:",nullzero,notnull,default:false"`
|
||||
NotifyPendingReply *bool `bun:",nullzero,notnull,default:false"`
|
||||
NotifyPendingReblog *bool `bun:",nullzero,notnull,default:false"`
|
||||
// NotificationFlags controls which notifications are delivered to a given subscription.
|
||||
// Corresponds to model.PushSubscriptionAlerts.
|
||||
NotificationFlags WebPushSubscriptionNotificationFlags `bun:",notnull"`
|
||||
}
|
||||
|
||||
// WebPushSubscriptionNotificationFlags is a bitfield representation of a set of NotificationType.
|
||||
type WebPushSubscriptionNotificationFlags int64
|
||||
|
||||
// WebPushSubscriptionNotificationFlagsFromSlice packs a slice of NotificationType into a WebPushSubscriptionNotificationFlags.
|
||||
func WebPushSubscriptionNotificationFlagsFromSlice(notificationTypes []NotificationType) WebPushSubscriptionNotificationFlags {
|
||||
var n WebPushSubscriptionNotificationFlags
|
||||
for _, notificationType := range notificationTypes {
|
||||
n.Set(notificationType, true)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
// ToSlice unpacks a WebPushSubscriptionNotificationFlags into a slice of NotificationType.
|
||||
func (n *WebPushSubscriptionNotificationFlags) ToSlice() []NotificationType {
|
||||
notificationTypes := make([]NotificationType, 0, NotificationTypeNumValues)
|
||||
for notificationType := NotificationUnknown; notificationType < NotificationTypeNumValues; notificationType++ {
|
||||
if n.Get(notificationType) {
|
||||
notificationTypes = append(notificationTypes, notificationType)
|
||||
}
|
||||
}
|
||||
return notificationTypes
|
||||
}
|
||||
|
||||
// Get tests to see if a given NotificationType is included in this set of flags.
|
||||
func (n *WebPushSubscriptionNotificationFlags) Get(notificationType NotificationType) bool {
|
||||
return *n&(1<<notificationType) != 0
|
||||
}
|
||||
|
||||
// Set adds or removes a given NotificationType to or from this set of flags.
|
||||
func (n *WebPushSubscriptionNotificationFlags) Set(notificationType NotificationType, value bool) {
|
||||
if value {
|
||||
*n |= 1 << notificationType
|
||||
} else {
|
||||
*n &= ^(1 << notificationType)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,20 +54,9 @@ func (p *Processor) CreateOrReplace(
|
|||
Endpoint: request.Subscription.Endpoint,
|
||||
Auth: request.Subscription.Keys.Auth,
|
||||
P256dh: request.Subscription.Keys.P256dh,
|
||||
NotifyFollow: &request.Data.Alerts.Follow,
|
||||
NotifyFollowRequest: &request.Data.Alerts.FollowRequest,
|
||||
NotifyFavourite: &request.Data.Alerts.Favourite,
|
||||
NotifyMention: &request.Data.Alerts.Mention,
|
||||
NotifyReblog: &request.Data.Alerts.Reblog,
|
||||
NotifyPoll: &request.Data.Alerts.Poll,
|
||||
NotifyStatus: &request.Data.Alerts.Status,
|
||||
NotifyUpdate: &request.Data.Alerts.Update,
|
||||
NotifyAdminSignup: &request.Data.Alerts.AdminSignup,
|
||||
NotifyAdminReport: &request.Data.Alerts.AdminReport,
|
||||
NotifyPendingFavourite: &request.Data.Alerts.PendingFavourite,
|
||||
NotifyPendingReply: &request.Data.Alerts.PendingReply,
|
||||
NotifyPendingReblog: &request.Data.Alerts.PendingReblog,
|
||||
NotificationFlags: alertsToNotificationFlags(request.Data.Alerts),
|
||||
}
|
||||
|
||||
if err := p.state.DB.PutWebPushSubscription(ctx, subscription); err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(
|
||||
gtserror.Newf("couldn't create Web Push subscription for token ID %s: %w", tokenID, err),
|
||||
|
|
|
@ -64,3 +64,25 @@ func (p *Processor) apiSubscription(ctx context.Context, subscription *gtsmodel.
|
|||
|
||||
return apiSubscription, nil
|
||||
}
|
||||
|
||||
// alertsToNotificationFlags turns the alerts section of a push subscription API request into a packed bitfield.
|
||||
func alertsToNotificationFlags(alerts *apimodel.WebPushSubscriptionAlerts) gtsmodel.WebPushSubscriptionNotificationFlags {
|
||||
var n gtsmodel.WebPushSubscriptionNotificationFlags
|
||||
|
||||
n.Set(gtsmodel.NotificationFollow, alerts.Follow)
|
||||
n.Set(gtsmodel.NotificationFollowRequest, alerts.FollowRequest)
|
||||
n.Set(gtsmodel.NotificationFavourite, alerts.Favourite)
|
||||
n.Set(gtsmodel.NotificationMention, alerts.Mention)
|
||||
n.Set(gtsmodel.NotificationReblog, alerts.Reblog)
|
||||
n.Set(gtsmodel.NotificationPoll, alerts.Poll)
|
||||
n.Set(gtsmodel.NotificationStatus, alerts.Status)
|
||||
// TODO: (Vyr) handle NotificationUpdate when edit patch is merged
|
||||
//n.Set(gtsmodel.NotificationUpdate, alerts.Update)
|
||||
n.Set(gtsmodel.NotificationAdminSignup, alerts.AdminSignup)
|
||||
n.Set(gtsmodel.NotificationAdminReport, alerts.AdminReport)
|
||||
n.Set(gtsmodel.NotificationPendingFave, alerts.PendingFavourite)
|
||||
n.Set(gtsmodel.NotificationPendingReply, alerts.PendingReply)
|
||||
n.Set(gtsmodel.NotificationPendingReblog, alerts.PendingReblog)
|
||||
|
||||
return n
|
||||
}
|
||||
|
|
|
@ -49,35 +49,11 @@ func (p *Processor) Update(
|
|||
}
|
||||
|
||||
// Update it.
|
||||
subscription.NotifyFollow = &request.Data.Alerts.Follow
|
||||
subscription.NotifyFollowRequest = &request.Data.Alerts.FollowRequest
|
||||
subscription.NotifyFavourite = &request.Data.Alerts.Favourite
|
||||
subscription.NotifyMention = &request.Data.Alerts.Mention
|
||||
subscription.NotifyReblog = &request.Data.Alerts.Reblog
|
||||
subscription.NotifyPoll = &request.Data.Alerts.Poll
|
||||
subscription.NotifyStatus = &request.Data.Alerts.Status
|
||||
subscription.NotifyUpdate = &request.Data.Alerts.Update
|
||||
subscription.NotifyAdminSignup = &request.Data.Alerts.AdminSignup
|
||||
subscription.NotifyAdminReport = &request.Data.Alerts.AdminReport
|
||||
subscription.NotifyPendingFavourite = &request.Data.Alerts.PendingFavourite
|
||||
subscription.NotifyPendingReply = &request.Data.Alerts.PendingReply
|
||||
subscription.NotifyPendingReblog = &request.Data.Alerts.PendingReblog
|
||||
subscription.NotificationFlags = alertsToNotificationFlags(request.Data.Alerts)
|
||||
if err = p.state.DB.UpdateWebPushSubscription(
|
||||
ctx,
|
||||
subscription,
|
||||
"notify_follow",
|
||||
"notify_follow_request",
|
||||
"notify_favourite",
|
||||
"notify_mention",
|
||||
"notify_reblog",
|
||||
"notify_poll",
|
||||
"notify_status",
|
||||
"notify_update",
|
||||
"notify_admin_signup",
|
||||
"notify_admin_report",
|
||||
"notify_pending_favourite",
|
||||
"notify_pending_reply",
|
||||
"notify_pending_reblog",
|
||||
"notification_flags",
|
||||
); err != nil {
|
||||
return nil, gtserror.NewErrorInternalError(
|
||||
gtserror.Newf("couldn't update Web Push subscription for token ID %s: %w", tokenID, err),
|
||||
|
|
|
@ -2831,19 +2831,19 @@ func (c *Converter) WebPushSubscriptionToAPIWebPushSubscription(
|
|||
Endpoint: subscription.Endpoint,
|
||||
ServerKey: vapidKeyPair.Public,
|
||||
Alerts: apimodel.WebPushSubscriptionAlerts{
|
||||
Follow: *subscription.NotifyFollow,
|
||||
FollowRequest: *subscription.NotifyFollowRequest,
|
||||
Favourite: *subscription.NotifyFavourite,
|
||||
Mention: *subscription.NotifyMention,
|
||||
Reblog: *subscription.NotifyReblog,
|
||||
Poll: *subscription.NotifyPoll,
|
||||
Status: *subscription.NotifyStatus,
|
||||
Update: *subscription.NotifyUpdate,
|
||||
AdminSignup: *subscription.NotifyAdminSignup,
|
||||
AdminReport: *subscription.NotifyAdminReport,
|
||||
PendingFavourite: *subscription.NotifyPendingFavourite,
|
||||
PendingReply: *subscription.NotifyPendingReply,
|
||||
PendingReblog: *subscription.NotifyPendingReblog,
|
||||
Follow: subscription.NotificationFlags.Get(gtsmodel.NotificationFollow),
|
||||
FollowRequest: subscription.NotificationFlags.Get(gtsmodel.NotificationFollowRequest),
|
||||
Favourite: subscription.NotificationFlags.Get(gtsmodel.NotificationFavourite),
|
||||
Mention: subscription.NotificationFlags.Get(gtsmodel.NotificationMention),
|
||||
Reblog: subscription.NotificationFlags.Get(gtsmodel.NotificationReblog),
|
||||
Poll: subscription.NotificationFlags.Get(gtsmodel.NotificationPoll),
|
||||
Status: subscription.NotificationFlags.Get(gtsmodel.NotificationStatus),
|
||||
Update: false, // TODO: (Vyr) handle NotificationUpdate when edit patch is merged
|
||||
AdminSignup: subscription.NotificationFlags.Get(gtsmodel.NotificationAdminSignup),
|
||||
AdminReport: subscription.NotificationFlags.Get(gtsmodel.NotificationAdminReport),
|
||||
PendingFavourite: subscription.NotificationFlags.Get(gtsmodel.NotificationPendingFave),
|
||||
PendingReply: subscription.NotificationFlags.Get(gtsmodel.NotificationPendingReply),
|
||||
PendingReblog: subscription.NotificationFlags.Get(gtsmodel.NotificationPendingReblog),
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
|
|
@ -85,45 +85,10 @@ func (r *realSender) Send(
|
|||
relevantSubscriptions := make([]*gtsmodel.WebPushSubscription, 0, len(subscriptions))
|
||||
for _, subscription := range subscriptions {
|
||||
// Check whether this subscription wants this type of notification.
|
||||
notify := false
|
||||
switch notification.NotificationType {
|
||||
case gtsmodel.NotificationFollow:
|
||||
notify = *subscription.NotifyFollow
|
||||
case gtsmodel.NotificationFollowRequest:
|
||||
notify = *subscription.NotifyFollowRequest
|
||||
case gtsmodel.NotificationMention:
|
||||
notify = *subscription.NotifyMention
|
||||
case gtsmodel.NotificationReblog:
|
||||
notify = *subscription.NotifyReblog
|
||||
case gtsmodel.NotificationFavourite:
|
||||
notify = *subscription.NotifyFavourite
|
||||
case gtsmodel.NotificationPoll:
|
||||
notify = *subscription.NotifyPoll
|
||||
case gtsmodel.NotificationStatus:
|
||||
notify = *subscription.NotifyStatus
|
||||
case gtsmodel.NotificationAdminSignup:
|
||||
notify = *subscription.NotifyAdminSignup
|
||||
case gtsmodel.NotificationAdminReport:
|
||||
notify = *subscription.NotifyAdminReport
|
||||
case gtsmodel.NotificationPendingFave:
|
||||
notify = *subscription.NotifyPendingFavourite
|
||||
case gtsmodel.NotificationPendingReply:
|
||||
notify = *subscription.NotifyPendingReply
|
||||
case gtsmodel.NotificationPendingReblog:
|
||||
notify = *subscription.NotifyPendingReblog
|
||||
default:
|
||||
log.Errorf(
|
||||
ctx,
|
||||
"notification type not supported by Web Push subscriptions: %v",
|
||||
notification.NotificationType,
|
||||
)
|
||||
continue
|
||||
}
|
||||
if !notify {
|
||||
continue
|
||||
}
|
||||
if subscription.NotificationFlags.Get(notification.NotificationType) {
|
||||
relevantSubscriptions = append(relevantSubscriptions, subscription)
|
||||
}
|
||||
}
|
||||
if len(relevantSubscriptions) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -3485,19 +3485,21 @@ func NewTestWebPushSubscriptions() map[string]*gtsmodel.WebPushSubscription {
|
|||
Endpoint: "https://example.test/push",
|
||||
Auth: "cgna/fzrYLDQyPf5hD7IsA==",
|
||||
P256dh: "BMYVItYVOX+AHBdtA62Q0i6c+F7MV2Gia3aoDr8mvHkuPBNIOuTLDfmFcnBqoZcQk6BtLcIONbxhHpy2R+mYIUY=",
|
||||
NotifyFollow: util.Ptr(true),
|
||||
NotifyFollowRequest: util.Ptr(true),
|
||||
NotifyFavourite: util.Ptr(true),
|
||||
NotifyMention: util.Ptr(true),
|
||||
NotifyReblog: util.Ptr(true),
|
||||
NotifyPoll: util.Ptr(true),
|
||||
NotifyStatus: util.Ptr(true),
|
||||
NotifyUpdate: util.Ptr(true),
|
||||
NotifyAdminSignup: util.Ptr(true),
|
||||
NotifyAdminReport: util.Ptr(true),
|
||||
NotifyPendingFavourite: util.Ptr(true),
|
||||
NotifyPendingReply: util.Ptr(true),
|
||||
NotifyPendingReblog: util.Ptr(true),
|
||||
NotificationFlags: gtsmodel.WebPushSubscriptionNotificationFlagsFromSlice([]gtsmodel.NotificationType{
|
||||
gtsmodel.NotificationFollow,
|
||||
gtsmodel.NotificationFollowRequest,
|
||||
gtsmodel.NotificationFavourite,
|
||||
gtsmodel.NotificationMention,
|
||||
gtsmodel.NotificationReblog,
|
||||
gtsmodel.NotificationPoll,
|
||||
gtsmodel.NotificationStatus,
|
||||
// TODO: (Vyr) add NotificationUpdate when edit patch is merged
|
||||
gtsmodel.NotificationAdminSignup,
|
||||
gtsmodel.NotificationAdminReport,
|
||||
gtsmodel.NotificationPendingFave,
|
||||
gtsmodel.NotificationPendingReply,
|
||||
gtsmodel.NotificationPendingReblog,
|
||||
}),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue