privacysettings.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  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 whatsmeow
  7. import (
  8. "context"
  9. "strconv"
  10. "time"
  11. waBinary "go.mau.fi/whatsmeow/binary"
  12. "go.mau.fi/whatsmeow/types"
  13. "go.mau.fi/whatsmeow/types/events"
  14. )
  15. // TryFetchPrivacySettings will fetch the user's privacy settings, either from the in-memory cache or from the server.
  16. func (cli *Client) TryFetchPrivacySettings(ctx context.Context, ignoreCache bool) (*types.PrivacySettings, error) {
  17. if cli == nil {
  18. return nil, ErrClientIsNil
  19. } else if val := cli.privacySettingsCache.Load(); val != nil && !ignoreCache {
  20. return val.(*types.PrivacySettings), nil
  21. }
  22. resp, err := cli.sendIQ(ctx, infoQuery{
  23. Namespace: "privacy",
  24. Type: iqGet,
  25. To: types.ServerJID,
  26. Content: []waBinary.Node{{Tag: "privacy"}},
  27. })
  28. if err != nil {
  29. return nil, err
  30. }
  31. privacyNode, ok := resp.GetOptionalChildByTag("privacy")
  32. if !ok {
  33. return nil, &ElementMissingError{Tag: "privacy", In: "response to privacy settings query"}
  34. }
  35. var settings types.PrivacySettings
  36. cli.parsePrivacySettings(&privacyNode, &settings)
  37. cli.privacySettingsCache.Store(&settings)
  38. return &settings, nil
  39. }
  40. // GetPrivacySettings will get the user's privacy settings. If an error occurs while fetching them, the error will be
  41. // logged, but the method will just return an empty struct.
  42. func (cli *Client) GetPrivacySettings(ctx context.Context) (settings types.PrivacySettings) {
  43. if cli == nil || cli.MessengerConfig != nil {
  44. return
  45. }
  46. settingsPtr, err := cli.TryFetchPrivacySettings(ctx, false)
  47. if err != nil {
  48. cli.Log.Errorf("Failed to fetch privacy settings: %v", err)
  49. } else {
  50. settings = *settingsPtr
  51. }
  52. return
  53. }
  54. // SetPrivacySetting will set the given privacy setting to the given value.
  55. // The privacy settings will be fetched from the server after the change and the new settings will be returned.
  56. // If an error occurs while fetching the new settings, will return an empty struct.
  57. func (cli *Client) SetPrivacySetting(ctx context.Context, name types.PrivacySettingType, value types.PrivacySetting) (settings types.PrivacySettings, err error) {
  58. settingsPtr, err := cli.TryFetchPrivacySettings(ctx, false)
  59. if err != nil {
  60. return settings, err
  61. }
  62. _, err = cli.sendIQ(ctx, infoQuery{
  63. Namespace: "privacy",
  64. Type: iqSet,
  65. To: types.ServerJID,
  66. Content: []waBinary.Node{{
  67. Tag: "privacy",
  68. Content: []waBinary.Node{{
  69. Tag: "category",
  70. Attrs: waBinary.Attrs{
  71. "name": string(name),
  72. "value": string(value),
  73. },
  74. }},
  75. }},
  76. })
  77. if err != nil {
  78. return settings, err
  79. }
  80. settings = *settingsPtr
  81. switch name {
  82. case types.PrivacySettingTypeGroupAdd:
  83. settings.GroupAdd = value
  84. case types.PrivacySettingTypeLastSeen:
  85. settings.LastSeen = value
  86. case types.PrivacySettingTypeStatus:
  87. settings.Status = value
  88. case types.PrivacySettingTypeProfile:
  89. settings.Profile = value
  90. case types.PrivacySettingTypeReadReceipts:
  91. settings.ReadReceipts = value
  92. case types.PrivacySettingTypeOnline:
  93. settings.Online = value
  94. case types.PrivacySettingTypeCallAdd:
  95. settings.CallAdd = value
  96. }
  97. cli.privacySettingsCache.Store(&settings)
  98. return
  99. }
  100. // SetDefaultDisappearingTimer will set the default disappearing message timer.
  101. func (cli *Client) SetDefaultDisappearingTimer(ctx context.Context, timer time.Duration) (err error) {
  102. _, err = cli.sendIQ(ctx, infoQuery{
  103. Namespace: "disappearing_mode",
  104. Type: iqSet,
  105. To: types.ServerJID,
  106. Content: []waBinary.Node{{
  107. Tag: "disappearing_mode",
  108. Attrs: waBinary.Attrs{
  109. "duration": strconv.Itoa(int(timer.Seconds())),
  110. },
  111. }},
  112. })
  113. return
  114. }
  115. func (cli *Client) parsePrivacySettings(privacyNode *waBinary.Node, settings *types.PrivacySettings) *events.PrivacySettings {
  116. var evt events.PrivacySettings
  117. for _, child := range privacyNode.GetChildren() {
  118. if child.Tag != "category" {
  119. continue
  120. }
  121. ag := child.AttrGetter()
  122. name := types.PrivacySettingType(ag.String("name"))
  123. value := types.PrivacySetting(ag.String("value"))
  124. switch name {
  125. case types.PrivacySettingTypeGroupAdd:
  126. settings.GroupAdd = value
  127. evt.GroupAddChanged = true
  128. case types.PrivacySettingTypeLastSeen:
  129. settings.LastSeen = value
  130. evt.LastSeenChanged = true
  131. case types.PrivacySettingTypeStatus:
  132. settings.Status = value
  133. evt.StatusChanged = true
  134. case types.PrivacySettingTypeProfile:
  135. settings.Profile = value
  136. evt.ProfileChanged = true
  137. case types.PrivacySettingTypeReadReceipts:
  138. settings.ReadReceipts = value
  139. evt.ReadReceiptsChanged = true
  140. case types.PrivacySettingTypeOnline:
  141. settings.Online = value
  142. evt.OnlineChanged = true
  143. case types.PrivacySettingTypeCallAdd:
  144. settings.CallAdd = value
  145. evt.CallAddChanged = true
  146. }
  147. }
  148. return &evt
  149. }
  150. func (cli *Client) handlePrivacySettingsNotification(ctx context.Context, privacyNode *waBinary.Node) {
  151. cli.Log.Debugf("Parsing privacy settings change notification")
  152. settings, err := cli.TryFetchPrivacySettings(ctx, false)
  153. if err != nil {
  154. cli.Log.Errorf("Failed to fetch privacy settings when handling change: %v", err)
  155. return
  156. }
  157. evt := cli.parsePrivacySettings(privacyNode, settings)
  158. cli.privacySettingsCache.Store(settings)
  159. cli.dispatchEvent(evt)
  160. }