slidge-whatsapp 0.2.6__cp313-cp313-manylinux_2_36_aarch64.whl → 0.2.7__cp313-cp313-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 (87) hide show
  1. slidge_whatsapp/event.go +8 -2
  2. slidge_whatsapp/generated/_whatsapp.cpython-313-aarch64-linux-gnu.h +166 -166
  3. slidge_whatsapp/generated/_whatsapp.cpython-313-aarch64-linux-gnu.so +0 -0
  4. slidge_whatsapp/generated/build.py +146 -146
  5. slidge_whatsapp/generated/whatsapp.c +1486 -1486
  6. slidge_whatsapp/generated/whatsapp.go +730 -730
  7. slidge_whatsapp/generated/whatsapp.py +1053 -1053
  8. slidge_whatsapp/generated/whatsapp_go.h +166 -166
  9. slidge_whatsapp/go.mod +6 -6
  10. slidge_whatsapp/go.sum +12 -18
  11. slidge_whatsapp/media/media.go +5 -1
  12. slidge_whatsapp/vendor/go.mau.fi/util/exhttp/json.go +1 -6
  13. slidge_whatsapp/vendor/go.mau.fi/util/exstrings/stringutil.go +76 -0
  14. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/armadillomessage.go +38 -6
  15. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/binary/encoder.go +1 -1
  16. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/call.go +1 -1
  17. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/client.go +64 -27
  18. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/connectionevents.go +8 -6
  19. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/download-to-file.go +19 -12
  20. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/download.go +22 -6
  21. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/group.go +2 -2
  22. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/internals.go +33 -17
  23. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/keepalive.go +1 -0
  24. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/message.go +198 -48
  25. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/notification.go +12 -7
  26. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/extra.go +7 -0
  27. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloAddMessage/InstamadilloAddMessage.pb.go +983 -0
  28. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloAddMessage/InstamadilloAddMessage.proto +85 -0
  29. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloAddMessage/extra.go +3 -0
  30. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloCoreTypeActionLog/InstamadilloCoreTypeActionLog.pb.go +197 -0
  31. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloCoreTypeActionLog/InstamadilloCoreTypeActionLog.proto +13 -0
  32. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloCoreTypeAdminMessage/InstamadilloCoreTypeAdminMessage.pb.go +279 -0
  33. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloCoreTypeAdminMessage/InstamadilloCoreTypeAdminMessage.proto +21 -0
  34. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloCoreTypeCollection/InstamadilloCoreTypeCollection.pb.go +137 -0
  35. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloCoreTypeCollection/InstamadilloCoreTypeCollection.proto +10 -0
  36. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloCoreTypeLink/InstamadilloCoreTypeLink.pb.go +313 -0
  37. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloCoreTypeLink/InstamadilloCoreTypeLink.proto +27 -0
  38. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloCoreTypeMedia/InstamadilloCoreTypeMedia.pb.go +1299 -0
  39. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloCoreTypeMedia/InstamadilloCoreTypeMedia.proto +112 -0
  40. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloCoreTypeText/InstamadilloCoreTypeText.pb.go +514 -0
  41. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloCoreTypeText/InstamadilloCoreTypeText.proto +47 -0
  42. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloDeleteMessage/InstamadilloDeleteMessage.pb.go +123 -0
  43. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloDeleteMessage/InstamadilloDeleteMessage.proto +7 -0
  44. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloDeleteMessage/extra.go +3 -0
  45. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloSupplementMessage/InstamadilloSupplementMessage.pb.go +720 -0
  46. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloSupplementMessage/InstamadilloSupplementMessage.proto +59 -0
  47. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloSupplementMessage/extra.go +3 -0
  48. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloTransportPayload/InstamadilloTransportPayload.pb.go +365 -0
  49. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloTransportPayload/InstamadilloTransportPayload.proto +33 -0
  50. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloXmaContentRef/InstamadilloXmaContentRef.pb.go +1238 -0
  51. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/instamadilloXmaContentRef/InstamadilloXmaContentRef.proto +105 -0
  52. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waArmadilloXMA/WAArmadilloXMA.pb.go +16 -4
  53. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waArmadilloXMA/WAArmadilloXMA.proto +3 -0
  54. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waCompanionReg/WACompanionReg.pb.go +16 -7
  55. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waCompanionReg/WACompanionReg.proto +1 -0
  56. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waE2E/WAWebProtobufsE2E.pb.go +2436 -1676
  57. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waE2E/WAWebProtobufsE2E.proto +85 -7
  58. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waLidMigrationSyncPayload/WAWebProtobufLidMigrationSyncPayload.pb.go +198 -0
  59. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waLidMigrationSyncPayload/WAWebProtobufLidMigrationSyncPayload.proto +14 -0
  60. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waMsgTransport/extra.go +7 -6
  61. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waStatusAttributions/WAStatusAttributions.pb.go +800 -0
  62. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waStatusAttributions/WAStatusAttributions.proto +72 -0
  63. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waSyncAction/WASyncAction.pb.go +678 -441
  64. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waSyncAction/WASyncAction.proto +20 -0
  65. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waWeb/WAWebProtobufsWeb.pb.go +11 -3
  66. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/proto/waWeb/WAWebProtobufsWeb.proto +2 -0
  67. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/receipt.go +13 -7
  68. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/reportingfields.json +1 -0
  69. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/reportingtoken.go +176 -0
  70. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/retry.go +10 -2
  71. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/send.go +32 -17
  72. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/sendfb.go +1 -0
  73. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/clientpayload.go +1 -1
  74. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/sqlstore/container.go +9 -6
  75. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/sqlstore/upgrades/00-latest-schema.sql +4 -2
  76. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/sqlstore/upgrades/10-chat-db-lid-migration-ts.sql +2 -0
  77. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/store/store.go +2 -0
  78. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/types/events/events.go +5 -2
  79. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/types/message.go +1 -0
  80. slidge_whatsapp/vendor/go.mau.fi/whatsmeow/user.go +2 -0
  81. slidge_whatsapp/vendor/golang.org/x/net/http2/frame.go +8 -8
  82. slidge_whatsapp/vendor/modules.txt +20 -6
  83. {slidge_whatsapp-0.2.6.dist-info → slidge_whatsapp-0.2.7.dist-info}/METADATA +1 -1
  84. {slidge_whatsapp-0.2.6.dist-info → slidge_whatsapp-0.2.7.dist-info}/RECORD +87 -54
  85. {slidge_whatsapp-0.2.6.dist-info → slidge_whatsapp-0.2.7.dist-info}/LICENSE +0 -0
  86. {slidge_whatsapp-0.2.6.dist-info → slidge_whatsapp-0.2.7.dist-info}/WHEEL +0 -0
  87. {slidge_whatsapp-0.2.6.dist-info → slidge_whatsapp-0.2.7.dist-info}/entry_points.txt +0 -0
