mautrix-whatsapp/whatsapp-ext/chat.go
2020-06-26 00:13:18 +03:00

183 lines
4.8 KiB
Go

// mautrix-whatsapp - A Matrix-WhatsApp puppeting bridge.
// Copyright (C) 2019 Tulir Asokan
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package whatsappExt
import (
"encoding/json"
"strings"
"github.com/Rhymen/go-whatsapp"
)
type ChatUpdateCommand string
const (
ChatUpdateCommandAction ChatUpdateCommand = "action"
)
type ChatUpdate struct {
JID string `json:"id"`
Command ChatUpdateCommand `json:"cmd"`
Data ChatUpdateData `json:"data"`
}
type ChatActionType string
const (
ChatActionNameChange ChatActionType = "subject"
ChatActionAddTopic ChatActionType = "desc_add"
ChatActionRemoveTopic ChatActionType = "desc_remove"
ChatActionRestrict ChatActionType = "restrict"
ChatActionAnnounce ChatActionType = "announce"
ChatActionPromote ChatActionType = "promote"
ChatActionDemote ChatActionType = "demote"
ChatActionIntroduce ChatActionType = "introduce"
ChatActionCreate ChatActionType = "create"
ChatActionRemove ChatActionType = "remove"
ChatActionAdd ChatActionType = "add"
)
type ChatUpdateData struct {
Action ChatActionType
SenderJID string
NameChange struct {
Name string `json:"subject"`
SetAt int64 `json:"s_t"`
SetBy string `json:"s_o"`
}
AddTopic struct {
Topic string `json:"desc"`
ID string `json:"descId"`
SetAt int64 `json:"descTime"`
SetBy string `json:"descOwner"`
}
RemoveTopic struct {
ID string `json:"descId"`
}
Introduce struct {
CreationTime int64 `json:"creation"`
Admins []string `json:"admins"`
SuperAdmins []string `json:"superadmins"`
Regulars []string `json:"regulars"`
}
Restrict bool
Announce bool
UserChange struct {
JIDs []string `json:"participants"`
}
}
func (cud *ChatUpdateData) UnmarshalJSON(data []byte) error {
var arr []json.RawMessage
err := json.Unmarshal(data, &arr)
if err != nil {
return err
} else if len(arr) < 3 {
return nil
}
err = json.Unmarshal(arr[0], &cud.Action)
if err != nil {
return err
}
err = json.Unmarshal(arr[1], &cud.SenderJID)
if err != nil {
return err
}
cud.SenderJID = strings.Replace(cud.SenderJID, OldUserSuffix, NewUserSuffix, 1)
var unmarshalTo interface{}
switch cud.Action {
case ChatActionIntroduce, ChatActionCreate:
err = json.Unmarshal(arr[2], &cud.NameChange)
if err != nil {
return err
}
err = json.Unmarshal(arr[2], &cud.AddTopic)
if err != nil {
return err
}
unmarshalTo = &cud.Introduce
case ChatActionNameChange:
unmarshalTo = &cud.NameChange
case ChatActionAddTopic:
unmarshalTo = &cud.AddTopic
case ChatActionRemoveTopic:
unmarshalTo = &cud.RemoveTopic
case ChatActionRestrict:
unmarshalTo = &cud.Restrict
case ChatActionAnnounce:
unmarshalTo = &cud.Announce
case ChatActionPromote, ChatActionDemote, ChatActionRemove, ChatActionAdd:
unmarshalTo = &cud.UserChange
default:
return nil
}
err = json.Unmarshal(arr[2], unmarshalTo)
if err != nil {
return err
}
cud.NameChange.SetBy = strings.Replace(cud.NameChange.SetBy, OldUserSuffix, NewUserSuffix, 1)
for index, jid := range cud.UserChange.JIDs {
cud.UserChange.JIDs[index] = strings.Replace(jid, OldUserSuffix, NewUserSuffix, 1)
}
for index, jid := range cud.Introduce.SuperAdmins {
cud.Introduce.SuperAdmins[index] = strings.Replace(jid, OldUserSuffix, NewUserSuffix, 1)
}
for index, jid := range cud.Introduce.Admins {
cud.Introduce.Admins[index] = strings.Replace(jid, OldUserSuffix, NewUserSuffix, 1)
}
for index, jid := range cud.Introduce.Regulars {
cud.Introduce.Regulars[index] = strings.Replace(jid, OldUserSuffix, NewUserSuffix, 1)
}
return nil
}
type ChatUpdateHandler interface {
whatsapp.Handler
HandleChatUpdate(ChatUpdate)
}
func (ext *ExtendedConn) handleMessageChatUpdate(message []byte) {
var event ChatUpdate
err := json.Unmarshal(message, &event)
if err != nil {
ext.jsonParseError(err)
return
}
event.JID = strings.Replace(event.JID, OldUserSuffix, NewUserSuffix, 1)
for _, handler := range ext.handlers {
chatUpdateHandler, ok := handler.(ChatUpdateHandler)
if !ok {
continue
}
if ext.shouldCallSynchronously(chatUpdateHandler) {
chatUpdateHandler.HandleChatUpdate(event)
} else {
go chatUpdateHandler.HandleChatUpdate(event)
}
}
}