From 74ed9c35d2385cbeaa1c4e25ffbae970fffaeed2 Mon Sep 17 00:00:00 2001 From: Sumner Evans Date: Wed, 17 Nov 2021 09:54:20 -0700 Subject: [PATCH] AppService.handleEvents: send BRIDGE checkpoint automatically --- appservice/appservice.go | 2 ++ appservice/http.go | 23 +++++++++++++++++ bridge/message_send_checkpoint.go | 41 +++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+) diff --git a/appservice/appservice.go b/appservice/appservice.go index f6853edd..051d4d67 100644 --- a/appservice/appservice.go +++ b/appservice/appservice.go @@ -109,6 +109,8 @@ type AppService struct { botClient *mautrix.Client botIntent *IntentAPI + MessageSendCheckpointEndpoint string + DefaultHTTPRetries int Live bool diff --git a/appservice/http.go b/appservice/http.go index 6b68b3df..7713d242 100644 --- a/appservice/http.go +++ b/appservice/http.go @@ -18,6 +18,7 @@ import ( "github.com/gorilla/mux" "maunium.net/go/mautrix" + "maunium.net/go/mautrix/bridge" "maunium.net/go/mautrix/event" "maunium.net/go/mautrix/id" ) @@ -197,6 +198,9 @@ func (as *AppService) handleEvents(evts []*event.Event, defaultTypeClass event.T } else if err != nil { as.Log.Debugfln("Failed to parse content of %s (type %s): %v", evt.ID, evt.Type.Type, err) } + + go as.sendMessageSendCheckpoint(evt) + if evt.Type.IsState() { // TODO remove this check after https://github.com/matrix-org/synapse/pull/11265 historical, ok := evt.Content.Raw["org.matrix.msc2716.historical"].(bool) @@ -208,6 +212,25 @@ func (as *AppService) handleEvents(evts []*event.Event, defaultTypeClass event.T } } +func (as *AppService) sendMessageSendCheckpoint(evt *event.Event) error { + endpoint := as.MessageSendCheckpointEndpoint + if endpoint == "" { + return nil + } + + if _, ok := bridge.GetCheckpointTypes()[evt.Type]; !ok { + return nil + } + + as.Log.Debugfln("Sending message send checkpoint for %s to API server", evt.ID) + + checkpoint := bridge.NewMessageSendCheckpoint(evt.ID, evt.RoomID, bridge.StepBridge, bridge.StatusSuccesss, evt.Type) + if evt.Type == event.EventMessage { + checkpoint.MessageType = evt.Content.AsMessage().MsgType + } + return checkpoint.Send(endpoint, as.Registration.AppToken) +} + // GetRoom handles a /rooms GET call from the homeserver. func (as *AppService) GetRoom(w http.ResponseWriter, r *http.Request) { if !as.CheckServerToken(w, r) { diff --git a/bridge/message_send_checkpoint.go b/bridge/message_send_checkpoint.go index cdc244bf..bf6cb79b 100644 --- a/bridge/message_send_checkpoint.go +++ b/bridge/message_send_checkpoint.go @@ -58,6 +58,47 @@ type MessageSendCheckpoint struct { Info string `json:"info"` } +func NewMessageSendCheckpoint(eventID id.EventID, roomID id.RoomID, step MessageSendCheckpointStep, status MessageSendCheckpointStatus, eventType event.Type) *MessageSendCheckpoint { + return &MessageSendCheckpoint{ + EventID: eventID, + RoomID: roomID, + Step: step, + Timestamp: time.Now(), + Status: status, + EventType: eventType, + ReportedBy: ReportedByBridge, + } +} + +func NewErrorMessageSendCheckpoint(eventID id.EventID, roomID id.RoomID, step MessageSendCheckpointStep, eventType event.Type, err error) *MessageSendCheckpoint { + return &MessageSendCheckpoint{ + EventID: eventID, + RoomID: roomID, + Step: step, + Timestamp: time.Now(), + Status: StatusPermFailure, + EventType: eventType, + ReportedBy: ReportedByBridge, + } +} + +func GetCheckpointTypes() map[event.Type]interface{} { + return map[event.Type]interface{}{ + event.EventRedaction: struct{}{}, + event.EventMessage: struct{}{}, + event.EventEncrypted: struct{}{}, + event.EventSticker: struct{}{}, + event.EventReaction: struct{}{}, + event.CallInvite: struct{}{}, + event.CallCandidates: struct{}{}, + event.CallSelectAnswer: struct{}{}, + event.CallAnswer: struct{}{}, + event.CallHangup: struct{}{}, + event.CallReject: struct{}{}, + event.CallNegotiate: struct{}{}, + } +} + func (cp *MessageSendCheckpoint) Send(endpoint string, asToken string) error { return SendCheckpoints(endpoint, asToken, []*MessageSendCheckpoint{cp}) }