push: add APNs push parsing
This commit is contained in:
@@ -16,7 +16,7 @@ require (
|
|||||||
go.uber.org/zap v1.27.0
|
go.uber.org/zap v1.27.0
|
||||||
golang.org/x/exp v0.0.0-20250128182459-e0ece0dbea4c
|
golang.org/x/exp v0.0.0-20250128182459-e0ece0dbea4c
|
||||||
golang.org/x/net v0.34.0
|
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 (
|
require (
|
||||||
|
|||||||
@@ -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=
|
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 h1:YiaRc0tEI3toYtJMRIfjP+jklH45uDHtT80nUamyD4M=
|
||||||
maunium.net/go/mauflag v1.0.0/go.mod h1:nLivPOpTpHnpzEh8jEdSL9UqO9+/KBJFmNRlwKfkPeA=
|
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.20250206130245-4c652f520080 h1:ph24b42dg5b8uwgyvQD/n/F/7/Ly5xz2RR1N4XCnTpI=
|
||||||
maunium.net/go/mautrix v0.23.1-0.20250203222456-475c4bf39d91/go.mod h1:q2U2IRLSFpglDhIpSjd8TnCNVzBNrUJBD8pmYCGQiwc=
|
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 h1:KEVeLJkUywCKVsnLIDlD/5gtayKp8VoCkksHCGGfT9Y=
|
||||||
nhooyr.io/websocket v1.8.17/go.mod h1:rN9OFWIUwuxg4fR5tELlYC04bXYowCP9GX47ivo2l+c=
|
nhooyr.io/websocket v1.8.17/go.mod h1:rN9OFWIUwuxg4fR5tELlYC04bXYowCP9GX47ivo2l+c=
|
||||||
rsc.io/qr v0.2.0 h1:6vBLea5/NRMVTz8V66gipeLycZMl/+UlFmk8DvqQ6WY=
|
rsc.io/qr v0.2.0 h1:6vBLea5/NRMVTz8V66gipeLycZMl/+UlFmk8DvqQ6WY=
|
||||||
|
|||||||
+34
-3
@@ -7,6 +7,7 @@ import (
|
|||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gotd/td/bin"
|
"github.com/gotd/td/bin"
|
||||||
@@ -41,7 +42,19 @@ type PushCustomData struct {
|
|||||||
ChatFromID int64 `json:"chat_from_id,string"`
|
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 {
|
type PushNotificationData struct {
|
||||||
|
Aps *Aps `json:"aps"` // Only present for APNs
|
||||||
|
|
||||||
LocKey string `json:"loc_key"`
|
LocKey string `json:"loc_key"`
|
||||||
LocArgs []string `json:"loc_args"`
|
LocArgs []string `json:"loc_args"`
|
||||||
Custom PushCustomData `json:"custom"`
|
Custom PushCustomData `json:"custom"`
|
||||||
@@ -231,10 +244,17 @@ func (t *TelegramClient) ConnectBackground(ctx context.Context, params *bridgev2
|
|||||||
var relatedPortal *bridgev2.Portal
|
var relatedPortal *bridgev2.Portal
|
||||||
var sender *bridgev2.Ghost
|
var sender *bridgev2.Ghost
|
||||||
var messageID networkid.MessageID
|
var messageID networkid.MessageID
|
||||||
var messageText, notificationText string
|
var messageText, notificationText, notificationTitle string
|
||||||
if data != nil {
|
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]
|
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)...)
|
notificationText = fmt.Sprintf(tpl, exslices.CastToAny(data.LocArgs)...)
|
||||||
}
|
}
|
||||||
switch data.LocKey {
|
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))
|
sender, err = t.main.Bridge.GetGhostByID(ctx, ids.MakeChannelUserID(data.Custom.FromID))
|
||||||
} else if data.Custom.ChatFromGroupID != 0 {
|
} else if data.Custom.ChatFromGroupID != 0 {
|
||||||
sender, err = t.main.Bridge.GetGhostByID(ctx, ids.MakeChannelUserID(data.Custom.ChatFromGroupID))
|
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 {
|
} else if data.Custom.FromID != 0 {
|
||||||
sender, err = t.main.Bridge.GetGhostByID(ctx, ids.MakeUserID(data.Custom.FromID))
|
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,
|
MessageID: messageID,
|
||||||
|
|
||||||
FormattedNotification: notificationText,
|
FormattedNotification: notificationText,
|
||||||
|
FormattedTitle: notificationTitle,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if FullSyncOnConnectBackground {
|
if FullSyncOnConnectBackground {
|
||||||
@@ -344,12 +367,20 @@ UserLoop:
|
|||||||
if len(plaintext) < int(jsonLength)+4 {
|
if len(plaintext) < int(jsonLength)+4 {
|
||||||
return userLoginID, nil, fmt.Errorf("decrypted payload too short (expected 4+%d, got %d)", jsonLength, len(plaintext))
|
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
|
var pmd PushNotificationData
|
||||||
err = json.Unmarshal(plaintext[4:jsonLength+4], &pmd)
|
err = json.Unmarshal(jsonData, &pmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
zerolog.Ctx(ctx).Debug().Str("raw_data", base64.StdEncoding.EncodeToString(plaintext)).Msg("Decrypted non-JSON push data")
|
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)
|
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
|
return userLoginID, &pmd, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user