mirror of
https://github.com/tulir/mautrix-whatsapp
synced 2024-12-23 22:14:06 +01:00
Add support for group invite messages
This commit is contained in:
parent
1e5d5c1a3e
commit
630095e28a
7 changed files with 138 additions and 110 deletions
72
commands.go
72
commands.go
|
@ -60,6 +60,7 @@ type CommandEvent struct {
|
|||
User *User
|
||||
Command string
|
||||
Args []string
|
||||
ReplyTo id.EventID
|
||||
}
|
||||
|
||||
// Reply sends a reply to command as notice
|
||||
|
@ -77,7 +78,7 @@ func (ce *CommandEvent) Reply(msg string, args ...interface{}) {
|
|||
}
|
||||
|
||||
// Handle handles messages to the bridge
|
||||
func (handler *CommandHandler) Handle(roomID id.RoomID, user *User, message string) {
|
||||
func (handler *CommandHandler) Handle(roomID id.RoomID, user *User, message string, replyTo id.EventID) {
|
||||
args := strings.Fields(message)
|
||||
if len(args) == 0 {
|
||||
args = []string{"unknown-command"}
|
||||
|
@ -91,6 +92,7 @@ func (handler *CommandHandler) Handle(roomID id.RoomID, user *User, message stri
|
|||
User: user,
|
||||
Command: strings.ToLower(args[0]),
|
||||
Args: args[1:],
|
||||
ReplyTo: replyTo,
|
||||
}
|
||||
handler.log.Debugfln("%s sent '%s' in %s", user.MXID, message, roomID)
|
||||
handler.CommandMux(ce)
|
||||
|
@ -130,7 +132,7 @@ func (handler *CommandHandler) CommandMux(ce *CommandEvent) {
|
|||
handler.CommandLogout(ce)
|
||||
case "toggle":
|
||||
handler.CommandToggle(ce)
|
||||
case "set-relay", "unset-relay", "login-matrix", "sync", "list", "open", "pm", "invite-link", "check-invite", "join", "create":
|
||||
case "set-relay", "unset-relay", "login-matrix", "sync", "list", "open", "pm", "invite-link", "check-invite", "join", "create", "accept":
|
||||
if !ce.User.HasSession() {
|
||||
ce.Reply("You are not logged in. Use the `login` command to log into WhatsApp.")
|
||||
return
|
||||
|
@ -160,6 +162,8 @@ func (handler *CommandHandler) CommandMux(ce *CommandEvent) {
|
|||
handler.CommandJoin(ce)
|
||||
case "create":
|
||||
handler.CommandCreate(ce)
|
||||
case "accept":
|
||||
handler.CommandAccept(ce)
|
||||
}
|
||||
default:
|
||||
ce.Reply("Unknown command, use the `help` command for help.")
|
||||
|
@ -281,6 +285,35 @@ func (handler *CommandHandler) CommandJoin(ce *CommandEvent) {
|
|||
ce.Reply("Successfully joined group `%s`, the portal should be created momentarily", jid)
|
||||
}
|
||||
|
||||
func (handler *CommandHandler) CommandAccept(ce *CommandEvent) {
|
||||
if ce.Portal == nil || len(ce.ReplyTo) == 0 {
|
||||
ce.Reply("You must reply to a group invite message when using this command.")
|
||||
return
|
||||
}
|
||||
evt, err := ce.Portal.MainIntent().GetEvent(ce.RoomID, ce.ReplyTo)
|
||||
if err != nil {
|
||||
handler.log.Errorln("Failed to get event %s to handle !wa accept command: %v", ce.ReplyTo, err)
|
||||
ce.Reply("Failed to get reply event")
|
||||
return
|
||||
}
|
||||
meta, ok := evt.Content.Raw[inviteMetaField].(map[string]interface{})
|
||||
if !ok {
|
||||
ce.Reply("That doesn't look like a group invite message.")
|
||||
return
|
||||
}
|
||||
jid, inviter, code, expiration, ok := parseInviteMeta(meta)
|
||||
if !ok {
|
||||
ce.Reply("That doesn't look like a group invite message.")
|
||||
return
|
||||
}
|
||||
err = ce.User.Client.AcceptGroupInvite(jid, inviter, code, expiration)
|
||||
if err != nil {
|
||||
ce.Reply("Failed to accept group invite: %v", err)
|
||||
return
|
||||
}
|
||||
ce.Reply("Successfully accepted the invite, the portal should be created momentarily")
|
||||
}
|
||||
|
||||
const cmdCreateHelp = `create - Create a group chat.`
|
||||
|
||||
func (handler *CommandHandler) CommandCreate(ce *CommandEvent) {
|
||||
|
@ -353,6 +386,41 @@ func (handler *CommandHandler) CommandCreate(ce *CommandEvent) {
|
|||
//ce.User.CreateUserPortal(database.PortalKeyWithMeta{PortalKey: portal.Key, InCommunity: inCommunity})
|
||||
}
|
||||
|
||||
func parseInviteMeta(meta map[string]interface{}) (jid, inviter types.JID, code string, expiration int64, ok bool) {
|
||||
var fieldFound bool
|
||||
code, fieldFound = meta["code"].(string)
|
||||
if !fieldFound {
|
||||
return
|
||||
}
|
||||
expirationStr, fieldFound := meta["expiration"].(string)
|
||||
if !fieldFound {
|
||||
return
|
||||
}
|
||||
inviterStr, fieldFound := meta["inviter"].(string)
|
||||
if !fieldFound {
|
||||
return
|
||||
}
|
||||
jidStr, fieldFound := meta["jid"].(string)
|
||||
if !fieldFound {
|
||||
return
|
||||
}
|
||||
var err error
|
||||
expiration, err = strconv.ParseInt(expirationStr, 10, 64)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
inviter, err = types.ParseJID(inviterStr)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
jid, err = types.ParseJID(jidStr)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
ok = true
|
||||
return
|
||||
}
|
||||
|
||||
const cmdSetPowerLevelHelp = `set-pl [user ID] <power level> - Change the power level in a portal room. Only for bridge admins.`
|
||||
|
||||
func (handler *CommandHandler) CommandSetPowerLevel(ce *CommandEvent) {
|
||||
|
|
|
@ -217,7 +217,7 @@ func (puppet *Puppet) handleReceiptEvent(portal *Portal, event *event.Event) {
|
|||
for eventID, receipts := range *event.Content.AsReceipt() {
|
||||
if receipt, ok := receipts.Read[puppet.CustomMXID]; !ok {
|
||||
// Ignore receipt events where this user isn't present.
|
||||
} else if isDoublePuppeted, _ := receipt.Extra["net.maunium.whatsapp.puppet"].(bool); isDoublePuppeted {
|
||||
} else if isDoublePuppeted, _ := receipt.Extra[doublePuppetField].(bool); isDoublePuppeted {
|
||||
puppet.customUser.log.Debugfln("Ignoring double puppeted read receipt %+v", event.Content.Raw)
|
||||
// Ignore double puppeted read receipts.
|
||||
} else if message := puppet.bridge.DB.Message.GetByMXID(eventID); message != nil {
|
||||
|
|
2
go.mod
2
go.mod
|
@ -8,7 +8,7 @@ require (
|
|||
github.com/mattn/go-sqlite3 v1.14.9
|
||||
github.com/prometheus/client_golang v1.11.0
|
||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
|
||||
go.mau.fi/whatsmeow v0.0.0-20211031175440-39cd01efeed7
|
||||
go.mau.fi/whatsmeow v0.0.0-20211031184143-96a325ea0d2e
|
||||
golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d
|
||||
google.golang.org/protobuf v1.27.1
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
|
|
4
go.sum
4
go.sum
|
@ -139,8 +139,8 @@ github.com/tidwall/sjson v1.2.3 h1:5+deguEhHSEjmuICXZ21uSSsXotWMA0orU783+Z7Cp8=
|
|||
github.com/tidwall/sjson v1.2.3/go.mod h1:5WdjKx3AQMvCJ4RG6/2UYT7dLrGvJUV1x4jdTAyGvZs=
|
||||
go.mau.fi/libsignal v0.0.0-20211024113310-f9fc6a1855f2 h1:xpQTMgJGGaF+c8jV/LA/FVXAPJxZbSAGeflOc+Ly6uQ=
|
||||
go.mau.fi/libsignal v0.0.0-20211024113310-f9fc6a1855f2/go.mod h1:3XlVlwOfp8f9Wri+C1D4ORqgUsN4ZvunJOoPjQMBhos=
|
||||
go.mau.fi/whatsmeow v0.0.0-20211031175440-39cd01efeed7 h1:AxqjTj5ejuTUGrpG21Ot/dIjY946OjveZM08SACeDhw=
|
||||
go.mau.fi/whatsmeow v0.0.0-20211031175440-39cd01efeed7/go.mod h1:ODEmmqeUn9eBDQHFc1S902YA3YFLtmaBujYRRFl53jI=
|
||||
go.mau.fi/whatsmeow v0.0.0-20211031184143-96a325ea0d2e h1:XZzLOVrnccvvzZz+PhonjTRfHmycuToZiwBNiI+g1KM=
|
||||
go.mau.fi/whatsmeow v0.0.0-20211031184143-96a325ea0d2e/go.mod h1:ODEmmqeUn9eBDQHFc1S902YA3YFLtmaBujYRRFl53jI=
|
||||
golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
|
|
2
main.go
2
main.go
|
@ -17,6 +17,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
|
@ -26,7 +27,6 @@ import (
|
|||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
_ "embed"
|
||||
|
||||
"google.golang.org/protobuf/proto"
|
||||
|
||||
|
|
|
@ -315,7 +315,7 @@ func (mx *MatrixHandler) shouldIgnoreEvent(evt *event.Event) bool {
|
|||
if _, isPuppet := mx.bridge.ParsePuppetMXID(evt.Sender); evt.Sender == mx.bridge.Bot.UserID || isPuppet {
|
||||
return true
|
||||
}
|
||||
isCustomPuppet, ok := evt.Content.Raw["net.maunium.whatsapp.puppet"].(bool)
|
||||
isCustomPuppet, ok := evt.Content.Raw[doublePuppetField].(bool)
|
||||
if ok && isCustomPuppet && mx.bridge.GetPuppetByCustomMXID(evt.Sender) != nil {
|
||||
return true
|
||||
}
|
||||
|
@ -406,6 +406,7 @@ func (mx *MatrixHandler) HandleMessage(evt *event.Event) {
|
|||
|
||||
user := mx.bridge.GetUserByMXID(evt.Sender)
|
||||
content := evt.Content.AsMessage()
|
||||
content.RemoveReplyFallback()
|
||||
if user.Whitelisted && content.MsgType == event.MsgText {
|
||||
commandPrefix := mx.bridge.Config.Bridge.CommandPrefix
|
||||
hasCommandPrefix := strings.HasPrefix(content.Body, commandPrefix)
|
||||
|
@ -413,7 +414,7 @@ func (mx *MatrixHandler) HandleMessage(evt *event.Event) {
|
|||
content.Body = strings.TrimLeft(content.Body[len(commandPrefix):], " ")
|
||||
}
|
||||
if hasCommandPrefix || evt.RoomID == user.ManagementRoom {
|
||||
mx.cmd.Handle(evt.RoomID, user, content.Body)
|
||||
mx.cmd.Handle(evt.RoomID, user, content.Body, content.GetReplyTo())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
161
portal.go
161
portal.go
|
@ -233,6 +233,7 @@ func (portal *Portal) shouldCreateRoom(msg PortalMessage) bool {
|
|||
waMsg.DocumentMessage,
|
||||
waMsg.ContactMessage,
|
||||
waMsg.LocationMessage,
|
||||
waMsg.GroupInviteMessage,
|
||||
}
|
||||
for _, message := range supportedMessages {
|
||||
if message != nil {
|
||||
|
@ -262,7 +263,9 @@ func (portal *Portal) getMessageType(waMsg *waProto.Message) string {
|
|||
return "contact"
|
||||
case waMsg.LocationMessage != nil:
|
||||
return "location"
|
||||
case waMsg.GetProtocolMessage() != nil:
|
||||
case waMsg.GroupInviteMessage != nil:
|
||||
return "group invite"
|
||||
case waMsg.ProtocolMessage != nil:
|
||||
switch waMsg.GetProtocolMessage().GetType() {
|
||||
case waProto.ProtocolMessage_REVOKE:
|
||||
return "revoke"
|
||||
|
@ -294,6 +297,8 @@ func (portal *Portal) convertMessage(intent *appservice.IntentAPI, source *User,
|
|||
return portal.convertContactMessage(intent, waMsg.GetContactMessage())
|
||||
case waMsg.LocationMessage != nil:
|
||||
return portal.convertLocationMessage(intent, waMsg.GetLocationMessage())
|
||||
case waMsg.GroupInviteMessage != nil:
|
||||
return portal.convertGroupInviteMessage(intent, info, waMsg.GetGroupInviteMessage())
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
|
@ -322,7 +327,7 @@ func (portal *Portal) handleUndecryptableMessage(source *User, evt *events.Undec
|
|||
}
|
||||
intent := portal.getMessageIntent(source, &evt.Info)
|
||||
content := undecryptableMessageContent
|
||||
resp, err := portal.sendMessage(intent, event.EventMessage, &content, evt.Info.Timestamp.UnixMilli())
|
||||
resp, err := portal.sendMessage(intent, event.EventMessage, &content, nil, evt.Info.Timestamp.UnixMilli())
|
||||
if err != nil {
|
||||
portal.log.Errorln("Failed to send decryption error of %s to Matrix: %v", evt.Info.ID, err)
|
||||
}
|
||||
|
@ -359,7 +364,7 @@ func (portal *Portal) handleMessage(source *User, evt *events.Message) {
|
|||
if existingMsg != nil {
|
||||
converted.Content.SetEdit(existingMsg.MXID)
|
||||
}
|
||||
resp, err := portal.sendMessage(converted.Intent, converted.Type, converted.Content, evt.Info.Timestamp.UnixMilli())
|
||||
resp, err := portal.sendMessage(converted.Intent, converted.Type, converted.Content, converted.Extra, evt.Info.Timestamp.UnixMilli())
|
||||
if err != nil {
|
||||
portal.log.Errorln("Failed to send %s to Matrix: %v", msgID, err)
|
||||
} else {
|
||||
|
@ -367,7 +372,7 @@ func (portal *Portal) handleMessage(source *User, evt *events.Message) {
|
|||
}
|
||||
// TODO figure out how to handle captions with undecryptable messages turning decryptable
|
||||
if converted.Caption != nil && existingMsg == nil {
|
||||
resp, err = portal.sendMessage(converted.Intent, converted.Type, converted.Caption, evt.Info.Timestamp.UnixMilli())
|
||||
resp, err = portal.sendMessage(converted.Intent, converted.Type, converted.Caption, nil, evt.Info.Timestamp.UnixMilli())
|
||||
if err != nil {
|
||||
portal.log.Errorln("Failed to send caption of %s to Matrix: %v", msgID, err)
|
||||
} else {
|
||||
|
@ -894,17 +899,20 @@ func (portal *Portal) parseWebMessageInfo(webMsg *waProto.WebMessageInfo) *types
|
|||
return &info
|
||||
}
|
||||
|
||||
const backfillIDField = "net.maunium.whatsapp.id"
|
||||
const backfillIDField = "fi.mau.whatsapp.backfill_msg_id"
|
||||
const doublePuppetField = "net.maunium.whatsapp.puppet"
|
||||
|
||||
func (portal *Portal) wrapBatchEvent(info *types.MessageInfo, intent *appservice.IntentAPI, eventType event.Type, content *event.MessageEventContent) (*event.Event, error) {
|
||||
func (portal *Portal) wrapBatchEvent(info *types.MessageInfo, intent *appservice.IntentAPI, eventType event.Type, content *event.MessageEventContent, extraContent map[string]interface{}) (*event.Event, error) {
|
||||
if extraContent == nil {
|
||||
extraContent = map[string]interface{}{}
|
||||
}
|
||||
extraContent[backfillIDField] = info.ID
|
||||
if intent.IsCustomPuppet {
|
||||
extraContent[doublePuppetField] = intent.IsCustomPuppet
|
||||
}
|
||||
wrappedContent := event.Content{
|
||||
Parsed: content,
|
||||
Raw: map[string]interface{}{
|
||||
backfillIDField: info.ID,
|
||||
},
|
||||
}
|
||||
if intent.IsCustomPuppet {
|
||||
wrappedContent.Raw["net.maunium.whatsapp.puppet"] = intent.IsCustomPuppet
|
||||
Raw: extraContent,
|
||||
}
|
||||
newEventType, err := portal.encrypt(&wrappedContent, eventType)
|
||||
if err != nil {
|
||||
|
@ -919,12 +927,12 @@ func (portal *Portal) wrapBatchEvent(info *types.MessageInfo, intent *appservice
|
|||
}
|
||||
|
||||
func (portal *Portal) appendBatchEvents(converted *ConvertedMessage, info *types.MessageInfo, eventsArray *[]*event.Event, infoArray *[]*types.MessageInfo) error {
|
||||
mainEvt, err := portal.wrapBatchEvent(info, converted.Intent, converted.Type, converted.Content)
|
||||
mainEvt, err := portal.wrapBatchEvent(info, converted.Intent, converted.Type, converted.Content, converted.Extra)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if converted.Caption != nil {
|
||||
captionEvt, err := portal.wrapBatchEvent(info, converted.Intent, converted.Type, converted.Caption)
|
||||
captionEvt, err := portal.wrapBatchEvent(info, converted.Intent, converted.Type, converted.Caption, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -1441,34 +1449,8 @@ func (portal *Portal) HandleMessageRevoke(user *User, info *types.MessageInfo, k
|
|||
return true
|
||||
}
|
||||
|
||||
//func (portal *Portal) HandleFakeMessage(_ *User, message FakeMessage) bool {
|
||||
// if portal.isRecentlyHandled(message.ID) {
|
||||
// return false
|
||||
// }
|
||||
//
|
||||
// content := event.MessageEventContent{
|
||||
// MsgType: event.MsgNotice,
|
||||
// Body: message.Text,
|
||||
// }
|
||||
// if message.Alert {
|
||||
// content.MsgType = event.MsgText
|
||||
// }
|
||||
// _, err := portal.sendMainIntentMessage(content)
|
||||
// if err != nil {
|
||||
// portal.log.Errorfln("Failed to handle fake message %s: %v", message.ID, err)
|
||||
// return true
|
||||
// }
|
||||
//
|
||||
// portal.recentlyHandledLock.Lock()
|
||||
// index := portal.recentlyHandledIndex
|
||||
// portal.recentlyHandledIndex = (portal.recentlyHandledIndex + 1) % recentlyHandledLength
|
||||
// portal.recentlyHandledLock.Unlock()
|
||||
// portal.recentlyHandled[index] = message.ID
|
||||
// return true
|
||||
//}
|
||||
|
||||
func (portal *Portal) sendMainIntentMessage(content interface{}) (*mautrix.RespSendEvent, error) {
|
||||
return portal.sendMessage(portal.MainIntent(), event.EventMessage, content, 0)
|
||||
func (portal *Portal) sendMainIntentMessage(content *event.MessageEventContent) (*mautrix.RespSendEvent, error) {
|
||||
return portal.sendMessage(portal.MainIntent(), event.EventMessage, content, nil, 0)
|
||||
}
|
||||
|
||||
func (portal *Portal) encrypt(content *event.Content, eventType event.Type) (event.Type, error) {
|
||||
|
@ -1486,12 +1468,13 @@ func (portal *Portal) encrypt(content *event.Content, eventType event.Type) (eve
|
|||
return eventType, nil
|
||||
}
|
||||
|
||||
func (portal *Portal) sendMessage(intent *appservice.IntentAPI, eventType event.Type, content interface{}, timestamp int64) (*mautrix.RespSendEvent, error) {
|
||||
wrappedContent := event.Content{Parsed: content}
|
||||
func (portal *Portal) sendMessage(intent *appservice.IntentAPI, eventType event.Type, content *event.MessageEventContent, extraContent map[string]interface{}, timestamp int64) (*mautrix.RespSendEvent, error) {
|
||||
wrappedContent := event.Content{Parsed: content, Raw: extraContent}
|
||||
if timestamp != 0 && intent.IsCustomPuppet {
|
||||
wrappedContent.Raw = map[string]interface{}{
|
||||
"net.maunium.whatsapp.puppet": intent.IsCustomPuppet,
|
||||
if wrappedContent.Raw == nil {
|
||||
wrappedContent.Raw = map[string]interface{}{}
|
||||
}
|
||||
wrappedContent.Raw[doublePuppetField] = intent.IsCustomPuppet
|
||||
}
|
||||
var err error
|
||||
eventType, err = portal.encrypt(&wrappedContent, eventType)
|
||||
|
@ -1510,6 +1493,7 @@ type ConvertedMessage struct {
|
|||
Intent *appservice.IntentAPI
|
||||
Type event.Type
|
||||
Content *event.MessageEventContent
|
||||
Extra map[string]interface{}
|
||||
Caption *event.MessageEventContent
|
||||
}
|
||||
|
||||
|
@ -1531,57 +1515,6 @@ func (portal *Portal) convertTextMessage(intent *appservice.IntentAPI, msg *waPr
|
|||
return &ConvertedMessage{Intent: intent, Type: event.EventMessage, Content: content}
|
||||
}
|
||||
|
||||
//func (portal *Portal) HandleStubMessage(source *User, message whatsapp.StubMessage, isBackfill bool) bool {
|
||||
// if portal.bridge.Config.Bridge.ChatMetaSync && (!portal.IsBroadcastList() || isBackfill) {
|
||||
// // Chat meta sync is enabled, so we use chat update commands and full-syncs instead of message history
|
||||
// // However, broadcast lists don't have update commands, so we handle these if it's not a backfill
|
||||
// return false
|
||||
// }
|
||||
// intent := portal.startHandling(source, message.Info, fmt.Sprintf("stub %s", message.Type.String()))
|
||||
// if intent == nil {
|
||||
// return false
|
||||
// }
|
||||
// var senderJID string
|
||||
// if message.Info.FromMe {
|
||||
// senderJID = source.JID
|
||||
// } else {
|
||||
// senderJID = message.Info.SenderJid
|
||||
// }
|
||||
// var eventID id.EventID
|
||||
// // TODO find more real event IDs
|
||||
// // TODO timestamp massaging
|
||||
// switch message.Type {
|
||||
// case waProto.WebMessageInfo_GROUP_CHANGE_SUBJECT:
|
||||
// portal.UpdateName(message.FirstParam, "", intent, true)
|
||||
// case waProto.WebMessageInfo_GROUP_CHANGE_ICON:
|
||||
// portal.UpdateAvatar(source, nil, true)
|
||||
// case waProto.WebMessageInfo_GROUP_CHANGE_DESCRIPTION:
|
||||
// if isBackfill {
|
||||
// // TODO fetch topic from server
|
||||
// }
|
||||
// //portal.UpdateTopic(message.FirstParam, "", intent, true)
|
||||
// case waProto.WebMessageInfo_GROUP_CHANGE_ANNOUNCE:
|
||||
// eventID = portal.RestrictMessageSending(message.FirstParam == "on")
|
||||
// case waProto.WebMessageInfo_GROUP_CHANGE_RESTRICT:
|
||||
// eventID = portal.RestrictMetadataChanges(message.FirstParam == "on")
|
||||
// case waProto.WebMessageInfo_GROUP_PARTICIPANT_ADD, waProto.WebMessageInfo_GROUP_PARTICIPANT_INVITE, waProto.WebMessageInfo_BROADCAST_ADD:
|
||||
// eventID = portal.HandleWhatsAppInvite(source, senderJID, intent, message.Params)
|
||||
// case waProto.WebMessageInfo_GROUP_PARTICIPANT_REMOVE, waProto.WebMessageInfo_GROUP_PARTICIPANT_LEAVE, waProto.WebMessageInfo_BROADCAST_REMOVE:
|
||||
// portal.HandleWhatsAppKick(source, senderJID, message.Params)
|
||||
// case waProto.WebMessageInfo_GROUP_PARTICIPANT_PROMOTE:
|
||||
// eventID = portal.ChangeAdminStatus(message.Params, true)
|
||||
// case waProto.WebMessageInfo_GROUP_PARTICIPANT_DEMOTE:
|
||||
// eventID = portal.ChangeAdminStatus(message.Params, false)
|
||||
// default:
|
||||
// return false
|
||||
// }
|
||||
// if len(eventID) == 0 {
|
||||
// eventID = id.EventID(fmt.Sprintf("net.maunium.whatsapp.fake::%s", message.Info.Id))
|
||||
// }
|
||||
// portal.markHandled(source, message.Info.Source, eventID, true)
|
||||
// return true
|
||||
//}
|
||||
|
||||
func (portal *Portal) convertLocationMessage(intent *appservice.IntentAPI, msg *waProto.LocationMessage) *ConvertedMessage {
|
||||
url := msg.GetUrl()
|
||||
if len(url) == 0 {
|
||||
|
@ -1630,6 +1563,33 @@ func (portal *Portal) convertLocationMessage(intent *appservice.IntentAPI, msg *
|
|||
return &ConvertedMessage{Intent: intent, Type: event.EventMessage, Content: content}
|
||||
}
|
||||
|
||||
const inviteMsg = `<a href="https://matrix.to/#/%s">%s</a> has invited you to join %s:
|
||||
<blockquote>%s</blockquote>
|
||||
The invite expires at %s. Reply to this message with <code>!wa accept</code> to accept the invite.`
|
||||
const inviteMetaField = "fi.mau.whatsapp.invite"
|
||||
|
||||
func (portal *Portal) convertGroupInviteMessage(intent *appservice.IntentAPI, info *types.MessageInfo, msg *waProto.GroupInviteMessage) *ConvertedMessage {
|
||||
puppet := portal.bridge.GetPuppetByJID(info.Sender)
|
||||
expiry := time.Unix(msg.GetInviteExpiration(), 0)
|
||||
htmlMessage := fmt.Sprintf(inviteMsg, intent.UserID, html.EscapeString(puppet.Displayname), msg.GetGroupName(), html.EscapeString(msg.GetCaption()), expiry)
|
||||
content := &event.MessageEventContent{
|
||||
MsgType: event.MsgText,
|
||||
Body: format.HTMLToText(htmlMessage),
|
||||
Format: event.FormatHTML,
|
||||
FormattedBody: htmlMessage,
|
||||
}
|
||||
extraAttrs := map[string]interface{}{
|
||||
inviteMetaField: map[string]interface{}{
|
||||
"jid": msg.GetGroupJid(),
|
||||
"code": msg.GetInviteCode(),
|
||||
"expiration": strconv.FormatInt(msg.GetInviteExpiration(), 10),
|
||||
"inviter": info.Sender.ToNonAD().String(),
|
||||
},
|
||||
}
|
||||
portal.SetReply(content, msg.GetContextInfo().GetStanzaId())
|
||||
return &ConvertedMessage{Intent: intent, Type: event.EventMessage, Content: content, Extra: extraAttrs}
|
||||
}
|
||||
|
||||
func (portal *Portal) convertContactMessage(intent *appservice.IntentAPI, msg *waProto.ContactMessage) *ConvertedMessage {
|
||||
fileName := fmt.Sprintf("%s.vcf", msg.GetDisplayName())
|
||||
data := []byte(msg.GetVcard())
|
||||
|
@ -1721,7 +1681,7 @@ func (portal *Portal) leaveWithPuppetMeta(intent *appservice.IntentAPI) (*mautri
|
|||
Membership: event.MembershipLeave,
|
||||
},
|
||||
Raw: map[string]interface{}{
|
||||
"net.maunium.whatsapp.puppet": true,
|
||||
doublePuppetField: true,
|
||||
},
|
||||
}
|
||||
return intent.SendStateEvent(portal.MXID, event.StateMember, intent.UserID.String(), &content)
|
||||
|
@ -1743,7 +1703,7 @@ func (portal *Portal) HandleWhatsAppInvite(source *User, senderJID *types.JID, j
|
|||
AvatarURL: puppet.AvatarURL.CUString(),
|
||||
},
|
||||
Raw: map[string]interface{}{
|
||||
"net.maunium.whatsapp.puppet": true,
|
||||
doublePuppetField: true,
|
||||
},
|
||||
}
|
||||
resp, err := intent.SendStateEvent(portal.MXID, event.StateMember, puppet.MXID.String(), &content)
|
||||
|
@ -2211,7 +2171,6 @@ func (portal *Portal) convertMatrixMessage(sender *User, evt *event.Event) (*waP
|
|||
var ctxInfo waProto.ContextInfo
|
||||
replyToID := content.GetReplyTo()
|
||||
if len(replyToID) > 0 {
|
||||
content.RemoveReplyFallback()
|
||||
replyToMsg := portal.bridge.DB.Message.GetByMXID(replyToID)
|
||||
if replyToMsg != nil {
|
||||
ctxInfo.StanzaId = &replyToMsg.JID
|
||||
|
@ -2359,7 +2318,7 @@ func (portal *Portal) sendErrorMessage(message string, confirmed bool) id.EventI
|
|||
if confirmed {
|
||||
certainty = "was not"
|
||||
}
|
||||
resp, err := portal.sendMainIntentMessage(event.MessageEventContent{
|
||||
resp, err := portal.sendMainIntentMessage(&event.MessageEventContent{
|
||||
MsgType: event.MsgNotice,
|
||||
Body: fmt.Sprintf("\u26a0 Your message %s bridged: %v", certainty, message),
|
||||
})
|
||||
|
|
Loading…
Reference in a new issue