chat.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. // mautrix-whatsapp - A Matrix-WhatsApp puppeting bridge.
  2. // Copyright (C) 2019 Tulir Asokan
  3. //
  4. // This program is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU Affero General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU Affero General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Affero General Public License
  15. // along with this program. If not, see <https://www.gnu.org/licenses/>.
  16. package whatsappExt
  17. import (
  18. "encoding/json"
  19. "strings"
  20. "github.com/Rhymen/go-whatsapp"
  21. )
  22. type ChatUpdateCommand string
  23. const (
  24. ChatUpdateCommandAction ChatUpdateCommand = "action"
  25. )
  26. type ChatUpdate struct {
  27. JID string `json:"id"`
  28. Command ChatUpdateCommand `json:"cmd"`
  29. Data ChatUpdateData `json:"data"`
  30. }
  31. type ChatActionType string
  32. const (
  33. ChatActionNameChange ChatActionType = "subject"
  34. ChatActionAddTopic ChatActionType = "desc_add"
  35. ChatActionRemoveTopic ChatActionType = "desc_remove"
  36. ChatActionRestrict ChatActionType = "restrict"
  37. ChatActionAnnounce ChatActionType = "announce"
  38. ChatActionPromote ChatActionType = "promote"
  39. ChatActionDemote ChatActionType = "demote"
  40. ChatActionIntroduce ChatActionType = "introduce"
  41. ChatActionRemove ChatActionType = "remove"
  42. )
  43. type ChatUpdateData struct {
  44. Action ChatActionType
  45. SenderJID string
  46. NameChange struct {
  47. Name string `json:"subject"`
  48. SetAt int64 `json:"s_t"`
  49. SetBy string `json:"s_o"`
  50. }
  51. AddTopic struct {
  52. Topic string `json:"desc"`
  53. ID string `json:"descId"`
  54. SetAt int64 `json:"descTime"`
  55. SetBy string `json:"descOwner"`
  56. }
  57. RemoveTopic struct {
  58. ID string `json:"descId"`
  59. }
  60. Introduce struct {
  61. CreationTime int64 `json:"creation"`
  62. Admins []string `json:"admins"`
  63. SuperAdmins []string `json:"superadmins"`
  64. Regulars []string `json:"regulars"`
  65. }
  66. Restrict bool
  67. Announce bool
  68. UserChange struct {
  69. JIDs []string `json:"participants"`
  70. }
  71. }
  72. func (cud *ChatUpdateData) UnmarshalJSON(data []byte) error {
  73. var arr []json.RawMessage
  74. err := json.Unmarshal(data, &arr)
  75. if err != nil {
  76. return err
  77. } else if len(arr) < 3 {
  78. return nil
  79. }
  80. err = json.Unmarshal(arr[0], &cud.Action)
  81. if err != nil {
  82. return err
  83. }
  84. err = json.Unmarshal(arr[1], &cud.SenderJID)
  85. if err != nil {
  86. return err
  87. }
  88. cud.SenderJID = strings.Replace(cud.SenderJID, OldUserSuffix, NewUserSuffix, 1)
  89. var unmarshalTo interface{}
  90. switch cud.Action {
  91. case ChatActionIntroduce:
  92. err = json.Unmarshal(arr[2], &cud.NameChange)
  93. if err != nil {
  94. return err
  95. }
  96. err = json.Unmarshal(arr[2], &cud.AddTopic)
  97. if err != nil {
  98. return err
  99. }
  100. unmarshalTo = &cud.Introduce
  101. case ChatActionNameChange:
  102. unmarshalTo = &cud.NameChange
  103. case ChatActionAddTopic:
  104. unmarshalTo = &cud.AddTopic
  105. case ChatActionRemoveTopic:
  106. unmarshalTo = &cud.RemoveTopic
  107. case ChatActionRestrict:
  108. unmarshalTo = &cud.Restrict
  109. case ChatActionAnnounce:
  110. unmarshalTo = &cud.Announce
  111. case ChatActionPromote, ChatActionDemote, ChatActionRemove:
  112. unmarshalTo = &cud.UserChange
  113. default:
  114. return nil
  115. }
  116. err = json.Unmarshal(arr[2], unmarshalTo)
  117. if err != nil {
  118. return err
  119. }
  120. cud.NameChange.SetBy = strings.Replace(cud.NameChange.SetBy, OldUserSuffix, NewUserSuffix, 1)
  121. for index, jid := range cud.UserChange.JIDs {
  122. cud.UserChange.JIDs[index] = strings.Replace(jid, OldUserSuffix, NewUserSuffix, 1)
  123. }
  124. for index, jid := range cud.Introduce.SuperAdmins {
  125. cud.Introduce.SuperAdmins[index] = strings.Replace(jid, OldUserSuffix, NewUserSuffix, 1)
  126. }
  127. for index, jid := range cud.Introduce.Admins {
  128. cud.Introduce.Admins[index] = strings.Replace(jid, OldUserSuffix, NewUserSuffix, 1)
  129. }
  130. for index, jid := range cud.Introduce.Regulars {
  131. cud.Introduce.Regulars[index] = strings.Replace(jid, OldUserSuffix, NewUserSuffix, 1)
  132. }
  133. return nil
  134. }
  135. type ChatUpdateHandler interface {
  136. whatsapp.Handler
  137. HandleChatUpdate(ChatUpdate)
  138. }
  139. func (ext *ExtendedConn) handleMessageChatUpdate(message []byte) {
  140. var event ChatUpdate
  141. err := json.Unmarshal(message, &event)
  142. if err != nil {
  143. ext.jsonParseError(err)
  144. return
  145. }
  146. event.JID = strings.Replace(event.JID, OldUserSuffix, NewUserSuffix, 1)
  147. for _, handler := range ext.handlers {
  148. chatUpdateHandler, ok := handler.(ChatUpdateHandler)
  149. if !ok {
  150. continue
  151. }
  152. if ext.shouldCallSynchronously(chatUpdateHandler) {
  153. chatUpdateHandler.HandleChatUpdate(event)
  154. } else {
  155. go chatUpdateHandler.HandleChatUpdate(event)
  156. }
  157. }
  158. }