Add JSONMessage parsing to whatsapp extensions
This commit is contained in:
parent
329bc9d8ce
commit
d13bf4ae64
7 changed files with 414 additions and 3 deletions
59
whatsapp-ext/conn.go
Normal file
59
whatsapp-ext/conn.go
Normal file
|
@ -0,0 +1,59 @@
|
|||
// mautrix-whatsapp - A Matrix-WhatsApp puppeting bridge.
|
||||
// Copyright (C) 2018 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 whatsapp_ext
|
||||
|
||||
import (
|
||||
"github.com/Rhymen/go-whatsapp"
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
type ConnInfo struct {
|
||||
ProtocolVersion []int `json:"protoVersion"`
|
||||
BinaryVersion int `json:"binVersion"`
|
||||
Phone struct {
|
||||
WhatsAppVersion string `json:"wa_version"`
|
||||
MCC int `json:"mcc"`
|
||||
MNC int `json:"mnc"`
|
||||
OSVersion string `json:"os_version"`
|
||||
DeviceManufacturer string `json:"device_manufacturer"`
|
||||
DeviceModel string `json:"device_model"`
|
||||
OSBuildNumber string `json:"os_build_number"`
|
||||
} `json:"phone"`
|
||||
Features map[string]interface{} `json:"features"`
|
||||
PushName string `json:"pushname"`
|
||||
}
|
||||
|
||||
type ConnInfoHandler interface {
|
||||
whatsapp.Handler
|
||||
HandleConnInfo(ConnInfo)
|
||||
}
|
||||
|
||||
func (ext *ExtendedConn) handleMessageConn(message []byte) {
|
||||
var event ConnInfo
|
||||
err := json.Unmarshal(message, &event)
|
||||
if err != nil {
|
||||
ext.jsonParseError(err)
|
||||
return
|
||||
}
|
||||
for _, handler := range ext.handlers {
|
||||
connInfoHandler, ok := handler.(ConnInfoHandler)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
connInfoHandler.HandleConnInfo(event)
|
||||
}
|
||||
}
|
93
whatsapp-ext/jsonmessage.go
Normal file
93
whatsapp-ext/jsonmessage.go
Normal file
|
@ -0,0 +1,93 @@
|
|||
// mautrix-whatsapp - A Matrix-WhatsApp puppeting bridge.
|
||||
// Copyright (C) 2018 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 whatsapp_ext
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/Rhymen/go-whatsapp"
|
||||
)
|
||||
|
||||
type JSONMessage []json.RawMessage
|
||||
|
||||
type JSONMessageType string
|
||||
|
||||
const (
|
||||
MessageMsgInfo JSONMessageType = "MsgInfo"
|
||||
MessagePresence JSONMessageType = "Presence"
|
||||
MessageStream JSONMessageType = "Stream"
|
||||
MessageConn JSONMessageType = "Conn"
|
||||
MessageProps JSONMessageType = "Props"
|
||||
)
|
||||
|
||||
func (ext *ExtendedConn) AddHandler(handler whatsapp.Handler) {
|
||||
ext.Conn.AddHandler(handler)
|
||||
ext.handlers = append(ext.handlers, handler)
|
||||
}
|
||||
|
||||
func (ext *ExtendedConn) HandleError(error) {}
|
||||
|
||||
type UnhandledJSONMessageHandler interface {
|
||||
whatsapp.Handler
|
||||
HandleUnhandledJSONMessage(string)
|
||||
}
|
||||
|
||||
type JSONParseErrorHandler interface {
|
||||
whatsapp.Handler
|
||||
HandleJSONParseError(error)
|
||||
}
|
||||
|
||||
func (ext *ExtendedConn) jsonParseError(err error) {
|
||||
for _, handler := range ext.handlers {
|
||||
errorHandler, ok := handler.(JSONParseErrorHandler)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
errorHandler.HandleJSONParseError(err)
|
||||
}
|
||||
}
|
||||
|
||||
func (ext *ExtendedConn) HandleJsonMessage(message string) {
|
||||
msg := JSONMessage{}
|
||||
err := json.Unmarshal([]byte(message), &msg)
|
||||
if err != nil || len(msg) < 2 {
|
||||
return
|
||||
}
|
||||
|
||||
var msgType JSONMessageType
|
||||
json.Unmarshal(msg[0], &msgType)
|
||||
|
||||
switch msgType {
|
||||
case MessagePresence:
|
||||
ext.handleMessagePresence(msg[1])
|
||||
case MessageStream:
|
||||
ext.handleMessageStream(msg[1:])
|
||||
case MessageConn:
|
||||
ext.handleMessageProps(msg[1])
|
||||
case MessageProps:
|
||||
ext.handleMessageProps(msg[1])
|
||||
case MessageMsgInfo:
|
||||
ext.handleMessageMsgInfo(msg[1])
|
||||
default:
|
||||
for _, handler := range ext.handlers {
|
||||
ujmHandler, ok := handler.(UnhandledJSONMessageHandler)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
ujmHandler.HandleUnhandledJSONMessage(message)
|
||||
}
|
||||
}
|
||||
}
|
63
whatsapp-ext/msginfo.go
Normal file
63
whatsapp-ext/msginfo.go
Normal file
|
@ -0,0 +1,63 @@
|
|||
// mautrix-whatsapp - A Matrix-WhatsApp puppeting bridge.
|
||||
// Copyright (C) 2018 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 whatsapp_ext
|
||||
|
||||
import (
|
||||
"github.com/Rhymen/go-whatsapp"
|
||||
"encoding/json"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type MsgInfoCommand string
|
||||
|
||||
const (
|
||||
MsgInfoCommandAcknowledge MsgInfoCommand = "ack"
|
||||
)
|
||||
|
||||
type MsgInfo struct {
|
||||
Command MsgInfoCommand `json:"cmd"`
|
||||
ID string `json:"id"`
|
||||
Acknowledgement int `json:"ack"`
|
||||
MessageFromJID string `json:"from"`
|
||||
SenderJID string `json:"participant"`
|
||||
ToJID string `json:"to"`
|
||||
Timestamp int64 `json:"t"`
|
||||
}
|
||||
|
||||
type MsgInfoHandler interface {
|
||||
whatsapp.Handler
|
||||
HandleMsgInfo(MsgInfo)
|
||||
}
|
||||
|
||||
func (ext *ExtendedConn) handleMessageMsgInfo(message []byte) {
|
||||
var event MsgInfo
|
||||
err := json.Unmarshal(message, &event)
|
||||
if err != nil {
|
||||
ext.jsonParseError(err)
|
||||
return
|
||||
}
|
||||
event.MessageFromJID = strings.Replace(event.MessageFromJID, OldUserSuffix, NewUserSuffix, 1)
|
||||
event.SenderJID = strings.Replace(event.SenderJID, OldUserSuffix, NewUserSuffix, 1)
|
||||
event.ToJID = strings.Replace(event.ToJID, OldUserSuffix, NewUserSuffix, 1)
|
||||
for _, handler := range ext.handlers {
|
||||
msgInfoHandler, ok := handler.(MsgInfoHandler)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
msgInfoHandler.HandleMsgInfo(event)
|
||||
}
|
||||
}
|
58
whatsapp-ext/presence.go
Normal file
58
whatsapp-ext/presence.go
Normal file
|
@ -0,0 +1,58 @@
|
|||
// mautrix-whatsapp - A Matrix-WhatsApp puppeting bridge.
|
||||
// Copyright (C) 2018 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 whatsapp_ext
|
||||
|
||||
import (
|
||||
"github.com/Rhymen/go-whatsapp"
|
||||
"encoding/json"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type PresenceType string
|
||||
|
||||
const (
|
||||
PresenceUnavailable PresenceType = "unavailable"
|
||||
PresenceAvailable PresenceType = "available"
|
||||
)
|
||||
|
||||
type Presence struct {
|
||||
JID string `json:"id"`
|
||||
Status PresenceType `json:"type"`
|
||||
Timestamp int64 `json:"t"`
|
||||
}
|
||||
|
||||
type PresenceHandler interface {
|
||||
whatsapp.Handler
|
||||
HandlePresence(Presence)
|
||||
}
|
||||
|
||||
func (ext *ExtendedConn) handleMessagePresence(message []byte) {
|
||||
var event Presence
|
||||
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 {
|
||||
presenceHandler, ok := handler.(PresenceHandler)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
presenceHandler.HandlePresence(event)
|
||||
}
|
||||
}
|
67
whatsapp-ext/props.go
Normal file
67
whatsapp-ext/props.go
Normal file
|
@ -0,0 +1,67 @@
|
|||
// mautrix-whatsapp - A Matrix-WhatsApp puppeting bridge.
|
||||
// Copyright (C) 2018 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 whatsapp_ext
|
||||
|
||||
import (
|
||||
"github.com/Rhymen/go-whatsapp"
|
||||
"encoding/json"
|
||||
)
|
||||
|
||||
type ProtocolProps struct {
|
||||
WebPresence bool `json:"webPresence"`
|
||||
NotificationQuery bool `json:"notificationQuery"`
|
||||
FacebookCrashLog bool `json:"fbCrashlog"`
|
||||
Bucket string `json:"bucket"`
|
||||
GIFSearch string `json:"gifSearch"`
|
||||
Spam bool `json:"SPAM"`
|
||||
SetBlock bool `json:"SET_BLOCK"`
|
||||
MessageInfo bool `json:"MESSAGE_INFO"`
|
||||
MaxFileSize int `json:"maxFileSize"`
|
||||
Media int `json:"media"`
|
||||
GroupNameLength int `json:"maxSubject"`
|
||||
GroupDescriptionLength int `json:"groupDescLength"`
|
||||
MaxParticipants int `json:"maxParticipants"`
|
||||
VideoMaxEdge int `json:"videoMaxEdge"`
|
||||
ImageMaxEdge int `json:"imageMaxEdge"`
|
||||
ImageMaxKilobytes int `json:"imageMaxKBytes"`
|
||||
Edit int `json:"edit"`
|
||||
FwdUIStartTimestamp int `json:"fwdUiStartTs"`
|
||||
GroupsV3 int `json:"groupsV3"`
|
||||
RestrictGroups int `json:"restrictGroups"`
|
||||
AnnounceGroups int `json:"announceGroups"`
|
||||
}
|
||||
|
||||
type ProtocolPropsHandler interface {
|
||||
whatsapp.Handler
|
||||
HandleProtocolProps(ProtocolProps)
|
||||
}
|
||||
|
||||
func (ext *ExtendedConn) handleMessageProps(message []byte) {
|
||||
var event ProtocolProps
|
||||
err := json.Unmarshal(message, &event)
|
||||
if err != nil {
|
||||
ext.jsonParseError(err)
|
||||
return
|
||||
}
|
||||
for _, handler := range ext.handlers {
|
||||
protocolPropsHandler, ok := handler.(ProtocolPropsHandler)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
protocolPropsHandler.HandleProtocolProps(event)
|
||||
}
|
||||
}
|
62
whatsapp-ext/stream.go
Normal file
62
whatsapp-ext/stream.go
Normal file
|
@ -0,0 +1,62 @@
|
|||
// mautrix-whatsapp - A Matrix-WhatsApp puppeting bridge.
|
||||
// Copyright (C) 2018 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 whatsapp_ext
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/Rhymen/go-whatsapp"
|
||||
)
|
||||
|
||||
type StreamType string
|
||||
|
||||
const (
|
||||
StreamUpdate = "update"
|
||||
StreamSleep = "asleep"
|
||||
)
|
||||
|
||||
type StreamEvent struct {
|
||||
Type StreamType
|
||||
Boolean bool
|
||||
Version string
|
||||
}
|
||||
|
||||
type StreamEventHandler interface {
|
||||
whatsapp.Handler
|
||||
HandleStreamEvent(StreamEvent)
|
||||
}
|
||||
|
||||
func (ext *ExtendedConn) handleMessageStream(message []json.RawMessage) {
|
||||
var event StreamEvent
|
||||
err := json.Unmarshal(message[0], &event.Type)
|
||||
if err != nil {
|
||||
ext.jsonParseError(err)
|
||||
return
|
||||
}
|
||||
|
||||
if event.Type == StreamUpdate && len(message) > 4 {
|
||||
json.Unmarshal(message[1], event.Boolean)
|
||||
json.Unmarshal(message[2], event.Version)
|
||||
}
|
||||
|
||||
for _, handler := range ext.handlers {
|
||||
streamHandler, ok := handler.(StreamEventHandler)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
streamHandler.HandleStreamEvent(event)
|
||||
}
|
||||
}
|
|
@ -26,14 +26,23 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
OldUserSuffix = "@c.us"
|
||||
NewUserSuffix = "@s.whatsapp.net"
|
||||
)
|
||||
|
||||
type ExtendedConn struct {
|
||||
*whatsapp.Conn
|
||||
|
||||
handlers []whatsapp.Handler
|
||||
}
|
||||
|
||||
func ExtendConn(conn *whatsapp.Conn) *ExtendedConn {
|
||||
return &ExtendedConn{
|
||||
ext := &ExtendedConn{
|
||||
Conn: conn,
|
||||
}
|
||||
ext.Conn.AddHandler(ext)
|
||||
return ext
|
||||
}
|
||||
|
||||
type GroupInfo struct {
|
||||
|
@ -64,7 +73,7 @@ func (ext *ExtendedConn) GetGroupMetaData(jid string) (*GroupInfo, error) {
|
|||
return nil, fmt.Errorf("failed to get group metadata: %v", err)
|
||||
}
|
||||
content := <-data
|
||||
fmt.Println("GROUP METADATA", content)
|
||||
|
||||
info := &GroupInfo{}
|
||||
err = json.Unmarshal([]byte(content), info)
|
||||
if err != nil {
|
||||
|
@ -72,7 +81,7 @@ func (ext *ExtendedConn) GetGroupMetaData(jid string) (*GroupInfo, error) {
|
|||
}
|
||||
|
||||
for index, participant := range info.Participants {
|
||||
info.Participants[index].JID = strings.Replace(participant.JID, "@c.us", "@s.whatsapp.net", 1)
|
||||
info.Participants[index].JID = strings.Replace(participant.JID, OldUserSuffix, NewUserSuffix, 1)
|
||||
}
|
||||
|
||||
return info, nil
|
||||
|
|
Loading…
Reference in a new issue