forked from MirrorHub/mautrix-whatsapp
Bridge incoming votes in MSC3381 polls
This commit is contained in:
parent
beb956973e
commit
b8dc3c0e56
3 changed files with 85 additions and 5 deletions
2
main.go
2
main.go
|
@ -87,6 +87,8 @@ func (br *WABridge) Init() {
|
||||||
|
|
||||||
// TODO this is a weird place for this
|
// TODO this is a weird place for this
|
||||||
br.EventProcessor.On(event.EphemeralEventPresence, br.HandlePresence)
|
br.EventProcessor.On(event.EphemeralEventPresence, br.HandlePresence)
|
||||||
|
br.EventProcessor.On(TypeMSC3881PollResponse, br.MatrixHandler.HandleMessage)
|
||||||
|
br.EventProcessor.On(TypeMSC3881V2PollResponse, br.MatrixHandler.HandleMessage)
|
||||||
|
|
||||||
Segment.log = br.Log.Sub("Segment")
|
Segment.log = br.Log.Sub("Segment")
|
||||||
Segment.key = br.Config.SegmentKey
|
Segment.key = br.Config.SegmentKey
|
||||||
|
|
|
@ -185,6 +185,8 @@ func (portal *Portal) sendMessageMetrics(evt *event.Event, err error, part strin
|
||||||
msgType = "reaction"
|
msgType = "reaction"
|
||||||
case event.EventRedaction:
|
case event.EventRedaction:
|
||||||
msgType = "redaction"
|
msgType = "redaction"
|
||||||
|
case TypeMSC3881PollResponse, TypeMSC3881V2PollResponse:
|
||||||
|
msgType = "poll response"
|
||||||
default:
|
default:
|
||||||
msgType = "unknown event"
|
msgType = "unknown event"
|
||||||
}
|
}
|
||||||
|
|
86
portal.go
86
portal.go
|
@ -33,6 +33,7 @@ import (
|
||||||
"math"
|
"math"
|
||||||
"mime"
|
"mime"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"reflect"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -315,7 +316,7 @@ func (portal *Portal) handleMatrixMessageLoopItem(msg PortalMatrixMessage) {
|
||||||
portal.handleMatrixReadReceipt(msg.user, "", evtTS, false)
|
portal.handleMatrixReadReceipt(msg.user, "", evtTS, false)
|
||||||
timings.implicitRR = time.Since(implicitRRStart)
|
timings.implicitRR = time.Since(implicitRRStart)
|
||||||
switch msg.evt.Type {
|
switch msg.evt.Type {
|
||||||
case event.EventMessage, event.EventSticker:
|
case event.EventMessage, event.EventSticker, TypeMSC3881V2PollResponse, TypeMSC3881PollResponse:
|
||||||
portal.HandleMatrixMessage(msg.user, msg.evt, timings)
|
portal.HandleMatrixMessage(msg.user, msg.evt, timings)
|
||||||
case event.EventRedaction:
|
case event.EventRedaction:
|
||||||
portal.HandleMatrixRedaction(msg.user, msg.evt)
|
portal.HandleMatrixRedaction(msg.user, msg.evt)
|
||||||
|
@ -2121,9 +2122,9 @@ func (portal *Portal) convertPollUpdateMessage(intent *appservice.IntentAPI, sou
|
||||||
selectedHashes[i] = hex.EncodeToString(opt)
|
selectedHashes[i] = hex.EncodeToString(opt)
|
||||||
}
|
}
|
||||||
|
|
||||||
evtType := event.Type{Class: event.MessageEventType, Type: "org.matrix.msc3381.poll.response"}
|
evtType := TypeMSC3881PollResponse
|
||||||
if portal.bridge.Config.Bridge.ExtEvPolls == 2 {
|
if portal.bridge.Config.Bridge.ExtEvPolls == 2 {
|
||||||
evtType.Type = "org.matrix.msc3381.v2.poll.response"
|
evtType = TypeMSC3881V2PollResponse
|
||||||
}
|
}
|
||||||
return &ConvertedMessage{
|
return &ConvertedMessage{
|
||||||
Intent: intent,
|
Intent: intent,
|
||||||
|
@ -3333,7 +3334,81 @@ func getUnstableWaveform(content map[string]interface{}) []byte {
|
||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
TypeMSC3881PollResponse = event.Type{Class: event.MessageEventType, Type: "org.matrix.msc3381.poll.response"}
|
||||||
|
TypeMSC3881V2PollResponse = event.Type{Class: event.MessageEventType, Type: "org.matrix.msc3881.v2.poll.response"}
|
||||||
|
)
|
||||||
|
|
||||||
|
type PollResponseContent struct {
|
||||||
|
RelatesTo event.RelatesTo `json:"m.relates_to"`
|
||||||
|
V1Response struct {
|
||||||
|
Answers []string `json:"answers"`
|
||||||
|
} `json:"org.matrix.msc3381.poll.response"`
|
||||||
|
V2Selections []string `json:"org.matrix.msc3381.v2.selections"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (content *PollResponseContent) GetRelatesTo() *event.RelatesTo {
|
||||||
|
return &content.RelatesTo
|
||||||
|
}
|
||||||
|
|
||||||
|
func (content *PollResponseContent) OptionalGetRelatesTo() *event.RelatesTo {
|
||||||
|
if content.RelatesTo.Type == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &content.RelatesTo
|
||||||
|
}
|
||||||
|
|
||||||
|
func (content *PollResponseContent) SetRelatesTo(rel *event.RelatesTo) {
|
||||||
|
content.RelatesTo = *rel
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
event.TypeMap[TypeMSC3881PollResponse] = reflect.TypeOf(PollResponseContent{})
|
||||||
|
event.TypeMap[TypeMSC3881V2PollResponse] = reflect.TypeOf(PollResponseContent{})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (portal *Portal) convertMatrixPollVote(_ context.Context, sender *User, evt *event.Event) (*waProto.Message, *User, error) {
|
||||||
|
content, ok := evt.Content.Parsed.(*PollResponseContent)
|
||||||
|
if !ok {
|
||||||
|
return nil, sender, fmt.Errorf("%w %T", errUnexpectedParsedContentType, evt.Content.Parsed)
|
||||||
|
}
|
||||||
|
var answers []string
|
||||||
|
if content.V1Response.Answers != nil {
|
||||||
|
answers = content.V1Response.Answers
|
||||||
|
} else if content.V2Selections != nil {
|
||||||
|
answers = content.V2Selections
|
||||||
|
}
|
||||||
|
pollMsg := portal.bridge.DB.Message.GetByMXID(content.RelatesTo.EventID)
|
||||||
|
if pollMsg == nil {
|
||||||
|
return nil, sender, errTargetNotFound
|
||||||
|
}
|
||||||
|
pollMsgInfo := &types.MessageInfo{
|
||||||
|
MessageSource: types.MessageSource{
|
||||||
|
Chat: portal.Key.JID,
|
||||||
|
Sender: pollMsg.Sender,
|
||||||
|
IsFromMe: pollMsg.Sender.User == sender.JID.User,
|
||||||
|
IsGroup: portal.IsGroupChat(),
|
||||||
|
},
|
||||||
|
ID: pollMsg.JID,
|
||||||
|
Type: "poll",
|
||||||
|
}
|
||||||
|
optionHashes := make([][]byte, 0, len(answers))
|
||||||
|
for _, selection := range answers {
|
||||||
|
hash, _ := hex.DecodeString(selection)
|
||||||
|
if hash != nil && len(hash) == 32 {
|
||||||
|
optionHashes = append(optionHashes, hash)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pollUpdate, err := sender.Client.EncryptPollVote(pollMsgInfo, &waProto.PollVoteMessage{
|
||||||
|
SelectedOptions: optionHashes,
|
||||||
|
})
|
||||||
|
return &waProto.Message{PollUpdateMessage: pollUpdate}, sender, err
|
||||||
|
}
|
||||||
|
|
||||||
func (portal *Portal) convertMatrixMessage(ctx context.Context, sender *User, evt *event.Event) (*waProto.Message, *User, error) {
|
func (portal *Portal) convertMatrixMessage(ctx context.Context, sender *User, evt *event.Event) (*waProto.Message, *User, error) {
|
||||||
|
if evt.Type == TypeMSC3881PollResponse || evt.Type == TypeMSC3881V2PollResponse {
|
||||||
|
return portal.convertMatrixPollVote(ctx, sender, evt)
|
||||||
|
}
|
||||||
content, ok := evt.Content.Parsed.(*event.MessageEventContent)
|
content, ok := evt.Content.Parsed.(*event.MessageEventContent)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, sender, fmt.Errorf("%w %T", errUnexpectedParsedContentType, evt.Content.Parsed)
|
return nil, sender, fmt.Errorf("%w %T", errUnexpectedParsedContentType, evt.Content.Parsed)
|
||||||
|
@ -3351,7 +3426,7 @@ func (portal *Portal) convertMatrixMessage(ctx context.Context, sender *User, ev
|
||||||
|
|
||||||
msg := &waProto.Message{}
|
msg := &waProto.Message{}
|
||||||
var ctxInfo waProto.ContextInfo
|
var ctxInfo waProto.ContextInfo
|
||||||
replyToID := content.GetReplyTo()
|
replyToID := content.RelatesTo.GetReplyTo()
|
||||||
if len(replyToID) > 0 {
|
if len(replyToID) > 0 {
|
||||||
replyToMsg := portal.bridge.DB.Message.GetByMXID(replyToID)
|
replyToMsg := portal.bridge.DB.Message.GetByMXID(replyToID)
|
||||||
if replyToMsg != nil && !replyToMsg.IsFakeJID() && replyToMsg.Type == database.MsgNormal {
|
if replyToMsg != nil && !replyToMsg.IsFakeJID() && replyToMsg.Type == database.MsgNormal {
|
||||||
|
@ -3570,7 +3645,8 @@ func (portal *Portal) HandleMatrixMessage(sender *User, evt *event.Event, timing
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
ms := metricSender{portal: portal, timings: &timings}
|
ms := metricSender{portal: portal, timings: &timings}
|
||||||
|
|
||||||
if err := portal.canBridgeFrom(sender, true); err != nil {
|
allowRelay := evt.Type != TypeMSC3881PollResponse && evt.Type != TypeMSC3881V2PollResponse
|
||||||
|
if err := portal.canBridgeFrom(sender, allowRelay); err != nil {
|
||||||
go ms.sendMessageMetrics(evt, err, "Ignoring", true)
|
go ms.sendMessageMetrics(evt, err, "Ignoring", true)
|
||||||
return
|
return
|
||||||
} else if portal.Key.JID == types.StatusBroadcastJID && portal.bridge.Config.Bridge.DisableStatusBroadcastSend {
|
} else if portal.Key.JID == types.StatusBroadcastJID && portal.bridge.Config.Bridge.DisableStatusBroadcastSend {
|
||||||
|
|
Loading…
Reference in a new issue