events.go 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620
  1. // Copyright (c) 2021 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. // Package events contains all the events that whatsmeow.Client emits to functions registered with AddEventHandler.
  7. package events
  8. import (
  9. "fmt"
  10. "strconv"
  11. "time"
  12. waBinary "git.bobomao.top/joey/testwh/binary"
  13. armadillo "git.bobomao.top/joey/testwh/proto"
  14. "git.bobomao.top/joey/testwh/proto/instamadilloTransportPayload"
  15. "git.bobomao.top/joey/testwh/proto/waArmadilloApplication"
  16. "git.bobomao.top/joey/testwh/proto/waConsumerApplication"
  17. "git.bobomao.top/joey/testwh/proto/waE2E"
  18. "git.bobomao.top/joey/testwh/proto/waHistorySync"
  19. "git.bobomao.top/joey/testwh/proto/waMsgApplication"
  20. "git.bobomao.top/joey/testwh/proto/waMsgTransport"
  21. "git.bobomao.top/joey/testwh/proto/waWeb"
  22. "git.bobomao.top/joey/testwh/types"
  23. )
  24. // QR is emitted after connecting when there's no session data in the device store.
  25. //
  26. // The QR codes are available in the Codes slice. You should render the strings as QR codes one by
  27. // one, switching to the next one whenever enough time has passed. WhatsApp web seems to show the
  28. // first code for 60 seconds and all other codes for 20 seconds.
  29. //
  30. // When the QR code has been scanned and pairing is complete, PairSuccess will be emitted. If you
  31. // run out of codes before scanning, the server will close the websocket, and you will have to
  32. // reconnect to get more codes.
  33. type QR struct {
  34. Codes []string
  35. }
  36. // PairSuccess is emitted after the QR code has been scanned with the phone and the handshake has
  37. // been completed. Note that this is generally followed by a websocket reconnection, so you should
  38. // wait for the Connected before trying to send anything.
  39. type PairSuccess struct {
  40. ID types.JID
  41. LID types.JID
  42. BusinessName string
  43. Platform string
  44. }
  45. // PairError is emitted when a pair-success event is received from the server, but finishing the pairing locally fails.
  46. type PairError struct {
  47. ID types.JID
  48. LID types.JID
  49. BusinessName string
  50. Platform string
  51. Error error
  52. }
  53. // QRScannedWithoutMultidevice is emitted when the pairing QR code is scanned, but the phone didn't have multidevice enabled.
  54. // The same QR code can still be scanned after this event, which means the user can just be told to enable multidevice and re-scan the code.
  55. type QRScannedWithoutMultidevice struct{}
  56. // Connected is emitted when the client has successfully connected to the WhatsApp servers
  57. // and is authenticated. The user who the client is authenticated as will be in the device store
  58. // at this point, which is why this event doesn't contain any data.
  59. type Connected struct{}
  60. // KeepAliveTimeout is emitted when the keepalive ping request to WhatsApp web servers times out.
  61. //
  62. // Currently, there's no automatic handling for these, but it's expected that the TCP connection will
  63. // either start working again or notice it's dead on its own eventually. Clients may use this event to
  64. // decide to force a disconnect+reconnect faster.
  65. type KeepAliveTimeout struct {
  66. ErrorCount int
  67. LastSuccess time.Time
  68. }
  69. // KeepAliveRestored is emitted if the keepalive pings start working again after some KeepAliveTimeout events.
  70. // Note that if the websocket disconnects before the pings start working, this event will not be emitted.
  71. type KeepAliveRestored struct{}
  72. // PermanentDisconnect is a class of events emitted when the client will not auto-reconnect by default.
  73. type PermanentDisconnect interface {
  74. PermanentDisconnectDescription() string
  75. }
  76. func (l *LoggedOut) PermanentDisconnectDescription() string { return l.Reason.String() }
  77. func (*StreamReplaced) PermanentDisconnectDescription() string { return "stream replaced" }
  78. func (*ClientOutdated) PermanentDisconnectDescription() string { return "client outdated" }
  79. func (*CATRefreshError) PermanentDisconnectDescription() string { return "CAT refresh failed" }
  80. func (tb *TemporaryBan) PermanentDisconnectDescription() string {
  81. return fmt.Sprintf("temporarily banned: %s", tb.String())
  82. }
  83. func (cf *ConnectFailure) PermanentDisconnectDescription() string {
  84. return fmt.Sprintf("connect failure: %s", cf.Reason.String())
  85. }
  86. // LoggedOut is emitted when the client has been unpaired from the phone.
  87. //
  88. // This can happen while connected (stream:error messages) or right after connecting (connect failure messages).
  89. //
  90. // This will not be emitted when the logout is initiated by this client (using Client.LogOut()).
  91. type LoggedOut struct {
  92. // OnConnect is true if the event was triggered by a connect failure message.
  93. // If it's false, the event was triggered by a stream:error message.
  94. OnConnect bool
  95. // If OnConnect is true, then this field contains the reason code.
  96. Reason ConnectFailureReason
  97. }
  98. // StreamReplaced is emitted when the client is disconnected by another client connecting with the same keys.
  99. //
  100. // This can happen if you accidentally start another process with the same session
  101. // or otherwise try to connect twice with the same session.
  102. type StreamReplaced struct{}
  103. // ManualLoginReconnect is emitted after login if DisableLoginAutoReconnect is set.
  104. type ManualLoginReconnect struct{}
  105. // TempBanReason is an error code included in temp ban error events.
  106. type TempBanReason int
  107. const (
  108. TempBanSentToTooManyPeople TempBanReason = 101
  109. TempBanBlockedByUsers TempBanReason = 102
  110. TempBanCreatedTooManyGroups TempBanReason = 103
  111. TempBanSentTooManySameMessage TempBanReason = 104
  112. TempBanBroadcastList TempBanReason = 106
  113. )
  114. var tempBanReasonMessage = map[TempBanReason]string{
  115. TempBanSentToTooManyPeople: "you sent too many messages to people who don't have you in their address books",
  116. TempBanBlockedByUsers: "too many people blocked you",
  117. TempBanCreatedTooManyGroups: "you created too many groups with people who don't have you in their address books",
  118. TempBanSentTooManySameMessage: "you sent the same message to too many people",
  119. TempBanBroadcastList: "you sent too many messages to a broadcast list",
  120. }
  121. // String returns the reason code and a human-readable description of the ban reason.
  122. func (tbr TempBanReason) String() string {
  123. msg, ok := tempBanReasonMessage[tbr]
  124. if !ok {
  125. msg = "you may have violated the terms of service (unknown error)"
  126. }
  127. return fmt.Sprintf("%d: %s", int(tbr), msg)
  128. }
  129. // TemporaryBan is emitted when there's a connection failure with the ConnectFailureTempBanned reason code.
  130. type TemporaryBan struct {
  131. Code TempBanReason
  132. Expire time.Duration
  133. }
  134. func (tb *TemporaryBan) String() string {
  135. if tb.Expire == 0 {
  136. return fmt.Sprintf("You've been temporarily banned: %v", tb.Code)
  137. }
  138. return fmt.Sprintf("You've been temporarily banned: %v. The ban expires in %v", tb.Code, tb.Expire)
  139. }
  140. // ConnectFailureReason is an error code included in connection failure events.
  141. type ConnectFailureReason int
  142. const (
  143. ConnectFailureGeneric ConnectFailureReason = 400
  144. ConnectFailureLoggedOut ConnectFailureReason = 401
  145. ConnectFailureTempBanned ConnectFailureReason = 402
  146. ConnectFailureMainDeviceGone ConnectFailureReason = 403 // this is now called LOCKED in the whatsapp web code
  147. ConnectFailureUnknownLogout ConnectFailureReason = 406 // this is now called BANNED in the whatsapp web code
  148. ConnectFailureClientOutdated ConnectFailureReason = 405
  149. ConnectFailureBadUserAgent ConnectFailureReason = 409
  150. ConnectFailureCATExpired ConnectFailureReason = 413
  151. ConnectFailureCATInvalid ConnectFailureReason = 414
  152. ConnectFailureNotFound ConnectFailureReason = 415
  153. // Status code unknown (not in WA web)
  154. ConnectFailureClientUnknown ConnectFailureReason = 418
  155. ConnectFailureInternalServerError ConnectFailureReason = 500
  156. ConnectFailureExperimental ConnectFailureReason = 501
  157. ConnectFailureServiceUnavailable ConnectFailureReason = 503
  158. )
  159. var connectFailureReasonMessage = map[ConnectFailureReason]string{
  160. ConnectFailureLoggedOut: "logged out from another device",
  161. ConnectFailureTempBanned: "account temporarily banned",
  162. ConnectFailureMainDeviceGone: "primary device was logged out", // seems to happen for both bans and switching phones
  163. ConnectFailureUnknownLogout: "logged out for unknown reason",
  164. ConnectFailureClientOutdated: "client is out of date",
  165. ConnectFailureBadUserAgent: "client user agent was rejected",
  166. ConnectFailureCATExpired: "messenger crypto auth token has expired",
  167. ConnectFailureCATInvalid: "messenger crypto auth token is invalid",
  168. }
  169. // IsLoggedOut returns true if the client should delete session data due to this connect failure.
  170. func (cfr ConnectFailureReason) IsLoggedOut() bool {
  171. return cfr == ConnectFailureLoggedOut || cfr == ConnectFailureMainDeviceGone || cfr == ConnectFailureUnknownLogout
  172. }
  173. func (cfr ConnectFailureReason) NumberString() string {
  174. return strconv.Itoa(int(cfr))
  175. }
  176. // String returns the reason code and a short human-readable description of the error.
  177. func (cfr ConnectFailureReason) String() string {
  178. msg, ok := connectFailureReasonMessage[cfr]
  179. if !ok {
  180. msg = "unknown error"
  181. }
  182. return fmt.Sprintf("%d: %s", int(cfr), msg)
  183. }
  184. // ConnectFailure is emitted when the WhatsApp server sends a <failure> node with an unknown reason.
  185. //
  186. // Known reasons are handled internally and emitted as different events (e.g. LoggedOut and TemporaryBan).
  187. type ConnectFailure struct {
  188. Reason ConnectFailureReason
  189. Message string
  190. Raw *waBinary.Node
  191. }
  192. // ClientOutdated is emitted when the WhatsApp server rejects the connection with the ConnectFailureClientOutdated code.
  193. type ClientOutdated struct{}
  194. type CATRefreshError struct {
  195. Error error
  196. }
  197. // StreamError is emitted when the WhatsApp server sends a <stream:error> node with an unknown code.
  198. //
  199. // Known codes are handled internally and emitted as different events (e.g. LoggedOut).
  200. type StreamError struct {
  201. Code string
  202. Raw *waBinary.Node
  203. }
  204. // Disconnected is emitted when the websocket is closed by the server.
  205. type Disconnected struct{}
  206. // HistorySync is emitted when the phone has sent a blob of historical messages.
  207. type HistorySync struct {
  208. Data *waHistorySync.HistorySync
  209. }
  210. type DecryptFailMode string
  211. const (
  212. DecryptFailShow DecryptFailMode = ""
  213. DecryptFailHide DecryptFailMode = "hide"
  214. )
  215. type UnavailableType string
  216. const (
  217. UnavailableTypeUnknown UnavailableType = ""
  218. UnavailableTypeViewOnce UnavailableType = "view_once"
  219. )
  220. // UndecryptableMessage is emitted when receiving a new message that failed to decrypt.
  221. //
  222. // The library will automatically ask the sender to retry. If the sender resends the message,
  223. // and it's decryptable, then it will be emitted as a normal Message event.
  224. //
  225. // The UndecryptableMessage event may also be repeated if the resent message is also undecryptable.
  226. type UndecryptableMessage struct {
  227. Info types.MessageInfo
  228. // IsUnavailable is true if the recipient device didn't send a ciphertext to this device at all
  229. // (as opposed to sending a ciphertext, but the ciphertext not being decryptable).
  230. IsUnavailable bool
  231. // Some message types are intentionally unavailable. Such types usually have a type specified here.
  232. UnavailableType UnavailableType
  233. DecryptFailMode DecryptFailMode
  234. }
  235. type NewsletterMessageMeta struct {
  236. // When a newsletter message is edited, the message isn't wrapped in an EditedMessage like normal messages.
  237. // Instead, the message is the new content, the ID is the original message ID, and the edit timestamp is here.
  238. EditTS time.Time
  239. // This is the timestamp of the original message for edits.
  240. OriginalTS time.Time
  241. }
  242. // Message is emitted when receiving a new message.
  243. type Message struct {
  244. Info types.MessageInfo // Information about the message like the chat and sender IDs
  245. Message *waE2E.Message // The actual message struct
  246. IsEphemeral bool // True if the message was unwrapped from an EphemeralMessage
  247. IsViewOnce bool // True if the message was unwrapped from a ViewOnceMessage, ViewOnceMessageV2 or ViewOnceMessageV2Extension
  248. IsViewOnceV2 bool // True if the message was unwrapped from a ViewOnceMessageV2 or ViewOnceMessageV2Extension
  249. IsViewOnceV2Extension bool // True if the message was unwrapped from a ViewOnceMessageV2Extension
  250. IsDocumentWithCaption bool // True if the message was unwrapped from a DocumentWithCaptionMessage
  251. IsLottieSticker bool // True if the message was unwrapped from a LottieStickerMessage
  252. IsBotInvoke bool // True if the message was unwrapped from a BotInvokeMessage
  253. IsEdit bool // True if the message was unwrapped from an EditedMessage
  254. // If this event was parsed from a WebMessageInfo (i.e. from a history sync or unavailable message request), the source data is here.
  255. SourceWebMsg *waWeb.WebMessageInfo
  256. // If this event is a response to an unavailable message request, the request ID is here.
  257. UnavailableRequestID types.MessageID
  258. // If the message was re-requested from the sender, this is the number of retries it took.
  259. RetryCount int
  260. NewsletterMeta *NewsletterMessageMeta
  261. // The raw message struct. This is the raw unmodified data, which means the actual message might
  262. // be wrapped in DeviceSentMessage, EphemeralMessage or ViewOnceMessage.
  263. RawMessage *waE2E.Message
  264. }
  265. type FBMessage struct {
  266. Info types.MessageInfo // Information about the message like the chat and sender IDs
  267. Message armadillo.MessageApplicationSub // The actual message struct
  268. // If the message was re-requested from the sender, this is the number of retries it took.
  269. RetryCount int
  270. Transport *waMsgTransport.MessageTransport // The first level of wrapping the message was in
  271. FBApplication *waMsgApplication.MessageApplication // The second level of wrapping the message was in, for FB messages
  272. IGTransport *instamadilloTransportPayload.TransportPayload // The second level of wrapping the message was in, for IG messages
  273. }
  274. func (evt *FBMessage) GetConsumerApplication() *waConsumerApplication.ConsumerApplication {
  275. if consumerApp, ok := evt.Message.(*waConsumerApplication.ConsumerApplication); ok {
  276. return consumerApp
  277. }
  278. return nil
  279. }
  280. func (evt *FBMessage) GetArmadillo() *waArmadilloApplication.Armadillo {
  281. if armadillo, ok := evt.Message.(*waArmadilloApplication.Armadillo); ok {
  282. return armadillo
  283. }
  284. return nil
  285. }
  286. // UnwrapRaw fills the Message, IsEphemeral and IsViewOnce fields based on the raw message in the RawMessage field.
  287. func (evt *Message) UnwrapRaw() *Message {
  288. evt.Message = evt.RawMessage
  289. if evt.Message.GetDeviceSentMessage().GetMessage() != nil {
  290. evt.Info.DeviceSentMeta = &types.DeviceSentMeta{
  291. DestinationJID: evt.Message.GetDeviceSentMessage().GetDestinationJID(),
  292. Phash: evt.Message.GetDeviceSentMessage().GetPhash(),
  293. }
  294. evt.Message = evt.Message.GetDeviceSentMessage().GetMessage()
  295. }
  296. if evt.Message.GetBotInvokeMessage().GetMessage() != nil {
  297. evt.Message = evt.Message.GetBotInvokeMessage().GetMessage()
  298. evt.IsBotInvoke = true
  299. }
  300. if evt.Message.GetEphemeralMessage().GetMessage() != nil {
  301. evt.Message = evt.Message.GetEphemeralMessage().GetMessage()
  302. evt.IsEphemeral = true
  303. }
  304. if evt.Message.GetViewOnceMessage().GetMessage() != nil {
  305. evt.Message = evt.Message.GetViewOnceMessage().GetMessage()
  306. evt.IsViewOnce = true
  307. }
  308. if evt.Message.GetViewOnceMessageV2().GetMessage() != nil {
  309. evt.Message = evt.Message.GetViewOnceMessageV2().GetMessage()
  310. evt.IsViewOnce = true
  311. evt.IsViewOnceV2 = true
  312. }
  313. if evt.Message.GetViewOnceMessageV2Extension().GetMessage() != nil {
  314. evt.Message = evt.Message.GetViewOnceMessageV2Extension().GetMessage()
  315. evt.IsViewOnce = true
  316. evt.IsViewOnceV2 = true
  317. evt.IsViewOnceV2Extension = true
  318. }
  319. if evt.Message.GetLottieStickerMessage().GetMessage() != nil {
  320. evt.Message = evt.Message.GetLottieStickerMessage().GetMessage()
  321. evt.IsLottieSticker = true
  322. }
  323. if evt.Message.GetDocumentWithCaptionMessage().GetMessage() != nil {
  324. evt.Message = evt.Message.GetDocumentWithCaptionMessage().GetMessage()
  325. evt.IsDocumentWithCaption = true
  326. }
  327. if evt.Message.GetEditedMessage().GetMessage() != nil {
  328. evt.Message = evt.Message.GetEditedMessage().GetMessage()
  329. evt.IsEdit = true
  330. }
  331. if evt.Message != nil && evt.RawMessage != nil && evt.Message.MessageContextInfo == nil && evt.RawMessage.MessageContextInfo != nil {
  332. evt.Message.MessageContextInfo = evt.RawMessage.MessageContextInfo
  333. }
  334. return evt
  335. }
  336. // Deprecated: use types.ReceiptType directly
  337. type ReceiptType = types.ReceiptType
  338. // Deprecated: use types.ReceiptType* constants directly
  339. const (
  340. ReceiptTypeDelivered = types.ReceiptTypeDelivered
  341. ReceiptTypeSender = types.ReceiptTypeSender
  342. ReceiptTypeRetry = types.ReceiptTypeRetry
  343. ReceiptTypeRead = types.ReceiptTypeRead
  344. ReceiptTypeReadSelf = types.ReceiptTypeReadSelf
  345. ReceiptTypePlayed = types.ReceiptTypePlayed
  346. )
  347. // Receipt is emitted when an outgoing message is delivered to or read by another user, or when another device reads an incoming message.
  348. //
  349. // N.B. WhatsApp on Android sends message IDs from newest message to oldest, but WhatsApp on iOS sends them in the opposite order (oldest first).
  350. type Receipt struct {
  351. types.MessageSource
  352. MessageIDs []types.MessageID
  353. Timestamp time.Time
  354. Type types.ReceiptType
  355. // When you read the message of another user in a group, this field contains the sender of the message.
  356. // For receipts from other users, the message sender is always you.
  357. MessageSender types.JID
  358. }
  359. // ChatPresence is emitted when a chat state update (also known as typing notification) is received.
  360. //
  361. // Note that WhatsApp won't send you these updates unless you mark yourself as online:
  362. //
  363. // client.SendPresence(types.PresenceAvailable)
  364. type ChatPresence struct {
  365. types.MessageSource
  366. State types.ChatPresence // The current state, either composing or paused
  367. Media types.ChatPresenceMedia // When composing, the type of message
  368. }
  369. // Presence is emitted when a presence update is received.
  370. //
  371. // Note that WhatsApp only sends you presence updates for individual users after you subscribe to them:
  372. //
  373. // client.SubscribePresence(user JID)
  374. type Presence struct {
  375. // The user whose presence event this is
  376. From types.JID
  377. // True if the user is now offline
  378. Unavailable bool
  379. // The time when the user was last online. This may be the zero value if the user has hid their last seen time.
  380. LastSeen time.Time
  381. }
  382. // JoinedGroup is emitted when you join or are added to a group.
  383. type JoinedGroup struct {
  384. Reason string // If the event was triggered by you using an invite link, this will be "invite".
  385. Type string // "new" if it's a newly created group.
  386. CreateKey types.MessageID // If you created the group, this is the same message ID you passed to CreateGroup.
  387. // For type new, the user who created the group and added you to it
  388. Sender *types.JID
  389. SenderPN *types.JID
  390. Notify string
  391. types.GroupInfo
  392. }
  393. // GroupInfo is emitted when the metadata of a group changes.
  394. type GroupInfo struct {
  395. JID types.JID // The group ID in question
  396. Notify string // Seems like a top-level type for the invite
  397. Sender *types.JID // The user who made the change. Doesn't seem to be present when notify=invite
  398. SenderPN *types.JID // The phone number of the user who made the change, if Sender is a LID.
  399. Timestamp time.Time // The time when the change occurred
  400. Name *types.GroupName // Group name change
  401. Topic *types.GroupTopic // Group topic (description) change
  402. Locked *types.GroupLocked // Group locked status change (can only admins edit group info?)
  403. Announce *types.GroupAnnounce // Group announce status change (can only admins send messages?)
  404. Ephemeral *types.GroupEphemeral // Disappearing messages change
  405. MembershipApprovalMode *types.GroupMembershipApprovalMode // Membership approval mode change
  406. Delete *types.GroupDelete
  407. Link *types.GroupLinkChange
  408. Unlink *types.GroupLinkChange
  409. NewInviteLink *string // Group invite link change
  410. PrevParticipantVersionID string
  411. ParticipantVersionID string
  412. JoinReason string // This will be "invite" if the user joined via invite link
  413. Join []types.JID // Users who joined or were added the group
  414. Leave []types.JID // Users who left or were removed from the group
  415. Promote []types.JID // Users who were promoted to admins
  416. Demote []types.JID // Users who were demoted to normal users
  417. Suspended bool // whether the group is suspended
  418. Unsuspended bool // whether the group is unsuspended
  419. UnknownChanges []*waBinary.Node
  420. }
  421. // Picture is emitted when a user's profile picture or group's photo is changed.
  422. //
  423. // You can use Client.GetProfilePictureInfo to get the actual image URL after this event.
  424. type Picture struct {
  425. JID types.JID // The user or group ID where the picture was changed.
  426. Author types.JID // The user who changed the picture.
  427. Timestamp time.Time // The timestamp when the picture was changed.
  428. Remove bool // True if the picture was removed.
  429. PictureID string // The new picture ID if it was not removed.
  430. }
  431. // UserAbout is emitted when a user's about status is changed.
  432. type UserAbout struct {
  433. JID types.JID // The user whose status was changed
  434. Status string // The new status
  435. Timestamp time.Time // The timestamp when the status was changed.
  436. }
  437. // IdentityChange is emitted when another user changes their primary device.
  438. type IdentityChange struct {
  439. JID types.JID
  440. Timestamp time.Time
  441. // Implicit will be set to true if the event was triggered by an untrusted identity error,
  442. // rather than an identity change notification from the server.
  443. Implicit bool
  444. }
  445. // PrivacySettings is emitted when the user changes their privacy settings.
  446. type PrivacySettings struct {
  447. NewSettings types.PrivacySettings
  448. GroupAddChanged bool
  449. LastSeenChanged bool
  450. StatusChanged bool
  451. ProfileChanged bool
  452. ReadReceiptsChanged bool
  453. OnlineChanged bool
  454. CallAddChanged bool
  455. }
  456. // OfflineSyncPreview is emitted right after connecting if the server is going to send events that the client missed during downtime.
  457. type OfflineSyncPreview struct {
  458. Total int
  459. AppDataChanges int
  460. Messages int
  461. Notifications int
  462. Receipts int
  463. }
  464. // OfflineSyncCompleted is emitted after the server has finished sending missed events.
  465. type OfflineSyncCompleted struct {
  466. Count int
  467. }
  468. type MediaRetryError struct {
  469. Code int
  470. }
  471. // MediaRetry is emitted when the phone sends a response to a media retry request.
  472. type MediaRetry struct {
  473. Ciphertext []byte
  474. IV []byte
  475. // Sometimes there's an unencrypted media retry error. In these cases, Ciphertext and IV will be nil.
  476. Error *MediaRetryError
  477. Timestamp time.Time // The time of the response.
  478. MessageID types.MessageID // The ID of the message.
  479. ChatID types.JID // The chat ID where the message was sent.
  480. SenderID types.JID // The user who sent the message. Only present in groups.
  481. FromMe bool // Whether the message was sent by the current user or someone else.
  482. }
  483. type BlocklistAction string
  484. const (
  485. BlocklistActionDefault BlocklistAction = ""
  486. BlocklistActionModify BlocklistAction = "modify"
  487. )
  488. // Blocklist is emitted when the user's blocked user list is changed.
  489. type Blocklist struct {
  490. // Action specifies what happened. If it's empty, there should be a list of changes in the Changes list.
  491. // If it's "modify", then the Changes list will be empty and the whole blocklist should be re-requested.
  492. Action BlocklistAction
  493. DHash string
  494. PrevDHash string
  495. Changes []BlocklistChange
  496. }
  497. type BlocklistChangeAction string
  498. const (
  499. BlocklistChangeActionBlock BlocklistChangeAction = "block"
  500. BlocklistChangeActionUnblock BlocklistChangeAction = "unblock"
  501. )
  502. type BlocklistChange struct {
  503. JID types.JID
  504. Action BlocklistChangeAction
  505. }
  506. type NewsletterJoin struct {
  507. types.NewsletterMetadata
  508. }
  509. type NewsletterLeave struct {
  510. ID types.JID `json:"id"`
  511. Role types.NewsletterRole `json:"role"`
  512. }
  513. type NewsletterMuteChange struct {
  514. ID types.JID `json:"id"`
  515. Mute types.NewsletterMuteState `json:"mute"`
  516. }
  517. type NewsletterLiveUpdate struct {
  518. JID types.JID
  519. Time time.Time
  520. Messages []*types.NewsletterMessage
  521. }