@@ -56,6 +56,15 @@ message CallLogRecord {
56
56
  optional CallType callType = 15;
57
57
  }
58
58
 
59
+ message PaymentTosAction {
60
+ enum PaymentNotice {
61
+ BR_PAY_PRIVACY_POLICY = 0;
62
+ }
63
+
64
+ required PaymentNotice paymentNotice = 1;
65
+ required bool accepted = 2;
66
+ }
67
+
59
68
  message NotificationActivitySettingAction {
60
69
  enum NotificationActivitySetting {
61
70
  DEFAULT_ALL_MESSAGES = 0;
@@ -244,6 +253,13 @@ message SyncActionValue {
244
253
  optional NotificationActivitySettingAction notificationActivitySettingAction = 60;
245
254
  optional LidContactAction lidContactAction = 61;
246
255
  optional CtwaPerCustomerDataSharingAction ctwaPerCustomerDataSharingAction = 62;
256
+ optional PaymentTosAction paymentTosAction = 63;
257
+ optional PrivacySettingChannelsPersonalisedRecommendationAction privacySettingChannelsPersonalisedRecommendationAction = 64;
258
+ optional BusinessBroadcastAssociationAction businessBroadcastAssociationAction = 65;
259
+ }
260
+
261
+ message BusinessBroadcastAssociationAction {
262
+ optional bool deleted = 1;
247
263
  }
248
264
 
249
265
  message CtwaPerCustomerDataSharingAction {
@@ -265,6 +281,10 @@ message FavoritesAction {
265
281
  repeated Favorite favorites = 1;
266
282
  }
267
283
 
284
+ message PrivacySettingChannelsPersonalisedRecommendationAction {
285
+ optional bool isUserOptedOut = 1;
286
+ }
287
+
268
288
  message PrivacySettingDisableLinkPreviewsAction {
269
289
  optional bool isPreviewsDisabled = 1;
270
290
  }
@@ -308,6 +308,8 @@ const (
308
308
  WebMessageInfo_BIZ_CUSTOMER_3PD_DATA_SHARING_OPT_OUT_MESSAGE WebMessageInfo_StubType = 215
309
309
  WebMessageInfo_CHANGE_LIMIT_SHARING WebMessageInfo_StubType = 216
310
310
  WebMessageInfo_GROUP_MEMBER_LINK_MODE WebMessageInfo_StubType = 217
311
+ WebMessageInfo_BIZ_AUTOMATICALLY_LABELED_CHAT_SYSTEM_MESSAGE WebMessageInfo_StubType = 218
312
+ WebMessageInfo_PHONE_NUMBER_HIDING_CHAT_DEPRECATED_MESSAGE WebMessageInfo_StubType = 219
311
313
  )
312
314
 
313
315
  // Enum value maps for WebMessageInfo_StubType.
@@ -531,6 +533,8 @@ var (
531
533
  215: "BIZ_CUSTOMER_3PD_DATA_SHARING_OPT_OUT_MESSAGE",
532
534
  216: "CHANGE_LIMIT_SHARING",
533
535
  217: "GROUP_MEMBER_LINK_MODE",
536
+ 218: "BIZ_AUTOMATICALLY_LABELED_CHAT_SYSTEM_MESSAGE",
537
+ 219: "PHONE_NUMBER_HIDING_CHAT_DEPRECATED_MESSAGE",
534
538
  }
535
539
  WebMessageInfo_StubType_value = map[string]int32{
536
540
  "UNKNOWN": 0,
@@ -751,6 +755,8 @@ var (
751
755
  "BIZ_CUSTOMER_3PD_DATA_SHARING_OPT_OUT_MESSAGE": 215,
752
756
  "CHANGE_LIMIT_SHARING": 216,
753
757
  "GROUP_MEMBER_LINK_MODE": 217,
758
+ "BIZ_AUTOMATICALLY_LABELED_CHAT_SYSTEM_MESSAGE": 218,
759
+ "PHONE_NUMBER_HIDING_CHAT_DEPRECATED_MESSAGE": 219,
754
760
  }
755
761
  )
756
762
 
@@ -3705,7 +3711,7 @@ var File_waWeb_WAWebProtobufsWeb_proto protoreflect.FileDescriptor
3705
3711
 
3706
3712
  const file_waWeb_WAWebProtobufsWeb_proto_rawDesc = "" +
3707
3713
  "\n" +
3708
- "\x1dwaWeb/WAWebProtobufsWeb.proto\x12\x11WAWebProtobufsWeb\x1a\x1dwaE2E/WAWebProtobufsE2E.proto\x1a\x17waCommon/WACommon.proto\"\x94V\n" +
3714
+ "\x1dwaWeb/WAWebProtobufsWeb.proto\x12\x11WAWebProtobufsWeb\x1a\x1dwaE2E/WAWebProtobufsE2E.proto\x1a\x17waCommon/WACommon.proto\"\xfaV\n" +
3709
3715
  "\x0eWebMessageInfo\x12&\n" +
3710
3716
  "\x03key\x18\x01 \x02(\v2\x14.WACommon.MessageKeyR\x03key\x124\n" +
3711
3717
  "\amessage\x18\x02 \x01(\v2\x1a.WAWebProtobufsE2E.MessageR\amessage\x12*\n" +
@@ -3778,7 +3784,7 @@ const file_waWeb_WAWebProtobufsWeb_proto_rawDesc = "" +
3778
3784
  "\x02FB\x10\x02\x12\a\n" +
3779
3785
  "\x03BSP\x10\x01\x12\x0e\n" +
3780
3786
  "\n" +
3781
- "BSP_AND_FB\x10\x03\"\xef9\n" +
3787
+ "BSP_AND_FB\x10\x03\"\xd5:\n" +
3782
3788
  "\bStubType\x12\v\n" +
3783
3789
  "\aUNKNOWN\x10\x00\x12\n" +
3784
3790
  "\n" +
@@ -4001,7 +4007,9 @@ const file_waWeb_WAWebProtobufsWeb_proto_rawDesc = "" +
4001
4007
  ",BIZ_CUSTOMER_3PD_DATA_SHARING_OPT_IN_MESSAGE\x10\xd6\x01\x122\n" +
4002
4008
  "-BIZ_CUSTOMER_3PD_DATA_SHARING_OPT_OUT_MESSAGE\x10\xd7\x01\x12\x19\n" +
4003
4009
  "\x14CHANGE_LIMIT_SHARING\x10\xd8\x01\x12\x1b\n" +
4004
- "\x16GROUP_MEMBER_LINK_MODE\x10\xd9\x01\"X\n" +
4010
+ "\x16GROUP_MEMBER_LINK_MODE\x10\xd9\x01\x122\n" +
4011
+ "-BIZ_AUTOMATICALLY_LABELED_CHAT_SYSTEM_MESSAGE\x10\xda\x01\x120\n" +
4012
+ "+PHONE_NUMBER_HIDING_CHAT_DEPRECATED_MESSAGE\x10\xdb\x01\"X\n" +
4005
4013
  "\x06Status\x12\t\n" +
4006
4014
  "\x05ERROR\x10\x00\x12\v\n" +
4007
4015
  "\aPENDING\x10\x01\x12\x0e\n" +
@@ -232,6 +232,8 @@ message WebMessageInfo {
232
232
  BIZ_CUSTOMER_3PD_DATA_SHARING_OPT_OUT_MESSAGE = 215;
233
233
  CHANGE_LIMIT_SHARING = 216;
234
234
  GROUP_MEMBER_LINK_MODE = 217;
235
+ BIZ_AUTOMATICALLY_LABELED_CHAT_SYSTEM_MESSAGE = 218;
236
+ PHONE_NUMBER_HIDING_CHAT_DEPRECATED_MESSAGE = 219;
235
237
  }
236
238
 
237
239
  enum Status {
@@ -11,26 +11,29 @@ import (
11
11
  "fmt"
12
12
  "time"
13
13
 
14
+ "go.mau.fi/util/ptr"
15
+
14
16
  waBinary "go.mau.fi/whatsmeow/binary"
15
17
  "go.mau.fi/whatsmeow/types"
16
18
  "go.mau.fi/whatsmeow/types/events"
17
19
  )
18
20
 
19
21
  func (cli *Client) handleReceipt(node *waBinary.Node) {
20
- defer cli.maybeDeferredAck(node)()
22
+ var cancelled bool
23
+ defer cli.maybeDeferredAck(cli.BackgroundEventCtx, node)(&cancelled)
21
24
  receipt, err := cli.parseReceipt(node)
22
25
  if err != nil {
23
26
  cli.Log.Warnf("Failed to parse receipt: %v", err)
24
27
  } else if receipt != nil {
25
28
  if receipt.Type == types.ReceiptTypeRetry {
26
29
  go func() {
27
- err := cli.handleRetryReceipt(context.TODO(), receipt, node)
30
+ err := cli.handleRetryReceipt(cli.BackgroundEventCtx, receipt, node)
28
31
  if err != nil {
29
32
  cli.Log.Errorf("Failed to handle retry receipt for %s/%s from %s: %v", receipt.Chat, receipt.MessageIDs[0], receipt.Sender, err)
30
33
  }
31
34
  }()
32
35
  }
33
- cli.dispatchEvent(receipt)
36
+ cancelled = cli.dispatchEvent(receipt)
34
37
  }
35
38
  }
36
39
 
@@ -50,7 +53,7 @@ func (cli *Client) handleGroupedReceipt(partialReceipt events.Receipt, participa
50
53
  cli.Log.Warnf("Failed to parse user node %s in grouped receipt: %v", child.XMLString(), ag.Error())
51
54
  continue
52
55
  }
53
- go cli.dispatchEvent(&receipt)
56
+ cli.dispatchEvent(&receipt)
54
57
  }
55
58
  }
56
59
 
@@ -97,14 +100,17 @@ func (cli *Client) parseReceipt(node *waBinary.Node) (*events.Receipt, error) {
97
100
  return &receipt, nil
98
101
  }
99
102
 
100
- func (cli *Client) maybeDeferredAck(node *waBinary.Node) func() {
103
+ func (cli *Client) maybeDeferredAck(ctx context.Context, node *waBinary.Node) func(cancelled ...*bool) {
101
104
  if cli.SynchronousAck {
102
- return func() {
105
+ return func(cancelled ...*bool) {
106
+ if ctx.Err() != nil || (len(cancelled) > 0 && ptr.Val(cancelled[0])) {
107
+ return
108
+ }
103
109
  cli.sendAck(node)
104
110
  }
105
111
  } else {
106
112
  go cli.sendAck(node)
107
- return func() {}
113
+ return func(...*bool) {}
108
114
  }
109
115
  }
110
116
 
@@ -0,0 +1 @@
1
+ [{"f":1},{"f":3,"s":[{"f":2},{"f":3},{"f":8},{"f":11},{"f":17,"s":[{"f":21},{"f":22}]},{"f":25}]},{"f":4,"s":[{"f":1},{"f":16},{"f":17,"s":[{"f":21},{"f":22}]}]},{"f":5,"s":[{"f":3},{"f":4},{"f":5},{"f":16},{"f":17,"s":[{"f":21},{"f":22}]}]},{"f":6,"s":[{"f":1},{"f":17,"s":[{"f":21},{"f":22}]},{"f":30}]},{"f":7,"s":[{"f":2},{"f":7},{"f":10},{"f":17,"s":[{"f":21},{"f":22}]},{"f":20}]},{"f":8,"s":[{"f":2},{"f":7},{"f":9},{"f":17,"s":[{"f":21},{"f":22}]},{"f":21}]},{"f":9,"s":[{"f":2},{"f":6},{"f":7},{"f":13},{"f":17,"s":[{"f":21},{"f":22}]},{"f":20}]},{"f":12,"s":[{"f":1},{"f":2},{"f":14,"m":true},{"f":15}]},{"f":18,"s":[{"f":6},{"f":16},{"f":17,"s":[{"f":21},{"f":22}]}]},{"f":26,"s":[{"f":4},{"f":5},{"f":8},{"f":13},{"f":17,"s":[{"f":21},{"f":22}]}]},{"f":28,"s":[{"f":1},{"f":2},{"f":4},{"f":5},{"f":6},{"f":7,"s":[{"f":21},{"f":22}]}]},{"f":37,"s":[{"f":1,"m":true}]},{"f":49,"s":[{"f":2},{"f":3,"s":[{"f":1},{"f":2}]},{"f":5,"s":[{"f":21},{"f":22}]},{"f":8,"s":[{"f":1},{"f":2}]}]},{"f":53,"s":[{"f":1,"m":true}]},{"f":55,"s":[{"f":1,"m":true}]},{"f":58,"s":[{"f":1,"m":true}]},{"f":59,"s":[{"f":1,"m":true}]},{"f":60,"s":[{"f":2},{"f":3,"s":[{"f":1},{"f":2}]},{"f":5,"s":[{"f":21},{"f":22}]},{"f":8,"s":[{"f":1},{"f":2}]}]},{"f":64,"s":[{"f":2},{"f":3,"s":[{"f":1},{"f":2}]},{"f":5,"s":[{"f":21},{"f":22}]},{"f":8,"s":[{"f":1},{"f":2}]}]},{"f":66,"s":[{"f":2},{"f":6},{"f":7},{"f":13},{"f":17,"s":[{"f":21},{"f":22}]},{"f":20}]},{"f":74,"s":[{"f":1,"m":true}]},{"f":87,"s":[{"f":1,"m":true}]},{"f":88,"s":[{"f":1},{"f":2,"s":[{"f":1}]},{"f":3,"s":[{"f":21},{"f":22}]}]},{"f":92,"s":[{"f":1,"m":true}]},{"f":93,"s":[{"f":1,"m":true}]},{"f":94,"s":[{"f":1,"m":true}]}]
@@ -0,0 +1,176 @@
1
+ // Copyright (c) 2025 Tulir Asokan
2
+ //
3
+ // This Source Code Form is subject to the terms of the Mozilla Public
4
+ // License, v. 2.0. If a copy of the MPL was not distributed with this
5
+ // file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
+
7
+ package whatsmeow
8
+
9
+ import (
10
+ "crypto/hmac"
11
+ "crypto/sha256"
12
+ _ "embed"
13
+ "encoding/binary"
14
+ "encoding/json"
15
+ "sort"
16
+ "sync"
17
+
18
+ "go.mau.fi/util/exerrors"
19
+ "go.mau.fi/util/exstrings"
20
+
21
+ waBinary "go.mau.fi/whatsmeow/binary"
22
+ "go.mau.fi/whatsmeow/proto/waE2E"
23
+ "go.mau.fi/whatsmeow/types"
24
+ )
25
+
26
+ //go:embed reportingfields.json
27
+ var reportingFieldsJSON string
28
+ var getReportingFields = sync.OnceValue(func() (output []reportingField) {
29
+ exerrors.PanicIfNotNil(json.Unmarshal(exstrings.UnsafeBytes(reportingFieldsJSON), &output))
30
+ return
31
+ })
32
+
33
+ type reportingField struct {
34
+ FieldNumber int `json:"f"`
35
+ IsMessage bool `json:"m,omitempty"`
36
+ Subfields []reportingField `json:"s,omitempty"`
37
+ }
38
+
39
+ func (cli *Client) shouldIncludeReportingToken(message *waE2E.Message) bool {
40
+ if !cli.SendReportingTokens {
41
+ return false
42
+ }
43
+ return message.ReactionMessage == nil &&
44
+ message.EncReactionMessage == nil &&
45
+ message.EncEventResponseMessage == nil &&
46
+ message.PollUpdateMessage == nil
47
+ }
48
+
49
+ func (cli *Client) getMessageReportingToken(
50
+ msgProtobuf []byte,
51
+ msg *waE2E.Message,
52
+ senderJID, remoteJID types.JID,
53
+ messageID types.MessageID,
54
+ ) waBinary.Node {
55
+ reportingSecret, _ := generateMsgSecretKey(
56
+ EncSecretReportToken, senderJID, messageID, remoteJID,
57
+ msg.GetMessageContextInfo().GetMessageSecret(),
58
+ )
59
+ hasher := hmac.New(sha256.New, reportingSecret)
60
+ hasher.Write(getReportingToken(msgProtobuf))
61
+ return waBinary.Node{
62
+ Tag: "reporting",
63
+ Content: []waBinary.Node{{
64
+ Tag: "reporting_token",
65
+ Attrs: waBinary.Attrs{"v": "2"},
66
+ Content: hasher.Sum(nil)[:16],
67
+ }},
68
+ }
69
+ }
70
+
71
+ func getReportingToken(messageProtobuf []byte) []byte {
72
+ return extractReportingTokenContent(messageProtobuf, getReportingFields())
73
+ }
74
+
75
+ // Helper to find config for a field number
76
+ func getConfigForField(fields []reportingField, fieldNum int) *reportingField {
77
+ for i := range fields {
78
+ if fields[i].FieldNumber == fieldNum {
79
+ return &fields[i]
80
+ }
81
+ }
82
+ return nil
83
+ }
84
+
85
+ // Protobuf wire types
86
+ const (
87
+ wireVarint = 0
88
+ wire64bit = 1
89
+ wireBytes = 2
90
+ wire32bit = 5
91
+ )
92
+
93
+ // Extracts the reporting token content recursively
94
+ func extractReportingTokenContent(data []byte, config []reportingField) []byte {
95
+ type field struct {
96
+ Num int
97
+ Bytes []byte
98
+ }
99
+ var fields []field
100
+ i := 0
101
+ for i < len(data) {
102
+ // Read tag (varint)
103
+ tag, tagLen := binary.Uvarint(data[i:])
104
+ if tagLen <= 0 {
105
+ break // malformed
106
+ }
107
+ fieldNum := int(tag >> 3)
108
+ wireType := int(tag & 0x7)
109
+ fieldCfg := getConfigForField(config, fieldNum)
110
+ fieldStart := i
111
+ i += tagLen
112
+ if fieldCfg == nil {
113
+ // Skip field
114
+ switch wireType {
115
+ case wireVarint:
116
+ _, n := binary.Uvarint(data[i:])
117
+ i += n
118
+ case wire64bit:
119
+ i += 8
120
+ case wireBytes:
121
+ l, n := binary.Uvarint(data[i:])
122
+ i += n + int(l)
123
+ case wire32bit:
124
+ i += 4
125
+ default:
126
+ return nil
127
+ }
128
+ continue
129
+ }
130
+ switch wireType {
131
+ case wireVarint:
132
+ _, n := binary.Uvarint(data[i:])
133
+ i += n
134
+ fields = append(fields, field{Num: fieldNum, Bytes: data[fieldStart:i]})
135
+ case wire64bit:
136
+ i += 8
137
+ fields = append(fields, field{Num: fieldNum, Bytes: data[fieldStart:i]})
138
+ case wireBytes:
139
+ l, n := binary.Uvarint(data[i:])
140
+ valStart := i + n
141
+ valEnd := valStart + int(l)
142
+ if fieldCfg.IsMessage || len(fieldCfg.Subfields) > 0 {
143
+ // Recursively extract subfields
144
+ sub := extractReportingTokenContent(data[valStart:valEnd], fieldCfg.Subfields)
145
+ if len(sub) > 0 {
146
+ // Re-encode tag and length
147
+ buf := make([]byte, 0, tagLen+n+len(sub))
148
+ tagBuf := make([]byte, binary.MaxVarintLen64)
149
+ tagN := binary.PutUvarint(tagBuf, tag)
150
+ lenBuf := make([]byte, binary.MaxVarintLen64)
151
+ lenN := binary.PutUvarint(lenBuf, uint64(len(sub)))
152
+ buf = append(buf, tagBuf[:tagN]...)
153
+ buf = append(buf, lenBuf[:lenN]...)
154
+ buf = append(buf, sub...)
155
+ fields = append(fields, field{Num: fieldNum, Bytes: buf})
156
+ }
157
+ } else {
158
+ fields = append(fields, field{Num: fieldNum, Bytes: data[fieldStart:valEnd]})
159
+ }
160
+ i = valEnd
161
+ case wire32bit:
162
+ i += 4
163
+ fields = append(fields, field{Num: fieldNum, Bytes: data[fieldStart:i]})
164
+ default:
165
+ return nil
166
+ }
167
+ }
168
+ // Sort by field number
169
+ sort.Slice(fields, func(i, j int) bool { return fields[i].Num < fields[j].Num })
170
+ // Concatenate
171
+ var out []byte
172
+ for _, f := range fields {
173
+ out = append(out, f.Bytes...)
174
+ }
175
+ return out
176
+ }
@@ -334,7 +334,7 @@ func (cli *Client) delayedRequestMessageFromPhone(info *types.MessageInfo) {
334
334
  cli.pendingPhoneRerequestsLock.Unlock()
335
335
  return
336
336
  }
337
- ctx, cancel := context.WithCancel(context.Background())
337
+ ctx, cancel := context.WithCancel(cli.BackgroundEventCtx)
338
338
  defer cancel()
339
339
  cli.pendingPhoneRerequests[info.ID] = cancel
340
340
  cli.pendingPhoneRerequestsLock.Unlock()
@@ -350,6 +350,10 @@ func (cli *Client) delayedRequestMessageFromPhone(info *types.MessageInfo) {
350
350
  cli.Log.Debugf("Cancelled delayed request for message %s from phone", info.ID)
351
351
  return
352
352
  }
353
+ cli.immediateRequestMessageFromPhone(ctx, info)
354
+ }
355
+
356
+ func (cli *Client) immediateRequestMessageFromPhone(ctx context.Context, info *types.MessageInfo) {
353
357
  _, err := cli.SendMessage(
354
358
  ctx,
355
359
  cli.getOwnID().ToNonAD(),
@@ -395,7 +399,11 @@ func (cli *Client) sendRetryReceipt(ctx context.Context, node *waBinary.Node, in
395
399
  return
396
400
  }
397
401
  if retryCount == 1 {
398
- go cli.delayedRequestMessageFromPhone(info)
402
+ if cli.SynchronousAck {
403
+ cli.immediateRequestMessageFromPhone(ctx, info)
404
+ } else {
405
+ go cli.delayedRequestMessageFromPhone(info)
406
+ }
399
407
  }
400
408
 
401
409
  var registrationIDBytes [4]byte
@@ -25,7 +25,6 @@ import (
25
25
  "go.mau.fi/libsignal/protocol"
26
26
  "go.mau.fi/libsignal/session"
27
27
  "go.mau.fi/libsignal/signalerror"
28
- "go.mau.fi/util/ptr"
29
28
  "go.mau.fi/util/random"
30
29
  "google.golang.org/protobuf/proto"
31
30
 
@@ -224,7 +223,7 @@ func (cli *Client) SendMessage(ctx context.Context, to types.JID, message *waE2E
224
223
  }
225
224
 
226
225
  isBotMode := isInlineBotMode || to.IsBot()
227
- needsMessageSecret := isBotMode
226
+ needsMessageSecret := isBotMode || cli.shouldIncludeReportingToken(message)
228
227
  var extraParams nodeExtraParams
229
228
 
230
229
  if needsMessageSecret {
@@ -296,10 +295,6 @@ func (cli *Client) SendMessage(ctx context.Context, to types.JID, message *waE2E
296
295
  if cachedData.AddressingMode == types.AddressingModeLID {
297
296
  ownID = cli.getOwnLID()
298
297
  extraParams.addressingMode = types.AddressingModeLID
299
- if req.Meta == nil {
300
- req.Meta = &types.MsgMetaInfo{}
301
- }
302
- req.Meta.DeprecatedLIDSession = ptr.Ptr(false)
303
298
  } else if cachedData.CommunityAnnouncementGroup && req.Meta != nil {
304
299
  ownID = cli.getOwnLID()
305
300
  // Why is this set to PN?
@@ -315,11 +310,6 @@ func (cli *Client) SendMessage(ctx context.Context, to types.JID, message *waE2E
315
310
  resp.DebugTimings.GetParticipants = time.Since(start)
316
311
  } else if to.Server == types.HiddenUserServer {
317
312
  ownID = cli.getOwnLID()
318
- extraParams.addressingMode = types.AddressingModeLID
319
- // if req.Meta == nil {
320
- // req.Meta = &types.MsgMetaInfo{}
321
- // }
322
- // req.Meta.DeprecatedLIDSession = ptr.Ptr(false)
323
313
  }
324
314
  if req.Meta != nil {
325
315
  extraParams.metaNode = &waBinary.Node{
@@ -361,8 +351,8 @@ func (cli *Client) SendMessage(ctx context.Context, to types.JID, message *waE2E
361
351
  var data []byte
362
352
  switch to.Server {
363
353
  case types.GroupServer, types.BroadcastServer:
364
- phash, data, err = cli.sendGroup(ctx, to, groupParticipants, req.ID, message, &resp.DebugTimings, extraParams)
365
- case types.DefaultUserServer, types.BotServer:
354
+ phash, data, err = cli.sendGroup(ctx, ownID, to, groupParticipants, req.ID, message, &resp.DebugTimings, extraParams)
355
+ case types.DefaultUserServer, types.BotServer, types.HiddenUserServer:
366
356
  if req.Peer {
367
357
  data, err = cli.sendPeerMessage(ctx, to, req.ID, message, &resp.DebugTimings)
368
358
  } else {
@@ -590,7 +580,7 @@ func ParseDisappearingTimerString(val string) (time.Duration, bool) {
590
580
  // In groups, the server will echo the change as a notification, so it'll show up as a *events.GroupInfo update.
591
581
  func (cli *Client) SetDisappearingTimer(chat types.JID, timer time.Duration) (err error) {
592
582
  switch chat.Server {
593
- case types.DefaultUserServer:
583
+ case types.DefaultUserServer, types.HiddenUserServer:
594
584
  _, err = cli.SendMessage(context.TODO(), chat, &waE2E.Message{
595
585
  ProtocolMessage: &waE2E.ProtocolMessage{
596
586
  Type: waE2E.ProtocolMessage_EPHEMERAL_SETTING.Enum(),
@@ -688,6 +678,7 @@ type nodeExtraParams struct {
688
678
 
689
679
  func (cli *Client) sendGroup(
690
680
  ctx context.Context,
681
+ ownID,
691
682
  to types.JID,
692
683
  participants []types.JID,
693
684
  id types.MessageID,
@@ -746,6 +737,9 @@ func (cli *Client) sendGroup(
746
737
  skMsg.Attrs["mediatype"] = mediaType
747
738
  }
748
739
  node.Content = append(node.GetChildren(), skMsg)
740
+ if cli.shouldIncludeReportingToken(message) && message.GetMessageContextInfo().GetMessageSecret() != nil {
741
+ node.Content = append(node.GetChildren(), cli.getMessageReportingToken(plaintext, message, ownID, to, id))
742
+ }
749
743
 
750
744
  start = time.Now()
751
745
  data, err := cli.sendNodeAndGetData(*node)
@@ -799,6 +793,20 @@ func (cli *Client) sendDM(
799
793
  if err != nil {
800
794
  return nil, err
801
795
  }
796
+
797
+ if cli.shouldIncludeReportingToken(message) && message.GetMessageContextInfo().GetMessageSecret() != nil {
798
+ node.Content = append(node.GetChildren(), cli.getMessageReportingToken(messagePlaintext, message, ownID, to, id))
799
+ }
800
+
801
+ if tcToken, err := cli.Store.PrivacyTokens.GetPrivacyToken(ctx, to); err != nil {
802
+ cli.Log.Warnf("Failed to get privacy token for %s: %v", to, err)
803
+ } else if tcToken != nil {
804
+ node.Content = append(node.GetChildren(), waBinary.Node{
805
+ Tag: "tctoken",
806
+ Content: tcToken.Token,
807
+ })
808
+ }
809
+
802
810
  start = time.Now()
803
811
  data, err := cli.sendNodeAndGetData(*node)
804
812
  timings.Send = time.Since(start)
@@ -983,8 +991,15 @@ func (cli *Client) preparePeerMessageNode(
983
991
  err = fmt.Errorf("failed to marshal message: %w", err)
984
992
  return nil, err
985
993
  }
994
+ encryptionIdentity := to
995
+ if to.Server == types.DefaultUserServer {
996
+ encryptionIdentity, err = cli.Store.LIDs.GetLIDForPN(ctx, to)
997
+ if err != nil {
998
+ return nil, fmt.Errorf("failed to get LID for PN %s: %w", to, err)
999
+ }
1000
+ }
986
1001
  start = time.Now()
987
- encrypted, isPreKey, err := cli.encryptMessageForDevice(ctx, plaintext, to, nil, nil)
1002
+ encrypted, isPreKey, err := cli.encryptMessageForDevice(ctx, plaintext, encryptionIdentity, nil, nil)
988
1003
  timings.PeerEncrypt = time.Since(start)
989
1004
  if err != nil {
990
1005
  return nil, fmt.Errorf("failed to encrypt peer message for %s: %v", to, err)
@@ -1154,7 +1169,7 @@ func (cli *Client) encryptMessageForDevices(
1154
1169
  for _, jid := range allDevices {
1155
1170
  plaintext := msgPlaintext
1156
1171
  if (jid.User == ownJID.User || jid.User == ownLID.User) && dsmPlaintext != nil {
1157
- if jid == ownJID {
1172
+ if jid == ownJID || jid == ownLID {
1158
1173
  continue
1159
1174
  }
1160
1175
  plaintext = dsmPlaintext
@@ -1273,7 +1288,7 @@ func (cli *Client) encryptMessageForDevice(
1273
1288
  } else if contains, err := cli.Store.ContainsSession(ctx, to.SignalAddress()); err != nil {
1274
1289
  return nil, false, err
1275
1290
  } else if !contains {
1276
- return nil, false, ErrNoSession
1291
+ return nil, false, fmt.Errorf("%w with %s", ErrNoSession, to.SignalAddress().String())
1277
1292
  }
1278
1293
  cipher := session.NewCipher(builder, to.SignalAddress())
1279
1294
  ciphertext, err := cipher.Encrypt(ctx, padMessage(plaintext))
@@ -36,6 +36,7 @@ import (
36
36
 
37
37
  const FBMessageVersion = 3
38
38
  const FBMessageApplicationVersion = 2
39
+ const IGMessageApplicationVersion = 3
39
40
  const FBConsumerMessageVersion = 1
40
41
  const FBArmadilloMessageVersion = 1
41
42
 
@@ -76,7 +76,7 @@ func (vc WAVersionContainer) ProtoAppVersion() *waWa6.ClientPayload_UserAgent_Ap
76
76
  }
77
77
 
78
78
  // waVersion is the WhatsApp web client version
79
- var waVersion = WAVersionContainer{2, 3000, 1022781640}
79
+ var waVersion = WAVersionContainer{2, 3000, 1024307498}
80
80
 
81
81
  // waVersionHash is the md5 hash of a dot-separated waVersion
82
82
  var waVersionHash [16]byte
@@ -115,7 +115,7 @@ const getAllDevicesQuery = `
115
115
  SELECT jid, lid, registration_id, noise_key, identity_key,
116
116
  signed_pre_key, signed_pre_key_id, signed_pre_key_sig,
117
117
  adv_key, adv_details, adv_account_sig, adv_account_sig_key, adv_device_sig,
118
- platform, business_name, push_name, facebook_uuid
118
+ platform, business_name, push_name, facebook_uuid, lid_migration_ts
119
119
  FROM whatsmeow_device
120
120
  `
121
121
 
@@ -133,7 +133,7 @@ func (c *Container) scanDevice(row dbutil.Scannable) (*store.Device, error) {
133
133
  &device.ID, &device.LID, &device.RegistrationID, &noisePriv, &identityPriv,
134
134
  &preKeyPriv, &device.SignedPreKey.KeyID, &preKeySig,
135
135
  &device.AdvSecretKey, &account.Details, &account.AccountSignature, &account.AccountSignatureKey, &account.DeviceSignature,
136
- &device.Platform, &device.BusinessName, &device.PushName, &fbUUID)
136
+ &device.Platform, &device.BusinessName, &device.PushName, &fbUUID, &device.LIDMigrationTimestamp)
137
137
  if err != nil {
138
138
  return nil, fmt.Errorf("failed to scan session: %w", err)
139
139
  } else if len(noisePriv) != 32 || len(identityPriv) != 32 || len(preKeyPriv) != 32 || len(preKeySig) != 64 {
@@ -202,13 +202,14 @@ const (
202
202
  INSERT INTO whatsmeow_device (jid, lid, registration_id, noise_key, identity_key,
203
203
  signed_pre_key, signed_pre_key_id, signed_pre_key_sig,
204
204
  adv_key, adv_details, adv_account_sig, adv_account_sig_key, adv_device_sig,
205
- platform, business_name, push_name, facebook_uuid)
206
- VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17)
205
+ platform, business_name, push_name, facebook_uuid, lid_migration_ts)
206
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18)
207
207
  ON CONFLICT (jid) DO UPDATE
208
208
  SET lid=excluded.lid,
209
209
  platform=excluded.platform,
210
210
  business_name=excluded.business_name,
211
- push_name=excluded.push_name
211
+ push_name=excluded.push_name,
212
+ lid_migration_ts=excluded.lid_migration_ts
212
213
  `
213
214
  deleteDeviceQuery = `DELETE FROM whatsmeow_device WHERE jid=$1`
214
215
  )
@@ -252,7 +253,9 @@ func (c *Container) PutDevice(ctx context.Context, device *store.Device) error {
252
253
  device.ID, device.LID, device.RegistrationID, device.NoiseKey.Priv[:], device.IdentityKey.Priv[:],
253
254
  device.SignedPreKey.Priv[:], device.SignedPreKey.KeyID, device.SignedPreKey.Signature[:],
254
255
  device.AdvSecretKey, device.Account.Details, device.Account.AccountSignature, device.Account.AccountSignatureKey, device.Account.DeviceSignature,
255
- device.Platform, device.BusinessName, device.PushName, uuid.NullUUID{UUID: device.FacebookUUID, Valid: device.FacebookUUID != uuid.Nil})
256
+ device.Platform, device.BusinessName, device.PushName, uuid.NullUUID{UUID: device.FacebookUUID, Valid: device.FacebookUUID != uuid.Nil},
257
+ device.LIDMigrationTimestamp,
258
+ )
256
259
 
257
260
  if !device.Initialized {
258
261
  c.initializeDevice(device)
@@ -1,4 +1,4 @@
1
- -- v0 -> v9 (compatible with v8+): Latest schema
1
+ -- v0 -> v10 (compatible with v8+): Latest schema
2
2
  CREATE TABLE whatsmeow_device (
3
3
  jid TEXT PRIMARY KEY,
4
4
  lid TEXT,
@@ -22,7 +22,9 @@ CREATE TABLE whatsmeow_device (
22
22
 
23
23
  platform TEXT NOT NULL DEFAULT '',
24
24
  business_name TEXT NOT NULL DEFAULT '',
25
- push_name TEXT NOT NULL DEFAULT ''
25
+ push_name TEXT NOT NULL DEFAULT '',
26
+
27
+ lid_migration_ts BIGINT NOT NULL DEFAULT 0
26
28
  );
27
29
 
28
30
  CREATE TABLE whatsmeow_identity_keys (
@@ -0,0 +1,2 @@
1
+ -- v10 (compatible with v8+): Add lid migration timestamp to device table
2
+ ALTER TABLE whatsmeow_device ADD COLUMN lid_migration_ts BIGINT NOT NULL DEFAULT 0;
@@ -192,6 +192,8 @@ type Device struct {
192
192
  BusinessName string
193
193
  PushName string
194
194
 
195
+ LIDMigrationTimestamp int64
196
+
195
197
  FacebookUUID uuid.UUID
196
198
 
197
199
  Initialized bool
@@ -14,6 +14,7 @@ import (
14
14
 
15
15
  waBinary "go.mau.fi/whatsmeow/binary"
16
16
  armadillo "go.mau.fi/whatsmeow/proto"
17
+ "go.mau.fi/whatsmeow/proto/instamadilloTransportPayload"
17
18
  "go.mau.fi/whatsmeow/proto/waArmadilloApplication"
18
19
  "go.mau.fi/whatsmeow/proto/waConsumerApplication"
19
20
  "go.mau.fi/whatsmeow/proto/waE2E"
@@ -319,8 +320,10 @@ type FBMessage struct {
319
320
  // If the message was re-requested from the sender, this is the number of retries it took.
320
321
  RetryCount int
321
322
 
322
- Transport *waMsgTransport.MessageTransport // The first level of wrapping the message was in
323
- Application *waMsgApplication.MessageApplication // The second level of wrapping the message was in
323
+ Transport *waMsgTransport.MessageTransport // The first level of wrapping the message was in
324
+
325
+ FBApplication *waMsgApplication.MessageApplication // The second level of wrapping the message was in, for FB messages
326
+ IGTransport *instamadilloTransportPayload.TransportPayload // The second level of wrapping the message was in, for IG messages
324
327
  }
325
328
 
326
329
  func (evt *FBMessage) GetConsumerApplication() *waConsumerApplication.ConsumerApplication {
@@ -78,6 +78,7 @@ type MsgMetaInfo struct {
78
78
  // Bot things
79
79
  TargetID MessageID
80
80
  TargetSender JID
81
+ TargetChat JID
81
82
 
82
83
  DeprecatedLIDSession *bool
83
84
 
@@ -561,6 +561,8 @@ func (cli *Client) GetProfilePictureInfo(jid types.JID, params *GetProfilePictur
561
561
  ag := picture.AttrGetter()
562
562
  if ag.OptionalInt("status") == 304 {
563
563
  return nil, nil
564
+ } else if ag.OptionalInt("status") == 204 {
565
+ return nil, ErrProfilePictureNotSet
564
566
  }
565
567
  info.ID = ag.String("id")
566
568
  info.URL = ag.String("url")