kick/invite (in portal room)
This commit is contained in:
parent
1251ac2204
commit
ab5d852629
|
@ -900,7 +900,7 @@ func (handler *CommandHandler) CommandInvite(ce *CommandEvent) {
|
|||
|
||||
userNumbers := strings.Split(ce.Args[1], ",")
|
||||
|
||||
if strings.HasSuffix(conversationId, whatsappExt.NewUserSuffix) {
|
||||
if strings.HasSuffix(conversationId, skypeExt.NewUserSuffix) {
|
||||
ce.Reply("**Usage:** `invite <group JID> <international phone number>,...`")
|
||||
return
|
||||
}
|
||||
|
|
135
matrix.go
135
matrix.go
|
@ -3,6 +3,8 @@ package main
|
|||
import (
|
||||
"fmt"
|
||||
skype "github.com/kelaresg/go-skypeapi"
|
||||
"github.com/kelaresg/matrix-skype/database"
|
||||
"maunium.net/go/mautrix"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
|
@ -52,6 +54,28 @@ func (mx *MatrixHandler) HandleEncryption(evt *event.Event) {
|
|||
}
|
||||
}
|
||||
|
||||
func (mx *MatrixHandler) joinAndCheckMembers(evt *event.Event, intent *appservice.IntentAPI) *mautrix.RespJoinedMembers {
|
||||
resp, err := intent.JoinRoomByID(evt.RoomID)
|
||||
if err != nil {
|
||||
mx.log.Debugfln("Failed to join room %s as %s with invite from %s: %v", evt.RoomID, intent.UserID, evt.Sender, err)
|
||||
return nil
|
||||
}
|
||||
|
||||
members, err := intent.JoinedMembers(resp.RoomID)
|
||||
if err != nil {
|
||||
mx.log.Debugfln("Failed to get members in room %s after accepting invite from %s as %s: %v", resp.RoomID, evt.Sender, intent.UserID, err)
|
||||
_, _ = intent.LeaveRoom(resp.RoomID)
|
||||
return nil
|
||||
}
|
||||
|
||||
if len(members.Joined) < 2 {
|
||||
mx.log.Debugln("Leaving empty room", resp.RoomID, "after accepting invite from", evt.Sender, "as", intent.UserID)
|
||||
_, _ = intent.LeaveRoom(resp.RoomID)
|
||||
return nil
|
||||
}
|
||||
return members
|
||||
}
|
||||
|
||||
func (mx *MatrixHandler) HandleBotInvite(evt *event.Event) {
|
||||
intent := mx.as.BotIntent()
|
||||
|
||||
|
@ -114,6 +138,102 @@ func (mx *MatrixHandler) HandleBotInvite(evt *event.Event) {
|
|||
}
|
||||
}
|
||||
|
||||
func (mx *MatrixHandler) handlePrivatePortal(roomID id.RoomID, inviter *User, puppet *Puppet, key database.PortalKey) {
|
||||
portal := mx.bridge.GetPortalByJID(key)
|
||||
|
||||
if len(portal.MXID) == 0 {
|
||||
mx.createPrivatePortalFromInvite(roomID, inviter, puppet, portal)
|
||||
return
|
||||
}
|
||||
|
||||
err := portal.MainIntent().EnsureInvited(portal.MXID, inviter.MXID)
|
||||
if err != nil {
|
||||
mx.log.Warnfln("Failed to invite %s to existing private chat portal %s with %s: %v. Redirecting portal to new room...", inviter.MXID, portal.MXID, puppet.JID, err)
|
||||
mx.createPrivatePortalFromInvite(roomID, inviter, puppet, portal)
|
||||
return
|
||||
}
|
||||
intent := puppet.DefaultIntent()
|
||||
_, _ = intent.SendNotice(roomID, "You already have a private chat portal with me at %s")
|
||||
mx.log.Debugln("Leaving private chat room", roomID, "as", puppet.MXID, "after accepting invite from", inviter.MXID, "as we already have chat with the user")
|
||||
_, _ = intent.LeaveRoom(roomID)
|
||||
}
|
||||
|
||||
|
||||
func (mx *MatrixHandler) createPrivatePortalFromInvite(roomID id.RoomID, inviter *User, puppet *Puppet, portal *Portal) {
|
||||
portal.MXID = roomID
|
||||
portal.Topic = "WhatsApp private chat"
|
||||
_, _ = portal.MainIntent().SetRoomTopic(portal.MXID, portal.Topic)
|
||||
if portal.bridge.Config.Bridge.PrivateChatPortalMeta {
|
||||
portal.Name = puppet.Displayname
|
||||
portal.AvatarURL = puppet.AvatarURL
|
||||
portal.Avatar = puppet.Avatar
|
||||
_, _ = portal.MainIntent().SetRoomName(portal.MXID, portal.Name)
|
||||
_, _ = portal.MainIntent().SetRoomAvatar(portal.MXID, portal.AvatarURL)
|
||||
} else {
|
||||
portal.Name = ""
|
||||
}
|
||||
portal.log.Infoln("Created private chat portal in %s after invite from", roomID, inviter.MXID)
|
||||
intent := puppet.DefaultIntent()
|
||||
|
||||
if mx.bridge.Config.Bridge.Encryption.Default {
|
||||
_, err := intent.InviteUser(roomID, &mautrix.ReqInviteUser{UserID: mx.bridge.Bot.UserID})
|
||||
if err != nil {
|
||||
portal.log.Warnln("Failed to invite bridge bot to enable e2be:", err)
|
||||
}
|
||||
err = mx.bridge.Bot.EnsureJoined(roomID)
|
||||
if err != nil {
|
||||
portal.log.Warnln("Failed to join as bridge bot to enable e2be:", err)
|
||||
}
|
||||
_, err = intent.SendStateEvent(roomID, event.StateEncryption, "", &event.EncryptionEventContent{Algorithm: id.AlgorithmMegolmV1})
|
||||
if err != nil {
|
||||
portal.log.Warnln("Failed to enable e2be:", err)
|
||||
}
|
||||
mx.as.StateStore.SetMembership(roomID, inviter.MXID, event.MembershipJoin)
|
||||
mx.as.StateStore.SetMembership(roomID, puppet.MXID, event.MembershipJoin)
|
||||
mx.as.StateStore.SetMembership(roomID, mx.bridge.Bot.UserID, event.MembershipJoin)
|
||||
portal.Encrypted = true
|
||||
}
|
||||
portal.Update()
|
||||
portal.UpdateBridgeInfo()
|
||||
_, _ = intent.SendNotice(roomID, "Private chat portal created")
|
||||
|
||||
err := portal.FillInitialHistory(inviter)
|
||||
if err != nil {
|
||||
portal.log.Errorln("Failed to fill history:", err)
|
||||
}
|
||||
|
||||
inviter.addPortalToCommunity(portal)
|
||||
inviter.addPuppetToCommunity(puppet)
|
||||
}
|
||||
|
||||
func (mx *MatrixHandler) HandlePuppetInvite(evt *event.Event, inviter *User, puppet *Puppet) {
|
||||
intent := puppet.DefaultIntent()
|
||||
members := mx.joinAndCheckMembers(evt, intent)
|
||||
if members == nil {
|
||||
return
|
||||
}
|
||||
var hasBridgeBot, hasOtherUsers bool
|
||||
for mxid, _ := range members.Joined {
|
||||
if mxid == intent.UserID || mxid == inviter.MXID {
|
||||
continue
|
||||
} else if mxid == mx.bridge.Bot.UserID {
|
||||
hasBridgeBot = true
|
||||
} else {
|
||||
hasOtherUsers = true
|
||||
}
|
||||
}
|
||||
if !hasBridgeBot && !hasOtherUsers {
|
||||
key := database.NewPortalKey(puppet.JID, inviter.JID)
|
||||
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.LeaveRoom(evt.RoomID)
|
||||
} else {
|
||||
_, _ = intent.SendNotice(evt.RoomID, "This puppet will remain inactive until this room is bridged to a WhatsApp group.")
|
||||
}
|
||||
}
|
||||
|
||||
func (mx *MatrixHandler) HandleMembership(evt *event.Event) {
|
||||
if _, isPuppet := mx.bridge.ParsePuppetMXID(evt.Sender); evt.Sender == mx.bridge.Bot.UserID || isPuppet {
|
||||
return
|
||||
|
@ -126,10 +246,6 @@ func (mx *MatrixHandler) HandleMembership(evt *event.Event) {
|
|||
content := evt.Content.AsMember()
|
||||
if content.Membership == event.MembershipInvite && id.UserID(evt.GetStateKey()) == mx.as.BotMXID() {
|
||||
mx.HandleBotInvite(evt)
|
||||
}
|
||||
|
||||
portal := mx.bridge.GetPortalByMXID(evt.RoomID)
|
||||
if portal == nil {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -138,6 +254,15 @@ func (mx *MatrixHandler) HandleMembership(evt *event.Event) {
|
|||
return
|
||||
}
|
||||
|
||||
portal := mx.bridge.GetPortalByMXID(evt.RoomID)
|
||||
if portal == nil {
|
||||
puppet := mx.bridge.GetPuppetByMXID(id.UserID(evt.GetStateKey()))
|
||||
if content.Membership == event.MembershipInvite && puppet != nil {
|
||||
mx.HandlePuppetInvite(evt, user, puppet)
|
||||
}
|
||||
return
|
||||
}
|
||||
isSelf := id.UserID(evt.GetStateKey()) == evt.Sender
|
||||
if content.Membership == event.MembershipLeave {
|
||||
if id.UserID(evt.GetStateKey()) == evt.Sender {
|
||||
if evt.Unsigned.PrevContent != nil {
|
||||
|
@ -152,6 +277,8 @@ func (mx *MatrixHandler) HandleMembership(evt *event.Event) {
|
|||
} else {
|
||||
portal.HandleMatrixKick(user, evt)
|
||||
}
|
||||
} else if content.Membership == event.MembershipInvite && !isSelf {
|
||||
portal.HandleMatrixInvite(user, evt)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
119
portal.go
119
portal.go
|
@ -1015,6 +1015,43 @@ var (
|
|||
StateHalfShotBridgeInfo = event.Type{Type: "uk.half-shot.bridge", Class: event.StateEventType}
|
||||
)
|
||||
|
||||
func (portal *Portal) getBridgeInfo() (string, BridgeInfoContent) {
|
||||
bridgeInfo := BridgeInfoContent{
|
||||
BridgeBot: portal.bridge.Bot.UserID,
|
||||
Creator: portal.MainIntent().UserID,
|
||||
Protocol: BridgeInfoSection{
|
||||
ID: "skype",
|
||||
DisplayName: "Skype",
|
||||
AvatarURL: id.ContentURIString(portal.bridge.Config.AppService.Bot.Avatar),
|
||||
ExternalURL: "https://www.skype.com/",
|
||||
},
|
||||
Channel: BridgeInfoSection{
|
||||
ID: portal.Key.JID,
|
||||
DisplayName: portal.Name,
|
||||
AvatarURL: portal.AvatarURL.CUString(),
|
||||
},
|
||||
}
|
||||
bridgeInfoStateKey := fmt.Sprintf("net.maunium.whatsapp://whatsapp/%s", portal.Key.JID)
|
||||
return bridgeInfoStateKey, bridgeInfo
|
||||
}
|
||||
|
||||
func (portal *Portal) UpdateBridgeInfo() {
|
||||
if len(portal.MXID) == 0 {
|
||||
portal.log.Debugln("Not updating bridge info: no Matrix room created")
|
||||
return
|
||||
}
|
||||
portal.log.Debugln("Updating bridge info...")
|
||||
stateKey, content := portal.getBridgeInfo()
|
||||
_, err := portal.MainIntent().SendStateEvent(portal.MXID, StateBridgeInfo, stateKey, content)
|
||||
if err != nil {
|
||||
portal.log.Warnln("Failed to update m.bridge:", err)
|
||||
}
|
||||
_, err = portal.MainIntent().SendStateEvent(portal.MXID, StateHalfShotBridgeInfo, stateKey, content)
|
||||
if err != nil {
|
||||
portal.log.Warnln("Failed to update uk.half-shot.bridge:", err)
|
||||
}
|
||||
}
|
||||
|
||||
func (portal *Portal) CreateMatrixRoom(user *User) error {
|
||||
portal.roomCreateLock.Lock()
|
||||
defer portal.roomCreateLock.Unlock()
|
||||
|
@ -1024,9 +1061,6 @@ func (portal *Portal) CreateMatrixRoom(user *User) error {
|
|||
|
||||
intent := portal.MainIntent()
|
||||
if err := intent.EnsureRegistered(); err != nil {
|
||||
fmt.Println()
|
||||
fmt.Println("CreateMatrixRoom0: ", err)
|
||||
fmt.Println()
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -1035,9 +1069,6 @@ func (portal *Portal) CreateMatrixRoom(user *User) error {
|
|||
|
||||
var metadata *skypeExt.GroupInfo
|
||||
if portal.IsPrivateChat() {
|
||||
fmt.Println()
|
||||
fmt.Println("CreateMatrixRoom1: ")
|
||||
fmt.Println()
|
||||
puppet := portal.bridge.GetPuppetByJID(portal.Key.JID+skypeExt.NewUserSuffix)
|
||||
if portal.bridge.Config.Bridge.PrivateChatPortalMeta {
|
||||
portal.Name = puppet.Displayname
|
||||
|
@ -1048,15 +1079,9 @@ func (portal *Portal) CreateMatrixRoom(user *User) error {
|
|||
}
|
||||
portal.Topic = "skype private chat"
|
||||
} else if portal.IsStatusBroadcastRoom() {
|
||||
fmt.Println()
|
||||
fmt.Println("CreateMatrixRoom2: ")
|
||||
fmt.Println()
|
||||
portal.Name = "skype Status Broadcast"
|
||||
portal.Topic = "skype status updates from your contacts"
|
||||
} else {
|
||||
fmt.Println()
|
||||
fmt.Println("CreateMatrixRoom3: ")
|
||||
fmt.Println()
|
||||
var err error
|
||||
metadata, err = user.Conn.GetGroupMetaData(portal.Key.JID)
|
||||
if err == nil {
|
||||
|
@ -1068,7 +1093,6 @@ func (portal *Portal) CreateMatrixRoom(user *User) error {
|
|||
if key == user.JID {
|
||||
continue
|
||||
}
|
||||
fmt.Println("CreateMatrixRoom3.1: ", key)
|
||||
if contact, ok := user.Conn.Store.Contacts[key]; ok {
|
||||
if len(portalName) > 0 {
|
||||
portalName = portalName + ", " + contact.DisplayName
|
||||
|
@ -2355,6 +2379,35 @@ func (portal *Portal) Delete() {
|
|||
portal.bridge.portalsLock.Unlock()
|
||||
}
|
||||
|
||||
func (portal *Portal) GetMatrixUsers() ([]id.UserID, error) {
|
||||
members, err := portal.MainIntent().JoinedMembers(portal.MXID)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to get member list")
|
||||
}
|
||||
var users []id.UserID
|
||||
for userID := range members.Joined {
|
||||
_, isPuppet := portal.bridge.ParsePuppetMXID(userID)
|
||||
if !isPuppet && userID != portal.bridge.Bot.UserID {
|
||||
users = append(users, userID)
|
||||
}
|
||||
}
|
||||
return users, nil
|
||||
}
|
||||
|
||||
func (portal *Portal) CleanupIfEmpty() {
|
||||
users, err := portal.GetMatrixUsers()
|
||||
if err != nil {
|
||||
portal.log.Errorfln("Failed to get Matrix user list to determine if portal needs to be cleaned up: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if len(users) == 0 {
|
||||
portal.log.Infoln("Room seems to be empty, cleaning up...")
|
||||
portal.Delete()
|
||||
portal.Cleanup(false)
|
||||
}
|
||||
}
|
||||
|
||||
func (portal *Portal) Cleanup(puppetsOnly bool) {
|
||||
if len(portal.MXID) == 0 {
|
||||
return
|
||||
|
@ -2401,9 +2454,45 @@ func (portal *Portal) HandleMatrixLeave(sender *User) {
|
|||
portal.Delete()
|
||||
portal.Cleanup(false)
|
||||
return
|
||||
} else {
|
||||
// TODO should we somehow deduplicate this call if this leave was sent by the bridge?
|
||||
err := sender.Conn.HandleGroupLeave(portal.Key.JID)
|
||||
if err != nil {
|
||||
portal.log.Errorfln("Failed to leave group as %s: %v", sender.MXID, err)
|
||||
return
|
||||
}
|
||||
//portal.log.Infoln("Leave response:", <-resp)
|
||||
portal.CleanupIfEmpty()
|
||||
}
|
||||
}
|
||||
|
||||
func (portal *Portal) HandleMatrixKick(sender *User, event *event.Event) {
|
||||
// TODO
|
||||
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)
|
||||
if puppet != nil {
|
||||
number = strings.Replace(number, skypeExt.NewUserSuffix, "", 1)
|
||||
err := sender.Conn.HandleGroupKick(portal.Key.JID, []string{number})
|
||||
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)
|
||||
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})
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
|
12
puppet.go
12
puppet.go
|
@ -19,7 +19,6 @@ import (
|
|||
)
|
||||
|
||||
func (bridge *Bridge) ParsePuppetMXID(mxid id.UserID) (types.SkypeID, bool) {
|
||||
fmt.Println("ParsePuppetMXID: ", bridge.Config.Bridge.FormatUsername("(.*)"))
|
||||
userIDRegex, err := regexp.Compile(fmt.Sprintf("^@%s:%s$",
|
||||
bridge.Config.Bridge.FormatUsername("(.*)"),
|
||||
bridge.Config.Homeserver.Domain))
|
||||
|
@ -31,8 +30,15 @@ func (bridge *Bridge) ParsePuppetMXID(mxid id.UserID) (types.SkypeID, bool) {
|
|||
if match == nil || len(match) != 2 {
|
||||
return "", false
|
||||
}
|
||||
|
||||
jid := types.SkypeID(match[1] + whatsappExt.NewUserSuffix)
|
||||
realId := match[1]
|
||||
cond1 := "8-live-"
|
||||
cond2 := "8-"
|
||||
if strings.HasPrefix(realId, cond1) {
|
||||
realId = strings.Replace(realId, cond1, "8:live:", 1)
|
||||
} else if strings.HasPrefix(realId, cond2){
|
||||
realId = strings.Replace(realId, cond2, "8:", 1)
|
||||
}
|
||||
jid := types.SkypeID(realId + skypeExt.NewUserSuffix)
|
||||
return jid, true
|
||||
}
|
||||
|
||||
|
|
|
@ -275,9 +275,10 @@ func (ext *ExtendedConn) HandleGroupShare(groupJid string) (err error, link stri
|
|||
|
||||
func (ext *ExtendedConn) HandleGroupKick(groupJid string, numbers[]string) (err error) {
|
||||
for _, number := range numbers{
|
||||
if err == nil {
|
||||
err = ext.Conn.RemoveMember(groupJid, number)
|
||||
if err != nil {
|
||||
fmt.Printf("%s Handle kick err", err)
|
||||
} else {
|
||||
_ = ext.Conn.RemoveMember(groupJid, number)
|
||||
}
|
||||
}
|
||||
return
|
||||
|
|
Loading…
Reference in New Issue