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
|
* [x] Plain text
|
||||||
* [ ] Media/files
|
* [ ] Media/files
|
||||||
* [x] Replies (RCS)
|
* [x] Replies (RCS)
|
||||||
* [ ] Reactions (RCS)
|
* [x] Reactions (RCS)
|
||||||
* [ ] Typing notifications (RCS)
|
* [ ] Typing notifications (RCS)
|
||||||
* [ ] Read receipts (RCS)
|
* [ ] Read receipts (RCS)
|
||||||
* Google Messages → Matrix
|
* Google Messages → Matrix
|
||||||
|
@ -12,9 +12,9 @@
|
||||||
* [x] Plain text
|
* [x] Plain text
|
||||||
* [x] Media/files
|
* [x] Media/files
|
||||||
* [x] Replies (RCS)
|
* [x] Replies (RCS)
|
||||||
* [ ] Reactions
|
* [x] Reactions (RCS)
|
||||||
* [ ] Typing notifications
|
* [ ] Typing notifications (RCS)
|
||||||
* [ ] Read receipts
|
* [ ] Read receipts (RCS)
|
||||||
* Misc
|
* Misc
|
||||||
* [x] Automatic portal creation
|
* [x] Automatic portal creation
|
||||||
* [x] After login
|
* [x] After login
|
||||||
|
|
|
@ -39,6 +39,7 @@ var (
|
||||||
errUnexpectedParsedContentType = errors.New("unexpected parsed content type")
|
errUnexpectedParsedContentType = errors.New("unexpected parsed content type")
|
||||||
errUnknownMsgType = errors.New("unknown msgtype")
|
errUnknownMsgType = errors.New("unknown msgtype")
|
||||||
errMediaUnsupportedType = errors.New("unsupported media type")
|
errMediaUnsupportedType = errors.New("unsupported media type")
|
||||||
|
errTargetNotFound = errors.New("target event not found")
|
||||||
|
|
||||||
errMessageTakingLong = errors.New("bridging the message is taking longer than usual")
|
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()
|
return event.MessageStatusUnsupported, event.MessageStatusFail, true, true, err.Error()
|
||||||
case errors.Is(err, context.DeadlineExceeded):
|
case errors.Is(err, context.DeadlineExceeded):
|
||||||
return event.MessageStatusTooOld, event.MessageStatusRetriable, false, true, "handling the message took too long and was cancelled"
|
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):
|
case errors.As(err, &ose):
|
||||||
return event.MessageStatusNetworkError, event.MessageStatusFail, true, true, ose.HumanError()
|
return event.MessageStatusNetworkError, event.MessageStatusFail, true, true, ose.HumanError()
|
||||||
default:
|
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.log.Debugfln("Handled Matrix %s %s", msgType, evtDescription)
|
||||||
portal.sendDeliveryReceipt(evt.ID)
|
portal.sendDeliveryReceipt(evt.ID)
|
||||||
portal.bridge.SendMessageSuccessCheckpoint(evt, status.MsgStepRemote, ms.getRetryNum())
|
portal.bridge.SendMessageSuccessCheckpoint(evt, status.MsgStepRemote, ms.getRetryNum())
|
||||||
|
if msgType != "message" {
|
||||||
|
portal.sendStatusEvent(origEvtID, evt.ID, nil)
|
||||||
|
}
|
||||||
if prevNotice := ms.popNoticeID(); prevNotice != "" {
|
if prevNotice := ms.popNoticeID(); prevNotice != "" {
|
||||||
_, _ = portal.MainIntent().RedactEvent(portal.MXID, prevNotice, mautrix.ReqRedact{
|
_, _ = portal.MainIntent().RedactEvent(portal.MXID, prevNotice, mautrix.ReqRedact{
|
||||||
Reason: "error resolved",
|
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) {
|
func (portal *Portal) HandleMatrixMessage(sender *User, evt *event.Event, timings messageTimings) {
|
||||||
ms := metricSender{portal: portal, timings: &timings}
|
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())
|
ctx := log.WithContext(context.TODO())
|
||||||
log.Debug().Dur("age", timings.totalReceive).Msg("Handling Matrix message")
|
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) {
|
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() {
|
func (portal *Portal) Delete() {
|
||||||
|
|
Loading…
Reference in a new issue