slidge-whatsapp 0.3.1__cp312-cp312-manylinux_2_36_aarch64.whl → 0.3.4__cp312-cp312-manylinux_2_36_aarch64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of slidge-whatsapp might be problematic. Click here for more details.

Files changed (74) hide show
  1. slidge_whatsapp/generated/_whatsapp.cpython-312-aarch64-linux-gnu.h +172 -172
  2. slidge_whatsapp/generated/_whatsapp.cpython-312-aarch64-linux-gnu.so +0 -0
  3. slidge_whatsapp/generated/build.py +138 -138
  4. slidge_whatsapp/generated/go.py +1 -1
  5. slidge_whatsapp/generated/whatsapp.c +1479 -1479
  6. slidge_whatsapp/generated/whatsapp.go +987 -987
  7. slidge_whatsapp/generated/whatsapp.py +1187 -1187
  8. slidge_whatsapp/generated/whatsapp_go.h +172 -172
  9. slidge_whatsapp/go.mod +9 -9
  10. slidge_whatsapp/go.sum +18 -18
  11. slidge_whatsapp/vendor/go.mau.fi/libsignal/session/SessionCipher.go +7 -2
  12. slidge_whatsapp/vendor/go.mau.fi/util/dbutil/module.go +2 -1
  13. slidge_whatsapp/vendor/go.mau.fi/util/dbutil/upgradetable.go +3 -0
  14. slidge_whatsapp/vendor/go.mau.fi/util/exsync/syncmap.go +48 -7
  15. slidge_whatsapp/vendor/go.mau.fi/util/exsync/syncset.go +13 -0
  16. slidge_whatsapp/vendor/go.mau.fi/util/jsontime/helpers.go +16 -5
  17. slidge_whatsapp/vendor/go.mau.fi/util/jsontime/integer.go +27 -12
  18. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/appstate/encode.go +39 -28
  19. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/appstate.go +17 -2
  20. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/armadillomessage.go +2 -1
  21. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/internals.go +18 -6
  22. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/message.go +40 -16
  23. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/pair.go +24 -21
  24. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/prekeys.go +21 -0
  25. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waE2E/WAWebProtobufsE2E.pb.go +3213 -2851
  26. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waE2E/WAWebProtobufsE2E.proto +108 -74
  27. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waStatusAttributions/WAStatusAttributions.pb.go +7 -3
  28. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waStatusAttributions/WAStatusAttributions.proto +1 -0
  29. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waSyncAction/WASyncAction.pb.go +7 -3
  30. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waSyncAction/WASyncAction.proto +1 -0
  31. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waWeb/WAWebProtobufsWeb.pb.go +35 -23
  32. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waWeb/WAWebProtobufsWeb.proto +5 -3
  33. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/receipt.go +47 -16
  34. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/retry.go +4 -10
  35. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/send.go +28 -42
  36. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/sendfb.go +33 -32
  37. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/clientpayload.go +1 -1
  38. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/noop.go +5 -1
  39. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/sessioncache.go +125 -0
  40. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/signal.go +8 -0
  41. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/sqlstore/store.go +34 -11
  42. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/store.go +5 -3
  43. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/types/jid.go +24 -9
  44. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/user.go +12 -1
  45. slidge_whatsapp/vendor/golang.org/x/crypto/curve25519/curve25519.go +7 -4
  46. slidge_whatsapp/vendor/golang.org/x/net/http2/config.go +11 -6
  47. slidge_whatsapp/vendor/golang.org/x/net/http2/config_go125.go +15 -0
  48. slidge_whatsapp/vendor/golang.org/x/net/http2/config_go126.go +15 -0
  49. slidge_whatsapp/vendor/golang.org/x/net/http2/frame.go +24 -1
  50. slidge_whatsapp/vendor/golang.org/x/net/http2/http2.go +0 -1
  51. slidge_whatsapp/vendor/golang.org/x/net/http2/server.go +35 -26
  52. slidge_whatsapp/vendor/golang.org/x/net/http2/transport.go +4 -2
  53. slidge_whatsapp/vendor/golang.org/x/net/http2/writesched.go +2 -0
  54. slidge_whatsapp/vendor/golang.org/x/net/http2/{writesched_priority.go → writesched_priority_rfc7540.go} +52 -52
  55. slidge_whatsapp/vendor/golang.org/x/net/http2/writesched_priority_rfc9128.go +209 -0
  56. slidge_whatsapp/vendor/golang.org/x/net/http2/writesched_roundrobin.go +1 -1
  57. slidge_whatsapp/vendor/golang.org/x/net/internal/httpcommon/request.go +2 -2
  58. slidge_whatsapp/vendor/golang.org/x/net/internal/socks/socks.go +1 -1
  59. slidge_whatsapp/vendor/golang.org/x/sys/unix/affinity_linux.go +9 -0
  60. slidge_whatsapp/vendor/golang.org/x/sys/unix/fdset.go +1 -3
  61. slidge_whatsapp/vendor/golang.org/x/sys/unix/ifreq_linux.go +1 -3
  62. slidge_whatsapp/vendor/golang.org/x/sys/unix/mkall.sh +1 -0
  63. slidge_whatsapp/vendor/golang.org/x/sys/unix/syscall_linux.go +1 -3
  64. slidge_whatsapp/vendor/golang.org/x/sys/unix/syscall_netbsd.go +17 -0
  65. slidge_whatsapp/vendor/golang.org/x/sys/windows/syscall_windows.go +2 -0
  66. slidge_whatsapp/vendor/golang.org/x/sys/windows/types_windows.go +16 -0
  67. slidge_whatsapp/vendor/golang.org/x/sys/windows/zsyscall_windows.go +18 -0
  68. slidge_whatsapp/vendor/golang.org/x/text/unicode/bidi/core.go +2 -9
  69. slidge_whatsapp/vendor/modules.txt +10 -10
  70. {slidge_whatsapp-0.3.1.dist-info → slidge_whatsapp-0.3.4.dist-info}/METADATA +1 -1
  71. {slidge_whatsapp-0.3.1.dist-info → slidge_whatsapp-0.3.4.dist-info}/RECORD +74 -70
  72. {slidge_whatsapp-0.3.1.dist-info → slidge_whatsapp-0.3.4.dist-info}/WHEEL +0 -0
  73. {slidge_whatsapp-0.3.1.dist-info → slidge_whatsapp-0.3.4.dist-info}/entry_points.txt +0 -0
  74. {slidge_whatsapp-0.3.1.dist-info → slidge_whatsapp-0.3.4.dist-info}/licenses/LICENSE +0 -0
