diff --git a/bridgestate.go b/bridgestate.go index c269c13..3062a22 100644 --- a/bridgestate.go +++ b/bridgestate.go @@ -20,23 +20,23 @@ import ( "fmt" "net/http" - "maunium.net/go/mautrix/bridge" + "maunium.net/go/mautrix/bridge/status" "maunium.net/go/mautrix/id" ) const ( - WALoggedOut bridge.StateErrorCode = "wa-logged-out" - WAMainDeviceGone bridge.StateErrorCode = "wa-main-device-gone" - WAUnknownLogout bridge.StateErrorCode = "wa-unknown-logout" - WANotConnected bridge.StateErrorCode = "wa-not-connected" - WAConnecting bridge.StateErrorCode = "wa-connecting" - WAKeepaliveTimeout bridge.StateErrorCode = "wa-keepalive-timeout" - WAPhoneOffline bridge.StateErrorCode = "wa-phone-offline" - WAConnectionFailed bridge.StateErrorCode = "wa-connection-failed" + WALoggedOut status.BridgeStateErrorCode = "wa-logged-out" + WAMainDeviceGone status.BridgeStateErrorCode = "wa-main-device-gone" + WAUnknownLogout status.BridgeStateErrorCode = "wa-unknown-logout" + WANotConnected status.BridgeStateErrorCode = "wa-not-connected" + WAConnecting status.BridgeStateErrorCode = "wa-connecting" + WAKeepaliveTimeout status.BridgeStateErrorCode = "wa-keepalive-timeout" + WAPhoneOffline status.BridgeStateErrorCode = "wa-phone-offline" + WAConnectionFailed status.BridgeStateErrorCode = "wa-connection-failed" ) func init() { - bridge.StateHumanErrors.Update(bridge.StateErrorMap{ + status.BridgeStateHumanErrors.Update(status.BridgeStateErrorMap{ WALoggedOut: "You were logged out from another device. Relogin to continue using the bridge.", WAMainDeviceGone: "Your phone was logged out from WhatsApp. Relogin to continue using the bridge.", WAUnknownLogout: "You were logged out for an unknown reason. Relogin to continue using the bridge.", @@ -68,24 +68,24 @@ func (prov *ProvisioningAPI) BridgeStatePing(w http.ResponseWriter, r *http.Requ } userID := r.URL.Query().Get("user_id") user := prov.bridge.GetUserByMXID(id.UserID(userID)) - var global bridge.State - global.StateEvent = bridge.StateRunning - var remote bridge.State + var global status.BridgeState + global.StateEvent = status.StateRunning + var remote status.BridgeState if user.IsConnected() { if user.Client.IsLoggedIn() { - remote.StateEvent = bridge.StateConnected + remote.StateEvent = status.StateConnected } else if user.Session != nil { - remote.StateEvent = bridge.StateConnecting + remote.StateEvent = status.StateConnecting remote.Error = WAConnecting } // else: unconfigured } else if user.Session != nil { - remote.StateEvent = bridge.StateBadCredentials + remote.StateEvent = status.StateBadCredentials remote.Error = WANotConnected } // else: unconfigured global = global.Fill(nil) - resp := bridge.GlobalState{ + resp := status.GlobalBridgeState{ BridgeState: global, - RemoteStates: map[string]bridge.State{}, + RemoteStates: map[string]status.BridgeState{}, } if len(remote.StateEvent) > 0 { remote = remote.Fill(user) diff --git a/commands.go b/commands.go index dbd557d..2c5d11a 100644 --- a/commands.go +++ b/commands.go @@ -38,6 +38,7 @@ import ( "maunium.net/go/mautrix" "maunium.net/go/mautrix/bridge" "maunium.net/go/mautrix/bridge/commands" + "maunium.net/go/mautrix/bridge/status" "maunium.net/go/mautrix/event" "maunium.net/go/mautrix/id" @@ -518,7 +519,7 @@ func fnLogout(ce *WrappedCommandEvent) { return } ce.User.Session = nil - ce.User.removeFromJIDMap(bridge.State{StateEvent: bridge.StateLoggedOut}) + ce.User.removeFromJIDMap(status.BridgeState{StateEvent: status.StateLoggedOut}) ce.User.DeleteConnection() ce.User.DeleteSession() ce.Reply("Logged out successfully.") @@ -575,7 +576,7 @@ func fnDeleteSession(ce *WrappedCommandEvent) { ce.Reply("Nothing to purge: no session information stored and no active connection.") return } - ce.User.removeFromJIDMap(bridge.State{StateEvent: bridge.StateLoggedOut}) + ce.User.removeFromJIDMap(status.BridgeState{StateEvent: status.StateLoggedOut}) ce.User.DeleteConnection() ce.User.DeleteSession() ce.Reply("Session information purged") @@ -600,7 +601,7 @@ func fnReconnect(ce *WrappedCommandEvent) { } } else { ce.User.DeleteConnection() - ce.User.BridgeState.Send(bridge.State{StateEvent: bridge.StateTransientDisconnect, Error: WANotConnected}) + ce.User.BridgeState.Send(status.BridgeState{StateEvent: status.StateTransientDisconnect, Error: WANotConnected}) ce.User.Connect() ce.Reply("Restarted connection to WhatsApp") } @@ -622,7 +623,7 @@ func fnDisconnect(ce *WrappedCommandEvent) { } ce.User.DeleteConnection() ce.Reply("Successfully disconnected. Use the `reconnect` command to reconnect.") - ce.User.BridgeState.Send(bridge.State{StateEvent: bridge.StateBadCredentials, Error: WANotConnected}) + ce.User.BridgeState.Send(status.BridgeState{StateEvent: status.StateBadCredentials, Error: WANotConnected}) } var cmdPing = &commands.FullHandler{ diff --git a/go.mod b/go.mod index 35d381a..360d4f1 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e google.golang.org/protobuf v1.28.0 maunium.net/go/maulogger/v2 v2.3.2 - maunium.net/go/mautrix v0.11.1-0.20220814160431-6f13ea458647 + maunium.net/go/mautrix v0.11.1-0.20220815133425-ba1fce8fce24 ) require ( diff --git a/go.sum b/go.sum index bc15c4d..a429252 100644 --- a/go.sum +++ b/go.sum @@ -122,5 +122,5 @@ maunium.net/go/mauflag v1.0.0 h1:YiaRc0tEI3toYtJMRIfjP+jklH45uDHtT80nUamyD4M= maunium.net/go/mauflag v1.0.0/go.mod h1:nLivPOpTpHnpzEh8jEdSL9UqO9+/KBJFmNRlwKfkPeA= maunium.net/go/maulogger/v2 v2.3.2 h1:1XmIYmMd3PoQfp9J+PaHhpt80zpfmMqaShzUTC7FwY0= maunium.net/go/maulogger/v2 v2.3.2/go.mod h1:TYWy7wKwz/tIXTpsx8G3mZseIRiC5DoMxSZazOHy68A= -maunium.net/go/mautrix v0.11.1-0.20220814160431-6f13ea458647 h1:CbSd7DSU7wXVNEhcjikUDuRtrDwegKFQfO4ZEwIxqgg= -maunium.net/go/mautrix v0.11.1-0.20220814160431-6f13ea458647/go.mod h1:hHvNi5iKVAiI2MAdAeXHtP4g9BvNEX2rsQpSF/x6Kx4= +maunium.net/go/mautrix v0.11.1-0.20220815133425-ba1fce8fce24 h1:40cxOxHwTw+UYdDTV//tHw9bjNMmJ9uH6ye+C1SbOGA= +maunium.net/go/mautrix v0.11.1-0.20220815133425-ba1fce8fce24/go.mod h1:hHvNi5iKVAiI2MAdAeXHtP4g9BvNEX2rsQpSF/x6Kx4= diff --git a/main.go b/main.go index 25c13cb..c3376bd 100644 --- a/main.go +++ b/main.go @@ -36,6 +36,7 @@ import ( "maunium.net/go/mautrix" "maunium.net/go/mautrix/bridge" "maunium.net/go/mautrix/bridge/commands" + "maunium.net/go/mautrix/bridge/status" "maunium.net/go/mautrix/event" "maunium.net/go/mautrix/id" "maunium.net/go/mautrix/util/configupgrade" @@ -194,7 +195,7 @@ func (br *WABridge) StartUsers() { go user.Connect() } if !foundAnySessions { - br.SendGlobalBridgeState(bridge.State{StateEvent: bridge.StateUnconfigured}.Fill(nil)) + br.SendGlobalBridgeState(status.BridgeState{StateEvent: status.StateUnconfigured}.Fill(nil)) } br.Log.Debugln("Starting custom puppets") for _, loopuppet := range br.GetAllPuppetsWithCustomMXID() { diff --git a/messagetracking.go b/messagetracking.go index 9a66b87..3b629ca 100644 --- a/messagetracking.go +++ b/messagetracking.go @@ -28,7 +28,7 @@ import ( "go.mau.fi/whatsmeow" "maunium.net/go/mautrix" - "maunium.net/go/mautrix/bridge" + "maunium.net/go/mautrix/bridge/status" "maunium.net/go/mautrix/event" "maunium.net/go/mautrix/id" ) @@ -197,9 +197,9 @@ func (portal *Portal) sendMessageMetrics(evt *event.Event, err error, part strin level = log.LevelDebug } portal.log.Logfln(level, "%s %s %s from %s: %v", part, msgType, evtDescription, evt.Sender, err) - reason, status, isCertain, sendNotice, _ := errorToStatusReason(err) - checkpointStatus := bridge.ReasonToCheckpointStatus(reason, status) - portal.bridge.SendMessageCheckpoint(evt, bridge.MsgStepRemote, err, checkpointStatus, ms.getRetryNum()) + reason, statusCode, isCertain, sendNotice, _ := errorToStatusReason(err) + checkpointStatus := status.ReasonToCheckpointStatus(reason, statusCode) + portal.bridge.SendMessageCheckpoint(evt, status.MsgStepRemote, err, checkpointStatus, ms.getRetryNum()) if sendNotice { ms.setNoticeID(portal.sendErrorMessage(evt, err, isCertain, ms.getNoticeID())) } @@ -207,7 +207,7 @@ func (portal *Portal) sendMessageMetrics(evt *event.Event, err error, part strin } else { portal.log.Debugfln("Handled Matrix %s %s", msgType, evtDescription) portal.sendDeliveryReceipt(evt.ID) - portal.bridge.SendMessageSuccessCheckpoint(evt, bridge.MsgStepRemote, ms.getRetryNum()) + portal.bridge.SendMessageSuccessCheckpoint(evt, status.MsgStepRemote, ms.getRetryNum()) portal.sendStatusEvent(origEvtID, evt.ID, nil) if prevNotice := ms.popNoticeID(); prevNotice != "" { _, _ = portal.MainIntent().RedactEvent(portal.MXID, prevNotice, mautrix.ReqRedact{ diff --git a/provisioning.go b/provisioning.go index 6921834..e90ba1e 100644 --- a/provisioning.go +++ b/provisioning.go @@ -39,7 +39,7 @@ import ( log "maunium.net/go/maulogger/v2" - "maunium.net/go/mautrix/bridge" + "maunium.net/go/mautrix/bridge/status" "maunium.net/go/mautrix/id" ) @@ -151,7 +151,7 @@ func (prov *ProvisioningAPI) DeleteSession(w http.ResponseWriter, r *http.Reques user.DeleteConnection() user.DeleteSession() jsonResponse(w, http.StatusOK, Response{true, "Session information purged"}) - user.removeFromJIDMap(bridge.State{StateEvent: bridge.StateLoggedOut}) + user.removeFromJIDMap(status.BridgeState{StateEvent: status.StateLoggedOut}) } func (prov *ProvisioningAPI) Disconnect(w http.ResponseWriter, r *http.Request) { @@ -165,7 +165,7 @@ func (prov *ProvisioningAPI) Disconnect(w http.ResponseWriter, r *http.Request) } user.DeleteConnection() jsonResponse(w, http.StatusOK, Response{true, "Disconnected from WhatsApp"}) - user.BridgeState.Send(bridge.State{StateEvent: bridge.StateBadCredentials, Error: WANotConnected}) + user.BridgeState.Send(status.BridgeState{StateEvent: status.StateBadCredentials, Error: WANotConnected}) } func (prov *ProvisioningAPI) Reconnect(w http.ResponseWriter, r *http.Request) { @@ -182,7 +182,7 @@ func (prov *ProvisioningAPI) Reconnect(w http.ResponseWriter, r *http.Request) { } } else { user.DeleteConnection() - user.BridgeState.Send(bridge.State{StateEvent: bridge.StateTransientDisconnect, Error: WANotConnected}) + user.BridgeState.Send(status.BridgeState{StateEvent: status.StateTransientDisconnect, Error: WANotConnected}) user.Connect() jsonResponse(w, http.StatusAccepted, Response{true, "Restarted connection to WhatsApp"}) } @@ -577,7 +577,7 @@ func (prov *ProvisioningAPI) Logout(w http.ResponseWriter, r *http.Request) { } user.bridge.Metrics.TrackConnectionState(user.JID, false) - user.removeFromJIDMap(bridge.State{StateEvent: bridge.StateLoggedOut}) + user.removeFromJIDMap(status.BridgeState{StateEvent: status.StateLoggedOut}) user.DeleteSession() jsonResponse(w, http.StatusOK, Response{true, "Logged out successfully."}) } diff --git a/user.go b/user.go index 05dac07..58e260e 100644 --- a/user.go +++ b/user.go @@ -38,6 +38,7 @@ import ( "maunium.net/go/mautrix/appservice" "maunium.net/go/mautrix/bridge" "maunium.net/go/mautrix/bridge/bridgeconfig" + "maunium.net/go/mautrix/bridge/status" "maunium.net/go/mautrix/event" "maunium.net/go/mautrix/format" "maunium.net/go/mautrix/id" @@ -161,7 +162,7 @@ func (user *User) addToJIDMap() { user.bridge.usersLock.Unlock() } -func (user *User) removeFromJIDMap(state bridge.State) { +func (user *User) removeFromJIDMap(state status.BridgeState) { user.bridge.usersLock.Lock() jidUser, ok := user.bridge.usersByUsername[user.JID.User] if ok && user == jidUser { @@ -533,13 +534,13 @@ func (user *User) Connect() bool { return false } user.log.Debugln("Connecting to WhatsApp") - user.BridgeState.Send(bridge.State{StateEvent: bridge.StateConnecting, Error: WAConnecting}) + user.BridgeState.Send(status.BridgeState{StateEvent: status.StateConnecting, Error: WAConnecting}) user.createClient(user.Session) err := user.Client.Connect() if err != nil { user.log.Warnln("Error connecting to WhatsApp:", err) - user.BridgeState.Send(bridge.State{ - StateEvent: bridge.StateUnknownError, + user.BridgeState.Send(status.BridgeState{ + StateEvent: status.StateUnknownError, Error: WAConnectionFailed, Info: map[string]interface{}{ "go_error": err.Error(), @@ -708,7 +709,7 @@ func (user *User) phoneSeen(ts time.Time) { } else if !user.PhoneRecentlySeen(false) { if user.BridgeState.GetPrev().Error == WAPhoneOffline && user.IsConnected() { user.log.Debugfln("Saw phone after current bridge state said it has been offline, switching state back to connected") - go user.BridgeState.Send(bridge.State{StateEvent: bridge.StateConnected}) + go user.BridgeState.Send(status.BridgeState{StateEvent: status.StateConnected}) } else { user.log.Debugfln("Saw phone after current bridge state said it has been offline, not sending new bridge state (prev: %s, connected: %t)", user.BridgeState.GetPrev().Error, user.IsConnected()) } @@ -762,19 +763,19 @@ func (user *User) HandleEvent(event interface{}) { } case *events.OfflineSyncPreview: user.log.Infofln("Server says it's going to send %d messages and %d receipts that were missed during downtime", v.Messages, v.Receipts) - go user.BridgeState.Send(bridge.State{ - StateEvent: bridge.StateBackfilling, + go user.BridgeState.Send(status.BridgeState{ + StateEvent: status.StateBackfilling, Message: fmt.Sprintf("backfilling %d messages and %d receipts", v.Messages, v.Receipts), }) case *events.OfflineSyncCompleted: if !user.PhoneRecentlySeen(true) { user.log.Infofln("Offline sync completed, but phone last seen date is still %s - sending phone offline bridge status", user.PhoneLastSeen) - go user.BridgeState.Send(bridge.State{StateEvent: bridge.StateTransientDisconnect, Error: WAPhoneOffline}) + go user.BridgeState.Send(status.BridgeState{StateEvent: status.StateTransientDisconnect, Error: WAPhoneOffline}) } else { - if user.BridgeState.GetPrev().StateEvent == bridge.StateBackfilling { + if user.BridgeState.GetPrev().StateEvent == status.StateBackfilling { user.log.Infoln("Offline sync completed") } - go user.BridgeState.Send(bridge.State{StateEvent: bridge.StateConnected}) + go user.BridgeState.Send(status.BridgeState{StateEvent: status.StateConnected}) } case *events.AppStateSyncComplete: if len(user.Client.Store.PushName) > 0 && v.Name == appstate.WAPatchCriticalBlock { @@ -812,23 +813,23 @@ func (user *User) HandleEvent(event interface{}) { } else { message = "Unknown stream error" } - go user.BridgeState.Send(bridge.State{StateEvent: bridge.StateUnknownError, Message: message}) + go user.BridgeState.Send(status.BridgeState{StateEvent: status.StateUnknownError, Message: message}) user.bridge.Metrics.TrackConnectionState(user.JID, false) case *events.ConnectFailure: - go user.BridgeState.Send(bridge.State{StateEvent: bridge.StateUnknownError, Message: fmt.Sprintf("Unknown connection failure: %s", v.Reason)}) + go user.BridgeState.Send(status.BridgeState{StateEvent: status.StateUnknownError, Message: fmt.Sprintf("Unknown connection failure: %s", v.Reason)}) user.bridge.Metrics.TrackConnectionState(user.JID, false) case *events.ClientOutdated: user.log.Errorfln("Got a client outdated connect failure. The bridge is likely out of date, please update immediately.") - go user.BridgeState.Send(bridge.State{StateEvent: bridge.StateUnknownError, Message: "Connect failure: 405 client outdated"}) + go user.BridgeState.Send(status.BridgeState{StateEvent: status.StateUnknownError, Message: "Connect failure: 405 client outdated"}) user.bridge.Metrics.TrackConnectionState(user.JID, false) case *events.TemporaryBan: - go user.BridgeState.Send(bridge.State{StateEvent: bridge.StateBadCredentials, Message: v.String()}) + go user.BridgeState.Send(status.BridgeState{StateEvent: status.StateBadCredentials, Message: v.String()}) user.bridge.Metrics.TrackConnectionState(user.JID, false) case *events.Disconnected: // Don't send the normal transient disconnect state if we're already in a different transient disconnect state. // TODO remove this if/when the phone offline state is moved to a sub-state of CONNECTED if user.BridgeState.GetPrev().Error != WAPhoneOffline && user.PhoneRecentlySeen(false) { - go user.BridgeState.Send(bridge.State{StateEvent: bridge.StateTransientDisconnect, Message: "Disconnected from WhatsApp. Trying to reconnect."}) + go user.BridgeState.Send(status.BridgeState{StateEvent: status.StateTransientDisconnect, Message: "Disconnected from WhatsApp. Trying to reconnect."}) } user.bridge.Metrics.TrackConnectionState(user.JID, false) case *events.Contact: @@ -913,10 +914,10 @@ func (user *User) HandleEvent(event interface{}) { case *events.AppState: // Ignore case *events.KeepAliveTimeout: - go user.BridgeState.Send(bridge.State{StateEvent: bridge.StateTransientDisconnect, Error: WAKeepaliveTimeout}) + go user.BridgeState.Send(status.BridgeState{StateEvent: status.StateTransientDisconnect, Error: WAKeepaliveTimeout}) case *events.KeepAliveRestored: user.log.Infof("Keepalive restored after timeouts, sending connected event") - go user.BridgeState.Send(bridge.State{StateEvent: bridge.StateConnected}) + go user.BridgeState.Send(status.BridgeState{StateEvent: status.StateConnected}) case *events.MarkChatAsRead: if user.bridge.Config.Bridge.SyncManualMarkedUnread { user.markUnread(user.GetPortalByJID(v.JID), !v.Action.GetRead()) @@ -1109,7 +1110,7 @@ func (user *User) handleLoggedOut(onConnect bool, reason events.ConnectFailureRe } else if reason == events.ConnectFailureMainDeviceGone { errorCode = WAMainDeviceGone } - user.removeFromJIDMap(bridge.State{StateEvent: bridge.StateBadCredentials, Error: errorCode}) + user.removeFromJIDMap(status.BridgeState{StateEvent: status.StateBadCredentials, Error: errorCode}) user.DeleteConnection() user.Session = nil user.JID = types.EmptyJID