slidge-whatsapp 0.3.7__cp312-cp312-manylinux_2_41_aarch64.whl → 0.3.8__cp312-cp312-manylinux_2_41_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.
Files changed (164) hide show
  1. slidge_whatsapp/config.py +7 -2
  2. slidge_whatsapp/contact.py +3 -2
  3. slidge_whatsapp/event.go +14 -9
  4. slidge_whatsapp/gateway.go +7 -1
  5. slidge_whatsapp/generated/_whatsapp.cpython-312-aarch64-linux-gnu.h +182 -178
  6. slidge_whatsapp/generated/_whatsapp.cpython-312-aarch64-linux-gnu.so +0 -0
  7. slidge_whatsapp/generated/build.py +146 -142
  8. slidge_whatsapp/generated/whatsapp.c +1456 -1376
  9. slidge_whatsapp/generated/whatsapp.go +1069 -1045
  10. slidge_whatsapp/generated/whatsapp.py +1324 -1298
  11. slidge_whatsapp/generated/whatsapp_go.h +182 -178
  12. slidge_whatsapp/go.mod +6 -6
  13. slidge_whatsapp/go.sum +12 -12
  14. slidge_whatsapp/group.py +25 -0
  15. slidge_whatsapp/session.go +69 -67
  16. slidge_whatsapp/session.py +11 -1
  17. slidge_whatsapp/vendor/github.com/coder/websocket/LICENSE.txt +13 -0
  18. slidge_whatsapp/vendor/github.com/coder/websocket/Makefile +18 -0
  19. slidge_whatsapp/vendor/github.com/coder/websocket/README.md +162 -0
  20. slidge_whatsapp/vendor/github.com/coder/websocket/accept.go +378 -0
  21. slidge_whatsapp/vendor/github.com/coder/websocket/close.go +335 -0
  22. slidge_whatsapp/vendor/github.com/coder/websocket/compress.go +234 -0
  23. slidge_whatsapp/vendor/github.com/coder/websocket/conn.go +306 -0
  24. slidge_whatsapp/vendor/github.com/coder/websocket/dial.go +347 -0
  25. slidge_whatsapp/vendor/github.com/coder/websocket/doc.go +33 -0
  26. slidge_whatsapp/vendor/github.com/coder/websocket/errors.go +8 -0
  27. slidge_whatsapp/vendor/github.com/coder/websocket/frame.go +173 -0
  28. slidge_whatsapp/vendor/github.com/coder/websocket/hijack.go +33 -0
  29. slidge_whatsapp/vendor/github.com/coder/websocket/internal/bpool/bpool.go +25 -0
  30. slidge_whatsapp/vendor/github.com/coder/websocket/internal/errd/wrap.go +14 -0
  31. slidge_whatsapp/vendor/github.com/coder/websocket/internal/util/util.go +15 -0
  32. slidge_whatsapp/vendor/github.com/coder/websocket/internal/wsjs/wsjs_js.go +169 -0
  33. slidge_whatsapp/vendor/github.com/coder/websocket/mask.go +128 -0
  34. slidge_whatsapp/vendor/github.com/coder/websocket/mask_amd64.s +127 -0
  35. slidge_whatsapp/vendor/github.com/coder/websocket/mask_arm64.s +72 -0
  36. slidge_whatsapp/vendor/github.com/coder/websocket/mask_asm.go +26 -0
  37. slidge_whatsapp/vendor/github.com/coder/websocket/mask_go.go +7 -0
  38. slidge_whatsapp/vendor/github.com/coder/websocket/netconn.go +233 -0
  39. slidge_whatsapp/vendor/github.com/coder/websocket/netconn_js.go +11 -0
  40. slidge_whatsapp/vendor/github.com/coder/websocket/netconn_notjs.go +19 -0
  41. slidge_whatsapp/vendor/github.com/coder/websocket/read.go +540 -0
  42. slidge_whatsapp/vendor/github.com/coder/websocket/stringer.go +91 -0
  43. slidge_whatsapp/vendor/github.com/coder/websocket/write.go +384 -0
  44. slidge_whatsapp/vendor/github.com/coder/websocket/ws_js.go +598 -0
  45. slidge_whatsapp/vendor/github.com/ebitengine/purego/func.go +1 -1
  46. slidge_whatsapp/vendor/github.com/ebitengine/purego/struct_amd64.go +1 -1
  47. slidge_whatsapp/vendor/github.com/ebitengine/purego/struct_arm64.go +3 -1
  48. slidge_whatsapp/vendor/github.com/ebitengine/purego/struct_loong64.go +1 -1
  49. slidge_whatsapp/vendor/github.com/vektah/gqlparser/v2/ast/directive.go +3 -0
  50. slidge_whatsapp/vendor/github.com/vektah/gqlparser/v2/ast/selection.go +3 -0
  51. slidge_whatsapp/vendor/github.com/vektah/gqlparser/v2/ast/value.go +4 -3
  52. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/appstate/encode.go +3 -0
  53. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/appstate.go +18 -4
  54. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/broadcast.go +3 -3
  55. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/call.go +6 -4
  56. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/client.go +90 -80
  57. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/connectionevents.go +14 -11
  58. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/download.go +4 -1
  59. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/group.go +47 -48
  60. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/handshake.go +3 -2
  61. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/internals.go +79 -75
  62. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/keepalive.go +8 -6
  63. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/mediaconn.go +1 -2
  64. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/mediaretry.go +2 -2
  65. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/message.go +42 -40
  66. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/newsletter.go +35 -32
  67. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/notification.go +2 -3
  68. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/pair-code.go +2 -4
  69. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/pair.go +19 -19
  70. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/prekeys.go +9 -8
  71. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/presence.go +9 -9
  72. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/privacysettings.go +4 -5
  73. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloAddMessage/InstamadilloAddMessage.pb.go +1 -1
  74. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloCoreTypeActionLog/InstamadilloCoreTypeActionLog.pb.go +1 -1
  75. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloCoreTypeAdminMessage/InstamadilloCoreTypeAdminMessage.pb.go +1 -1
  76. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloCoreTypeCollection/InstamadilloCoreTypeCollection.pb.go +1 -1
  77. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloCoreTypeLink/InstamadilloCoreTypeLink.pb.go +1 -1
  78. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloCoreTypeMedia/InstamadilloCoreTypeMedia.pb.go +1 -1
  79. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloCoreTypeText/InstamadilloCoreTypeText.pb.go +1 -1
  80. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloDeleteMessage/InstamadilloDeleteMessage.pb.go +1 -1
  81. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloSupplementMessage/InstamadilloSupplementMessage.pb.go +1 -1
  82. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloTransportPayload/InstamadilloTransportPayload.pb.go +1 -1
  83. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloXmaContentRef/InstamadilloXmaContentRef.pb.go +1 -1
  84. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waAICommon/WAAICommon.pb.go +1145 -335
  85. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waAICommon/WAAICommon.proto +78 -0
  86. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waAdv/WAAdv.pb.go +1 -1
  87. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waArmadilloApplication/WAArmadilloApplication.pb.go +1 -1
  88. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waArmadilloXMA/WAArmadilloXMA.pb.go +1 -1
  89. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waCert/WACert.pb.go +1 -1
  90. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waChatLockSettings/WAProtobufsChatLockSettings.pb.go +1 -1
  91. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waCommon/WACommon.pb.go +1 -1
  92. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waCompanionReg/WACompanionReg.pb.go +22 -4
  93. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waCompanionReg/WACompanionReg.proto +2 -0
  94. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waConsumerApplication/WAConsumerApplication.pb.go +1 -1
  95. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waDeviceCapabilities/WAProtobufsDeviceCapabilities.pb.go +104 -30
  96. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waDeviceCapabilities/WAProtobufsDeviceCapabilities.proto +7 -0
  97. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waE2E/WAWebProtobufsE2E.pb.go +1037 -963
  98. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waE2E/WAWebProtobufsE2E.proto +15 -8
  99. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waHistorySync/WAWebProtobufsHistorySync.pb.go +1 -1
  100. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waLidMigrationSyncPayload/WAWebProtobufLidMigrationSyncPayload.pb.go +1 -1
  101. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waMediaTransport/WAMediaTransport.pb.go +1 -1
  102. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waMmsRetry/WAMmsRetry.pb.go +1 -1
  103. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waMsgApplication/WAMsgApplication.pb.go +1 -1
  104. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waMsgTransport/WAMsgTransport.pb.go +1 -1
  105. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waMultiDevice/WAMultiDevice.pb.go +1 -1
  106. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waServerSync/WAServerSync.pb.go +1 -1
  107. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waStatusAttributions/WAStatusAttributions.pb.go +40 -35
  108. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waStatusAttributions/WAStatusAttributions.proto +1 -0
  109. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waSyncAction/WASyncAction.pb.go +921 -653
  110. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waSyncAction/WASyncAction.proto +44 -15
  111. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waUserPassword/WAProtobufsUserPassword.pb.go +1 -1
  112. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waVnameCert/WAWebProtobufsVnameCert.pb.go +1 -1
  113. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waWa6/WAWebProtobufsWa6.pb.go +9 -5
  114. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waWa6/WAWebProtobufsWa6.proto +1 -0
  115. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waWeb/WAWebProtobufsWeb.pb.go +193 -115
  116. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waWeb/WAWebProtobufsWeb.proto +9 -0
  117. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/push.go +2 -4
  118. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/receipt.go +12 -12
  119. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/request.go +25 -19
  120. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/retry.go +2 -2
  121. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/send.go +43 -27
  122. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/sendfb.go +4 -4
  123. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/socket/constants.go +1 -1
  124. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/socket/framesocket.go +43 -56
  125. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/socket/noisehandshake.go +9 -3
  126. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/socket/noisesocket.go +36 -22
  127. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/clientpayload.go +24 -4
  128. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/store.go +12 -0
  129. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/types/events/appstate.go +2 -1
  130. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/upload.go +1 -1
  131. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/user.go +79 -40
  132. slidge_whatsapp/vendor/golang.org/x/sys/unix/mkerrors.sh +2 -0
  133. slidge_whatsapp/vendor/golang.org/x/sys/unix/syscall_linux.go +6 -0
  134. slidge_whatsapp/vendor/golang.org/x/sys/unix/zerrors_linux.go +359 -0
  135. slidge_whatsapp/vendor/golang.org/x/sys/unix/zsyscall_linux.go +10 -0
  136. slidge_whatsapp/vendor/golang.org/x/sys/unix/ztypes_linux.go +31 -0
  137. slidge_whatsapp/vendor/golang.org/x/sys/windows/syscall_windows.go +15 -0
  138. slidge_whatsapp/vendor/golang.org/x/sys/windows/types_windows.go +76 -0
  139. slidge_whatsapp/vendor/golang.org/x/sys/windows/zsyscall_windows.go +37 -0
  140. slidge_whatsapp/vendor/modules.txt +12 -8
  141. {slidge_whatsapp-0.3.7.dist-info → slidge_whatsapp-0.3.8.dist-info}/METADATA +1 -1
  142. {slidge_whatsapp-0.3.7.dist-info → slidge_whatsapp-0.3.8.dist-info}/RECORD +145 -136
  143. slidge_whatsapp/vendor/github.com/gorilla/websocket/.gitignore +0 -25
  144. slidge_whatsapp/vendor/github.com/gorilla/websocket/AUTHORS +0 -9
  145. slidge_whatsapp/vendor/github.com/gorilla/websocket/LICENSE +0 -22
  146. slidge_whatsapp/vendor/github.com/gorilla/websocket/README.md +0 -33
  147. slidge_whatsapp/vendor/github.com/gorilla/websocket/client.go +0 -434
  148. slidge_whatsapp/vendor/github.com/gorilla/websocket/compression.go +0 -148
  149. slidge_whatsapp/vendor/github.com/gorilla/websocket/conn.go +0 -1238
  150. slidge_whatsapp/vendor/github.com/gorilla/websocket/doc.go +0 -227
  151. slidge_whatsapp/vendor/github.com/gorilla/websocket/join.go +0 -42
  152. slidge_whatsapp/vendor/github.com/gorilla/websocket/json.go +0 -60
  153. slidge_whatsapp/vendor/github.com/gorilla/websocket/mask.go +0 -55
  154. slidge_whatsapp/vendor/github.com/gorilla/websocket/mask_safe.go +0 -16
  155. slidge_whatsapp/vendor/github.com/gorilla/websocket/prepared.go +0 -102
  156. slidge_whatsapp/vendor/github.com/gorilla/websocket/proxy.go +0 -77
  157. slidge_whatsapp/vendor/github.com/gorilla/websocket/server.go +0 -365
  158. slidge_whatsapp/vendor/github.com/gorilla/websocket/tls_handshake.go +0 -21
  159. slidge_whatsapp/vendor/github.com/gorilla/websocket/tls_handshake_116.go +0 -21
  160. slidge_whatsapp/vendor/github.com/gorilla/websocket/util.go +0 -298
  161. slidge_whatsapp/vendor/github.com/gorilla/websocket/x_net_proxy.go +0 -473
  162. {slidge_whatsapp-0.3.7.dist-info → slidge_whatsapp-0.3.8.dist-info}/WHEEL +0 -0
  163. {slidge_whatsapp-0.3.7.dist-info → slidge_whatsapp-0.3.8.dist-info}/entry_points.txt +0 -0
  164. {slidge_whatsapp-0.3.7.dist-info → slidge_whatsapp-0.3.8.dist-info}/licenses/LICENSE +0 -0
