Add support for reactions from Matrix
This commit is contained in:
parent
376f908a03
commit
b5257f53d3
3 changed files with 85 additions and 5 deletions
|
@ -4,7 +4,7 @@
|
|||
* [x] Plain text
|
||||
* [ ] Media/files
|
||||
* [x] Replies (RCS)
|
||||
* [ ] Reactions (RCS)
|
||||
* [x] Reactions (RCS)
|
||||
* [ ] Typing notifications (RCS)
|
||||
* [ ] Read receipts (RCS)
|
||||
* Google Messages → Matrix
|
||||
|
@ -12,9 +12,9 @@
|
|||
* [x] Plain text
|
||||
* [x] Media/files
|
||||
* [x] Replies (RCS)
|
||||
* [ ] Reactions
|
||||
* [ ] Typing notifications
|
||||
* [ ] Read receipts
|
||||
* [x] Reactions (RCS)
|
||||
* [ ] Typing notifications (RCS)
|
||||
* [ ] Read receipts (RCS)
|
||||
* Misc
|
||||
* [x] Automatic portal creation
|
||||
* [x] After login
|
||||
|
|
|
@ -39,6 +39,7 @@ var (
|
|||
errUnexpectedParsedContentType = errors.New("unexpected parsed content type")
|
||||
errUnknownMsgType = errors.New("unknown msgtype")
|
||||
errMediaUnsupportedType = errors.New("unsupported media type")
|
||||
errTargetNotFound = errors.New("target event not found")
|
||||
|
||||
errMessageTakingLong = errors.New("bridging the message is taking longer than usual")
|
||||
)
|
||||
|
@ -73,6 +74,8 @@ func errorToStatusReason(err error) (reason event.MessageStatusReason, status ev
|
|||
return event.MessageStatusUnsupported, event.MessageStatusFail, true, true, err.Error()
|
||||
case errors.Is(err, context.DeadlineExceeded):
|
||||
return event.MessageStatusTooOld, event.MessageStatusRetriable, false, true, "handling the message took too long and was cancelled"
|
||||
case errors.Is(err, errTargetNotFound):
|
||||
return event.MessageStatusGenericError, event.MessageStatusFail, true, false, ""
|
||||
case errors.As(err, &ose):
|
||||
return event.MessageStatusNetworkError, event.MessageStatusFail, true, true, ose.HumanError()
|
||||
default:
|
||||
|
@ -187,6 +190,9 @@ func (portal *Portal) sendMessageMetrics(evt *event.Event, err error, part strin
|
|||
portal.log.Debugfln("Handled Matrix %s %s", msgType, evtDescription)
|
||||
portal.sendDeliveryReceipt(evt.ID)
|
||||
portal.bridge.SendMessageSuccessCheckpoint(evt, status.MsgStepRemote, ms.getRetryNum())
|
||||
if msgType != "message" {
|
||||
portal.sendStatusEvent(origEvtID, evt.ID, nil)
|
||||
}
|
||||
if prevNotice := ms.popNoticeID(); prevNotice != "" {
|
||||
_, _ = portal.MainIntent().RedactEvent(portal.MXID, prevNotice, mautrix.ReqRedact{
|
||||
Reason: "error resolved",
|
||||
|
|
76
portal.go
76
portal.go
|
@ -1174,7 +1174,10 @@ func (portal *Portal) uploadMedia(intent *appservice.IntentAPI, data []byte, con
|
|||
func (portal *Portal) HandleMatrixMessage(sender *User, evt *event.Event, timings messageTimings) {
|
||||
ms := metricSender{portal: portal, timings: &timings}
|
||||
|
||||
log := portal.zlog.With().Str("event_id", evt.ID.String()).Logger()
|
||||
log := portal.zlog.With().
|
||||
Str("event_id", evt.ID.String()).
|
||||
Str("action", "handle matrix message").
|
||||
Logger()
|
||||
ctx := log.WithContext(context.TODO())
|
||||
log.Debug().Dur("age", timings.totalReceive).Msg("Handling Matrix message")
|
||||
|
||||
|
@ -1225,7 +1228,78 @@ func (portal *Portal) HandleMatrixMessage(sender *User, evt *event.Event, timing
|
|||
}
|
||||
|
||||
func (portal *Portal) HandleMatrixReaction(sender *User, evt *event.Event) {
|
||||
err := portal.handleMatrixReaction(sender, evt)
|
||||
go portal.sendMessageMetrics(evt, err, "Error sending", nil)
|
||||
}
|
||||
|
||||
func (portal *Portal) handleMatrixReaction(sender *User, evt *event.Event) error {
|
||||
content, ok := evt.Content.Parsed.(*event.ReactionEventContent)
|
||||
if !ok {
|
||||
return fmt.Errorf("unexpected parsed content type %T", evt.Content.Parsed)
|
||||
}
|
||||
log := portal.zlog.With().
|
||||
Str("event_id", evt.ID.String()).
|
||||
Str("target_event_id", content.RelatesTo.EventID.String()).
|
||||
Str("action", "handle matrix reaction").
|
||||
Logger()
|
||||
ctx := log.WithContext(context.Background())
|
||||
log.Debug().Msg("Handling Matrix reaction")
|
||||
|
||||
msg, err := portal.bridge.DB.Message.GetByMXID(ctx, content.RelatesTo.EventID)
|
||||
if err != nil {
|
||||
log.Err(err).Msg("Failed to get reaction target event")
|
||||
return fmt.Errorf("failed to get event from database")
|
||||
} else if msg == nil {
|
||||
return errTargetNotFound
|
||||
}
|
||||
|
||||
existingReaction, err := portal.bridge.DB.Reaction.GetByID(ctx, portal.Key, msg.ID, portal.SelfUserID)
|
||||
if err != nil {
|
||||
log.Err(err).Msg("Failed to get existing reaction")
|
||||
return fmt.Errorf("failed to get existing reaction from database")
|
||||
}
|
||||
|
||||
emoji := variationselector.Remove(content.RelatesTo.Key)
|
||||
action := binary.Reaction_ADD
|
||||
if existingReaction != nil {
|
||||
action = binary.Reaction_SWITCH
|
||||
}
|
||||
resp, err := sender.Client.Messages.React(&binary.SendReactionPayload{
|
||||
MessageID: msg.ID,
|
||||
ReactionData: &binary.ReactionData{
|
||||
Unicode: emoji,
|
||||
Type: binary.UnicodeToEmojiType(emoji),
|
||||
},
|
||||
Action: action,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to send reaction: %w", err)
|
||||
} else if !resp.Success {
|
||||
return fmt.Errorf("got non-success response")
|
||||
}
|
||||
if existingReaction == nil {
|
||||
existingReaction = portal.bridge.DB.Reaction.New()
|
||||
existingReaction.Chat = portal.Key
|
||||
existingReaction.MessageID = msg.ID
|
||||
existingReaction.Sender = portal.SelfUserID
|
||||
} else if sender.DoublePuppetIntent != nil {
|
||||
_, err = sender.DoublePuppetIntent.RedactEvent(portal.MXID, existingReaction.MXID)
|
||||
if err != nil {
|
||||
log.Err(err).Msg("Failed to redact old reaction with double puppet after new Matrix reaction")
|
||||
}
|
||||
} else {
|
||||
_, err = portal.MainIntent().RedactEvent(portal.MXID, existingReaction.MXID)
|
||||
if err != nil {
|
||||
log.Err(err).Msg("Failed to redact old reaction with main intent after new Matrix reaction")
|
||||
}
|
||||
}
|
||||
existingReaction.Reaction = emoji
|
||||
existingReaction.MXID = evt.ID
|
||||
err = existingReaction.Insert(ctx)
|
||||
if err != nil {
|
||||
log.Err(err).Msg("Failed to save reaction from Matrix to database")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (portal *Portal) Delete() {
|
||||
|
|
Loading…
Reference in a new issue