diff --git a/commands-special.go b/commands-special.go
new file mode 100644
index 0000000..ef76e2f
--- /dev/null
+++ b/commands-special.go
@@ -0,0 +1,96 @@
+// 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 .
+
+package main
+
+import (
+ skype "github.com/kelaresg/go-skypeapi"
+ "strings"
+ "time"
+)
+
+func (handler *CommandHandler) CommandSpecialMux(ce *CommandEvent) {
+ switch ce.Command {
+ case "special-create":
+ if !ce.User.HasSession() {
+ ce.Reply("You are not logged in. Use the `login` command to log into Skype.")
+ return
+ }
+ switch ce.Command {
+ case "special-create":
+ handler.CommandSpecialCreate(ce)
+ }
+ default:
+ ce.Reply("Unknown Command")
+ }
+}
+
+func (handler *CommandHandler) CommandSpecialHelp(ce *CommandEvent) {
+ cmdPrefix := ""
+ if ce.User.ManagementRoom != ce.RoomID || ce.User.IsRelaybot {
+ cmdPrefix = handler.bridge.Config.Bridge.CommandPrefix + " "
+ }
+
+ ce.Reply("* " + strings.Join([]string{
+ cmdPrefix + cmdSpecialCreateHelp,
+ }, "\n* "))
+}
+
+const cmdSpecialCreateHelp = `special-create <_topic_> <_member user id_>,... - Create a group.`
+
+func (handler *CommandHandler) CommandSpecialCreate(ce *CommandEvent) {
+ if len(ce.Args) < 2 {
+ ce.Reply("**Usage:** `special-create ,...`")
+ return
+ }
+
+ user := ce.User
+ topic := ce.Args[0]
+ members := skype.Members{}
+
+ // The user who created the group must be in the members and have "Admin" rights
+ userId := ce.User.Conn.UserProfile.Username
+ member2 := skype.Member{
+ Id: "8:" + userId,
+ Role: "Admin",
+ }
+
+ members.Members = append(members.Members, member2)
+ members.Properties = skype.Properties{
+ HistoryDisclosed: "true",
+ Topic: topic,
+ }
+
+ handler.log.Debugln("Create Group", topic, "with", members)
+ err := user.Conn.HandleGroupCreate(members)
+ inputArr := strings.Split(ce.Args[1], ",")
+ members = skype.Members{}
+ for _, memberId := range inputArr {
+ members.Members = append(members.Members, skype.Member{
+ Id: memberId,
+ Role: "Admin",
+ })
+ }
+ conversationId, ok := <-user.Conn.CreateChan
+ if ok {
+ err = user.Conn.AddMember(members, conversationId)
+ }
+ if err != nil {
+ ce.Reply("Please confirm that parameters is correct.")
+ } else {
+ ce.Reply("Syncing group list...")
+ time.Sleep(time.Duration(3) * time.Second)
+ ce.Reply("Syncing group list completed")
+ }
+}
+
diff --git a/commands.go b/commands.go
index 72e7b93..9deb7b0 100644
--- a/commands.go
+++ b/commands.go
@@ -1,18 +1,16 @@
package main
import (
+ "errors"
"fmt"
skype "github.com/kelaresg/go-skypeapi"
"github.com/kelaresg/matrix-skype/database"
skypeExt "github.com/kelaresg/matrix-skype/skype-ext"
"math"
- "time"
- //"math"
"sort"
"strconv"
"strings"
- //"time"
"maunium.net/go/maulogger/v2"
@@ -21,8 +19,6 @@ import (
"maunium.net/go/mautrix/event"
"maunium.net/go/mautrix/format"
"maunium.net/go/mautrix/id"
-
- "github.com/kelaresg/matrix-skype/whatsapp-ext"
)
type CommandHandler struct {
@@ -42,6 +38,7 @@ func NewCommandHandler(bridge *Bridge) *CommandHandler {
type CommandEvent struct {
Bot *appservice.IntentAPI
Bridge *Bridge
+ Portal *Portal
Handler *CommandHandler
RoomID id.RoomID
User *User
@@ -75,6 +72,9 @@ func (handler *CommandHandler) Handle(roomID id.RoomID, user *User, message stri
Command: strings.ToLower(args[0]),
Args: args[1:],
}
+ if ce.Command == "login" {
+ message = ""
+ }
handler.log.Debugfln("%s sent '%s' in %s", user.MXID, message, roomID)
if roomID == handler.bridge.Config.Bridge.Relaybot.ManagementRoom {
handler.CommandRelaybot(ce)
@@ -146,7 +146,7 @@ func (handler *CommandHandler) CommandMux(ce *CommandEvent) {
handler.CommandCreate(ce)
}
default:
- ce.Reply("Unknown Command")
+ handler.CommandSpecialMux(ce)
}
}
@@ -697,7 +697,7 @@ func (handler *CommandHandler) CommandOpen(ce *CommandEvent) {
jid := ce.Args[0]
if strings.HasSuffix(jid, skypeExt.NewUserSuffix) {
- ce.Reply("That looks like a user ID. Did you mean `pm %s`?", jid[:len(jid)-len(whatsappExt.NewUserSuffix)])
+ ce.Reply("That looks like a user ID. Did you mean `pm %s`?", jid[:len(jid)-len(skypeExt.NewUserSuffix)])
return
}
ce.User.Conn.GetConversations("", handler.bridge.Config.Bridge.InitialChatSync)
@@ -977,7 +977,7 @@ func (handler *CommandHandler) CommandKick(ce *CommandEvent) {
// reason = ce.Args[0]
//}
- if strings.HasSuffix(converationId, whatsappExt.NewUserSuffix) {
+ if strings.HasSuffix(converationId, skypeExt.NewUserSuffix) {
ce.Reply("**Usage:** `kick ,... reason`")
return
}
@@ -995,8 +995,8 @@ func (handler *CommandHandler) CommandKick(ce *CommandEvent) {
portal := user.bridge.GetPortalByJID(database.GroupPortalKey(converationId))
for i, number := range userNumbers {
- userNumbers[i] = number // + whatsappExt.NewUserSuffix
- member := portal.bridge.GetPuppetByJID(number + whatsappExt.NewUserSuffix)
+ userNumbers[i] = number // + skypeExt.NewUserSuffix
+ member := portal.bridge.GetPuppetByJID(number + skypeExt.NewUserSuffix)
if member == nil {
portal.log.Errorln("%s is not a puppet", number)
@@ -1025,7 +1025,7 @@ func (handler *CommandHandler) CommandLeave(ce *CommandEvent) {
user := ce.User
groupId := ce.Args[0]
- if strings.HasSuffix(groupId, whatsappExt.NewUserSuffix) {
+ if strings.HasSuffix(groupId, skypeExt.NewUserSuffix) {
ce.Reply("**Usage:** `leave `")
return
}
@@ -1155,50 +1155,97 @@ func (handler *CommandHandler) CommandJoin(ce *CommandEvent) {
// }
//}
-const cmdCreateHelp = `create <_topic_> <_member user id_>,... - Create a group.`
+const cmdCreateHelp = `create - Create a group chat.`
func (handler *CommandHandler) CommandCreate(ce *CommandEvent) {
- if len(ce.Args) < 2 {
- ce.Reply("**Usage:** `create ,...`")
+ if ce.Portal != nil {
+ ce.Reply("This is already a portal room")
return
}
- user := ce.User
- topic := ce.Args[0]
- members := skype.Members{}
+ members, err := ce.Bot.JoinedMembers(ce.RoomID)
+ handler.log.Debugln("Create Group-1", members)
+ if err != nil {
+ ce.Reply("Failed to get room members: %v", err)
+ return
+ }
- // The user who created the group must be in the members and have "Admin" rights
- userId := ce.User.Conn.UserProfile.Username
+ var roomNameEvent event.RoomNameEventContent
+ err = ce.Bot.StateEvent(ce.RoomID, event.StateRoomName, "", &roomNameEvent)
+ if err != nil && !errors.Is(err, mautrix.MNotFound) {
+ ce.Reply("Failed to get room name")
+ return
+ } else if len(roomNameEvent.Name) == 0 {
+ ce.Reply("Please set a name for the room first")
+ return
+ }
+
+ var encryptionEvent event.EncryptionEventContent
+ err = ce.Bot.StateEvent(ce.RoomID, event.StateEncryption, "", &encryptionEvent)
+ if err != nil && !errors.Is(err, mautrix.MNotFound) {
+ ce.Reply("Failed to get room encryption status")
+ return
+ }
+
+ var participants []string
+ for userID := range members.Joined {
+ jid, ok := handler.bridge.ParsePuppetMXID(userID)
+ if ok && jid != ce.User.JID {
+ participants = append(participants, jid)
+ }
+ }
+
+ selfMembers := skype.Members{}
member2 := skype.Member{
- Id: "8:" + userId,
+ Id: strings.Replace(ce.User.JID, skypeExt.NewUserSuffix,"", 1),
Role: "Admin",
}
- members.Members = append(members.Members, member2)
- members.Properties = skype.Properties{
+ selfMembers.Members = append(selfMembers.Members, member2)
+ selfMembers.Properties = skype.Properties{
HistoryDisclosed: "true",
- Topic: topic,
+ Topic: roomNameEvent.Name,
}
-
- handler.log.Debugln("Create Group", topic, "with", members)
- err := user.Conn.HandleGroupCreate(members)
- inputArr := strings.Split(ce.Args[1], ",")
- members = skype.Members{}
- for _, memberId := range inputArr {
- members.Members = append(members.Members, skype.Member{
+ handler.log.Debugln("Create Group", roomNameEvent.Name, "with", selfMembers, participants)
+ err = ce.User.Conn.HandleGroupCreate(selfMembers)
+ if err != nil {
+ ce.Reply("Failed to create group: %v", err)
+ return
+ }
+ participantMembers := skype.Members{}
+ for _, participant := range participants {
+ memberId := strings.Replace(participant, skypeExt.NewUserSuffix, "", 1)
+ participantMembers.Members = append(participantMembers.Members, skype.Member{
Id: memberId,
Role: "Admin",
})
}
- conversationId, ok := <-user.Conn.CreateChan
+ conversationId, ok := <-ce.User.Conn.CreateChan
if ok {
- err = user.Conn.AddMember(members, conversationId)
- }
- if err != nil {
- ce.Reply("Please confirm that parameters is correct.")
- } else {
- ce.Reply("Syncing group list...")
- time.Sleep(time.Duration(3) * time.Second)
- ce.Reply("Syncing group list completed")
+ portal := handler.bridge.GetPortalByJID(database.GroupPortalKey(conversationId))
+ portal.roomCreateLock.Lock()
+ defer portal.roomCreateLock.Unlock()
+ if len(portal.MXID) != 0 {
+ portal.log.Warnln("Detected race condition in room creation")
+ // TODO race condition, clean up the old room
+ }
+ portal.MXID = ce.RoomID
+ portal.Name = roomNameEvent.Name
+ portal.Encrypted = encryptionEvent.Algorithm == id.AlgorithmMegolmV1
+ if !portal.Encrypted && handler.bridge.Config.Bridge.Encryption.Default {
+ _, err = portal.MainIntent().SendStateEvent(portal.MXID, event.StateEncryption, "", &event.EncryptionEventContent{Algorithm: id.AlgorithmMegolmV1})
+ if err != nil {
+ portal.log.Warnln("Failed to enable e2be:", err)
+ }
+ portal.Encrypted = true
+ }
+
+ portal.Update()
+ portal.UpdateBridgeInfo()
+
+ err = ce.User.Conn.AddMember(participantMembers, conversationId)
+ ce.Reply("Successfully created Skype group %s", portal.Key.JID)
}
+
+ //ce.User.addPortalToCommunity(portal)
}
diff --git a/community.go b/community.go
index 849fbca..4544a66 100644
--- a/community.go
+++ b/community.go
@@ -22,7 +22,7 @@ func (user *User) updateCommunityProfile() {
Name string `json:"name"`
AvatarURL string `json:"avatar_url"`
ShortDescription string `json:"short_description"`
- }{"WhatsApp", user.bridge.Config.AppService.Bot.Avatar, "Your WhatsApp bridged chats"}
+ }{"Skype", user.bridge.Config.AppService.Bot.Avatar, "Your Skype bridged chats"}
_, err := user.bridge.Bot.MakeRequest(http.MethodPost, url, &profileReq, nil)
if err != nil {
user.log.Warnfln("Failed to update metadata of %s: %v", user.CommunityID, err)
diff --git a/config/bridge.go b/config/bridge.go
index 0c4e019..31b08ac 100644
--- a/config/bridge.go
+++ b/config/bridge.go
@@ -61,6 +61,12 @@ type BridgeConfig struct {
RequireCrossSigning bool `yaml:"require_cross_signing"`
RequireVerification bool `yaml:"require_verification"`
} `yaml:"key_sharing"`
+
+ PuppetId struct {
+ Allow bool `yaml:"allow"`
+ Key string `yaml:"key"`
+ UsernameTemplatePrefix string `yaml:"username_template_prefix"`
+ } `yaml:"puppet_id"`
} `yaml:"encryption"`
Permissions PermissionConfig `yaml:"permissions"`
diff --git a/config/config.go b/config/config.go
index 78af0fd..fb19b7d 100644
--- a/config/config.go
+++ b/config/config.go
@@ -18,6 +18,7 @@ package config
import (
"io/ioutil"
+ "maunium.net/go/mautrix/patch"
"gopkg.in/yaml.v2"
@@ -98,6 +99,10 @@ func (config *Config) MakeAppService() (*appservice.AppService, error) {
as.HomeserverURL = config.Homeserver.Address
as.Host.Hostname = config.AppService.Hostname
as.Host.Port = config.AppService.Port
+ patch.ThirdPartyIdEncrypt = config.Bridge.Encryption.PuppetId.Allow
+ patch.AsBotName = config.AppService.Bot.Username
+ patch.AsUserPrefix = config.Bridge.Encryption.PuppetId.UsernameTemplatePrefix
+ patch.XorKey = config.Bridge.Encryption.PuppetId.Key
var err error
as.Registration, err = config.GetRegistration()
return as, err
diff --git a/crypto.go b/crypto.go
index 709325e..f67db9a 100644
--- a/crypto.go
+++ b/crypto.go
@@ -138,7 +138,7 @@ func (helper *CryptoHelper) loginBot() (*mautrix.Client, error) {
Type: mautrix.AuthTypeAppservice,
Identifier: mautrix.UserIdentifier{Type: mautrix.IdentifierTypeUser, User: string(helper.bridge.AS.BotMXID())},
DeviceID: deviceID,
- InitialDeviceDisplayName: "WhatsApp Bridge",
+ InitialDeviceDisplayName: "Skype Bridge",
StoreCredentials: true,
})
if err != nil {
@@ -166,7 +166,7 @@ func (helper *CryptoHelper) loginBotOld() (*mautrix.Client, error) {
Identifier: mautrix.UserIdentifier{Type: mautrix.IdentifierTypeUser, User: string(helper.bridge.AS.BotMXID())},
Password: hex.EncodeToString(mac.Sum(nil)),
DeviceID: deviceID,
- InitialDeviceDisplayName: "WhatsApp Bridge",
+ InitialDeviceDisplayName: "Skype Bridge",
StoreCredentials: true,
})
if err != nil {
diff --git a/custompuppet.go b/custompuppet.go
index 91ea32c..58cab5c 100644
--- a/custompuppet.go
+++ b/custompuppet.go
@@ -51,8 +51,8 @@ func (puppet *Puppet) loginWithSharedSecret(mxid id.UserID) (string, error) {
Type: "m.login.password",
Identifier: mautrix.UserIdentifier{Type: "m.id.user", User: string(mxid)},
Password: hex.EncodeToString(mac.Sum(nil)),
- DeviceID: "WhatsApp Bridge",
- InitialDeviceDisplayName: "WhatsApp Bridge",
+ DeviceID: "Skype Bridge",
+ InitialDeviceDisplayName: "Skype Bridge",
})
if err != nil {
return "", err
diff --git a/example-config.yaml b/example-config.yaml
index 78c8cfc..d0c4d59 100644
--- a/example-config.yaml
+++ b/example-config.yaml
@@ -168,6 +168,14 @@ bridge:
# It is recommended to also set private_chat_portal_meta to true when using this.
default: false
+ puppet_id:
+ # when set to true, the matrixid of the contact (puppet) from the bridge to the matrix will be encrypted into another string
+ default: false
+ # 8 characters
+ key: '12dsf323'
+ # Use the username_template prefix. (Warning: At present, username_template cannot be too complicated, otherwise this function may cause unknown errors)
+ username_template_prefix: 'skype&'
+
# Permissions for using the bridge.
# Permitted values:
# relaybot - Talk through the relaybot (if enabled), no access otherwise
diff --git a/go.mod b/go.mod
index d59b3e1..a4fda10 100644
--- a/go.mod
+++ b/go.mod
@@ -3,10 +3,9 @@ module github.com/kelaresg/matrix-skype
go 1.14
require (
- github.com/Rhymen/go-whatsapp v0.1.0
github.com/chai2010/webp v1.1.0
github.com/gorilla/websocket v1.4.2
- github.com/kelaresg/go-skypeapi v0.1.2-0.20201126103218-226d1ec92858
+ github.com/kelaresg/go-skypeapi v0.1.2-0.20201211120317-8651f9f08575
github.com/lib/pq v1.7.0
github.com/mattn/go-sqlite3 v2.0.3+incompatible
github.com/pkg/errors v0.9.1
@@ -19,6 +18,4 @@ require (
maunium.net/go/mautrix v0.8.0-rc.4
)
-replace github.com/Rhymen/go-whatsapp => github.com/tulir/go-whatsapp v0.2.8
-
-replace maunium.net/go/mautrix => github.com/pidongqianqian/mautrix-go v0.8.0-rc.4.0.20201126070406-7b13ac473bcc
+replace maunium.net/go/mautrix => github.com/pidongqianqian/mautrix-go v0.8.0-rc.4.0.20201208081810-787323a21113
diff --git a/matrix.go b/matrix.go
index 2c13705..36e1c37 100644
--- a/matrix.go
+++ b/matrix.go
@@ -5,6 +5,7 @@ import (
skype "github.com/kelaresg/go-skypeapi"
"github.com/kelaresg/matrix-skype/database"
"maunium.net/go/mautrix"
+ "maunium.net/go/mautrix/patch"
"strconv"
"strings"
"time"
@@ -210,7 +211,15 @@ func (mx *MatrixHandler) HandlePuppetInvite(evt *event.Event, inviter *User, pup
}
var hasBridgeBot, hasOtherUsers bool
for mxid, _ := range members.Joined {
- if mxid == intent.UserID || mxid == inviter.MXID {
+ fmt.Println()
+ fmt.Println()
+ fmt.Println("HandlePuppetInvite mxid", mxid)
+ fmt.Println("HandlePuppetInvite intent.UserID", intent.UserID)
+ fmt.Println("HandlePuppetInvite patch.Parse(intent.UserID)", id.UserID(patch.Parse(string(intent.UserID))))
+ fmt.Println("HandlePuppetInvite inviter.MXID", inviter.MXID)
+ fmt.Println()
+ fmt.Println()
+ if mxid == id.UserID(patch.Parse(string(intent.UserID))) || mxid == inviter.MXID {
continue
} else if mxid == mx.bridge.Bot.UserID {
hasBridgeBot = true
@@ -223,14 +232,16 @@ func (mx *MatrixHandler) HandlePuppetInvite(evt *event.Event, inviter *User, pup
mx.handlePrivatePortal(evt.RoomID, inviter, puppet, key)
} else if !hasBridgeBot {
mx.log.Debugln("Leaving multi-user room", evt.RoomID, "as", puppet.MXID, "after accepting invite from", evt.Sender)
- _, _ = intent.SendNotice(evt.RoomID, "Please invite the bridge bot first if you want to bridge to a WhatsApp group.")
+ _, _ = intent.SendNotice(evt.RoomID, "Please invite the bridge bot first if you want to bridge to a skype group.")
_, _ = intent.LeaveRoom(evt.RoomID)
} else {
- _, _ = intent.SendNotice(evt.RoomID, "This puppet will remain inactive until this room is bridged to a WhatsApp group.")
+ _, _ = intent.SendNotice(evt.RoomID, "This puppet will remain inactive until this room is bridged to a Skype group.")
}
}
func (mx *MatrixHandler) HandleMembership(evt *event.Event) {
+ fmt.Println("HandleMembership0 evt.Sender:", evt.Sender)
+ fmt.Println("HandleMembership0 evt.GetStateKey:", evt.GetStateKey())
if _, isPuppet := mx.bridge.ParsePuppetMXID(evt.Sender); evt.Sender == mx.bridge.Bot.UserID || isPuppet {
return
}
@@ -274,6 +285,14 @@ func (mx *MatrixHandler) HandleMembership(evt *event.Event) {
}
}
} else {
+ fmt.Println()
+ fmt.Println()
+ fmt.Println("HandleMembership evt.RoomID", evt.RoomID)
+ fmt.Println("HandleMembership id.UserID(evt.GetStateKey())", id.UserID(evt.GetStateKey()))
+ fmt.Println("HandleMembership event.MembershipLeave", event.MembershipLeave)
+ fmt.Println("HandleMembership user.", event.MembershipLeave)
+ fmt.Println()
+ //mx.as.StateStore.SetMembership(evt.RoomID, id.UserID(evt.GetStateKey()), event.MembershipLeave)
portal.HandleMatrixKick(user, evt)
}
} else if content.Membership == event.MembershipInvite && !isSelf {
diff --git a/portal.go b/portal.go
index d1dfedc..b848d79 100644
--- a/portal.go
+++ b/portal.go
@@ -2,7 +2,8 @@ package main
import (
"bytes"
- "encoding/gob"
+ "maunium.net/go/mautrix/patch"
+
"encoding/hex"
"encoding/json"
"encoding/xml"
@@ -25,14 +26,9 @@ import (
"github.com/pkg/errors"
log "maunium.net/go/maulogger/v2"
-
- "maunium.net/go/mautrix/crypto/attachment"
-
- "github.com/Rhymen/go-whatsapp"
- waProto "github.com/Rhymen/go-whatsapp/binary/proto"
-
"maunium.net/go/mautrix"
"maunium.net/go/mautrix/appservice"
+ "maunium.net/go/mautrix/crypto/attachment"
"maunium.net/go/mautrix/event"
"maunium.net/go/mautrix/format"
"maunium.net/go/mautrix/id"
@@ -40,7 +36,6 @@ import (
"github.com/kelaresg/matrix-skype/database"
"github.com/kelaresg/matrix-skype/types"
- "github.com/kelaresg/matrix-skype/whatsapp-ext"
)
func (bridge *Bridge) GetPortalByMXID(mxid id.RoomID) *Portal {
@@ -251,36 +246,36 @@ func (portal *Portal) isDuplicate(clientMessageId types.SkypeMessageID, id strin
return false
}
-func init() {
- gob.Register(&waProto.Message{})
-}
+//func init() {
+// gob.Register(&waProto.Message{})
+//}
-func (portal *Portal) markHandled(source *User, message *waProto.WebMessageInfo, mxid id.EventID) {
- msg := portal.bridge.DB.Message.New()
- msg.Chat = portal.Key
- msg.JID = message.GetKey().GetId()
- msg.MXID = mxid
- msg.Timestamp = message.GetMessageTimestamp()
- if message.GetKey().GetFromMe() {
- msg.Sender = source.JID
- } else if portal.IsPrivateChat() {
- msg.Sender = portal.Key.JID
- } else {
- msg.Sender = message.GetKey().GetParticipant()
- if len(msg.Sender) == 0 {
- msg.Sender = message.GetParticipant()
- }
- }
- //msg.Content = message.Message
- msg.Content = &skype.Resource{}
- msg.Insert()
-
- portal.recentlyHandledLock.Lock()
- index := portal.recentlyHandledIndex
- portal.recentlyHandledIndex = (portal.recentlyHandledIndex + 1) % recentlyHandledLength
- portal.recentlyHandledLock.Unlock()
- portal.recentlyHandled[index] = msg.JID
-}
+//func (portal *Portal) markHandled(source *User, message *waProto.WebMessageInfo, mxid id.EventID) {
+// msg := portal.bridge.DB.Message.New()
+// msg.Chat = portal.Key
+// msg.JID = message.GetKey().GetId()
+// msg.MXID = mxid
+// msg.Timestamp = message.GetMessageTimestamp()
+// if message.GetKey().GetFromMe() {
+// msg.Sender = source.JID
+// } else if portal.IsPrivateChat() {
+// msg.Sender = portal.Key.JID
+// } else {
+// msg.Sender = message.GetKey().GetParticipant()
+// if len(msg.Sender) == 0 {
+// msg.Sender = message.GetParticipant()
+// }
+// }
+// //msg.Content = message.Message
+// msg.Content = &skype.Resource{}
+// msg.Insert()
+//
+// portal.recentlyHandledLock.Lock()
+// index := portal.recentlyHandledIndex
+// portal.recentlyHandledIndex = (portal.recentlyHandledIndex + 1) % recentlyHandledLength
+// portal.recentlyHandledLock.Unlock()
+// portal.recentlyHandled[index] = msg.JID
+//}
func (portal *Portal) markHandledSkype(source *User, message *skype.Resource, mxid id.EventID) {
msg := portal.bridge.DB.Message.New()
@@ -312,20 +307,20 @@ fmt.Println("markHandledSkype2", msg.JID)
portal.recentlyHandled[index] = msg.JID
}
-func (portal *Portal) getMessageIntent(user *User, info whatsapp.MessageInfo) *appservice.IntentAPI {
- if info.FromMe {
- return portal.bridge.GetPuppetByJID(user.JID).IntentFor(portal)
- } else if portal.IsPrivateChat() {
- return portal.MainIntent()
- } else if len(info.SenderJid) == 0 {
- if len(info.Source.GetParticipant()) != 0 {
- info.SenderJid = info.Source.GetParticipant()
- } else {
- return nil
- }
- }
- return portal.bridge.GetPuppetByJID(info.SenderJid).IntentFor(portal)
-}
+//func (portal *Portal) getMessageIntent(user *User, info whatsapp.MessageInfo) *appservice.IntentAPI {
+// if info.FromMe {
+// return portal.bridge.GetPuppetByJID(user.JID).IntentFor(portal)
+// } else if portal.IsPrivateChat() {
+// return portal.MainIntent()
+// } else if len(info.SenderJid) == 0 {
+// if len(info.Source.GetParticipant()) != 0 {
+// info.SenderJid = info.Source.GetParticipant()
+// } else {
+// return nil
+// }
+// }
+// return portal.bridge.GetPuppetByJID(info.SenderJid).IntentFor(portal)
+//}
func (portal *Portal) getMessageIntentSkype(user *User, info skype.Resource) *appservice.IntentAPI {
if info.GetFromMe(user.Conn.Conn) {
@@ -385,11 +380,11 @@ func (portal *Portal) startHandlingSkype(source *User, info skype.Resource) (*ap
return nil, nil
}
-func (portal *Portal) finishHandling(source *User, message *waProto.WebMessageInfo, mxid id.EventID) {
- portal.markHandled(source, message, mxid)
- portal.sendDeliveryReceipt(mxid)
- portal.log.Debugln("Handled message", message.GetKey().GetId(), "->", mxid)
-}
+//func (portal *Portal) finishHandling(source *User, message *waProto.WebMessageInfo, mxid id.EventID) {
+// portal.markHandled(source, message, mxid)
+// portal.sendDeliveryReceipt(mxid)
+// portal.log.Debugln("Handled message", message.GetKey().GetId(), "->", mxid)
+//}
func (portal *Portal) finishHandlingSkype(source *User, message *skype.Resource, mxid id.EventID) {
portal.markHandledSkype(source, message, mxid)
@@ -638,10 +633,10 @@ func (portal *Portal) SyncSkype(user *User, chat skype.Conversation) {
} else {
fmt.Println("SyncSkype ensureUserInvited", portal.MXID)
portal.ensureUserInvited(user)
- rep, err := portal.MainIntent().SetPowerLevel(portal.MXID, user.MXID, 95)
- if err != nil {
- portal.log.Warnfln("SyncSkype: SetPowerLevel err: ", err, rep)
- }
+ //rep, err := portal.MainIntent().SetPowerLevel(portal.MXID, user.MXID, 95)
+ //if err != nil {
+ // portal.log.Warnfln("SyncSkype: SetPowerLevel err: ", err, rep)
+ //}
//if portal.IsPrivateChat() {
// preUserIds,_ := portal.GetMatrixUsers()
@@ -776,7 +771,7 @@ func (portal *Portal) ChangeAdminStatus(jids []string, setAdmin bool) {
// UserID: member.MXID,
// })
// if err != nil {
-// portal.log.Errorln("Error %s member from whatsapp: %v", action, err)
+// portal.log.Errorln("Error %s member from skype: %v", action, err)
// }
// }
//}
@@ -786,13 +781,14 @@ func (portal *Portal) membershipRemove(content string) {
err := xml.Unmarshal([]byte(content), &xmlFormat)
for _, target := range xmlFormat.Targets {
member := portal.bridge.GetPuppetByJID(target)
-
- memberMaxid := strings.Replace(string(member.MXID), "@skype&8:", "@skype&8-", 1)
- _, err = portal.MainIntent().KickUser(portal.MXID, &mautrix.ReqKickUser{
- UserID: id.UserID(memberMaxid),
- })
- if err != nil {
- portal.log.Errorln("Error %v member from whatsapp:", err)
+ memberMXID := id.UserID(patch.Parse(string(member.MXID)))
+ if portal.bridge.AS.StateStore.IsInRoom(portal.MXID, memberMXID) {
+ _, err = portal.MainIntent().KickUser(portal.MXID, &mautrix.ReqKickUser{
+ UserID: member.MXID,
+ })
+ if err != nil {
+ portal.log.Errorln("Error kick member from matrix after kick from skype: %v", err)
+ }
}
}
}
@@ -1291,21 +1287,21 @@ func (portal *Portal) MainIntent() *appservice.IntentAPI {
return portal.bridge.Bot
}
-func (portal *Portal) SetReply(content *event.MessageEventContent, info whatsapp.ContextInfo) {
- if len(info.QuotedMessageID) == 0 {
- return
- }
- message := portal.bridge.DB.Message.GetByJID(portal.Key, info.QuotedMessageID)
- if message != nil {
- evt, err := portal.MainIntent().GetEvent(portal.MXID, message.MXID)
- if err != nil {
- portal.log.Warnln("Failed to get reply target:", err)
- return
- }
- content.SetReply(evt)
- }
- return
-}
+//func (portal *Portal) SetReply(content *event.MessageEventContent, info whatsapp.ContextInfo) {
+// if len(info.QuotedMessageID) == 0 {
+// return
+// }
+// message := portal.bridge.DB.Message.GetByJID(portal.Key, info.QuotedMessageID)
+// if message != nil {
+// evt, err := portal.MainIntent().GetEvent(portal.MXID, message.MXID)
+// if err != nil {
+// portal.log.Warnln("Failed to get reply target:", err)
+// return
+// }
+// content.SetReply(evt)
+// }
+// return
+//}
func (portal *Portal) SetReplySkype(content *event.MessageEventContent, info skype.Resource) {
if len(info.Id) == 0 {
@@ -1347,32 +1343,31 @@ func (portal *Portal) HandleMessageRevokeSkype(user *User, message skype.Resourc
msg.Delete()
}
-
-func (portal *Portal) HandleMessageRevoke(user *User, message whatsappExt.MessageRevocation) {
- msg := portal.bridge.DB.Message.GetByJID(portal.Key, message.Id)
- if msg == nil {
- return
- }
- var intent *appservice.IntentAPI
- if message.FromMe {
- if portal.IsPrivateChat() {
- intent = portal.bridge.GetPuppetByJID(user.JID).CustomIntent()
- } else {
- intent = portal.bridge.GetPuppetByJID(user.JID).IntentFor(portal)
- }
- } else if len(message.Participant) > 0 {
- intent = portal.bridge.GetPuppetByJID(message.Participant).IntentFor(portal)
- }
- if intent == nil {
- intent = portal.MainIntent()
- }
- _, err := intent.RedactEvent(portal.MXID, msg.MXID)
- if err != nil {
- portal.log.Errorln("Failed to redact %s: %v", msg.JID, err)
- return
- }
- msg.Delete()
-}
+//func (portal *Portal) HandleMessageRevoke(user *User, message whatsappExt.MessageRevocation) {
+// msg := portal.bridge.DB.Message.GetByJID(portal.Key, message.Id)
+// if msg == nil {
+// return
+// }
+// var intent *appservice.IntentAPI
+// if message.FromMe {
+// if portal.IsPrivateChat() {
+// intent = portal.bridge.GetPuppetByJID(user.JID).CustomIntent()
+// } else {
+// intent = portal.bridge.GetPuppetByJID(user.JID).IntentFor(portal)
+// }
+// } else if len(message.Participant) > 0 {
+// intent = portal.bridge.GetPuppetByJID(message.Participant).IntentFor(portal)
+// }
+// if intent == nil {
+// intent = portal.MainIntent()
+// }
+// _, err := intent.RedactEvent(portal.MXID, msg.MXID)
+// if err != nil {
+// portal.log.Errorln("Failed to redact %s: %v", msg.JID, err)
+// return
+// }
+// msg.Delete()
+//}
func (portal *Portal) HandleFakeMessage(source *User, message FakeMessage) {
if portal.isRecentlyHandled(message.ID) {
@@ -1484,13 +1479,12 @@ func (portal *Portal) HandleLocationMessageSkype(source *User, message skype.Res
geo := fmt.Sprintf("geo:%.6f,%.6f", float32(latitude)/1000000, float32(longitude)/1000000)
content := &event.MessageEventContent{
MsgType: event.MsgText,
- Body: fmt.Sprintf("Location: %s%s
", locationMessage.A.Href, locationMessage.Address, geo),
+ Body: fmt.Sprintf("Location: %s%s
\n", locationMessage.A.Href, locationMessage.Address, geo),
Format: event.FormatHTML,
- FormattedBody: fmt.Sprintf("Location: %s%s
", locationMessage.A.Href, locationMessage.Address, geo),
+ FormattedBody: fmt.Sprintf("Location: %s%s
\n", locationMessage.A.Href, locationMessage.Address, geo),
GeoURI: geo,
}
- //portal.SetReply(content, message.ContextInfo)
portal.SetReplySkype(content, message)
_, _ = intent.UserTyping(portal.MXID, false, 0)
@@ -1579,7 +1573,7 @@ func (portal *Portal) HandleMediaMessageSkype(source *User, download func(conn *
}
data, mediaMessage, err := download(source.Conn.Conn, mediaType)
- if err == whatsapp.ErrMediaDownloadFailedWith404 || err == whatsapp.ErrMediaDownloadFailedWith410 {
+ if err == skype.ErrMediaDownloadFailedWith404 || err == skype.ErrMediaDownloadFailedWith410 {
portal.log.Warnfln("Failed to download media for %s: %v. Calling LoadMediaInfo and retrying download...", info.Id, err)
//_, err = source.Conn.LoadMediaInfo(info.RemoteJid, info.Id, info.FromMe)
//if err != nil {
@@ -1588,7 +1582,7 @@ func (portal *Portal) HandleMediaMessageSkype(source *User, download func(conn *
//}
data, mediaMessage, err = download(source.Conn.Conn, mediaType)
}
- if err == whatsapp.ErrNoURLPresent {
+ if err == skype.ErrNoURLPresent {
portal.log.Debugfln("No URL present error for media message %s, ignoring...", info.Id)
return
} else if err != nil {
@@ -1819,54 +1813,6 @@ func (portal *Portal) preprocessMatrixMediaSkype(relaybotFormatted bool, content
return caption, uint64(len(data)), data
}
-func (portal *Portal) preprocessMatrixMedia(sender *User, relaybotFormatted bool, content *event.MessageEventContent, eventID id.EventID, mediaType whatsapp.MediaType) *MediaUpload {
- //var caption string
- //if relaybotFormatted {
- // caption = portal.bridge.Formatter.ParseMatrix(content.FormattedBody)
- //}
-
- var file *event.EncryptedFileInfo
- rawMXC := content.URL
- if content.File != nil {
- file = content.File
- rawMXC = file.URL
- }
- mxc, err := rawMXC.Parse()
- if err != nil {
- portal.log.Errorln("Malformed content URL in %s: %v", eventID, err)
- return nil
- }
- data, err := portal.MainIntent().DownloadBytes(mxc)
- if err != nil {
- portal.log.Errorfln("Failed to download media in %s: %v", eventID, err)
- return nil
- }
- if file != nil {
- data, err = file.Decrypt(data)
- if err != nil {
- portal.log.Errorfln("Failed to decrypt media in %s: %v", eventID, err)
- return nil
- }
- }
-
- //url, mediaKey, fileEncSHA256, fileSHA256, fileLength, err := sender.Conn.Upload(bytes.NewReader(data), mediaType)
- //if err != nil {
- // portal.log.Errorfln("Failed to upload media in %s: %v", eventID, err)
- // return nil
- //}
- //
- //return &MediaUpload{
- // Caption: caption,
- // URL: url,
- // MediaKey: mediaKey,
- // FileEncSHA256: fileEncSHA256,
- // FileSHA256: fileSHA256,
- // FileLength: fileLength,
- // Thumbnail: portal.downloadThumbnail(content, eventID),
- //}
- return nil
-}
-
type MediaUpload struct {
Caption string
URL string
@@ -2098,145 +2044,6 @@ func (portal *Portal) convertMatrixMessageSkype(sender *User, evt *event.Event)
return info, sender, content
}
-func (portal *Portal) convertMatrixMessage(sender *User, evt *event.Event) (*waProto.WebMessageInfo, *User, *event.MessageEventContent) {
- content, ok := evt.Content.Parsed.(*event.MessageEventContent)
- if !ok {
- portal.log.Debugfln("Failed to handle event %s: unexpected parsed content type %T", evt.ID, evt.Content.Parsed)
- return nil, sender, content
- }
-
- ts := uint64(evt.Timestamp / 1000)
- status := waProto.WebMessageInfo_ERROR
- fromMe := true
- info := &waProto.WebMessageInfo{
- Key: &waProto.MessageKey{
- FromMe: &fromMe,
- Id: makeMessageID(),
- RemoteJid: &portal.Key.JID,
- },
- MessageTimestamp: &ts,
- Message: &waProto.Message{},
- Status: &status,
- }
- //ctxInfo := &waProto.ContextInfo{}
- replyToID := content.GetReplyTo()
- if len(replyToID) > 0 {
- content.RemoveReplyFallback()
- msg := portal.bridge.DB.Message.GetByMXID(replyToID)
- //if msg != nil && msg.Content != nil {
- if msg != nil {
- //ctxInfo.StanzaId = &msg.JID
- //ctxInfo.Participant = &msg.Sender
- //ctxInfo.QuotedMessage = msg.Content
- }
- }
- relaybotFormatted := false
- if sender.NeedsRelaybot(portal) {
- if !portal.HasRelaybot() {
- if sender.HasSession() {
- portal.log.Debugln("Database says", sender.MXID, "not in chat and no relaybot, but trying to send anyway")
- } else {
- portal.log.Debugln("Ignoring message from", sender.MXID, "in chat with no relaybot")
- return nil, sender, content
- }
- } else {
- relaybotFormatted = portal.addRelaybotFormat(sender, content)
- sender = portal.bridge.Relaybot
- }
- }
- if evt.Type == event.EventSticker {
- content.MsgType = event.MsgImage
- }
-fmt.Println("convertMatrixMessage content.MsgType: ", content.MsgType)
- switch content.MsgType {
- case event.MsgText, event.MsgEmote, event.MsgNotice:
- text := content.Body
- if content.Format == event.FormatHTML {
- text = portal.bridge.Formatter.ParseMatrix(content.FormattedBody)
- }
- if content.MsgType == event.MsgEmote && !relaybotFormatted {
- text = "/me " + text
- }
- //ctxInfo.MentionedJid = mentionRegex.FindAllString(text, -1)
- //for index, mention := range ctxInfo.MentionedJid {
- // ctxInfo.MentionedJid[index] = mention[1:] + whatsappExt.NewUserSuffix
- //}
- //if ctxInfo.StanzaId != nil || ctxInfo.MentionedJid != nil {
- // info.Message.ExtendedTextMessage = &waProto.ExtendedTextMessage{
- // Text: &text,
- // ContextInfo: ctxInfo,
- // }
- //} else {
- // info.Message.Conversation = &text
- //}
- case event.MsgImage:
- media := portal.preprocessMatrixMedia(sender, relaybotFormatted, content, evt.ID, whatsapp.MediaImage)
- if media == nil {
- return nil, sender, content
- }
- info.Message.ImageMessage = &waProto.ImageMessage{
- Caption: &media.Caption,
- JpegThumbnail: media.Thumbnail,
- Url: &media.URL,
- MediaKey: media.MediaKey,
- Mimetype: &content.GetInfo().MimeType,
- FileEncSha256: media.FileEncSHA256,
- FileSha256: media.FileSHA256,
- FileLength: &media.FileLength,
- }
- case event.MsgVideo:
- media := portal.preprocessMatrixMedia(sender, relaybotFormatted, content, evt.ID, whatsapp.MediaVideo)
- if media == nil {
- return nil, sender, content
- }
- duration := uint32(content.GetInfo().Duration)
- info.Message.VideoMessage = &waProto.VideoMessage{
- Caption: &media.Caption,
- JpegThumbnail: media.Thumbnail,
- Url: &media.URL,
- MediaKey: media.MediaKey,
- Mimetype: &content.GetInfo().MimeType,
- Seconds: &duration,
- FileEncSha256: media.FileEncSHA256,
- FileSha256: media.FileSHA256,
- FileLength: &media.FileLength,
- }
- case event.MsgAudio:
- media := portal.preprocessMatrixMedia(sender, relaybotFormatted, content, evt.ID, whatsapp.MediaAudio)
- if media == nil {
- return nil, sender, content
- }
- duration := uint32(content.GetInfo().Duration)
- info.Message.AudioMessage = &waProto.AudioMessage{
- Url: &media.URL,
- MediaKey: media.MediaKey,
- Mimetype: &content.GetInfo().MimeType,
- Seconds: &duration,
- FileEncSha256: media.FileEncSHA256,
- FileSha256: media.FileSHA256,
- FileLength: &media.FileLength,
- }
- case event.MsgFile:
- media := portal.preprocessMatrixMedia(sender, relaybotFormatted, content, evt.ID, whatsapp.MediaDocument)
- if media == nil {
- return nil, sender, content
- }
- info.Message.DocumentMessage = &waProto.DocumentMessage{
- Url: &media.URL,
- FileName: &content.Body,
- MediaKey: media.MediaKey,
- Mimetype: &content.GetInfo().MimeType,
- FileEncSha256: media.FileEncSHA256,
- FileSha256: media.FileSHA256,
- FileLength: &media.FileLength,
- }
- default:
- portal.log.Debugln("Unhandled Matrix event %s: unknown msgtype %s", evt.ID, content.MsgType)
- return nil, sender, content
- }
- return info, sender, content
-}
-
func (portal *Portal) wasMessageSent(sender *User, id string) bool {
//_, err := sender.Conn.LoadMessagesAfter(portal.Key.JID, id, true, 0)
//if err != nil {
@@ -2512,32 +2319,27 @@ func (portal *Portal) HandleMatrixLeave(sender *User) {
}
func (portal *Portal) HandleMatrixKick(sender *User, evt *event.Event) {
- number, _:= portal.bridge.ParsePuppetMXID(id.UserID(evt.GetStateKey()))
- puppet := portal.bridge.GetPuppetByMXID(id.UserID(evt.GetStateKey()))
- fmt.Println("HandleMatrixKick", puppet)
+ jid, _:= portal.bridge.ParsePuppetMXID(id.UserID(evt.GetStateKey()))
+ puppet := portal.bridge.GetPuppetByJID(jid)
if puppet != nil {
- number = strings.Replace(number, skypeExt.NewUserSuffix, "", 1)
- err := sender.Conn.HandleGroupKick(portal.Key.JID, []string{number})
+ jid = strings.Replace(jid, skypeExt.NewUserSuffix, "", 1)
+ err := sender.Conn.HandleGroupKick(portal.Key.JID, []string{jid})
if err != nil {
portal.log.Errorfln("Failed to kick %s from group as %s: %v", puppet.JID, sender.MXID, err)
return
}
- //portal.log.Infoln("Kick %s response: %s", puppet.JID, <-resp)
}
}
func (portal *Portal) HandleMatrixInvite(sender *User, evt *event.Event) {
- number, _:= portal.bridge.ParsePuppetMXID(id.UserID(evt.GetStateKey()))
- puppet := portal.bridge.GetPuppetByMXID(id.UserID(evt.GetStateKey()))
- fmt.Println("HandleMatrixInvite", puppet)
+ jid, _:= portal.bridge.ParsePuppetMXID(id.UserID(evt.GetStateKey()))
+ puppet := portal.bridge.GetPuppetByJID(jid)
if puppet != nil {
- number = strings.Replace(number, "8:", "", 1)
- number = strings.Replace(number, skypeExt.NewUserSuffix, "", 1)
- err := sender.Conn.HandleGroupInvite(portal.Key.JID, []string{number})
+ jid = strings.Replace(jid, skypeExt.NewUserSuffix, "", 1)
+ err := sender.Conn.HandleGroupInvite(portal.Key.JID, []string{jid})
if err != nil {
portal.log.Errorfln("Failed to add %s to group as %s: %v", puppet.JID, sender.MXID, err)
return
}
- //portal.log.Infoln("Add %s response: %s", puppet.JID, <-resp)
}
}
diff --git a/puppet.go b/puppet.go
index 31543dd..15bdfdc 100644
--- a/puppet.go
+++ b/puppet.go
@@ -15,7 +15,7 @@ import (
"github.com/kelaresg/matrix-skype/database"
"github.com/kelaresg/matrix-skype/types"
- "github.com/kelaresg/matrix-skype/whatsapp-ext"
+ //"github.com/kelaresg/matrix-skype/whatsapp-ext"
)
func (bridge *Bridge) ParsePuppetMXID(mxid id.UserID) (types.SkypeID, bool) {
@@ -134,10 +134,8 @@ func (bridge *Bridge) NewPuppet(dbPuppet *database.Puppet) *Puppet {
MXID: id.NewUserID(
bridge.Config.Bridge.FormatUsername(
- // dbPuppet.JID,
- //),
strings.Replace(
- strings.Replace(dbPuppet.JID, whatsappExt.NewUserSuffix, "", 1),
+ strings.Replace(dbPuppet.JID, skypeExt.NewUserSuffix, "", 1),
":",
"-",
-1,
@@ -164,7 +162,7 @@ type Puppet struct {
}
func (puppet *Puppet) PhoneNumber() string {
- return strings.Replace(puppet.JID, whatsappExt.NewUserSuffix, "", 1)
+ return strings.Replace(puppet.JID, skypeExt.NewUserSuffix, "", 1)
}
func (puppet *Puppet) IntentFor(portal *Portal) *appservice.IntentAPI {
@@ -272,7 +270,7 @@ func (puppet *Puppet) UpdateName(source *User, contact skype.Contact) bool {
func (puppet *Puppet) updatePortalMeta(meta func(portal *Portal)) {
if puppet.bridge.Config.Bridge.PrivateChatPortalMeta {
- jid := strings.Replace(puppet.JID, whatsappExt.NewUserSuffix, "", 1)
+ jid := strings.Replace(puppet.JID, skypeExt.NewUserSuffix, "", 1)
for _, portal := range puppet.bridge.GetAllPortalsByJID(jid) {
meta(portal)
}
diff --git a/skype-ext/chat.go b/skype-ext/chat.go
index 70453dd..28845e4 100644
--- a/skype-ext/chat.go
+++ b/skype-ext/chat.go
@@ -18,9 +18,8 @@ package skypeExt
import (
"encoding/json"
+ skype "github.com/kelaresg/go-skypeapi"
"strings"
-
- "github.com/Rhymen/go-whatsapp"
)
type ChatUpdateCommand string
@@ -155,7 +154,7 @@ func (cud *ChatUpdateData) UnmarshalJSON(data []byte) error {
}
type ChatUpdateHandler interface {
- whatsapp.Handler
+ skype.Handler
HandleChatUpdate(ChatUpdate)
}
diff --git a/skype-ext/cmd.go b/skype-ext/cmd.go
index fcbda17..75ef250 100644
--- a/skype-ext/cmd.go
+++ b/skype-ext/cmd.go
@@ -18,9 +18,8 @@ package skypeExt
import (
"encoding/json"
+ skype "github.com/kelaresg/go-skypeapi"
"strings"
-
- "github.com/Rhymen/go-whatsapp"
)
type CommandType string
@@ -41,7 +40,7 @@ type Command struct {
}
type CommandHandler interface {
- whatsapp.Handler
+ skype.Handler
HandleCommand(Command)
}
diff --git a/skype-ext/userid.go b/skype-ext/userid.go
deleted file mode 100644
index 2150b97..0000000
--- a/skype-ext/userid.go
+++ /dev/null
@@ -1,154 +0,0 @@
-package skypeExt
-
-import (
- "bytes"
- "encoding/hex"
- "fmt"
- "strings"
-)
-
-// UserID represents a Matrix user ID.
-// https://matrix.org/docs/spec/appendices#user-identifiers
-type UserID string
-
-func NewUserID(localpart, homeserver string) UserID {
- return UserID(fmt.Sprintf("@%s:%s", localpart, homeserver))
-}
-
-func NewEncodedUserID(localpart, homeserver string) UserID {
- return NewUserID(EncodeUserLocalpart(localpart), homeserver)
-}
-
-// Parse parses the user ID into the localpart and server name.
-// See http://matrix.org/docs/spec/intro.html#user-identifiers
-func (userID UserID) Parse() (localpart, homeserver string, err error) {
- if len(userID) == 0 || userID[0] != '@' || !strings.ContainsRune(string(userID), ':') {
- err = fmt.Errorf("%s is not a valid user id", userID)
- return
- }
- parts := strings.SplitN(string(userID), ":", 2)
- localpart, homeserver = strings.TrimPrefix(parts[0], "@"), parts[1]
- return
-}
-
-func (userID UserID) ParseAndDecode() (localpart, homeserver string, err error) {
- localpart, homeserver, err = userID.Parse()
- if err == nil {
- localpart, err = DecodeUserLocalpart(localpart)
- }
- return
-}
-
-func (userID UserID) String() string {
- return string(userID)
-}
-
-const lowerhex = "0123456789abcdef"
-
-// encode the given byte using quoted-printable encoding (e.g "=2f")
-// and writes it to the buffer
-// See https://golang.org/src/mime/quotedprintable/writer.go
-func encode(buf *bytes.Buffer, b byte) {
- buf.WriteByte('=')
- buf.WriteByte(lowerhex[b>>4])
- buf.WriteByte(lowerhex[b&0x0f])
-}
-
-// escape the given alpha character and writes it to the buffer
-func escape(buf *bytes.Buffer, b byte) {
- buf.WriteByte('_')
- if b == '_' {
- buf.WriteByte('_') // another _
- } else {
- buf.WriteByte(b + 0x20) // ASCII shift A-Z to a-z
- }
-}
-
-func shouldEncode(b byte) bool {
- return b != '-' && b != '.' && b != '_' && !(b >= '0' && b <= '9') && !(b >= 'a' && b <= 'z') && !(b >= 'A' && b <= 'Z')
-}
-
-func shouldEscape(b byte) bool {
- return (b >= 'A' && b <= 'Z') || b == '_'
-}
-
-func isValidByte(b byte) bool {
- return isValidEscapedChar(b) || (b >= '0' && b <= '9') || b == '.' || b == '=' || b == '-'
-}
-
-func isValidEscapedChar(b byte) bool {
- return b == '_' || (b >= 'a' && b <= 'z')
-}
-
-// EncodeUserLocalpart encodes the given string into Matrix-compliant user ID localpart form.
-// See http://matrix.org/docs/spec/intro.html#mapping-from-other-character-sets
-//
-// This returns a string with only the characters "a-z0-9._=-". The uppercase range A-Z
-// are encoded using leading underscores ("_"). Characters outside the aforementioned ranges
-// (including literal underscores ("_") and equals ("=")) are encoded as UTF8 code points (NOT NCRs)
-// and converted to lower-case hex with a leading "=". For example:
-// Alph@Bet_50up => _alph=40_bet=5f50up
-func EncodeUserLocalpart(str string) string {
- strBytes := []byte(str)
- var outputBuffer bytes.Buffer
- for _, b := range strBytes {
- if shouldEncode(b) {
- encode(&outputBuffer, b)
- } else if shouldEscape(b) {
- escape(&outputBuffer, b)
- } else {
- outputBuffer.WriteByte(b)
- }
- }
- return outputBuffer.String()
-}
-
-// DecodeUserLocalpart decodes the given string back into the original input string.
-// Returns an error if the given string is not a valid user ID localpart encoding.
-// See http://matrix.org/docs/spec/intro.html#mapping-from-other-character-sets
-//
-// This decodes quoted-printable bytes back into UTF8, and unescapes casing. For
-// example:
-// _alph=40_bet=5f50up => Alph@Bet_50up
-// Returns an error if the input string contains characters outside the
-// range "a-z0-9._=-", has an invalid quote-printable byte (e.g. not hex), or has
-// an invalid _ escaped byte (e.g. "_5").
-func DecodeUserLocalpart(str string) (string, error) {
- strBytes := []byte(str)
- var outputBuffer bytes.Buffer
- for i := 0; i < len(strBytes); i++ {
- b := strBytes[i]
- if !isValidByte(b) {
- return "", fmt.Errorf("Byte pos %d: Invalid byte", i)
- }
-
- if b == '_' { // next byte is a-z and should be upper-case or is another _ and should be a literal _
- if i+1 >= len(strBytes) {
- return "", fmt.Errorf("Byte pos %d: expected _[a-z_] encoding but ran out of string", i)
- }
- if !isValidEscapedChar(strBytes[i+1]) { // invalid escaping
- return "", fmt.Errorf("Byte pos %d: expected _[a-z_] encoding", i)
- }
- if strBytes[i+1] == '_' {
- outputBuffer.WriteByte('_')
- } else {
- outputBuffer.WriteByte(strBytes[i+1] - 0x20) // ASCII shift a-z to A-Z
- }
- i++ // skip next byte since we just handled it
- } else if b == '=' { // next 2 bytes are hex and should be buffered ready to be read as utf8
- if i+2 >= len(strBytes) {
- return "", fmt.Errorf("Byte pos: %d: expected quote-printable encoding but ran out of string", i)
- }
- dst := make([]byte, 1)
- _, err := hex.Decode(dst, strBytes[i+1:i+3])
- if err != nil {
- return "", err
- }
- outputBuffer.WriteByte(dst[0])
- i += 2 // skip next 2 bytes since we just handled it
- } else { // pass through
- outputBuffer.WriteByte(b)
- }
- }
- return outputBuffer.String(), nil
-}
diff --git a/user.go b/user.go
index f567ffe..216e94d 100644
--- a/user.go
+++ b/user.go
@@ -12,20 +12,20 @@ import (
"sync"
"time"
- "github.com/pkg/errors"
+ //"github.com/pkg/errors"
"github.com/skip2/go-qrcode"
log "maunium.net/go/maulogger/v2"
"maunium.net/go/mautrix"
- "github.com/Rhymen/go-whatsapp"
- waProto "github.com/Rhymen/go-whatsapp/binary/proto"
+ //"github.com/Rhymen/go-whatsapp"
+ //waProto "github.com/Rhymen/go-whatsapp/binary/proto"
"maunium.net/go/mautrix/event"
"maunium.net/go/mautrix/id"
"github.com/kelaresg/matrix-skype/database"
"github.com/kelaresg/matrix-skype/types"
- "github.com/kelaresg/matrix-skype/whatsapp-ext"
+ //"github.com/kelaresg/matrix-skype/whatsapp-ext"
)
type User struct {
@@ -183,7 +183,7 @@ func (user *User) GetManagementRoom() id.RoomID {
return user.ManagementRoom
}
resp, err := user.bridge.Bot.CreateRoom(&mautrix.ReqCreateRoom{
- Topic: "WhatsApp bridge notices",
+ Topic: "Skype bridge notices",
IsDirect: true,
})
if err != nil {
@@ -587,13 +587,13 @@ func (user *User) syncPortals(chatMap map[string]skype.Conversation, createAll b
}
}
-func (user *User) HandleContactList(contacts []whatsapp.Contact) {
- contactMap := make(map[string]whatsapp.Contact)
- for _, contact := range contacts {
- contactMap[contact.Jid] = contact
- }
- // go user.syncPuppets(contactMap)
-}
+//func (user *User) HandleContactList(contacts []whatsapp.Contact) {
+// contactMap := make(map[string]whatsapp.Contact)
+// for _, contact := range contacts {
+// contactMap[contact.Jid] = contact
+// }
+// // go user.syncPuppets(contactMap)
+//}
func (user *User) syncPuppets(contacts map[string]skype.Contact) {
if contacts == nil {
@@ -636,20 +636,6 @@ func (user *User) updateLastConnectionIfNecessary() {
}
func (user *User) HandleError(err error) {
- if errors.Cause(err) != whatsapp.ErrInvalidWsData {
- user.log.Errorfln("WhatsApp error: %v", err)
- }
- if closed, ok := err.(*whatsapp.ErrConnectionClosed); ok {
- if closed.Code == 1000 && user.cleanDisconnection {
- user.cleanDisconnection = false
- user.log.Infoln("Clean disconnection by server")
- return
- }
- go user.tryReconnect(fmt.Sprintf("Your WhatsApp connection was closed with websocket status code %d", closed.Code))
- } else if failed, ok := err.(*whatsapp.ErrConnectionFailed); ok {
- user.ConnectionErrors++
- go user.tryReconnect(fmt.Sprintf("Your WhatsApp connection failed: %v", failed.Err))
- }
// Otherwise unknown error, probably mostly harmless
}
@@ -762,21 +748,21 @@ func (user *User) HandleImageMessage(message skype.Resource) {
user.putMessage(PortalMessage{message.Jid, user, message, uint64(message.Timestamp)})
}
-func (user *User) HandleStickerMessage(message whatsapp.StickerMessage) {
- user.putMessage(PortalMessage{message.Info.RemoteJid, user, message, message.Info.Timestamp})
-}
-
-func (user *User) HandleVideoMessage(message whatsapp.VideoMessage) {
- user.putMessage(PortalMessage{message.Info.RemoteJid, user, message, message.Info.Timestamp})
-}
-
-func (user *User) HandleAudioMessage(message whatsapp.AudioMessage) {
- user.putMessage(PortalMessage{message.Info.RemoteJid, user, message, message.Info.Timestamp})
-}
-
-func (user *User) HandleDocumentMessage(message whatsapp.DocumentMessage) {
- user.putMessage(PortalMessage{message.Info.RemoteJid, user, message, message.Info.Timestamp})
-}
+//func (user *User) HandleStickerMessage(message whatsapp.StickerMessage) {
+// user.putMessage(PortalMessage{message.Info.RemoteJid, user, message, message.Info.Timestamp})
+//}
+//
+//func (user *User) HandleVideoMessage(message whatsapp.VideoMessage) {
+// user.putMessage(PortalMessage{message.Info.RemoteJid, user, message, message.Info.Timestamp})
+//}
+//
+//func (user *User) HandleAudioMessage(message whatsapp.AudioMessage) {
+// user.putMessage(PortalMessage{message.Info.RemoteJid, user, message, message.Info.Timestamp})
+//}
+//
+//func (user *User) HandleDocumentMessage(message whatsapp.DocumentMessage) {
+// user.putMessage(PortalMessage{message.Info.RemoteJid, user, message, message.Info.Timestamp})
+//}
func (user *User) HandleContactMessage(message skype.Resource) {
user.log.Debugf("HandleContactMessage: ", message)
@@ -798,40 +784,40 @@ type FakeMessage struct {
Alert bool
}
-func (user *User) HandleCallInfo(info whatsappExt.CallInfo) {
- if info.Data != nil {
- return
- }
- data := FakeMessage{
- ID: info.ID,
- }
- switch info.Type {
- case whatsappExt.CallOffer:
- if !user.bridge.Config.Bridge.CallNotices.Start {
- return
- }
- data.Text = "Incoming call"
- data.Alert = true
- case whatsappExt.CallOfferVideo:
- if !user.bridge.Config.Bridge.CallNotices.Start {
- return
- }
- data.Text = "Incoming video call"
- data.Alert = true
- case whatsappExt.CallTerminate:
- if !user.bridge.Config.Bridge.CallNotices.End {
- return
- }
- data.Text = "Call ended"
- data.ID += "E"
- default:
- return
- }
- portal := user.GetPortalByJID(info.From)
- if portal != nil {
- portal.messages <- PortalMessage{info.From, user, data, 0}
- }
-}
+//func (user *User) HandleCallInfo(info whatsappExt.CallInfo) {
+// if info.Data != nil {
+// return
+// }
+// data := FakeMessage{
+// ID: info.ID,
+// }
+// switch info.Type {
+// case whatsappExt.CallOffer:
+// if !user.bridge.Config.Bridge.CallNotices.Start {
+// return
+// }
+// data.Text = "Incoming call"
+// data.Alert = true
+// case whatsappExt.CallOfferVideo:
+// if !user.bridge.Config.Bridge.CallNotices.Start {
+// return
+// }
+// data.Text = "Incoming video call"
+// data.Alert = true
+// case whatsappExt.CallTerminate:
+// if !user.bridge.Config.Bridge.CallNotices.End {
+// return
+// }
+// data.Text = "Call ended"
+// data.ID += "E"
+// default:
+// return
+// }
+// portal := user.GetPortalByJID(info.From)
+// if portal != nil {
+// portal.messages <- PortalMessage{info.From, user, data, 0}
+// }
+//}
func (user *User) HandleTypingStatus(info skype.Resource) {
sendId := info.SendId + skypeExt.NewUserSuffix
@@ -904,62 +890,62 @@ func (user *User) HandlePresence(info skype.Resource) {
}
}
-func (user *User) HandlePresenceWA(info whatsappExt.Presence) {
- puppet := user.bridge.GetPuppetByJID(info.SenderJID)
- switch info.Status {
- case whatsapp.PresenceUnavailable:
- _ = puppet.DefaultIntent().SetPresence("offline")
- case whatsapp.PresenceAvailable:
- if len(puppet.typingIn) > 0 && puppet.typingAt+15 > time.Now().Unix() {
- portal := user.bridge.GetPortalByMXID(puppet.typingIn)
- _, _ = puppet.IntentFor(portal).UserTyping(puppet.typingIn, false, 0)
- puppet.typingIn = ""
- puppet.typingAt = 0
- }
- _ = puppet.DefaultIntent().SetPresence("online")
- case whatsapp.PresenceComposing:
- portal := user.GetPortalByJID(info.JID)
- if len(puppet.typingIn) > 0 && puppet.typingAt+15 > time.Now().Unix() {
- if puppet.typingIn == portal.MXID {
- return
- }
- _, _ = puppet.IntentFor(portal).UserTyping(puppet.typingIn, false, 0)
- }
- puppet.typingIn = portal.MXID
- puppet.typingAt = time.Now().Unix()
- _, _ = puppet.IntentFor(portal).UserTyping(portal.MXID, true, 15*1000)
- _ = puppet.DefaultIntent().SetPresence("online")
- }
-}
+//func (user *User) HandlePresenceWA(info whatsappExt.Presence) {
+// puppet := user.bridge.GetPuppetByJID(info.SenderJID)
+// switch info.Status {
+// case whatsapp.PresenceUnavailable:
+// _ = puppet.DefaultIntent().SetPresence("offline")
+// case whatsapp.PresenceAvailable:
+// if len(puppet.typingIn) > 0 && puppet.typingAt+15 > time.Now().Unix() {
+// portal := user.bridge.GetPortalByMXID(puppet.typingIn)
+// _, _ = puppet.IntentFor(portal).UserTyping(puppet.typingIn, false, 0)
+// puppet.typingIn = ""
+// puppet.typingAt = 0
+// }
+// _ = puppet.DefaultIntent().SetPresence("online")
+// case whatsapp.PresenceComposing:
+// portal := user.GetPortalByJID(info.JID)
+// if len(puppet.typingIn) > 0 && puppet.typingAt+15 > time.Now().Unix() {
+// if puppet.typingIn == portal.MXID {
+// return
+// }
+// _, _ = puppet.IntentFor(portal).UserTyping(puppet.typingIn, false, 0)
+// }
+// puppet.typingIn = portal.MXID
+// puppet.typingAt = time.Now().Unix()
+// _, _ = puppet.IntentFor(portal).UserTyping(portal.MXID, true, 15*1000)
+// _ = puppet.DefaultIntent().SetPresence("online")
+// }
+//}
-func (user *User) HandleMsgInfo(info whatsappExt.MsgInfo) {
- if (info.Command == whatsappExt.MsgInfoCommandAck || info.Command == whatsappExt.MsgInfoCommandAcks) && info.Acknowledgement == whatsappExt.AckMessageRead {
- portal := user.GetPortalByJID(info.ToJID)
- if len(portal.MXID) == 0 {
- return
- }
-
- go func() {
- intent := user.bridge.GetPuppetByJID(info.SenderJID).IntentFor(portal)
- for _, id := range info.IDs {
- msg := user.bridge.DB.Message.GetByJID(portal.Key, id)
- if msg == nil {
- continue
- }
-
- err := intent.MarkRead(portal.MXID, msg.MXID)
- if err != nil {
- user.log.Warnln("Failed to mark message %s as read by %s: %v", msg.MXID, info.SenderJID, err)
- }
- }
- }()
- }
-}
+//func (user *User) HandleMsgInfo(info whatsappExt.MsgInfo) {
+// if (info.Command == whatsappExt.MsgInfoCommandAck || info.Command == whatsappExt.MsgInfoCommandAcks) && info.Acknowledgement == whatsappExt.AckMessageRead {
+// portal := user.GetPortalByJID(info.ToJID)
+// if len(portal.MXID) == 0 {
+// return
+// }
+//
+// go func() {
+// intent := user.bridge.GetPuppetByJID(info.SenderJID).IntentFor(portal)
+// for _, id := range info.IDs {
+// msg := user.bridge.DB.Message.GetByJID(portal.Key, id)
+// if msg == nil {
+// continue
+// }
+//
+// err := intent.MarkRead(portal.MXID, msg.MXID)
+// if err != nil {
+// user.log.Warnln("Failed to mark message %s as read by %s: %v", msg.MXID, info.SenderJID, err)
+// }
+// }
+// }()
+// }
+//}
func (user *User) HandleCommand(cmd skypeExt.Command) {
switch cmd.Type {
case skypeExt.CommandPicture:
- if strings.HasSuffix(cmd.JID, whatsappExt.NewUserSuffix) {
+ if strings.HasSuffix(cmd.JID, skypeExt.NewUserSuffix) {
puppet := user.bridge.GetPuppetByJID(cmd.JID)
go puppet.UpdateAvatar(user, cmd.ProfilePicInfo)
} else {
@@ -1145,9 +1131,9 @@ func (user *User) HandleJsonMessage(message string) {
user.updateLastConnectionIfNecessary()
}
-func (user *User) HandleRawMessage(message *waProto.WebMessageInfo) {
- user.updateLastConnectionIfNecessary()
-}
+//func (user *User) HandleRawMessage(message *waProto.WebMessageInfo) {
+// user.updateLastConnectionIfNecessary()
+//}
func (user *User) NeedsRelaybot(portal *Portal) bool {
return false
diff --git a/whatsapp-ext/call.go b/whatsapp-ext/call.go
deleted file mode 100644
index 29575c3..0000000
--- a/whatsapp-ext/call.go
+++ /dev/null
@@ -1,72 +0,0 @@
-// matrix-skype - 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 .
-
-package whatsappExt
-
-import (
- "encoding/json"
- "strings"
-
- "github.com/Rhymen/go-whatsapp"
-)
-
-type CallInfoType string
-
-const (
- CallOffer CallInfoType = "offer"
- CallOfferVideo CallInfoType = "offer_video"
- CallTransport CallInfoType = "transport"
- CallRelayLatency CallInfoType = "relaylatency"
- CallTerminate CallInfoType = "terminate"
-)
-
-type CallInfo struct {
- ID string `json:"id"`
- Type CallInfoType `json:"type"`
- From string `json:"from"`
-
- Platform string `json:"platform"`
- Version []int `json:"version"`
-
- Data [][]interface{} `json:"data"`
-}
-
-type CallInfoHandler interface {
- whatsapp.Handler
- HandleCallInfo(CallInfo)
-}
-
-func (ext *ExtendedConn) handleMessageCall(message []byte) {
- var event CallInfo
- err := json.Unmarshal(message, &event)
- if err != nil {
- ext.jsonParseError(err)
- return
- }
- event.From = strings.Replace(event.From, OldUserSuffix, NewUserSuffix, 1)
- for _, handler := range ext.handlers {
- callInfoHandler, ok := handler.(CallInfoHandler)
- if !ok {
- continue
- }
-
- if ext.shouldCallSynchronously(callInfoHandler) {
- callInfoHandler.HandleCallInfo(event)
- } else {
- go callInfoHandler.HandleCallInfo(event)
- }
- }
-}
diff --git a/whatsapp-ext/chat.go b/whatsapp-ext/chat.go
deleted file mode 100644
index 8de0a99..0000000
--- a/whatsapp-ext/chat.go
+++ /dev/null
@@ -1,174 +0,0 @@
-// matrix-skype - 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 .
-
-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"
- ChatActionRemove ChatActionType = "remove"
- ChatActionAdd ChatActionType = "add"
- ChatActionIntroduce ChatActionType = "introduce"
- ChatActionCreate ChatActionType = "create"
-)
-
-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"`
- }
-
- RemoveTopic struct {
- ID string `json:"descId"`
- }
-
- Restrict bool
-
- Announce bool
-
- PermissionChange struct {
- JIDs []string `json:"participants"`
- }
-
- MemberAction struct {
- JIDs []string `json:"participants"`
- }
-
- Create struct {
- Creation int64 `json:"creation"`
- Name string `json:"subject"`
- SetAt int64 `json:"s_t"`
- SetBy string `json:"s_o"`
- Admins []string `json:"admins"`
- SuperAdmins []string `json:"superadmins"`
- Regulars []string `json:"regulars"`
- }
-}
-
-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 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:
- unmarshalTo = &cud.PermissionChange
- case ChatActionAdd, ChatActionRemove:
- unmarshalTo = &cud.MemberAction
- case ChatActionCreate:
- unmarshalTo = &cud.Create
- 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.PermissionChange.JIDs {
- cud.PermissionChange.JIDs[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)
- }
- }
-}
diff --git a/whatsapp-ext/cmd.go b/whatsapp-ext/cmd.go
deleted file mode 100644
index 0954df3..0000000
--- a/whatsapp-ext/cmd.go
+++ /dev/null
@@ -1,69 +0,0 @@
-// matrix-skype - 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 .
-
-package whatsappExt
-
-import (
- "encoding/json"
- "strings"
-
- "github.com/Rhymen/go-whatsapp"
-)
-
-type CommandType string
-
-const (
- CommandPicture CommandType = "picture"
- CommandDisconnect CommandType = "disconnect"
-)
-
-type Command struct {
- Type CommandType `json:"type"`
- JID string `json:"jid"`
-
- *ProfilePicInfo
- Kind string `json:"kind"`
-
- Raw json.RawMessage `json:"-"`
-}
-
-type CommandHandler interface {
- whatsapp.Handler
- HandleCommand(Command)
-}
-
-func (ext *ExtendedConn) handleMessageCommand(message []byte) {
- var event Command
- err := json.Unmarshal(message, &event)
- if err != nil {
- ext.jsonParseError(err)
- return
- }
- event.Raw = message
- event.JID = strings.Replace(event.JID, OldUserSuffix, NewUserSuffix, 1)
- for _, handler := range ext.handlers {
- commandHandler, ok := handler.(CommandHandler)
- if !ok {
- continue
- }
-
- if ext.shouldCallSynchronously(commandHandler) {
- commandHandler.HandleCommand(event)
- } else {
- go commandHandler.HandleCommand(event)
- }
- }
-}
diff --git a/whatsapp-ext/conn.go b/whatsapp-ext/conn.go
deleted file mode 100644
index 8ce4345..0000000
--- a/whatsapp-ext/conn.go
+++ /dev/null
@@ -1,65 +0,0 @@
-// matrix-skype - 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 .
-
-package whatsappExt
-
-import (
- "encoding/json"
-
- "github.com/Rhymen/go-whatsapp"
-)
-
-type ConnInfo struct {
- ProtocolVersion []int `json:"protoVersion"`
- BinaryVersion int `json:"binVersion"`
- Phone struct {
- WhatsAppVersion string `json:"wa_version"`
- MCC string `json:"mcc"`
- MNC string `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
- }
-
- if ext.shouldCallSynchronously(connInfoHandler) {
- connInfoHandler.HandleConnInfo(event)
- } else {
- go connInfoHandler.HandleConnInfo(event)
- }
- }
-}
diff --git a/whatsapp-ext/jsonmessage.go b/whatsapp-ext/jsonmessage.go
deleted file mode 100644
index e0ac474..0000000
--- a/whatsapp-ext/jsonmessage.go
+++ /dev/null
@@ -1,105 +0,0 @@
-// matrix-skype - 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 .
-
-package whatsappExt
-
-import (
- "encoding/json"
-
- "github.com/Rhymen/go-whatsapp"
-)
-
-type JSONMessage []json.RawMessage
-
-type JSONMessageType string
-
-const (
- MessageMsgInfo JSONMessageType = "MsgInfo"
- MessageMsg JSONMessageType = "Msg"
- MessagePresence JSONMessageType = "Presence"
- MessageStream JSONMessageType = "Stream"
- MessageConn JSONMessageType = "Conn"
- MessageProps JSONMessageType = "Props"
- MessageCmd JSONMessageType = "Cmd"
- MessageChat JSONMessageType = "Chat"
- MessageCall JSONMessageType = "Call"
-)
-
-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 {
- ext.jsonParseError(err)
- 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.handleMessageConn(msg[1])
- case MessageProps:
- ext.handleMessageProps(msg[1])
- case MessageMsgInfo, MessageMsg:
- ext.handleMessageMsgInfo(msgType, msg[1])
- case MessageCmd:
- ext.handleMessageCommand(msg[1])
- case MessageChat:
- ext.handleMessageChatUpdate(msg[1])
- case MessageCall:
- ext.handleMessageCall(msg[1])
- default:
- for _, handler := range ext.handlers {
- ujmHandler, ok := handler.(UnhandledJSONMessageHandler)
- if !ok {
- continue
- }
-
- if ext.shouldCallSynchronously(ujmHandler) {
- ujmHandler.HandleUnhandledJSONMessage(message)
- } else {
- go ujmHandler.HandleUnhandledJSONMessage(message)
- }
- }
- }
-}
diff --git a/whatsapp-ext/msginfo.go b/whatsapp-ext/msginfo.go
deleted file mode 100644
index 702c322..0000000
--- a/whatsapp-ext/msginfo.go
+++ /dev/null
@@ -1,95 +0,0 @@
-// matrix-skype - 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 .
-
-package whatsappExt
-
-import (
- "encoding/json"
- "strings"
-
- "github.com/Rhymen/go-whatsapp"
-)
-
-type MsgInfoCommand string
-
-const (
- MsgInfoCommandAck MsgInfoCommand = "ack"
- MsgInfoCommandAcks MsgInfoCommand = "acks"
-)
-
-type Acknowledgement int
-
-const (
- AckMessageSent Acknowledgement = 1
- AckMessageDelivered Acknowledgement = 2
- AckMessageRead Acknowledgement = 3
-)
-
-type JSONStringOrArray []string
-
-func (jsoa *JSONStringOrArray) UnmarshalJSON(data []byte) error {
- var str string
- if json.Unmarshal(data, &str) == nil {
- *jsoa = []string{str}
- return nil
- }
- var strs []string
- json.Unmarshal(data, &strs)
- *jsoa = strs
- return nil
-}
-
-type MsgInfo struct {
- Command MsgInfoCommand `json:"cmd"`
- IDs JSONStringOrArray `json:"id"`
- Acknowledgement Acknowledgement `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(msgType JSONMessageType, 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)
- if msgType == MessageMsg {
- event.SenderJID = event.ToJID
- }
- for _, handler := range ext.handlers {
- msgInfoHandler, ok := handler.(MsgInfoHandler)
- if !ok {
- continue
- }
-
- if ext.shouldCallSynchronously(msgInfoHandler) {
- msgInfoHandler.HandleMsgInfo(event)
- } else {
- go msgInfoHandler.HandleMsgInfo(event)
- }
- }
-}
diff --git a/whatsapp-ext/presence.go b/whatsapp-ext/presence.go
deleted file mode 100644
index 01365d2..0000000
--- a/whatsapp-ext/presence.go
+++ /dev/null
@@ -1,67 +0,0 @@
-// matrix-skype - 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 .
-
-package whatsappExt
-
-import (
- "encoding/json"
- "strings"
-
- "github.com/Rhymen/go-whatsapp"
-)
-
-type Presence struct {
- JID string `json:"id"`
- SenderJID string `json:"participant"`
- Status whatsapp.Presence `json:"type"`
- Timestamp int64 `json:"t"`
- Deny bool `json:"deny"`
-}
-
-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)
- if len(event.SenderJID) == 0 {
- if strings.Index(event.JID,"@g.us") > -1 {
- return
- }
- event.SenderJID = event.JID
- } else {
- event.SenderJID = strings.Replace(event.SenderJID, OldUserSuffix, NewUserSuffix, 1)
- }
- for _, handler := range ext.handlers {
- presenceHandler, ok := handler.(PresenceHandler)
- if !ok {
- continue
- }
-
- if ext.shouldCallSynchronously(presenceHandler) {
- presenceHandler.HandlePresence(event)
- } else {
- go presenceHandler.HandlePresence(event)
- }
- }
-}
diff --git a/whatsapp-ext/props.go b/whatsapp-ext/props.go
deleted file mode 100644
index 4245683..0000000
--- a/whatsapp-ext/props.go
+++ /dev/null
@@ -1,73 +0,0 @@
-// matrix-skype - 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 .
-
-package whatsappExt
-
-import (
- "encoding/json"
-
- "github.com/Rhymen/go-whatsapp"
-)
-
-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
- }
-
- if ext.shouldCallSynchronously(protocolPropsHandler) {
- protocolPropsHandler.HandleProtocolProps(event)
- } else {
- go protocolPropsHandler.HandleProtocolProps(event)
- }
- }
-}
diff --git a/whatsapp-ext/protomessage.go b/whatsapp-ext/protomessage.go
deleted file mode 100644
index ca00f05..0000000
--- a/whatsapp-ext/protomessage.go
+++ /dev/null
@@ -1,59 +0,0 @@
-// matrix-skype - 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 .
-
-package whatsappExt
-
-import (
- "github.com/Rhymen/go-whatsapp"
- "github.com/Rhymen/go-whatsapp/binary/proto"
-)
-
-type MessageRevokeHandler interface {
- whatsapp.Handler
- HandleMessageRevoke(key MessageRevocation)
-}
-
-type MessageRevocation struct {
- Id string
- RemoteJid string
- FromMe bool
- Participant string
-}
-
-func (ext *ExtendedConn) HandleRawMessage(message *proto.WebMessageInfo) {
- protoMsg := message.GetMessage().GetProtocolMessage()
- if protoMsg != nil && protoMsg.GetType() == proto.ProtocolMessage_REVOKE {
- key := protoMsg.GetKey()
- deletedMessage := MessageRevocation{
- Id: key.GetId(),
- RemoteJid: key.GetRemoteJid(),
- FromMe: key.GetFromMe(),
- Participant: key.GetParticipant(),
- }
- for _, handler := range ext.handlers {
- mrHandler, ok := handler.(MessageRevokeHandler)
- if !ok {
- continue
- }
-
- if ext.shouldCallSynchronously(mrHandler) {
- mrHandler.HandleMessageRevoke(deletedMessage)
- } else {
- go mrHandler.HandleMessageRevoke(deletedMessage)
- }
- }
- }
-}
diff --git a/whatsapp-ext/stream.go b/whatsapp-ext/stream.go
deleted file mode 100644
index bd82672..0000000
--- a/whatsapp-ext/stream.go
+++ /dev/null
@@ -1,68 +0,0 @@
-// matrix-skype - 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 .
-
-package whatsappExt
-
-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
- }
-
- if ext.shouldCallSynchronously(streamHandler) {
- streamHandler.HandleStreamEvent(event)
- } else {
- go streamHandler.HandleStreamEvent(event)
- }
- }
-}
diff --git a/whatsapp-ext/whatsapp.go b/whatsapp-ext/whatsapp.go
deleted file mode 100644
index 5c356c3..0000000
--- a/whatsapp-ext/whatsapp.go
+++ /dev/null
@@ -1,206 +0,0 @@
-// matrix-skype - 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 .
-
-package whatsappExt
-
-import (
- "encoding/json"
- "fmt"
- "io"
- "io/ioutil"
- "net/http"
- "strings"
-
- "github.com/Rhymen/go-whatsapp"
-)
-
-const (
- OldUserSuffix = "@c.us"
- //NewUserSuffix = "@s.whatsapp.net"
- NewUserSuffix = "@s.skype.net"
-)
-
-type ExtendedConn struct {
- *whatsapp.Conn
-
- handlers []whatsapp.Handler
-}
-
-func ExtendConn(conn *whatsapp.Conn) *ExtendedConn {
- ext := &ExtendedConn{
- Conn: conn,
- }
- ext.Conn.AddHandler(ext)
- return ext
-}
-
-func (ext *ExtendedConn) AddHandler(handler whatsapp.Handler) {
- ext.Conn.AddHandler(handler)
- ext.handlers = append(ext.handlers, handler)
-}
-
-
-func (ext *ExtendedConn) RemoveHandler(handler whatsapp.Handler) bool {
- ext.Conn.RemoveHandler(handler)
- for i, v := range ext.handlers {
- if v == handler {
- ext.handlers = append(ext.handlers[:i], ext.handlers[i+1:]...)
- return true
- }
- }
- return false
-}
-
-func (ext *ExtendedConn) RemoveHandlers() {
- ext.Conn.RemoveHandlers()
- ext.handlers = make([]whatsapp.Handler, 0)
-}
-
-func (ext *ExtendedConn) shouldCallSynchronously(handler whatsapp.Handler) bool {
- sh, ok := handler.(whatsapp.SyncHandler)
- return ok && sh.ShouldCallSynchronously()
-}
-
-func (ext *ExtendedConn) ShouldCallSynchronously() bool {
- return true
-}
-
-type GroupInfo struct {
- JID string `json:"jid"`
- OwnerJID string `json:"owner"`
-
- Name string `json:"subject"`
- NameSetTime int64 `json:"subjectTime"`
- NameSetBy string `json:"subjectOwner"`
-
- Topic string `json:"desc"`
- TopicID string `json:"descId"`
- TopicSetAt int64 `json:"descTime"`
- TopicSetBy string `json:"descOwner"`
-
- GroupCreated int64 `json:"creation"`
-
- Status int16 `json:"status"`
-
- Participants []struct {
- JID string `json:"id"`
- IsAdmin bool `json:"isAdmin"`
- IsSuperAdmin bool `json:"isSuperAdmin"`
- } `json:"participants"`
-}
-
-func (ext *ExtendedConn) GetGroupMetaData(jid string) (*GroupInfo, error) {
- data, err := ext.Conn.GetGroupMetaData(jid)
- if err != nil {
- return nil, fmt.Errorf("failed to get group metadata: %v", err)
- }
- content := <-data
-
- info := &GroupInfo{}
- err = json.Unmarshal([]byte(content), info)
- if err != nil {
- return info, fmt.Errorf("failed to unmarshal group metadata: %v", err)
- }
-
- for index, participant := range info.Participants {
- info.Participants[index].JID = strings.Replace(participant.JID, OldUserSuffix, NewUserSuffix, 1)
- }
- info.NameSetBy = strings.Replace(info.NameSetBy, OldUserSuffix, NewUserSuffix, 1)
- info.TopicSetBy = strings.Replace(info.TopicSetBy, OldUserSuffix, NewUserSuffix, 1)
-
- return info, nil
-}
-
-type ProfilePicInfo struct {
- URL string `json:"eurl"`
- Tag string `json:"tag"`
-
- Status int16 `json:"status"`
-}
-
-func (ppi *ProfilePicInfo) Download() (io.ReadCloser, error) {
- resp, err := http.Get(ppi.URL)
- if err != nil {
- return nil, err
- }
- return resp.Body, nil
-}
-
-func (ppi *ProfilePicInfo) DownloadBytes() ([]byte, error) {
- body, err := ppi.Download()
- if err != nil {
- return nil, err
- }
- defer body.Close()
- data, err := ioutil.ReadAll(body)
- return data, err
-}
-
-func (ext *ExtendedConn) GetProfilePicThumb(jid string) (*ProfilePicInfo, error) {
- data, err := ext.Conn.GetProfilePicThumb(jid)
- if err != nil {
- return nil, fmt.Errorf("failed to get avatar: %v", err)
- }
- content := <-data
- info := &ProfilePicInfo{}
- err = json.Unmarshal([]byte(content), info)
- if err != nil {
- return info, fmt.Errorf("failed to unmarshal avatar info: %v", err)
- }
- return info, nil
-}
-
-func (ext *ExtendedConn) HandleGroupInvite(groupJid string, numbers[]string) (err error) {
- var parts []string
- parts = append(parts, numbers...)
- _, err = ext.Conn.AddMember(groupJid, parts)
- if err != nil {
- fmt.Printf("%s Handle Invite err", err)
- }
- return
-}
-
-func (ext *ExtendedConn) HandleGroupJoin(code string) (jid string, err error) {
- return ext.Conn.GroupAcceptInviteCode(code)
-}
-
-func (ext *ExtendedConn) HandleGroupKick(groupJid string, numbers[]string) (err error) {
- var parts []string
- parts = append(parts, numbers...)
- _, err = ext.Conn.RemoveMember(groupJid, parts)
- if err != nil {
- fmt.Printf("%s Handle kick err", err)
- }
- return
-}
-
-func (ext *ExtendedConn) HandleGroupCreate(subject string, numbers[]string) (err error) {
- var parts []string
- parts = append(parts, numbers...)
- _, err = ext.Conn.CreateGroup(subject, parts)
- if err != nil {
- fmt.Printf("%s HandleGroupCreate err", err)
- }
- return
-}
-
-func (ext *ExtendedConn) HandleGroupLeave(groupJid string) (err error) {
- _, err = ext.Conn.LeaveGroup(groupJid)
- if err != nil {
- fmt.Printf("%s HandleGroupLeave err", err)
- }
- return
-}