@@ -289,8 +289,7 @@ func (cli *Client) fetchAppStatePatches(ctx context.Context, name appstate.WAPat
289
289
  if !snapshot {
290
290
  attrs["version"] = fromVersion
291
291
  }
292
- resp, err := cli.sendIQ(infoQuery{
293
- Context: ctx,
292
+ resp, err := cli.sendIQ(ctx, infoQuery{
294
293
  Namespace: "w:sync:app:state",
295
294
  Type: "set",
296
295
  To: types.ServerJID,
@@ -384,8 +383,7 @@ func (cli *Client) sendAppState(ctx context.Context, patch appstate.PatchInfo, w
384
383
  return err
385
384
  }
386
385
 
387
- resp, err := cli.sendIQ(infoQuery{
388
- Context: ctx,
386
+ resp, err := cli.sendIQ(ctx, infoQuery{
389
387
  Namespace: "w:sync:app:state",
390
388
  Type: iqSet,
391
389
  To: types.ServerJID,
@@ -429,3 +427,19 @@ func (cli *Client) sendAppState(ctx context.Context, patch appstate.PatchInfo, w
429
427
 
430
428
  return nil
431
429
  }
430
+
431
+ func (cli *Client) MarkNotDirty(ctx context.Context, cleanType string, ts time.Time) error {
432
+ _, err := cli.sendIQ(ctx, infoQuery{
433
+ Namespace: "urn:xmpp:whatsapp:dirty",
434
+ Type: iqSet,
435
+ To: types.ServerJID,
436
+ Content: []waBinary.Node{{
437
+ Tag: "clean",
438
+ Attrs: waBinary.Attrs{
439
+ "type": cleanType,
440
+ "timestamp": ts.Unix(),
441
+ },
442
+ }},
443
+ })
444
+ return err
445
+ }
@@ -45,7 +45,7 @@ func (cli *Client) getBroadcastListParticipants(ctx context.Context, jid types.J
45
45
  }
46
46
 
47
47
  func (cli *Client) getStatusBroadcastRecipients(ctx context.Context) ([]types.JID, error) {
48
- statusPrivacyOptions, err := cli.GetStatusPrivacy()
48
+ statusPrivacyOptions, err := cli.GetStatusPrivacy(ctx)
49
49
  if err != nil {
50
50
  return nil, fmt.Errorf("failed to get status privacy: %w", err)
51
51
  }
@@ -90,8 +90,8 @@ var DefaultStatusPrivacy = []types.StatusPrivacy{{
90
90
  // GetStatusPrivacy gets the user's status privacy settings (who to send status broadcasts to).
91
91
  //
92
92
  // There can be multiple different stored settings, the first one is always the default.
93
- func (cli *Client) GetStatusPrivacy() ([]types.StatusPrivacy, error) {
94
- resp, err := cli.sendIQ(infoQuery{
93
+ func (cli *Client) GetStatusPrivacy(ctx context.Context) ([]types.StatusPrivacy, error) {
94
+ resp, err := cli.sendIQ(ctx, infoQuery{
95
95
  Namespace: "status",
96
96
  Type: iqGet,
97
97
  To: types.ServerJID,
@@ -7,13 +7,15 @@
7
7
  package whatsmeow
8
8
 
9
9
  import (
10
+ "context"
11
+
10
12
  waBinary "go.mau.fi/whatsmeow/binary"
11
13
  "go.mau.fi/whatsmeow/types"
12
14
  "go.mau.fi/whatsmeow/types/events"
13
15
  )
14
16
 
15
- func (cli *Client) handleCallEvent(node *waBinary.Node) {
16
- defer cli.maybeDeferredAck(cli.BackgroundEventCtx, node)()
17
+ func (cli *Client) handleCallEvent(ctx context.Context, node *waBinary.Node) {
18
+ defer cli.maybeDeferredAck(ctx, node)()
17
19
 
18
20
  if len(node.GetChildren()) != 1 {
19
21
  cli.dispatchEvent(&events.UnknownCallEvent{Node: node})
@@ -101,13 +103,13 @@ func (cli *Client) handleCallEvent(node *waBinary.Node) {
101
103
  }
102
104
 
103
105
  // RejectCall reject an incoming call.
104
- func (cli *Client) RejectCall(callFrom types.JID, callID string) error {
106
+ func (cli *Client) RejectCall(ctx context.Context, callFrom types.JID, callID string) error {
105
107
  ownID := cli.getOwnID()
106
108
  if ownID.IsEmpty() {
107
109
  return ErrNotLoggedIn
108
110
  }
109
111
  ownID, callFrom = ownID.ToNonAD(), callFrom.ToNonAD()
110
- return cli.sendNode(waBinary.Node{
112
+ return cli.sendNode(ctx, waBinary.Node{
111
113
  Tag: "call",
112
114
  Attrs: waBinary.Attrs{"id": cli.GenerateMessageID(), "from": ownID, "to": callFrom},
113
115
  Content: []waBinary.Node{{
@@ -12,6 +12,7 @@ import (
12
12
  "encoding/hex"
13
13
  "errors"
14
14
  "fmt"
15
+ "net"
15
16
  "net/http"
16
17
  "net/url"
17
18
  "runtime/debug"
@@ -19,7 +20,6 @@ import (
19
20
  "sync/atomic"
20
21
  "time"
21
22
 
22
- "github.com/gorilla/websocket"
23
23
  "go.mau.fi/util/exhttp"
24
24
  "go.mau.fi/util/exsync"
25
25
  "go.mau.fi/util/random"
@@ -41,7 +41,7 @@ import (
41
41
  // EventHandler is a function that can handle events from WhatsApp.
42
42
  type EventHandler func(evt any)
43
43
  type EventHandlerWithSuccessStatus func(evt any) bool
44
- type nodeHandler func(node *waBinary.Node)
44
+ type nodeHandler func(ctx context.Context, node *waBinary.Node)
45
45
 
46
46
  var nextHandlerID uint32
47
47
 
@@ -65,7 +65,6 @@ type Client struct {
65
65
  socket *socket.NoiseSocket
66
66
  socketLock sync.RWMutex
67
67
  socketWait chan struct{}
68
- wsDialer *websocket.Dialer
69
68
 
70
69
  isLoggedIn atomic.Bool
71
70
  expectedDisconnect *exsync.Event
@@ -171,10 +170,9 @@ type Client struct {
171
170
  uniqueID string
172
171
  idCounter atomic.Uint64
173
172
 
174
- proxy Proxy
175
- socksProxy proxy.Dialer
176
- proxyOnlyLogin bool
177
- http *http.Client
173
+ mediaHTTP *http.Client
174
+ websocketHTTP *http.Client
175
+ preLoginHTTP *http.Client
178
176
 
179
177
  // This field changes the client to act like a Messenger client instead of a WhatsApp one.
180
178
  //
@@ -222,11 +220,13 @@ func NewClient(deviceStore *store.Device, log waLog.Logger) *Client {
222
220
  log = waLog.Noop
223
221
  }
224
222
  uniqueIDPrefix := random.Bytes(2)
223
+ baseHTTPClient := &http.Client{
224
+ Transport: (http.DefaultTransport.(*http.Transport)).Clone(),
225
+ }
225
226
  cli := &Client{
226
- http: &http.Client{
227
- Transport: (http.DefaultTransport.(*http.Transport)).Clone(),
228
- },
229
- proxy: http.ProxyFromEnvironment,
227
+ mediaHTTP: baseHTTPClient,
228
+ websocketHTTP: baseHTTPClient,
229
+ preLoginHTTP: baseHTTPClient,
230
230
  Store: deviceStore,
231
231
  Log: log,
232
232
  recvLog: log.Sub("Recv"),
@@ -292,7 +292,10 @@ func (cli *Client) SetProxyAddress(addr string, opts ...SetProxyOptions) error {
292
292
  if parsed.Scheme == "http" || parsed.Scheme == "https" {
293
293
  cli.SetProxy(http.ProxyURL(parsed), opts...)
294
294
  } else if parsed.Scheme == "socks5" {
295
- px, err := proxy.FromURL(parsed, proxy.Direct)
295
+ px, err := proxy.FromURL(parsed, &net.Dialer{
296
+ Timeout: 30 * time.Second,
297
+ KeepAlive: 30 * time.Second,
298
+ })
296
299
  if err != nil {
297
300
  return err
298
301
  }
@@ -330,21 +333,16 @@ func (cli *Client) SetProxy(proxy Proxy, opts ...SetProxyOptions) {
330
333
  if len(opts) > 0 {
331
334
  opt = opts[0]
332
335
  }
333
- if !opt.NoWebsocket {
334
- cli.proxy = proxy
335
- cli.socksProxy = nil
336
- }
337
- if !opt.NoMedia {
338
- transport := cli.http.Transport.(*http.Transport)
339
- transport.Proxy = proxy
340
- transport.Dial = nil
341
- transport.DialContext = nil
342
- }
336
+ transport := (http.DefaultTransport.(*http.Transport)).Clone()
337
+ transport.Proxy = proxy
338
+ cli.setTransport(transport, opt)
343
339
  }
344
340
 
345
341
  type SetProxyOptions struct {
346
342
  // If NoWebsocket is true, the proxy won't be used for the websocket
347
343
  NoWebsocket bool
344
+ // If OnlyLogin is true, the proxy will be used for the pre-login websocket, but not the post-login one
345
+ OnlyLogin bool
348
346
  // If NoMedia is true, the proxy won't be used for media uploads/downloads
349
347
  NoMedia bool
350
348
  }
@@ -357,27 +355,40 @@ func (cli *Client) SetSOCKSProxy(px proxy.Dialer, opts ...SetProxyOptions) {
357
355
  if len(opts) > 0 {
358
356
  opt = opts[0]
359
357
  }
358
+ transport := (http.DefaultTransport.(*http.Transport)).Clone()
359
+ pxc := px.(proxy.ContextDialer)
360
+ transport.DialContext = pxc.DialContext
361
+ cli.setTransport(transport, opt)
362
+ }
363
+
364
+ func (cli *Client) setTransport(transport *http.Transport, opt SetProxyOptions) {
360
365
  if !opt.NoWebsocket {
361
- cli.socksProxy = px
362
- cli.proxy = nil
366
+ cli.preLoginHTTP.Transport = transport
367
+ if !opt.OnlyLogin {
368
+ cli.websocketHTTP.Transport = transport
369
+ }
363
370
  }
364
371
  if !opt.NoMedia {
365
- transport := cli.http.Transport.(*http.Transport)
366
- transport.Proxy = nil
367
- transport.Dial = cli.socksProxy.Dial
368
- contextDialer, ok := cli.socksProxy.(proxy.ContextDialer)
369
- if ok {
370
- transport.DialContext = contextDialer.DialContext
371
- } else {
372
- transport.DialContext = nil
373
- }
372
+ cli.mediaHTTP.Transport = transport
374
373
  }
375
374
  }
376
375
 
377
- // ToggleProxyOnlyForLogin changes whether the proxy set with SetProxy or related methods
378
- // is only used for the pre-login websocket and not authenticated websockets.
379
- func (cli *Client) ToggleProxyOnlyForLogin(only bool) {
380
- cli.proxyOnlyLogin = only
376
+ // SetMediaHTTPClient sets the HTTP client used to download media.
377
+ // This will overwrite any set proxy calls.
378
+ func (cli *Client) SetMediaHTTPClient(h *http.Client) {
379
+ cli.mediaHTTP = h
380
+ }
381
+
382
+ // SetWebsocketHTTPClient sets the HTTP client used to establish the websocket connection for logged-in sessions.
383
+ // This will overwrite any set proxy calls.
384
+ func (cli *Client) SetWebsocketHTTPClient(h *http.Client) {
385
+ cli.websocketHTTP = h
386
+ }
387
+
388
+ // SetPreLoginHTTPClient sets the HTTP client used to establish the websocket connection before login.
389
+ // This will overwrite any set proxy calls.
390
+ func (cli *Client) SetPreLoginHTTPClient(h *http.Client) {
391
+ cli.preLoginHTTP = h
381
392
  }
382
393
 
383
394
  func (cli *Client) getSocketWaitChan() <-chan struct{} {
@@ -430,13 +441,13 @@ func (cli *Client) WaitForConnection(timeout time.Duration) bool {
430
441
  return true
431
442
  }
432
443
 
433
- func (cli *Client) SetWSDialer(dialer *websocket.Dialer) {
434
- cli.wsDialer = dialer
435
- }
436
-
437
444
  // Connect connects the client to the WhatsApp web websocket. After connection, it will either
438
445
  // authenticate if there's data in the device store, or emit a QREvent to set up a new link.
439
446
  func (cli *Client) Connect() error {
447
+ return cli.ConnectContext(cli.BackgroundEventCtx)
448
+ }
449
+
450
+ func (cli *Client) ConnectContext(ctx context.Context) error {
440
451
  if cli == nil {
441
452
  return ErrClientIsNil
442
453
  }
@@ -444,24 +455,24 @@ func (cli *Client) Connect() error {
444
455
  cli.socketLock.Lock()
445
456
  defer cli.socketLock.Unlock()
446
457
 
447
- err := cli.unlockedConnect()
458
+ err := cli.unlockedConnect(ctx)
448
459
  if exhttp.IsNetworkError(err) && cli.InitialAutoReconnect && cli.EnableAutoReconnect {
449
460
  cli.Log.Errorf("Initial connection failed but reconnecting in background (%v)", err)
450
461
  go cli.dispatchEvent(&events.Disconnected{})
451
- go cli.autoReconnect()
462
+ go cli.autoReconnect(ctx)
452
463
  return nil
453
464
  }
454
465
  return err
455
466
  }
456
467
 
457
- func (cli *Client) connect() error {
468
+ func (cli *Client) connect(ctx context.Context) error {
458
469
  cli.socketLock.Lock()
459
470
  defer cli.socketLock.Unlock()
460
471
 
461
- return cli.unlockedConnect()
472
+ return cli.unlockedConnect(ctx)
462
473
  }
463
474
 
464
- func (cli *Client) unlockedConnect() error {
475
+ func (cli *Client) unlockedConnect(ctx context.Context) error {
465
476
  if cli.socket != nil {
466
477
  if !cli.socket.IsConnected() {
467
478
  cli.unlockedDisconnect()
@@ -471,21 +482,11 @@ func (cli *Client) unlockedConnect() error {
471
482
  }
472
483
 
473
484
  cli.resetExpectedDisconnect()
474
- var wsDialer websocket.Dialer
475
- if cli.wsDialer != nil {
476
- wsDialer = *cli.wsDialer
477
- } else if !cli.proxyOnlyLogin || cli.Store.ID == nil {
478
- if cli.proxy != nil {
479
- wsDialer.Proxy = cli.proxy
480
- } else if cli.socksProxy != nil {
481
- wsDialer.NetDial = cli.socksProxy.Dial
482
- contextDialer, ok := cli.socksProxy.(proxy.ContextDialer)
483
- if ok {
484
- wsDialer.NetDialContext = contextDialer.DialContext
485
- }
486
- }
485
+ client := cli.websocketHTTP
486
+ if cli.Store.ID == nil {
487
+ client = cli.preLoginHTTP
487
488
  }
488
- fs := socket.NewFrameSocket(cli.Log.Sub("Socket"), wsDialer)
489
+ fs := socket.NewFrameSocket(cli.Log.Sub("Socket"), client)
489
490
  if cli.MessengerConfig != nil {
490
491
  fs.URL = cli.MessengerConfig.WebsocketURL
491
492
  fs.HTTPHeaders.Set("Origin", cli.MessengerConfig.BaseURL)
@@ -496,15 +497,15 @@ func (cli *Client) unlockedConnect() error {
496
497
  //fs.HTTPHeaders.Set("Sec-Fetch-Mode", "websocket")
497
498
  //fs.HTTPHeaders.Set("Sec-Fetch-Site", "cross-site")
498
499
  }
499
- if err := fs.Connect(); err != nil {
500
+ if err := fs.Connect(ctx); err != nil {
500
501
  fs.Close(0)
501
502
  return err
502
- } else if err = cli.doHandshake(fs, *keys.NewKeyPair()); err != nil {
503
+ } else if err = cli.doHandshake(ctx, fs, *keys.NewKeyPair()); err != nil {
503
504
  fs.Close(0)
504
505
  return fmt.Errorf("noise handshake failed: %w", err)
505
506
  }
506
- go cli.keepAliveLoop(cli.socket.Context())
507
- go cli.handlerQueueLoop(cli.socket.Context())
507
+ go cli.keepAliveLoop(ctx, fs.Context())
508
+ go cli.handlerQueueLoop(ctx, fs.Context())
508
509
  return nil
509
510
  }
510
511
 
@@ -513,7 +514,7 @@ func (cli *Client) IsLoggedIn() bool {
513
514
  return cli != nil && cli.isLoggedIn.Load()
514
515
  }
515
516
 
516
- func (cli *Client) onDisconnect(ns *socket.NoiseSocket, remote bool) {
517
+ func (cli *Client) onDisconnect(ctx context.Context, ns *socket.NoiseSocket, remote bool) {
517
518
  ns.Stop(false)
518
519
  cli.socketLock.Lock()
519
520
  defer cli.socketLock.Unlock()
@@ -523,7 +524,7 @@ func (cli *Client) onDisconnect(ns *socket.NoiseSocket, remote bool) {
523
524
  if !cli.isExpectedDisconnect() && remote {
524
525
  cli.Log.Debugf("Emitting Disconnected event")
525
526
  go cli.dispatchEvent(&events.Disconnected{})
526
- go cli.autoReconnect()
527
+ go cli.autoReconnect(ctx)
527
528
  } else if remote {
528
529
  cli.Log.Debugf("OnDisconnect() called, but it was expected, so not emitting event")
529
530
  } else {
@@ -546,7 +547,7 @@ func (cli *Client) isExpectedDisconnect() bool {
546
547
  return cli.expectedDisconnect.IsSet()
547
548
  }
548
549
 
549
- func (cli *Client) autoReconnect() {
550
+ func (cli *Client) autoReconnect(ctx context.Context) {
550
551
  if !cli.EnableAutoReconnect || cli.Store.ID == nil {
551
552
  return
552
553
  }
@@ -554,15 +555,20 @@ func (cli *Client) autoReconnect() {
554
555
  autoReconnectDelay := time.Duration(cli.AutoReconnectErrors) * 2 * time.Second
555
556
  cli.Log.Debugf("Automatically reconnecting after %v", autoReconnectDelay)
556
557
  cli.AutoReconnectErrors++
557
- if cli.expectedDisconnect.WaitTimeout(autoReconnectDelay) {
558
+ if cli.expectedDisconnect.WaitTimeoutCtx(ctx, autoReconnectDelay) == nil {
559
+ cli.Log.Debugf("Cancelling automatic reconnect due to expected disconnect")
560
+ return
561
+ } else if ctx.Err() != nil {
562
+ cli.Log.Debugf("Cancelling automatic reconnect due to context cancellation")
558
563
  return
559
564
  }
560
- err := cli.connect()
565
+ err := cli.connect(ctx)
561
566
  if errors.Is(err, ErrAlreadyConnected) {
562
567
  cli.Log.Debugf("Connect() said we're already connected after autoreconnect sleep")
563
568
  return
564
569
  } else if err != nil {
565
570
  if cli.expectedDisconnect.IsSet() {
571
+ cli.Log.Debugf("Autoreconnect failed, but disconnect was expected, not reconnecting")
566
572
  return
567
573
  }
568
574
  cli.Log.Errorf("Error reconnecting after autoreconnect sleep: %v", err)
@@ -629,7 +635,7 @@ func (cli *Client) Logout(ctx context.Context) error {
629
635
  if ownID.IsEmpty() {
630
636
  return ErrNotLoggedIn
631
637
  }
632
- _, err := cli.sendIQ(infoQuery{
638
+ _, err := cli.sendIQ(ctx, infoQuery{
633
639
  Namespace: "md",
634
640
  Type: "set",
635
641
  To: types.ServerJID,
@@ -737,7 +743,7 @@ func (cli *Client) RemoveEventHandlers() {
737
743
  cli.eventHandlersLock.Unlock()
738
744
  }
739
745
 
740
- func (cli *Client) handleFrame(data []byte) {
746
+ func (cli *Client) handleFrame(ctx context.Context, data []byte) {
741
747
  decompressed, err := waBinary.Unpack(data)
742
748
  if err != nil {
743
749
  cli.Log.Warnf("Failed to decompress frame: %v", err)
@@ -756,15 +762,19 @@ func (cli *Client) handleFrame(data []byte) {
756
762
  cli.Log.Warnf("Received stream end frame")
757
763
  }
758
764
  // TODO should we do something else?
759
- } else if cli.receiveResponse(node) {
765
+ } else if cli.receiveResponse(ctx, node) {
760
766
  // handled
761
767
  } else if _, ok := cli.nodeHandlers[node.Tag]; ok {
762
768
  select {
763
769
  case cli.handlerQueue <- node:
770
+ case <-ctx.Done():
764
771
  default:
765
772
  cli.Log.Warnf("Handler queue is full, message ordering is no longer guaranteed")
766
773
  go func() {
767
- cli.handlerQueue <- node
774
+ select {
775
+ case cli.handlerQueue <- node:
776
+ case <-ctx.Done():
777
+ }
768
778
  }()
769
779
  }
770
780
  } else if node.Tag != "ack" {
@@ -772,7 +782,7 @@ func (cli *Client) handleFrame(data []byte) {
772
782
  }
773
783
  }
774
784
 
775
- func (cli *Client) handlerQueueLoop(ctx context.Context) {
785
+ func (cli *Client) handlerQueueLoop(evtCtx, connCtx context.Context) {
776
786
  ticker := time.NewTicker(30 * time.Second)
777
787
  ticker.Stop()
778
788
  cli.Log.Debugf("Starting handler queue loop")
@@ -783,7 +793,7 @@ Loop:
783
793
  doneChan := make(chan struct{}, 1)
784
794
  start := time.Now()
785
795
  go func() {
786
- cli.nodeHandlers[node.Tag](node)
796
+ cli.nodeHandlers[node.Tag](evtCtx, node)
787
797
  duration := time.Since(start)
788
798
  doneChan <- struct{}{}
789
799
  if duration > 5*time.Second {
@@ -802,14 +812,14 @@ Loop:
802
812
  }
803
813
  cli.Log.Warnf("Continuing handling of %s in background as it's taking too long", node.XMLString())
804
814
  ticker.Stop()
805
- case <-ctx.Done():
815
+ case <-connCtx.Done():
806
816
  cli.Log.Debugf("Closing handler queue loop")
807
817
  return
808
818
  }
809
819
  }
810
820
  }
811
821
 
812
- func (cli *Client) sendNodeAndGetData(node waBinary.Node) ([]byte, error) {
822
+ func (cli *Client) sendNodeAndGetData(ctx context.Context, node waBinary.Node) ([]byte, error) {
813
823
  if cli == nil {
814
824
  return nil, ErrClientIsNil
815
825
  }
@@ -826,11 +836,11 @@ func (cli *Client) sendNodeAndGetData(node waBinary.Node) ([]byte, error) {
826
836
  }
827
837
 
828
838
  cli.sendLog.Debugf("%s", node.XMLString())
829
- return payload, sock.SendFrame(payload)
839
+ return payload, sock.SendFrame(ctx, payload)
830
840
  }
831
841
 
832
- func (cli *Client) sendNode(node waBinary.Node) error {
833
- _, err := cli.sendNodeAndGetData(node)
842
+ func (cli *Client) sendNode(ctx context.Context, node waBinary.Node) error {
843
+ _, err := cli.sendNodeAndGetData(ctx, node)
834
844
  return err
835
845
  }
836
846
 
@@ -16,8 +16,7 @@ import (
16
16
  "go.mau.fi/whatsmeow/types/events"
17
17
  )
18
18
 
19
- func (cli *Client) handleStreamError(node *waBinary.Node) {
20
- ctx := cli.BackgroundEventCtx
19
+ func (cli *Client) handleStreamError(ctx context.Context, node *waBinary.Node) {
21
20
  cli.isLoggedIn.Store(false)
22
21
  cli.clearResponseWaiters(node)
23
22
  code, _ := node.Attrs["code"].(string)
@@ -33,7 +32,7 @@ func (cli *Client) handleStreamError(node *waBinary.Node) {
33
32
  cli.Log.Infof("Got 515 code, reconnecting...")
34
33
  go func() {
35
34
  cli.Disconnect()
36
- err := cli.connect()
35
+ err := cli.connect(ctx)
37
36
  if err != nil {
38
37
  cli.Log.Errorf("Failed to reconnect after 515 code: %v", err)
39
38
  }
@@ -70,7 +69,7 @@ func (cli *Client) handleStreamError(node *waBinary.Node) {
70
69
  }
71
70
  }
72
71
 
73
- func (cli *Client) handleIB(node *waBinary.Node) {
72
+ func (cli *Client) handleIB(ctx context.Context, node *waBinary.Node) {
74
73
  children := node.GetChildren()
75
74
  for _, child := range children {
76
75
  ag := child.AttrGetter()
@@ -89,12 +88,18 @@ func (cli *Client) handleIB(node *waBinary.Node) {
89
88
  cli.dispatchEvent(&events.OfflineSyncCompleted{
90
89
  Count: ag.Int("count"),
91
90
  })
91
+ case "dirty":
92
+ //ts := ag.UnixTime("timestamp")
93
+ //typ := ag.String("type") // account_sync
94
+ //go func() {
95
+ // err := cli.MarkNotDirty(ctx, typ, ts)
96
+ // zerolog.Ctx(ctx).Debug().Err(err).Msg("Marked dirty item as clean")
97
+ //}()
92
98
  }
93
99
  }
94
100
  }
95
101
 
96
- func (cli *Client) handleConnectFailure(node *waBinary.Node) {
97
- ctx := cli.BackgroundEventCtx
102
+ func (cli *Client) handleConnectFailure(ctx context.Context, node *waBinary.Node) {
98
103
  ag := node.AttrGetter()
99
104
  reason := events.ConnectFailureReason(ag.Int("reason"))
100
105
  message := ag.OptionalString("message")
@@ -150,8 +155,7 @@ func (cli *Client) handleConnectFailure(node *waBinary.Node) {
150
155
  }
151
156
  }
152
157
 
153
- func (cli *Client) handleConnectSuccess(node *waBinary.Node) {
154
- ctx := cli.BackgroundEventCtx
158
+ func (cli *Client) handleConnectSuccess(ctx context.Context, node *waBinary.Node) {
155
159
  cli.Log.Infof("Successfully authenticated")
156
160
  cli.LastSuccessfulConnect = time.Now()
157
161
  cli.AutoReconnectErrors = 0
@@ -182,7 +186,7 @@ func (cli *Client) handleConnectSuccess(node *waBinary.Node) {
182
186
  } else {
183
187
  cli.Log.Debugf("Database has %d prekeys, server says we have %d", dbCount, serverCount)
184
188
  if serverCount < MinPreKeyCount || dbCount < MinPreKeyCount {
185
- cli.uploadPreKeys(ctx)
189
+ cli.uploadPreKeys(ctx, dbCount == 0 && serverCount == 0)
186
190
  sc, _ := cli.getServerPreKeyCount(ctx)
187
191
  cli.Log.Debugf("Prekey count after upload: %d", sc)
188
192
  }
@@ -205,11 +209,10 @@ func (cli *Client) SetPassive(ctx context.Context, passive bool) error {
205
209
  if passive {
206
210
  tag = "passive"
207
211
  }
208
- _, err := cli.sendIQ(infoQuery{
212
+ _, err := cli.sendIQ(ctx, infoQuery{
209
213
  Namespace: "passive",
210
214
  Type: "set",
211
215
  To: types.ServerJID,
212
- Context: ctx,
213
216
  Content: []waBinary.Node{{Tag: tag}},
214
217
  })
215
218
  if err != nil {
@@ -255,6 +255,9 @@ func (cli *Client) DownloadMediaWithPath(
255
255
  mediaType MediaType,
256
256
  mmsType string,
257
257
  ) (data []byte, err error) {
258
+ if !strings.HasPrefix(directPath, "/") {
259
+ return nil, fmt.Errorf("media download path does not start with slash: %s", directPath)
260
+ }
258
261
  var mediaConn *MediaConn
259
262
  mediaConn, err = cli.refreshMediaConn(ctx, false)
260
263
  if err != nil {
@@ -365,7 +368,7 @@ func (cli *Client) doMediaDownloadRequest(ctx context.Context, url string) (*htt
365
368
  req.Header.Set("User-Agent", cli.MessengerConfig.UserAgent)
366
369
  }
367
370
  // TODO user agent for whatsapp downloads?
368
- resp, err := cli.http.Do(req)
371
+ resp, err := cli.mediaHTTP.Do(req)
369
372
  if err != nil {
370
373
  return nil, err
371
374
  }