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 ( const (
WALoggedOut status.BridgeStateErrorCode = "wa-logged-out" GMListenError status.BridgeStateErrorCode = "gm-listen-error"
WAMainDeviceGone status.BridgeStateErrorCode = "wa-main-device-gone" GMFatalError status.BridgeStateErrorCode = "gm-listen-fatal-error"
WAUnknownLogout status.BridgeStateErrorCode = "wa-unknown-logout" GMNotConnected status.BridgeStateErrorCode = "gm-not-connected"
WANotConnected status.BridgeStateErrorCode = "wa-not-connected" GMConnecting status.BridgeStateErrorCode = "gm-connecting"
WAConnecting status.BridgeStateErrorCode = "wa-connecting" GMConnectionFailed status.BridgeStateErrorCode = "gm-connection-failed"
WAKeepaliveTimeout status.BridgeStateErrorCode = "wa-keepalive-timeout"
WAPhoneOffline status.BridgeStateErrorCode = "wa-phone-offline"
WAConnectionFailed status.BridgeStateErrorCode = "wa-connection-failed"
WADisconnected status.BridgeStateErrorCode = "wa-transient-disconnect"
) )
func init() { func init() {
status.BridgeStateHumanErrors.Update(status.BridgeStateErrorMap{ 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.",
})
} }
func (user *User) GetRemoteID() string { func (user *User) GetRemoteID() string {

View file

@ -173,7 +173,7 @@ func fnReconnect(ce *WrappedCommandEvent) {
} }
} else { } else {
ce.User.DeleteConnection() 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.User.Connect()
ce.Reply("Restarted connection to Google Messages") ce.Reply("Restarted connection to Google Messages")
} }
@ -195,7 +195,7 @@ func fnDisconnect(ce *WrappedCommandEvent) {
} }
ce.User.DeleteConnection() ce.User.DeleteConnection()
ce.Reply("Successfully disconnected. Use the `reconnect` command to reconnect.") 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{ var cmdPing = &commands.FullHandler{

View file

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

View file

@ -8,6 +8,7 @@ import (
"io" "io"
"net/http" "net/http"
"os" "os"
"time"
"go.mau.fi/mautrix-gmessages/libgm/events" "go.mau.fi/mautrix-gmessages/libgm/events"
"go.mau.fi/mautrix-gmessages/libgm/util" "go.mau.fi/mautrix-gmessages/libgm/util"
@ -25,6 +26,7 @@ type RPC struct {
func (r *RPC) ListenReceiveMessages(payload []byte) { func (r *RPC) ListenReceiveMessages(payload []byte) {
r.listenID++ r.listenID++
listenID := r.listenID listenID := r.listenID
errored := true
for r.listenID == listenID { for r.listenID == listenID {
r.client.Logger.Debug().Msg("Starting new long-polling request") r.client.Logger.Debug().Msg("Starting new long-polling request")
req, err := http.NewRequest("POST", util.RECEIVE_MESSAGES, bytes.NewReader(payload)) 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) 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") //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 { 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.client.Logger.Debug().Int("statusCode", resp.StatusCode).Msg("Long polling opened")
r.conn = resp.Body r.conn = resp.Body

21
user.go
View file

@ -29,7 +29,6 @@ import (
"github.com/rs/zerolog" "github.com/rs/zerolog"
"maunium.net/go/maulogger/v2" "maunium.net/go/maulogger/v2"
"maunium.net/go/maulogger/v2/maulogadapt" "maunium.net/go/maulogger/v2/maulogadapt"
"maunium.net/go/mautrix" "maunium.net/go/mautrix"
"maunium.net/go/mautrix/appservice" "maunium.net/go/mautrix/appservice"
"maunium.net/go/mautrix/bridge" "maunium.net/go/mautrix/bridge"
@ -445,14 +444,14 @@ func (user *User) Connect() bool {
user.tryAutomaticDoublePuppeting() user.tryAutomaticDoublePuppeting()
} }
user.zlog.Debug().Msg("Connecting to Google Messages") 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() user.createClient()
err := user.Client.Connect(user.Session.WebAuthKey) err := user.Client.Connect(user.Session.WebAuthKey)
if err != nil { if err != nil {
user.zlog.Err(err).Msg("Error connecting to Google Messages") user.zlog.Err(err).Msg("Error connecting to Google Messages")
user.BridgeState.Send(status.BridgeState{ user.BridgeState.Send(status.BridgeState{
StateEvent: status.StateUnknownError, StateEvent: status.StateUnknownError,
Error: WAConnectionFailed, Error: GMConnectionFailed,
Info: map[string]interface{}{ Info: map[string]interface{}{
"go_error": err.Error(), "go_error": err.Error(),
}, },
@ -531,6 +530,22 @@ func (user *User) HandleEvent(event interface{}) {
if user.hackyLoginCommand != nil { if user.hackyLoginCommand != nil {
user.hackyLoginCommandPrevEvent = user.sendQR(user.hackyLoginCommand, v.URL, user.hackyLoginCommandPrevEvent) 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: case *events.PairSuccessful:
user.hackyLoginCommand = nil user.hackyLoginCommand = nil
user.hackyLoginCommandPrevEvent = "" user.hackyLoginCommandPrevEvent = ""