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.
|
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.
|
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.
|
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.
|
// 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 is a Base64-encoded Diffie-Hellman public key on the P-256 elliptic curve.
|
||||||
P256dh string `bun:",nullzero,notnull"`
|
P256dh string `bun:",nullzero,notnull"`
|
||||||
|
|
||||||
// NotifyFollow and friends control which notifications are delivered to a given subscription.
|
// NotificationFlags controls which notifications are delivered to a given subscription.
|
||||||
// Corresponds to NotificationType and model.PushSubscriptionAlerts.
|
// Corresponds to model.PushSubscriptionAlerts.
|
||||||
NotifyFollow *bool `bun:",nullzero,notnull,default:false"`
|
NotificationFlags WebPushSubscriptionNotificationFlags `bun:",notnull"`
|
||||||
NotifyFollowRequest *bool `bun:",nullzero,notnull,default:false"`
|
}
|
||||||
NotifyFavourite *bool `bun:",nullzero,notnull,default:false"`
|
|
||||||
NotifyMention *bool `bun:",nullzero,notnull,default:false"`
|
// WebPushSubscriptionNotificationFlags is a bitfield representation of a set of NotificationType.
|
||||||
NotifyReblog *bool `bun:",nullzero,notnull,default:false"`
|
type WebPushSubscriptionNotificationFlags int64
|
||||||
NotifyPoll *bool `bun:",nullzero,notnull,default:false"`
|
|
||||||
NotifyStatus *bool `bun:",nullzero,notnull,default:false"`
|
// WebPushSubscriptionNotificationFlagsFromSlice packs a slice of NotificationType into a WebPushSubscriptionNotificationFlags.
|
||||||
NotifyUpdate *bool `bun:",nullzero,notnull,default:false"`
|
func WebPushSubscriptionNotificationFlagsFromSlice(notificationTypes []NotificationType) WebPushSubscriptionNotificationFlags {
|
||||||
NotifyAdminSignup *bool `bun:",nullzero,notnull,default:false"`
|
var n WebPushSubscriptionNotificationFlags
|
||||||
NotifyAdminReport *bool `bun:",nullzero,notnull,default:false"`
|
for _, notificationType := range notificationTypes {
|
||||||
NotifyPendingFavourite *bool `bun:",nullzero,notnull,default:false"`
|
n.Set(notificationType, true)
|
||||||
NotifyPendingReply *bool `bun:",nullzero,notnull,default:false"`
|
}
|
||||||
NotifyPendingReblog *bool `bun:",nullzero,notnull,default:false"`
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,26 +48,15 @@ func (p *Processor) CreateOrReplace(
|
||||||
|
|
||||||
// Insert a new one.
|
// Insert a new one.
|
||||||
subscription := >smodel.WebPushSubscription{
|
subscription := >smodel.WebPushSubscription{
|
||||||
ID: id.NewULID(),
|
ID: id.NewULID(),
|
||||||
AccountID: accountID,
|
AccountID: accountID,
|
||||||
TokenID: tokenID,
|
TokenID: tokenID,
|
||||||
Endpoint: request.Subscription.Endpoint,
|
Endpoint: request.Subscription.Endpoint,
|
||||||
Auth: request.Subscription.Keys.Auth,
|
Auth: request.Subscription.Keys.Auth,
|
||||||
P256dh: request.Subscription.Keys.P256dh,
|
P256dh: request.Subscription.Keys.P256dh,
|
||||||
NotifyFollow: &request.Data.Alerts.Follow,
|
NotificationFlags: alertsToNotificationFlags(request.Data.Alerts),
|
||||||
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,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := p.state.DB.PutWebPushSubscription(ctx, subscription); err != nil {
|
if err := p.state.DB.PutWebPushSubscription(ctx, subscription); err != nil {
|
||||||
return nil, gtserror.NewErrorInternalError(
|
return nil, gtserror.NewErrorInternalError(
|
||||||
gtserror.Newf("couldn't create Web Push subscription for token ID %s: %w", tokenID, err),
|
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
|
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.
|
// Update it.
|
||||||
subscription.NotifyFollow = &request.Data.Alerts.Follow
|
subscription.NotificationFlags = alertsToNotificationFlags(request.Data.Alerts)
|
||||||
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
|
|
||||||
if err = p.state.DB.UpdateWebPushSubscription(
|
if err = p.state.DB.UpdateWebPushSubscription(
|
||||||
ctx,
|
ctx,
|
||||||
subscription,
|
subscription,
|
||||||
"notify_follow",
|
"notification_flags",
|
||||||
"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",
|
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return nil, gtserror.NewErrorInternalError(
|
return nil, gtserror.NewErrorInternalError(
|
||||||
gtserror.Newf("couldn't update Web Push subscription for token ID %s: %w", tokenID, err),
|
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,
|
Endpoint: subscription.Endpoint,
|
||||||
ServerKey: vapidKeyPair.Public,
|
ServerKey: vapidKeyPair.Public,
|
||||||
Alerts: apimodel.WebPushSubscriptionAlerts{
|
Alerts: apimodel.WebPushSubscriptionAlerts{
|
||||||
Follow: *subscription.NotifyFollow,
|
Follow: subscription.NotificationFlags.Get(gtsmodel.NotificationFollow),
|
||||||
FollowRequest: *subscription.NotifyFollowRequest,
|
FollowRequest: subscription.NotificationFlags.Get(gtsmodel.NotificationFollowRequest),
|
||||||
Favourite: *subscription.NotifyFavourite,
|
Favourite: subscription.NotificationFlags.Get(gtsmodel.NotificationFavourite),
|
||||||
Mention: *subscription.NotifyMention,
|
Mention: subscription.NotificationFlags.Get(gtsmodel.NotificationMention),
|
||||||
Reblog: *subscription.NotifyReblog,
|
Reblog: subscription.NotificationFlags.Get(gtsmodel.NotificationReblog),
|
||||||
Poll: *subscription.NotifyPoll,
|
Poll: subscription.NotificationFlags.Get(gtsmodel.NotificationPoll),
|
||||||
Status: *subscription.NotifyStatus,
|
Status: subscription.NotificationFlags.Get(gtsmodel.NotificationStatus),
|
||||||
Update: *subscription.NotifyUpdate,
|
Update: false, // TODO: (Vyr) handle NotificationUpdate when edit patch is merged
|
||||||
AdminSignup: *subscription.NotifyAdminSignup,
|
AdminSignup: subscription.NotificationFlags.Get(gtsmodel.NotificationAdminSignup),
|
||||||
AdminReport: *subscription.NotifyAdminReport,
|
AdminReport: subscription.NotificationFlags.Get(gtsmodel.NotificationAdminReport),
|
||||||
PendingFavourite: *subscription.NotifyPendingFavourite,
|
PendingFavourite: subscription.NotificationFlags.Get(gtsmodel.NotificationPendingFave),
|
||||||
PendingReply: *subscription.NotifyPendingReply,
|
PendingReply: subscription.NotificationFlags.Get(gtsmodel.NotificationPendingReply),
|
||||||
PendingReblog: *subscription.NotifyPendingReblog,
|
PendingReblog: subscription.NotificationFlags.Get(gtsmodel.NotificationPendingReblog),
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,44 +85,9 @@ func (r *realSender) Send(
|
||||||
relevantSubscriptions := make([]*gtsmodel.WebPushSubscription, 0, len(subscriptions))
|
relevantSubscriptions := make([]*gtsmodel.WebPushSubscription, 0, len(subscriptions))
|
||||||
for _, subscription := range subscriptions {
|
for _, subscription := range subscriptions {
|
||||||
// Check whether this subscription wants this type of notification.
|
// Check whether this subscription wants this type of notification.
|
||||||
notify := false
|
if subscription.NotificationFlags.Get(notification.NotificationType) {
|
||||||
switch notification.NotificationType {
|
relevantSubscriptions = append(relevantSubscriptions, subscription)
|
||||||
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
|
|
||||||
}
|
|
||||||
relevantSubscriptions = append(relevantSubscriptions, subscription)
|
|
||||||
}
|
}
|
||||||
if len(relevantSubscriptions) == 0 {
|
if len(relevantSubscriptions) == 0 {
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -3479,25 +3479,27 @@ func NewTestUserMutes() map[string]*gtsmodel.UserMute {
|
||||||
func NewTestWebPushSubscriptions() map[string]*gtsmodel.WebPushSubscription {
|
func NewTestWebPushSubscriptions() map[string]*gtsmodel.WebPushSubscription {
|
||||||
return map[string]*gtsmodel.WebPushSubscription{
|
return map[string]*gtsmodel.WebPushSubscription{
|
||||||
"local_account_1_token_1": {
|
"local_account_1_token_1": {
|
||||||
ID: "01G65Z755AFWAKHE12NY0CQ9FH",
|
ID: "01G65Z755AFWAKHE12NY0CQ9FH",
|
||||||
AccountID: "01F8MH1H7YV1Z7D2C8K2730QBF",
|
AccountID: "01F8MH1H7YV1Z7D2C8K2730QBF",
|
||||||
TokenID: "01F8MGTQW4DKTDF8SW5CT9HYGA",
|
TokenID: "01F8MGTQW4DKTDF8SW5CT9HYGA",
|
||||||
Endpoint: "https://example.test/push",
|
Endpoint: "https://example.test/push",
|
||||||
Auth: "cgna/fzrYLDQyPf5hD7IsA==",
|
Auth: "cgna/fzrYLDQyPf5hD7IsA==",
|
||||||
P256dh: "BMYVItYVOX+AHBdtA62Q0i6c+F7MV2Gia3aoDr8mvHkuPBNIOuTLDfmFcnBqoZcQk6BtLcIONbxhHpy2R+mYIUY=",
|
P256dh: "BMYVItYVOX+AHBdtA62Q0i6c+F7MV2Gia3aoDr8mvHkuPBNIOuTLDfmFcnBqoZcQk6BtLcIONbxhHpy2R+mYIUY=",
|
||||||
NotifyFollow: util.Ptr(true),
|
NotificationFlags: gtsmodel.WebPushSubscriptionNotificationFlagsFromSlice([]gtsmodel.NotificationType{
|
||||||
NotifyFollowRequest: util.Ptr(true),
|
gtsmodel.NotificationFollow,
|
||||||
NotifyFavourite: util.Ptr(true),
|
gtsmodel.NotificationFollowRequest,
|
||||||
NotifyMention: util.Ptr(true),
|
gtsmodel.NotificationFavourite,
|
||||||
NotifyReblog: util.Ptr(true),
|
gtsmodel.NotificationMention,
|
||||||
NotifyPoll: util.Ptr(true),
|
gtsmodel.NotificationReblog,
|
||||||
NotifyStatus: util.Ptr(true),
|
gtsmodel.NotificationPoll,
|
||||||
NotifyUpdate: util.Ptr(true),
|
gtsmodel.NotificationStatus,
|
||||||
NotifyAdminSignup: util.Ptr(true),
|
// TODO: (Vyr) add NotificationUpdate when edit patch is merged
|
||||||
NotifyAdminReport: util.Ptr(true),
|
gtsmodel.NotificationAdminSignup,
|
||||||
NotifyPendingFavourite: util.Ptr(true),
|
gtsmodel.NotificationAdminReport,
|
||||||
NotifyPendingReply: util.Ptr(true),
|
gtsmodel.NotificationPendingFave,
|
||||||
NotifyPendingReblog: util.Ptr(true),
|
gtsmodel.NotificationPendingReply,
|
||||||
|
gtsmodel.NotificationPendingReblog,
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue