Update bridge states

This commit is contained in:
Tulir Asokan 2023-07-04 00:03:36 +03:00
parent 8ab8504023
commit 922ffdcf6b
5 changed files with 59 additions and 26 deletions

View file

@ -21,29 +21,15 @@ import (
)
const (
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"
WADisconnected status.BridgeStateErrorCode = "wa-transient-disconnect"
GMListenError status.BridgeStateErrorCode = "gm-listen-error"
GMFatalError status.BridgeStateErrorCode = "gm-listen-fatal-error"
GMNotConnected status.BridgeStateErrorCode = "gm-not-connected"
GMConnecting status.BridgeStateErrorCode = "gm-connecting"
GMConnectionFailed status.BridgeStateErrorCode = "gm-connection-failed"
)
func init() {
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.",
WANotConnected: "You're not connected to WhatsApp",
WAConnecting: "Reconnecting to WhatsApp...",
WAKeepaliveTimeout: "The WhatsApp web servers are not responding. The bridge will try to reconnect.",
WAPhoneOffline: "Your phone hasn't been seen in over 12 days. The bridge is currently connected, but will get disconnected if you don't open the app soon.",
WAConnectionFailed: "Connecting to the WhatsApp web servers failed.",
WADisconnected: "Disconnected from WhatsApp. Trying to reconnect.",
})
status.BridgeStateHumanErrors.Update(status.BridgeStateErrorMap{})
}
func (user *User) GetRemoteID() string {

View file

@ -173,7 +173,7 @@ func fnReconnect(ce *WrappedCommandEvent) {
}
} else {
ce.User.DeleteConnection()
ce.User.BridgeState.Send(status.BridgeState{StateEvent: status.StateTransientDisconnect, Error: WANotConnected})
ce.User.BridgeState.Send(status.BridgeState{StateEvent: status.StateTransientDisconnect, Error: GMNotConnected})
ce.User.Connect()
ce.Reply("Restarted connection to Google Messages")
}
@ -195,7 +195,7 @@ func fnDisconnect(ce *WrappedCommandEvent) {
}
ce.User.DeleteConnection()
ce.Reply("Successfully disconnected. Use the `reconnect` command to reconnect.")
ce.User.BridgeState.Send(status.BridgeState{StateEvent: status.StateBadCredentials, Error: WANotConnected})
ce.User.BridgeState.Send(status.BridgeState{StateEvent: status.StateBadCredentials, Error: GMNotConnected})
}
var cmdPing = &commands.FullHandler{

View file

@ -1,6 +1,8 @@
package events
import (
"net/http"
"go.mau.fi/mautrix-gmessages/libgm/util"
)
@ -13,3 +15,13 @@ func NewClientReady(session *util.SessionResponse) *ClientReady {
Session: session,
}
}
type ListenFatalError struct {
Resp *http.Response
}
type ListenTemporaryError struct {
Error error
}
type ListenRecovered struct{}

View file

@ -8,6 +8,7 @@ import (
"io"
"net/http"
"os"
"time"
"go.mau.fi/mautrix-gmessages/libgm/events"
"go.mau.fi/mautrix-gmessages/libgm/util"
@ -25,6 +26,7 @@ type RPC struct {
func (r *RPC) ListenReceiveMessages(payload []byte) {
r.listenID++
listenID := r.listenID
errored := true
for r.listenID == listenID {
r.client.Logger.Debug().Msg("Starting new long-polling request")
req, err := http.NewRequest("POST", util.RECEIVE_MESSAGES, bytes.NewReader(payload))
@ -35,7 +37,25 @@ func (r *RPC) ListenReceiveMessages(payload []byte) {
resp, reqErr := r.http.Do(req)
//r.client.Logger.Info().Any("bodyLength", len(payload)).Any("url", util.RECEIVE_MESSAGES).Any("headers", resp.Request.Header).Msg("RPC Request Headers")
if reqErr != nil {
panic(fmt.Errorf("Error making request: %v", err))
r.client.triggerEvent(&events.ListenTemporaryError{Error: reqErr})
errored = true
r.client.Logger.Err(err).Msg("Error making listen request, retrying in 5 seconds")
time.Sleep(5 * time.Second)
continue
}
if resp.StatusCode >= 400 && resp.StatusCode < 501 {
r.client.triggerEvent(&events.ListenFatalError{Resp: resp})
return
} else if resp.StatusCode >= 500 {
r.client.triggerEvent(&events.ListenTemporaryError{Error: fmt.Errorf("http %d while polling", resp.StatusCode)})
errored = true
r.client.Logger.Debug().Int("statusCode", resp.StatusCode).Msg("5xx error in long polling, retrying in 5 seconds")
time.Sleep(5 * time.Second)
continue
}
if errored {
errored = false
r.client.triggerEvent(&events.ListenRecovered{})
}
r.client.Logger.Debug().Int("statusCode", resp.StatusCode).Msg("Long polling opened")
r.conn = resp.Body

21
user.go
View file

@ -29,7 +29,6 @@ import (
"github.com/rs/zerolog"
"maunium.net/go/maulogger/v2"
"maunium.net/go/maulogger/v2/maulogadapt"
"maunium.net/go/mautrix"
"maunium.net/go/mautrix/appservice"
"maunium.net/go/mautrix/bridge"
@ -445,14 +444,14 @@ func (user *User) Connect() bool {
user.tryAutomaticDoublePuppeting()
}
user.zlog.Debug().Msg("Connecting to Google Messages")
user.BridgeState.Send(status.BridgeState{StateEvent: status.StateConnecting, Error: WAConnecting})
user.BridgeState.Send(status.BridgeState{StateEvent: status.StateConnecting, Error: GMConnecting})
user.createClient()
err := user.Client.Connect(user.Session.WebAuthKey)
if err != nil {
user.zlog.Err(err).Msg("Error connecting to Google Messages")
user.BridgeState.Send(status.BridgeState{
StateEvent: status.StateUnknownError,
Error: WAConnectionFailed,
Error: GMConnectionFailed,
Info: map[string]interface{}{
"go_error": err.Error(),
},
@ -531,6 +530,22 @@ func (user *User) HandleEvent(event interface{}) {
if user.hackyLoginCommand != nil {
user.hackyLoginCommandPrevEvent = user.sendQR(user.hackyLoginCommand, v.URL, user.hackyLoginCommandPrevEvent)
}
case *events.ListenFatalError:
user.BridgeState.Send(status.BridgeState{
StateEvent: status.StateUnknownError,
Error: GMFatalError,
Message: fmt.Sprintf("HTTP %d in long polling loop", v.Resp.StatusCode),
})
case *events.ListenTemporaryError:
user.BridgeState.Send(status.BridgeState{
StateEvent: status.StateTransientDisconnect,
Error: GMListenError,
Message: v.Error.Error(),
})
case *events.ListenRecovered:
user.BridgeState.Send(status.BridgeState{
StateEvent: status.StateConnected,
})
case *events.PairSuccessful:
user.hackyLoginCommand = nil
user.hackyLoginCommandPrevEvent = ""