@@ -10,12 +10,19 @@ import (
10
10
  "time"
11
11
  )
12
12
 
13
+ func zeroSafeUnixToTime(val int64, fn func(int64) time.Time) time.Time {
14
+ if val == 0 {
15
+ return time.Time{}
16
+ }
17
+ return fn(val)
18
+ }
19
+
13
20
  func UM(time time.Time) UnixMilli {
14
21
  return UnixMilli{Time: time}
15
22
  }
16
23
 
17
24
  func UMInt(ts int64) UnixMilli {
18
- return UM(time.UnixMilli(ts))
25
+ return UM(zeroSafeUnixToTime(ts, time.UnixMilli))
19
26
  }
20
27
 
21
28
  func UnixMilliNow() UnixMilli {
@@ -26,8 +33,8 @@ func UMicro(time time.Time) UnixMicro {
26
33
  return UnixMicro{Time: time}
27
34
  }
28
35
 
29
- func UMicroInto(ts int64) UnixMicro {
30
- return UMicro(time.UnixMicro(ts))
36
+ func UMicroInt(ts int64) UnixMicro {
37
+ return UMicro(zeroSafeUnixToTime(ts, time.UnixMicro))
31
38
  }
32
39
 
33
40
  func UnixMicroNow() UnixMicro {
@@ -39,7 +46,9 @@ func UN(time time.Time) UnixNano {
39
46
  }
40
47
 
41
48
  func UNInt(ts int64) UnixNano {
42
- return UN(time.Unix(0, ts))
49
+ return UN(zeroSafeUnixToTime(ts, func(i int64) time.Time {
50
+ return time.Unix(0, i)
51
+ }))
43
52
  }
44
53
 
45
54
  func UnixNanoNow() UnixNano {
@@ -51,7 +60,9 @@ func U(time time.Time) Unix {
51
60
  }
52
61
 
53
62
  func UInt(ts int64) Unix {
54
- return U(time.Unix(ts, 0))
63
+ return U(zeroSafeUnixToTime(ts, func(i int64) time.Time {
64
+ return time.Unix(i, 0)
65
+ }))
55
66
  }
56
67
 
57
68
  func UnixNow() Unix {
@@ -57,6 +57,13 @@ func anyIntegerToTime(src any, unixConv func(int64) time.Time, into *time.Time)
57
57
  return nil
58
58
  }
59
59
 
60
+ func zeroSafeUnix(t time.Time, method func(time.Time) int64) int64 {
61
+ if t.IsZero() {
62
+ return 0
63
+ }
64
+ return method(t)
65
+ }
66
+
60
67
  var _ sql.Scanner = &UnixMilli{}
61
68
  var _ driver.Valuer = UnixMilli{}
62
69
 
@@ -65,9 +72,6 @@ type UnixMilli struct {
65
72
  }
66
73
 
67
74
  func (um UnixMilli) MarshalJSON() ([]byte, error) {
68
- if um.IsZero() {
69
- return []byte{'0'}, nil
70
- }
71
75
  return json.Marshal(um.UnixMilli())
72
76
  }
73
77
 
@@ -83,6 +87,11 @@ func (um *UnixMilli) Scan(src any) error {
83
87
  return anyIntegerToTime(src, time.UnixMilli, &um.Time)
84
88
  }
85
89
 
90
+ func (um UnixMilli) Unix() int64 { return zeroSafeUnix(um.Time, time.Time.Unix) }
91
+ func (um UnixMilli) UnixMilli() int64 { return zeroSafeUnix(um.Time, time.Time.UnixMilli) }
92
+ func (um UnixMilli) UnixMicro() int64 { return zeroSafeUnix(um.Time, time.Time.UnixMicro) }
93
+ func (um UnixMilli) UnixNano() int64 { return zeroSafeUnix(um.Time, time.Time.UnixNano) }
94
+
86
95
  var _ sql.Scanner = &UnixMicro{}
87
96
  var _ driver.Valuer = UnixMicro{}
88
97
 
@@ -91,9 +100,6 @@ type UnixMicro struct {
91
100
  }
92
101
 
93
102
  func (um UnixMicro) MarshalJSON() ([]byte, error) {
94
- if um.IsZero() {
95
- return []byte{'0'}, nil
96
- }
97
103
  return json.Marshal(um.UnixMicro())
98
104
  }
99
105
 
@@ -109,6 +115,11 @@ func (um *UnixMicro) Scan(src any) error {
109
115
  return anyIntegerToTime(src, time.UnixMicro, &um.Time)
110
116
  }
111
117
 
118
+ func (um UnixMicro) Unix() int64 { return zeroSafeUnix(um.Time, time.Time.Unix) }
119
+ func (um UnixMicro) UnixMilli() int64 { return zeroSafeUnix(um.Time, time.Time.UnixMilli) }
120
+ func (um UnixMicro) UnixMicro() int64 { return zeroSafeUnix(um.Time, time.Time.UnixMicro) }
121
+ func (um UnixMicro) UnixNano() int64 { return zeroSafeUnix(um.Time, time.Time.UnixNano) }
122
+
112
123
  var _ sql.Scanner = &UnixNano{}
113
124
  var _ driver.Valuer = UnixNano{}
114
125
 
@@ -117,9 +128,6 @@ type UnixNano struct {
117
128
  }
118
129
 
119
130
  func (un UnixNano) MarshalJSON() ([]byte, error) {
120
- if un.IsZero() {
121
- return []byte{'0'}, nil
122
- }
123
131
  return json.Marshal(un.UnixNano())
124
132
  }
125
133
 
@@ -139,14 +147,16 @@ func (un *UnixNano) Scan(src any) error {
139
147
  }, &un.Time)
140
148
  }
141
149
 
150
+ func (un UnixNano) Unix() int64 { return zeroSafeUnix(un.Time, time.Time.Unix) }
151
+ func (un UnixNano) UnixMilli() int64 { return zeroSafeUnix(un.Time, time.Time.UnixMilli) }
152
+ func (un UnixNano) UnixMicro() int64 { return zeroSafeUnix(un.Time, time.Time.UnixMicro) }
153
+ func (un UnixNano) UnixNano() int64 { return zeroSafeUnix(un.Time, time.Time.UnixNano) }
154
+
142
155
  type Unix struct {
143
156
  time.Time
144
157
  }
145
158
 
146
159
  func (u Unix) MarshalJSON() ([]byte, error) {
147
- if u.IsZero() {
148
- return []byte{'0'}, nil
149
- }
150
160
  return json.Marshal(u.Unix())
151
161
  }
152
162
 
@@ -168,3 +178,8 @@ func (u *Unix) Scan(src any) error {
168
178
  return time.Unix(i, 0)
169
179
  }, &u.Time)
170
180
  }
