From c2e07d5e3fe46ea8cfb4209f1053c73337dd414c Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Thu, 6 Feb 2025 15:13:31 +0200 Subject: [PATCH] push: add APNs push parsing --- go.mod | 2 +- go.sum | 4 ++-- pkg/connector/push.go | 37 ++++++++++++++++++++++++++++++++++--- 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index edb16c92..66240a0a 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( go.uber.org/zap v1.27.0 golang.org/x/exp v0.0.0-20250128182459-e0ece0dbea4c golang.org/x/net v0.34.0 - maunium.net/go/mautrix v0.23.1-0.20250203222456-475c4bf39d91 + maunium.net/go/mautrix v0.23.1-0.20250206130245-4c652f520080 ) require ( diff --git a/go.sum b/go.sum index c41ef1da..e3d41f24 100644 --- a/go.sum +++ b/go.sum @@ -120,8 +120,8 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= maunium.net/go/mauflag v1.0.0 h1:YiaRc0tEI3toYtJMRIfjP+jklH45uDHtT80nUamyD4M= maunium.net/go/mauflag v1.0.0/go.mod h1:nLivPOpTpHnpzEh8jEdSL9UqO9+/KBJFmNRlwKfkPeA= -maunium.net/go/mautrix v0.23.1-0.20250203222456-475c4bf39d91 h1:jbga2dSYVTd3MgAKugiz5+mIYp+qxUOCDokUGZOEWRg= -maunium.net/go/mautrix v0.23.1-0.20250203222456-475c4bf39d91/go.mod h1:q2U2IRLSFpglDhIpSjd8TnCNVzBNrUJBD8pmYCGQiwc= +maunium.net/go/mautrix v0.23.1-0.20250206130245-4c652f520080 h1:ph24b42dg5b8uwgyvQD/n/F/7/Ly5xz2RR1N4XCnTpI= +maunium.net/go/mautrix v0.23.1-0.20250206130245-4c652f520080/go.mod h1:q2U2IRLSFpglDhIpSjd8TnCNVzBNrUJBD8pmYCGQiwc= nhooyr.io/websocket v1.8.17 h1:KEVeLJkUywCKVsnLIDlD/5gtayKp8VoCkksHCGGfT9Y= nhooyr.io/websocket v1.8.17/go.mod h1:rN9OFWIUwuxg4fR5tELlYC04bXYowCP9GX47ivo2l+c= rsc.io/qr v0.2.0 h1:6vBLea5/NRMVTz8V66gipeLycZMl/+UlFmk8DvqQ6WY= diff --git a/pkg/connector/push.go b/pkg/connector/push.go index fd2d07bc..f02f22cd 100644 --- a/pkg/connector/push.go +++ b/pkg/connector/push.go @@ -7,6 +7,7 @@ import ( "encoding/binary" "encoding/json" "fmt" + "strings" "time" "github.com/gotd/td/bin" @@ -41,7 +42,19 @@ type PushCustomData struct { ChatFromID int64 `json:"chat_from_id,string"` } +type Aps struct { + Alert Alert `json:"alert"` + ThreadID string `json:"thread-id"` +} + +type Alert struct { + Title string `json:"title"` + Body string `json:"body"` +} + type PushNotificationData struct { + Aps *Aps `json:"aps"` // Only present for APNs + LocKey string `json:"loc_key"` LocArgs []string `json:"loc_args"` Custom PushCustomData `json:"custom"` @@ -231,10 +244,17 @@ func (t *TelegramClient) ConnectBackground(ctx context.Context, params *bridgev2 var relatedPortal *bridgev2.Portal var sender *bridgev2.Ghost var messageID networkid.MessageID - var messageText, notificationText string + var messageText, notificationText, notificationTitle string if data != nil { + if data.Aps != nil { + notificationTitle = data.Aps.Alert.Title + notificationText = data.Aps.Alert.Body + if data.LocKey == "" { + messageText = data.Aps.Alert.Body + } + } tpl, ok := PushMessageFormats[data.LocKey] - if ok { + if ok && (len(data.LocArgs) > 0 || !strings.Contains(tpl, "%[1]")) { notificationText = fmt.Sprintf(tpl, exslices.CastToAny(data.LocArgs)...) } switch data.LocKey { @@ -258,6 +278,8 @@ func (t *TelegramClient) ConnectBackground(ctx context.Context, params *bridgev2 sender, err = t.main.Bridge.GetGhostByID(ctx, ids.MakeChannelUserID(data.Custom.FromID)) } else if data.Custom.ChatFromGroupID != 0 { sender, err = t.main.Bridge.GetGhostByID(ctx, ids.MakeChannelUserID(data.Custom.ChatFromGroupID)) + } else if data.Custom.ChatFromID != 0 { + sender, err = t.main.Bridge.GetGhostByID(ctx, ids.MakeUserID(data.Custom.ChatFromID)) } else if data.Custom.FromID != 0 { sender, err = t.main.Bridge.GetGhostByID(ctx, ids.MakeUserID(data.Custom.FromID)) } @@ -277,6 +299,7 @@ func (t *TelegramClient) ConnectBackground(ctx context.Context, params *bridgev2 MessageID: messageID, FormattedNotification: notificationText, + FormattedTitle: notificationTitle, }) } if FullSyncOnConnectBackground { @@ -344,12 +367,20 @@ UserLoop: if len(plaintext) < int(jsonLength)+4 { return userLoginID, nil, fmt.Errorf("decrypted payload too short (expected 4+%d, got %d)", jsonLength, len(plaintext)) } + jsonData := plaintext[4 : jsonLength+4] var pmd PushNotificationData - err = json.Unmarshal(plaintext[4:jsonLength+4], &pmd) + err = json.Unmarshal(jsonData, &pmd) if err != nil { zerolog.Ctx(ctx).Debug().Str("raw_data", base64.StdEncoding.EncodeToString(plaintext)).Msg("Decrypted non-JSON push data") return userLoginID, nil, fmt.Errorf("failed to unmarshal decrypted payload: %w", err) } + if pmd.Aps != nil { + // APNs notifications don't have custom data nested in a separate key, they have it at the top level + err = json.Unmarshal(jsonData, &pmd.Custom) + if err != nil { + return userLoginID, nil, fmt.Errorf("failed to unmarshal APNs data into custom field: %w", err) + } + } return userLoginID, &pmd, nil }