push: implement parsing native notifications (#87)
This commit is contained in:
@@ -10,12 +10,13 @@ require (
|
||||
github.com/gotd/td v0.111.0
|
||||
github.com/rs/zerolog v1.33.0
|
||||
github.com/stretchr/testify v1.10.0
|
||||
go.mau.fi/util v0.8.4-0.20250110124612-64d4dbbec957
|
||||
github.com/tidwall/gjson v1.18.0
|
||||
go.mau.fi/util v0.8.4
|
||||
go.mau.fi/zerozap v0.1.1
|
||||
go.uber.org/zap v1.27.0
|
||||
golang.org/x/exp v0.0.0-20250103183323-7d7fa50e5329
|
||||
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8
|
||||
golang.org/x/net v0.34.0
|
||||
maunium.net/go/mautrix v0.22.2-0.20250110154103-bbcb1904e268
|
||||
maunium.net/go/mautrix v0.23.1-0.20250122131841-524379bdb327
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -31,7 +32,7 @@ require (
|
||||
github.com/gotd/neo v0.1.5 // indirect
|
||||
github.com/klauspost/compress v1.17.11 // indirect
|
||||
github.com/lib/pq v1.10.9 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.14.24 // indirect
|
||||
github.com/petermattis/goid v0.0.0-20241211131331-93ee7e083c43 // indirect
|
||||
@@ -39,7 +40,6 @@ require (
|
||||
github.com/rs/xid v1.6.0 // indirect
|
||||
github.com/segmentio/asm v1.2.0 // indirect
|
||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e // indirect
|
||||
github.com/tidwall/gjson v1.18.0 // indirect
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
github.com/tidwall/pretty v1.2.1 // indirect
|
||||
github.com/tidwall/sjson v1.2.5 // indirect
|
||||
@@ -59,4 +59,4 @@ require (
|
||||
rsc.io/qr v0.2.0 // indirect
|
||||
)
|
||||
|
||||
replace github.com/gotd/td => github.com/beeper/td v0.107.1-0.20241219153009-6e671c4e86b0
|
||||
replace github.com/gotd/td => github.com/beeper/td v0.107.1-0.20250122125324-9af21bf4109e
|
||||
|
||||
@@ -2,8 +2,8 @@ filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||
github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU=
|
||||
github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU=
|
||||
github.com/beeper/td v0.107.1-0.20241219153009-6e671c4e86b0 h1:+bLLCnRdnntmNGLvxigSlDPUOJlsqHw6cxTgNTGMGW4=
|
||||
github.com/beeper/td v0.107.1-0.20241219153009-6e671c4e86b0/go.mod h1:5Db4K0d5B+vGIBpNVv2F0ABM14f0PcRJ+RQlKRnUcZQ=
|
||||
github.com/beeper/td v0.107.1-0.20250122125324-9af21bf4109e h1:8qzwKf37vqg1rO6tPIWybxCXUygOGFjl+TA9rZrCDFE=
|
||||
github.com/beeper/td v0.107.1-0.20250122125324-9af21bf4109e/go.mod h1:5Db4K0d5B+vGIBpNVv2F0ABM14f0PcRJ+RQlKRnUcZQ=
|
||||
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
|
||||
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
|
||||
github.com/coder/websocket v1.8.12 h1:5bUXkEPPIbewrnkU8LTCLVaxi4N4J8ahufH2vlo4NAo=
|
||||
@@ -38,8 +38,9 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
||||
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
|
||||
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
@@ -76,8 +77,8 @@ github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
|
||||
github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
|
||||
github.com/yuin/goldmark v1.7.8 h1:iERMLn0/QJeHFhxSt3p6PeN9mGnvIKSpG9YYorDMnic=
|
||||
github.com/yuin/goldmark v1.7.8/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
|
||||
go.mau.fi/util v0.8.4-0.20250110124612-64d4dbbec957 h1:tsLt3t6ARc55niz+JMgJy6U4sL210Z0K/nyxF09xT0E=
|
||||
go.mau.fi/util v0.8.4-0.20250110124612-64d4dbbec957/go.mod h1:MOfGTs1CBuK6ERTcSL4lb5YU7/ujz09eOPVEDckuazY=
|
||||
go.mau.fi/util v0.8.4 h1:mVKlJcXWfVo8ZW3f4vqtjGpqtZqJvX4ETekxawt2vnQ=
|
||||
go.mau.fi/util v0.8.4/go.mod h1:MOfGTs1CBuK6ERTcSL4lb5YU7/ujz09eOPVEDckuazY=
|
||||
go.mau.fi/zeroconfig v0.1.3 h1:As9wYDKmktjmNZW5i1vn8zvJlmGKHeVxHVIBMXsm4kM=
|
||||
go.mau.fi/zeroconfig v0.1.3/go.mod h1:NcSJkf180JT+1IId76PcMuLTNa1CzsFFZ0nBygIQM70=
|
||||
go.mau.fi/zerozap v0.1.1 h1:mxE/dW4wtkqBYOXOEEzXldk5qKB+ahsZXjoTGnvEhZQ=
|
||||
@@ -96,8 +97,8 @@ go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
||||
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||
golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
|
||||
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
|
||||
golang.org/x/exp v0.0.0-20250103183323-7d7fa50e5329 h1:9kj3STMvgqy3YA4VQXBrN7925ICMxD5wzMRcgA30588=
|
||||
golang.org/x/exp v0.0.0-20250103183323-7d7fa50e5329/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c=
|
||||
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 h1:yqrTHse8TCMW1M1ZCP+VAR/l0kKxwaAIqN/il7x4voA=
|
||||
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8/go.mod h1:tujkw807nyEEAamNbDrEGzRav+ilXA7PCRAd6xsmwiU=
|
||||
golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
|
||||
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
|
||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -119,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.22.2-0.20250110154103-bbcb1904e268 h1:p+3TofdhqiVYIkLjgzidayg2XriGUEbj+nbWs3/UQbk=
|
||||
maunium.net/go/mautrix v0.22.2-0.20250110154103-bbcb1904e268/go.mod h1:07i96D7BALyuAqxFhRzvaId8FC9NABgRQBPY5HWndf4=
|
||||
maunium.net/go/mautrix v0.23.1-0.20250122131841-524379bdb327 h1:Fb1bAUNz3eEYI6jegWv1OLwWJQRy8TzvlrvZfS4qc2U=
|
||||
maunium.net/go/mautrix v0.23.1-0.20250122131841-524379bdb327/go.mod h1:AGnnaz3ylGikUo1I1MJVn9QLsl2No1/ZNnGDyO0QD5s=
|
||||
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=
|
||||
|
||||
+69
-1
@@ -2,17 +2,85 @@ package connector
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/gotd/td/bin"
|
||||
"github.com/gotd/td/crypto"
|
||||
"github.com/gotd/td/tg"
|
||||
"github.com/tidwall/gjson"
|
||||
"go.mau.fi/util/random"
|
||||
"maunium.net/go/mautrix/bridgev2"
|
||||
"maunium.net/go/mautrix/bridgev2/networkid"
|
||||
)
|
||||
|
||||
var _ bridgev2.PushableNetworkAPI = (*TelegramClient)(nil)
|
||||
var (
|
||||
_ bridgev2.PushableNetworkAPI = (*TelegramClient)(nil)
|
||||
_ bridgev2.PushParsingNetwork = (*TelegramConnector)(nil)
|
||||
)
|
||||
|
||||
var PushAppSandbox = false
|
||||
|
||||
// TODO
|
||||
type PushNotificationData map[string]any
|
||||
|
||||
func (tg *TelegramConnector) ParsePushNotification(ctx context.Context, data json.RawMessage) (networkid.UserLoginID, any, error) {
|
||||
val := gjson.GetBytes(data, "p")
|
||||
if val.Type != gjson.String {
|
||||
return "", nil, fmt.Errorf("missing or invalid p field")
|
||||
}
|
||||
valBytes, err := base64.RawURLEncoding.DecodeString(val.Str)
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("failed to base64 decode p field: %w", err)
|
||||
}
|
||||
var em crypto.EncryptedMessage
|
||||
err = em.DecodeWithoutCopy(&bin.Buffer{Buf: valBytes})
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("failed to decode auth key and message ID: %w", err)
|
||||
}
|
||||
userIDs, err := tg.Bridge.DB.UserLogin.GetAllUserIDsWithLogins(ctx)
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("failed to get users with logins: %w", err)
|
||||
}
|
||||
var matchingAuthKey *crypto.AuthKey
|
||||
var userLoginID networkid.UserLoginID
|
||||
UserLoop:
|
||||
for _, userID := range userIDs {
|
||||
user, err := tg.Bridge.GetExistingUserByMXID(ctx, userID)
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("failed to get user %s: %w", userID, err)
|
||||
}
|
||||
for _, login := range user.GetUserLogins() {
|
||||
key := login.Metadata.(*UserLoginMetadata).PushEncryptionKey
|
||||
if len(key) != 256 {
|
||||
continue
|
||||
}
|
||||
authKey := crypto.Key(key).WithID()
|
||||
if authKey.ID == em.AuthKeyID {
|
||||
matchingAuthKey = &authKey
|
||||
userLoginID = login.ID
|
||||
break UserLoop
|
||||
}
|
||||
}
|
||||
}
|
||||
if matchingAuthKey == nil {
|
||||
return "", nil, fmt.Errorf("no matching auth key found")
|
||||
}
|
||||
c := crypto.NewClientCipher(rand.Reader)
|
||||
plaintext, err := c.DecryptRaw(*matchingAuthKey, &em)
|
||||
if err != nil {
|
||||
return userLoginID, nil, fmt.Errorf("failed to decrypt payload: %w", err)
|
||||
}
|
||||
pmd := make(PushNotificationData)
|
||||
err = json.Unmarshal(plaintext, &pmd)
|
||||
if err != nil {
|
||||
return userLoginID, nil, fmt.Errorf("failed to unmarshal decrypted payload: %w", err)
|
||||
}
|
||||
return userLoginID, pmd, nil
|
||||
}
|
||||
|
||||
func (t *TelegramClient) RegisterPushNotifications(ctx context.Context, pushType bridgev2.PushType, token string) error {
|
||||
meta := t.userLogin.Metadata.(*UserLoginMetadata)
|
||||
if meta.PushEncryptionKey == nil {
|
||||
|
||||
Reference in New Issue
Block a user