181
+
182
+ func (u Unix) Unix() int64 { return zeroSafeUnix(u.Time, time.Time.Unix) }
183
+ func (u Unix) UnixMilli() int64 { return zeroSafeUnix(u.Time, time.Time.UnixMilli) }
184
+ func (u Unix) UnixMicro() int64 { return zeroSafeUnix(u.Time, time.Time.UnixMicro) }
185
+ func (u Unix) UnixNano() int64 { return zeroSafeUnix(u.Time, time.Time.UnixNano) }
@@ -93,30 +93,18 @@ func BuildPin(target types.JID, pin bool) PatchInfo {
93
93
  //
94
94
  // Archiving a chat will also unpin it automatically.
95
95
  func BuildArchive(target types.JID, archive bool, lastMessageTimestamp time.Time, lastMessageKey *waCommon.MessageKey) PatchInfo {
96
- if lastMessageTimestamp.IsZero() {
97
- lastMessageTimestamp = time.Now()
98
- }
99
96
  archiveMutationInfo := MutationInfo{
100
97
  Index: []string{IndexArchive, target.String()},
101
98
  Version: 3,
102
99
  Value: &waSyncAction.SyncActionValue{
103
100
  ArchiveChatAction: &waSyncAction.ArchiveChatAction{
104
- Archived: &archive,
105
- MessageRange: &waSyncAction.SyncActionMessageRange{
106
- LastMessageTimestamp: proto.Int64(lastMessageTimestamp.Unix()),
107
- // TODO set LastSystemMessageTimestamp?
108
- },
101
+ Archived: &archive,
102
+ MessageRange: newMessageRange(lastMessageTimestamp, lastMessageKey),
103
+ // TODO set LastSystemMessageTimestamp?
109
104
  },
110
105
  },
111
106
  }
112
107
 
113
- if lastMessageKey != nil {
114
- archiveMutationInfo.Value.ArchiveChatAction.MessageRange.Messages = []*waSyncAction.SyncActionMessage{{
115
- Key: lastMessageKey,
116
- Timestamp: proto.Int64(lastMessageTimestamp.Unix()),
117
- }}
118
- }
119
-
120
108
  mutations := []MutationInfo{archiveMutationInfo}
121
109
  if archive {
122
110
  mutations = append(mutations, newPinMutationInfo(target, false))
@@ -132,20 +120,9 @@ func BuildArchive(target types.JID, archive bool, lastMessageTimestamp time.Time
132
120
 
133
121
  // BuildMarkChatAsRead builds an app state patch for marking a chat as read or unread.
134
122
  func BuildMarkChatAsRead(target types.JID, read bool, lastMessageTimestamp time.Time, lastMessageKey *waCommon.MessageKey) PatchInfo {
135
- if lastMessageTimestamp.IsZero() {
136
- lastMessageTimestamp = time.Now()
137
- }
138
123
  action := &waSyncAction.MarkChatAsReadAction{
139
- Read: proto.Bool(read),
140
- MessageRange: &waSyncAction.SyncActionMessageRange{
141
- LastMessageTimestamp: proto.Int64(lastMessageTimestamp.Unix()),
142
- },
143
- }
144
- if lastMessageKey != nil {
145
- action.MessageRange.Messages = []*waSyncAction.SyncActionMessage{{
146
- Key: lastMessageKey,
147
- Timestamp: proto.Int64(lastMessageTimestamp.Unix()),
148
- }}
124
+ Read: proto.Bool(read),
125
+ MessageRange: newMessageRange(lastMessageTimestamp, lastMessageKey),
149
126
  }
150
127
 
151
128
  return PatchInfo{
@@ -355,3 +332,37 @@ func (proc *Processor) EncodePatch(ctx context.Context, keyID []byte, state Hash
355
332
 
356
333
  return result, nil
357
334
  }
335
+
336
+ // BuildDeleteChat builds an app state patch for deleting a chat.
337
+ func BuildDeleteChat(target types.JID, lastMessageTimestamp time.Time, lastMessageKey *waCommon.MessageKey) PatchInfo {
338
+ action := &waSyncAction.DeleteChatAction{
339
+ MessageRange: newMessageRange(lastMessageTimestamp, lastMessageKey),
340
+ }
341
+
342
+ return PatchInfo{
343
+ Type: WAPatchRegular,
344
+ Mutations: []MutationInfo{{
345
+ Index: []string{IndexDeleteChat, target.String()},
346
+ Version: 6,
347
+ Value: &waSyncAction.SyncActionValue{
348
+ DeleteChatAction: action,
349
+ },
350
+ }},
351
+ }
352
+ }
353
+
354
+ func newMessageRange(lastMessageTimestamp time.Time, lastMessageKey *waCommon.MessageKey) *waSyncAction.SyncActionMessageRange {
355
+ if lastMessageTimestamp.IsZero() {
356
+ lastMessageTimestamp = time.Now()
357
+ }
358
+ messageRange := &waSyncAction.SyncActionMessageRange{
359
+ LastMessageTimestamp: proto.Int64(lastMessageTimestamp.Unix()),
360
+ }
361
+ if lastMessageKey != nil {
362
+ messageRange.Messages = []*waSyncAction.SyncActionMessage{{
363
+ Key: lastMessageKey,
364
+ Timestamp: proto.Int64(lastMessageTimestamp.Unix()),
365
+ }}
366
+ }
367
+ return messageRange
368
+ }
@@ -351,13 +351,17 @@ func (cli *Client) requestAppStateKeys(ctx context.Context, rawKeyIDs [][]byte)
351
351
  }
352
352
  }
353
353
 
354
- // SendAppState sends the given app state patch, then resyncs that app state type from the server
354
+ // SendAppState sends the given app state patch, then triggers a background resync of that app state type
355
355
  // to update local caches and send events for the updates.
356
356
  //
357
357
  // You can use the Build methods in the appstate package to build the parameter for this method, e.g.
358
358
  //
359
359
  // cli.SendAppState(ctx, appstate.BuildMute(targetJID, true, 24 * time.Hour))
360
360
  func (cli *Client) SendAppState(ctx context.Context, patch appstate.PatchInfo) error {
361
+ return cli.sendAppState(ctx, patch, false)
362
+ }
363
+
364
+ func (cli *Client) sendAppState(ctx context.Context, patch appstate.PatchInfo, waitForSync bool) error {
361
365
  if cli == nil {
362
366
  return ErrClientIsNil
363
367
  }
@@ -412,5 +416,16 @@ func (cli *Client) SendAppState(ctx context.Context, patch appstate.PatchInfo) e
412
416
  return fmt.Errorf("%w: %s", ErrAppStateUpdate, respCollection.XMLString())
413
417
  }
414
418
 
415
- return cli.FetchAppState(ctx, patch.Type, false, false)
419
+ if waitForSync {
420
+ return cli.FetchAppState(ctx, patch.Type, false, false)
421
+ }
422
+
423
+ go func() {
424
+ err := cli.FetchAppState(ctx, patch.Type, false, false)
425
+ if err != nil {
426
+ cli.Log.Errorf("Failed to resync app state %s after sending update: %v", patch.Type, err)
427
+ }
428
+ }()
429
+
430
+ return nil
416
431
  }
@@ -22,10 +22,11 @@ import (
22
22
  "go.mau.fi/whatsmeow/types/events"
23
23
  )
24
24
 
25
- func (cli *Client) handleDecryptedArmadillo(ctx context.Context, info *types.MessageInfo, decrypted []byte, retryCount int) (handlerFailed bool) {
25
+ func (cli *Client) handleDecryptedArmadillo(ctx context.Context, info *types.MessageInfo, decrypted []byte, retryCount int) (handlerFailed, protobufFailed bool) {
26
26
  dec, err := decodeArmadillo(decrypted)
27
27
  if err != nil {
28
28
  cli.Log.Warnf("Failed to decode armadillo message from %s: %v", info.SourceString(), err)
29
+ protobufFailed = true
29
30
  return
30
31
  }
31
32
  dec.Info = *info
@@ -67,7 +67,11 @@ func (int *DangerousInternalClient) RequestAppStateKeys(ctx context.Context, raw
67
67
  int.c.requestAppStateKeys(ctx, rawKeyIDs)
68
68
  }
69
69
 
70
- func (int *DangerousInternalClient) HandleDecryptedArmadillo(ctx context.Context, info *types.MessageInfo, decrypted []byte, retryCount int) (handlerFailed bool) {
70
+ func (int *DangerousInternalClient) SendAppState(ctx context.Context, patch appstate.PatchInfo, waitForSync bool) error {
71
+ return int.c.sendAppState(ctx, patch, waitForSync)
72
+ }
73
+
74
+ func (int *DangerousInternalClient) HandleDecryptedArmadillo(ctx context.Context, info *types.MessageInfo, decrypted []byte, retryCount int) (handlerFailed, protobufFailed bool) {
71
75
  return int.c.handleDecryptedArmadillo(ctx, info, decrypted, retryCount)
72
76
  }
73
77
 
@@ -479,6 +483,10 @@ func (int *DangerousInternalClient) UploadPreKeys(ctx context.Context) {
479
483
  int.c.uploadPreKeys(ctx)
480
484
  }
481
485
 
486
+ func (int *DangerousInternalClient) FetchPreKeysNoError(ctx context.Context, retryDevices []types.JID) map[types.JID]*prekey.Bundle {
487
+ return int.c.fetchPreKeysNoError(ctx, retryDevices)
488
+ }
489
+
482
490
  func (int *DangerousInternalClient) FetchPreKeys(ctx context.Context, users []types.JID) (map[types.JID]preKeyResp, error) {
483
491
  return int.c.fetchPreKeys(ctx, users)
484
492
  }
@@ -511,16 +519,20 @@ func (int *DangerousInternalClient) ParseReceipt(node *waBinary.Node) (*events.R
511
519
  return int.c.parseReceipt(node)
512
520
  }
513
521
 
522
+ func (int *DangerousInternalClient) BackgroundIfAsyncAck(fn func()) {
523
+ int.c.backgroundIfAsyncAck(fn)
524
+ }
525
+
514
526
  func (int *DangerousInternalClient) MaybeDeferredAck(ctx context.Context, node *waBinary.Node) func(...*bool) {
515
527
  return int.c.maybeDeferredAck(ctx, node)
516
528
  }
517
529
 
518
- func (int *DangerousInternalClient) SendAck(node *waBinary.Node) {
519
- int.c.sendAck(node)
530
+ func (int *DangerousInternalClient) SendAck(node *waBinary.Node, error int) {
531
+ int.c.sendAck(node, error)
520
532
  }
521
533
 
522
- func (int *DangerousInternalClient) SendMessageReceipt(info *types.MessageInfo) {
523
- int.c.sendMessageReceipt(info)
534
+ func (int *DangerousInternalClient) SendMessageReceipt(info *types.MessageInfo, node *waBinary.Node) {
535
+ int.c.sendMessageReceipt(info, node)
524
536
  }
525
537
 
526
538
  func (int *DangerousInternalClient) GenerateRequestID() string {
@@ -611,7 +623,7 @@ func (int *DangerousInternalClient) PrepareMessageNodeV3(ctx context.Context, to
611
623
  return int.c.prepareMessageNodeV3(ctx, to, ownID, id, payload, skdm, msgAttrs, frankingTag, participants, timings)
612
624
  }
613
625
 
614
- func (int *DangerousInternalClient) EncryptMessageForDevicesV3(ctx context.Context, allDevices []types.JID, ownID types.JID, id string, payload *waMsgTransport.MessageTransport_Payload, skdm *waMsgTransport.MessageTransport_Protocol_Ancillary_SenderKeyDistributionMessage, dsm *waMsgTransport.MessageTransport_Protocol_Integral_DeviceSentMessage, encAttrs waBinary.Attrs) []waBinary.Node {
626
+ func (int *DangerousInternalClient) EncryptMessageForDevicesV3(ctx context.Context, allDevices []types.JID, ownID types.JID, id string, payload *waMsgTransport.MessageTransport_Payload, skdm *waMsgTransport.MessageTransport_Protocol_Ancillary_SenderKeyDistributionMessage, dsm *waMsgTransport.MessageTransport_Protocol_Integral_DeviceSentMessage, encAttrs waBinary.Attrs) ([]waBinary.Node, error) {
615
627
  return int.c.encryptMessageForDevicesV3(ctx, allDevices, ownID, id, payload, skdm, dsm, encAttrs)
616
628
  }
617
629
 
@@ -124,6 +124,11 @@ func (cli *Client) parseMessageSource(node *waBinary.Node, requireParticipant bo
124
124
  source.Sender = from
125
125
  // TODO IsFromMe?
126
126
  } else if from.User == clientID.User || from.User == clientLID.User {
127
+ if from.Server == types.HostedServer {
128
+ from.Server = types.DefaultUserServer
129
+ } else if from.Server == types.HostedLIDServer {
130
+ from.Server = types.HiddenUserServer
131
+ }
127
132
  source.IsFromMe = true
128
133
  source.Sender = from
129
134
  recipient := ag.OptionalJID("recipient")
@@ -132,7 +137,7 @@ func (cli *Client) parseMessageSource(node *waBinary.Node, requireParticipant bo
132
137
  } else {
133
138
  source.Chat = from.ToNonAD()
134
139
  }
135
- if source.Chat.Server == types.HiddenUserServer {
140
+ if source.Chat.Server == types.HiddenUserServer || source.Chat.Server == types.HostedLIDServer {
136
141
  source.RecipientAlt = ag.OptionalJIDOrEmpty("peer_recipient_pn")
137
142
  } else {
138
143
  source.RecipientAlt = ag.OptionalJIDOrEmpty("peer_recipient_lid")
@@ -148,9 +153,14 @@ func (cli *Client) parseMessageSource(node *waBinary.Node, requireParticipant bo
148
153
  source.Chat = from
149
154
  }
150
155
  } else {
156
+ if from.Server == types.HostedServer {
157
+ from.Server = types.DefaultUserServer
158
+ } else if from.Server == types.HostedLIDServer {
159
+ from.Server = types.HiddenUserServer
160
+ }
151
161
  source.Chat = from.ToNonAD()
152
162
  source.Sender = from
153
- if source.Sender.Server == types.HiddenUserServer {
163
+ if source.Sender.Server == types.HiddenUserServer || source.Chat.Server == types.HostedLIDServer {
154
164
  source.SenderAlt = ag.OptionalJIDOrEmpty("sender_pn")
155
165
  } else {
156
166
  source.SenderAlt = ag.OptionalJIDOrEmpty("sender_lid")
@@ -291,13 +301,10 @@ func (cli *Client) decryptMessages(ctx context.Context, info *types.MessageInfo,
291
301
  if ok && len(node.GetChildrenByTag("enc")) == 0 {
292
302
  uType := events.UnavailableType(unavailableNode.AttrGetter().String("type"))
293
303
  cli.Log.Warnf("Unavailable message %s from %s (type: %q)", info.ID, info.SourceString(), uType)
294
- if cli.SynchronousAck {
304
+ cli.backgroundIfAsyncAck(func() {
295
305
  cli.immediateRequestMessageFromPhone(ctx, info)
296
- cli.sendAck(node)
297
- } else {
298
- go cli.delayedRequestMessageFromPhone(info)
299
- go cli.sendAck(node)
300
- }
306
+ cli.sendAck(node, 0)
307
+ })
301
308
  cli.dispatchEvent(&events.UndecryptableMessage{Info: *info, IsUnavailable: true, UnavailableType: uType})
302
309
  return
303
310
  }
@@ -320,10 +327,12 @@ func (cli *Client) decryptMessages(ctx context.Context, info *types.MessageInfo,
320
327
  cli.Log.Warnf("No LID found for %s", info.Sender)
321
328
  }
322
329
  }
330
+ var recognizedStanza, protobufFailed bool
323
331
  for _, child := range children {
324
332
  if child.Tag != "enc" {
325
333
  continue
326
334
  }
335
+ recognizedStanza = true
327
336
  ag := child.AttrGetter()
328
337
  encType, ok := ag.GetString("type", false)
329
338
  if !ok {
@@ -371,16 +380,26 @@ func (cli *Client) decryptMessages(ctx context.Context, info *types.MessageInfo,
371
380
  if errors.Is(err, EventAlreadyProcessed) {
372
381
  cli.Log.Debugf("Ignoring message %s from %s: %v", info.ID, info.SourceString(), err)
373
382
  continue
383
+ } else if errors.Is(err, signalerror.ErrOldCounter) {
384
+ cli.Log.Warnf("Ignoring message %s from %s: %v", info.ID, info.SourceString(), err)
385
+ continue
374
386
  } else if err != nil {
375
387
  cli.Log.Warnf("Error decrypting message %s from %s: %v", info.ID, info.SourceString(), err)
376
388
  if ctx.Err() != nil || errors.Is(err, context.Canceled) {
377
389
  return
378
390
  }
379
391
  isUnavailable := encType == "skmsg" && !containsDirectMsg && errors.Is(err, signalerror.ErrNoSenderKeyForUser)
380
- if cli.SynchronousAck {
392
+ if encType == "msmsg" {
393
+ cli.backgroundIfAsyncAck(func() {
394
+ cli.sendAck(node, NackMissingMessageSecret)
395
+ })
396
+ } else if cli.SynchronousAck {
381
397
  cli.sendRetryReceipt(ctx, node, info, isUnavailable)
398
+ // TODO this probably isn't supposed to ack
399
+ cli.sendAck(node, 0)
382
400
  } else {
383
401
  go cli.sendRetryReceipt(context.WithoutCancel(ctx), node, info, isUnavailable)
402
+ go cli.sendAck(node, 0)
384
403
  }
385
404
  cli.dispatchEvent(&events.UndecryptableMessage{
386
405
  Info: *info,
@@ -396,15 +415,16 @@ func (cli *Client) decryptMessages(ctx context.Context, info *types.MessageInfo,
396
415
  var handlerFailed bool
397
416
  switch ag.Int("v") {
398
417
  case 2:
399
- // TODO send nack instead of receipt for proto unmarshal errors (both this one and armadillo)
400
418
  err = proto.Unmarshal(decrypted, &msg)
401
419
  if err != nil {
402
420
  cli.Log.Warnf("Error unmarshaling decrypted message from %s: %v", info.SourceString(), err)
421
+ protobufFailed = true
403
422
  continue
404
423
  }
424
+ protobufFailed = false
405
425
  handlerFailed = cli.handleDecryptedMessage(ctx, info, &msg, retryCount)
406
426
  case 3:
407
- handlerFailed = cli.handleDecryptedArmadillo(ctx, info, decrypted, retryCount)
427
+ handlerFailed, protobufFailed = cli.handleDecryptedArmadillo(ctx, info, decrypted, retryCount)
408
428
  default:
409
429
  cli.Log.Warnf("Unknown version %d in decrypted message from %s", ag.Int("v"), info.SourceString())
410
430
  }
@@ -438,11 +458,15 @@ func (cli *Client) decryptMessages(ctx context.Context, info *types.MessageInfo,
438
458
  }
439
459
  }
440
460
  }
441
- if cli.SynchronousAck {
442
- cli.sendMessageReceipt(info)
443
- } else {
444
- go cli.sendMessageReceipt(info)
445
- }
461
+ cli.backgroundIfAsyncAck(func() {
462
+ if !recognizedStanza {
463
+ cli.sendAck(node, NackUnrecognizedStanza)
464
+ } else if protobufFailed {
465
+ cli.sendAck(node, NackInvalidProtobuf)
466
+ } else {
467
+ cli.sendMessageReceipt(info, node)
468
+ }
469
+ })
446
470
  return
447
471
  }
448
472
 
@@ -26,10 +26,11 @@ import (
26
26
  )
27
27
 
28
28
  var (
29
- AdvPrefixAccountSignature = []byte{6, 0}
30
- AdvPrefixDeviceSignatureGenerate = []byte{6, 1}
31
- AdvHostedPrefixDeviceIdentityAccountSignature = []byte{6, 5}
32
- AdvHostedPrefixDeviceIdentityDeviceSignatureVerification = []byte{6, 6}
29
+ AdvAccountSignaturePrefix = []byte{6, 0}
30
+ AdvDeviceSignaturePrefix = []byte{6, 1}
31
+
32
+ AdvHostedAccountSignaturePrefix = []byte{6, 5}
33
+ AdvHostedDeviceSignaturePrefix = []byte{6, 6}
33
34
  )
34
35
 
35
36
  func (cli *Client) handleIQ(node *waBinary.Node) {
@@ -113,11 +114,11 @@ func (cli *Client) handlePair(ctx context.Context, deviceIdentityBytes []byte, r
113
114
  cli.sendPairError(reqID, 500, "internal-error")
114
115
  return &PairProtoError{"failed to parse device identity container in pair success message", err}
115
116
  }
116
- isHostedAccount := deviceIdentityContainer.AccountType != nil && *deviceIdentityContainer.AccountType == waAdv.ADVEncryptionType_HOSTED
117
117
 
118
118
  h := hmac.New(sha256.New, cli.Store.AdvSecretKey)
119
- if isHostedAccount {
120
- h.Write(AdvHostedPrefixDeviceIdentityAccountSignature)
119
+ if deviceIdentityContainer.GetAccountType() == waAdv.ADVEncryptionType_HOSTED {
120
+ h.Write(AdvHostedAccountSignaturePrefix)
121
+ //cli.Store.IsHosted = true
121
122
  }
122
123
  h.Write(deviceIdentityContainer.Details)
123
124
 
@@ -134,13 +135,6 @@ func (cli *Client) handlePair(ctx context.Context, deviceIdentityBytes []byte, r
134
135
  return &PairProtoError{"failed to parse signed device identity in pair success message", err}
135
136
  }
136
137
 
137
- if !verifyDeviceIdentityAccountSignature(&deviceIdentity, cli.Store.IdentityKey) {
138
- cli.sendPairError(reqID, 401, "signature-mismatch")
139
- return ErrPairInvalidDeviceSignature
140
- }
141
-
142
- deviceIdentity.DeviceSignature = generateDeviceSignature(&deviceIdentity, cli.Store.IdentityKey, isHostedAccount)[:]
143
-
144
138
  var deviceIdentityDetails waAdv.ADVDeviceIdentity
145
139
  err = proto.Unmarshal(deviceIdentity.Details, &deviceIdentityDetails)
146
140
  if err != nil {
@@ -148,6 +142,13 @@ func (cli *Client) handlePair(ctx context.Context, deviceIdentityBytes []byte, r
148
142
  return &PairProtoError{"failed to parse device identity details in pair success message", err}
149
143
  }
150
144
 
145
+ if !verifyAccountSignature(&deviceIdentity, cli.Store.IdentityKey, deviceIdentityDetails.GetDeviceType() == waAdv.ADVEncryptionType_HOSTED) {
146
+ cli.sendPairError(reqID, 401, "signature-mismatch")
147
+ return ErrPairInvalidDeviceSignature
148
+ }
149
+
150
+ deviceIdentity.DeviceSignature = generateDeviceSignature(&deviceIdentity, cli.Store.IdentityKey)[:]
151
+
151
152
  if cli.PrePairCallback != nil && !cli.PrePairCallback(jid, platform, businessName) {
152
153
  cli.sendPairError(reqID, 500, "internal-error")
153
154
  return ErrPairRejectedLocally
@@ -224,7 +225,7 @@ func concatBytes(data ...[]byte) []byte {
224
225
  return output
225
226
  }
226
227
 
227
- func verifyDeviceIdentityAccountSignature(deviceIdentity *waAdv.ADVSignedDeviceIdentity, ikp *keys.KeyPair) bool {
228
+ func verifyAccountSignature(deviceIdentity *waAdv.ADVSignedDeviceIdentity, ikp *keys.KeyPair, isHosted bool) bool {
228
229
  if len(deviceIdentity.AccountSignatureKey) != 32 || len(deviceIdentity.AccountSignature) != 64 {
229
230
  return false
230
231
  }
@@ -232,15 +233,17 @@ func verifyDeviceIdentityAccountSignature(deviceIdentity *waAdv.ADVSignedDeviceI
232
233
  signatureKey := ecc.NewDjbECPublicKey(*(*[32]byte)(deviceIdentity.AccountSignatureKey))
233
234
  signature := *(*[64]byte)(deviceIdentity.AccountSignature)
234
235
 
235
- message := concatBytes(AdvPrefixAccountSignature, deviceIdentity.Details, ikp.Pub[:])
236
+ prefix := AdvAccountSignaturePrefix
237
+ if isHosted {
238
+ prefix = AdvHostedAccountSignaturePrefix
239
+ }
240
+ message := concatBytes(prefix, deviceIdentity.Details, ikp.Pub[:])
241
+
236
242
  return ecc.VerifySignature(signatureKey, message, signature)
237
243
  }
238
244
 
239
- func generateDeviceSignature(deviceIdentity *waAdv.ADVSignedDeviceIdentity, ikp *keys.KeyPair, isHostedAccount bool) *[64]byte {
240
- prefix := AdvPrefixDeviceSignatureGenerate
241
- if isHostedAccount {
242
- prefix = AdvHostedPrefixDeviceIdentityDeviceSignatureVerification
243
- }
245
+ func generateDeviceSignature(deviceIdentity *waAdv.ADVSignedDeviceIdentity, ikp *keys.KeyPair) *[64]byte {
246
+ prefix := AdvDeviceSignaturePrefix
244
247
  message := concatBytes(prefix, deviceIdentity.Details, ikp.Pub[:], deviceIdentity.AccountSignatureKey)
245
248
  sig := ecc.CalculateSignature(ecc.NewDjbECPrivateKey(*ikp.Priv), message)
246
249
  return &sig
@@ -93,6 +93,27 @@ func (cli *Client) uploadPreKeys(ctx context.Context) {
93
93
  return
94
94
  }
95
95
 
96
+ func (cli *Client) fetchPreKeysNoError(ctx context.Context, retryDevices []types.JID) map[types.JID]*prekey.Bundle {
97
+ if len(retryDevices) == 0 {
98
+ return nil
99
+ }
100
+ bundlesResp, err := cli.fetchPreKeys(ctx, retryDevices)
101
+ if err != nil {
102
+ cli.Log.Warnf("Failed to fetch prekeys for %v with no existing session: %v", retryDevices, err)
103
+ return nil
104
+ }
105
+ bundles := make(map[types.JID]*prekey.Bundle, len(retryDevices))
106
+ for _, jid := range retryDevices {
107
+ resp := bundlesResp[jid]
108
+ if resp.err != nil {
109
+ cli.Log.Warnf("Failed to fetch prekey for %s: %v", jid, resp.err)
110
+ continue
111
+ }
112
+ bundles[jid] = resp.bundle
113
+ }
114
+ return bundles
115
+ }
116
+
96
117
  type preKeyResp struct {
97
118
  bundle *prekey.Bundle
98
119
  err error