From e25bf2960996fb084b51deebf24e34eb1b2f8636 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Thu, 16 May 2019 00:18:43 +0300 Subject: [PATCH] Handle startup connection errors --- commands.go | 47 +++++++++++++++++++++++++++++++-------------- example-config.yaml | 3 +++ user.go | 15 ++++++++++----- 3 files changed, 46 insertions(+), 19 deletions(-) diff --git a/commands.go b/commands.go index 820eb42..6b845a0 100644 --- a/commands.go +++ b/commands.go @@ -81,18 +81,20 @@ func (handler *CommandHandler) Handle(roomID types.MatrixRoomID, user *User, mes handler.CommandLogin(ce) case "help": handler.CommandHelp(ce) - case "logout", "reconnect", "disconnect", "sync", "list", "open", "pm": + case "reconnect": + handler.CommandReconnect(ce) + case "logout", "disconnect", "sync", "list", "open", "pm": if ce.User.Conn == nil { - ce.Reply("You are not logged in.") - ce.Reply("Please use the login command to log into WhatsApp.") + ce.Reply("You are not logged in. Use the `login` command to log into WhatsApp.") + return + } else if !ce.User.Connected { + ce.Reply("You are not connected to WhatsApp. Use the `reconnect` command to reconnect.") return } switch cmd { case "logout": handler.CommandLogout(ce) - case "reconnect": - handler.CommandReconnect(ce) case "disconnect": handler.CommandDisconnect(ce) case "sync": @@ -130,7 +132,7 @@ func (handler *CommandHandler) CommandLogout(ce *CommandEvent) { err := ce.User.Conn.Logout() if err != nil { ce.User.log.Warnln("Error while logging out:", err) - ce.Reply("Error while logging out (see logs for details)") + ce.Reply("Unknown error while logging out: %v", err) return } _, err = ce.User.Conn.Disconnect() @@ -148,16 +150,33 @@ const cmdReconnectHelp = `reconnect - Reconnect to WhatsApp` func (handler *CommandHandler) CommandReconnect(ce *CommandEvent) { err := ce.User.Conn.Restore() - if err == whatsapp.ErrAlreadyLoggedIn { - if ce.User.Connected { - ce.Reply("You were already connected.") + if err == whatsapp.ErrInvalidSession { + if ce.User.Session != nil { + ce.User.log.Debugln("Got invalid session error when reconnecting, but user has session. Retrying using RestoreWithSession()...") + var sess whatsapp.Session + sess, err = ce.User.Conn.RestoreWithSession(*ce.User.Session) + if err == nil { + ce.User.SetSession(&sess) + } } else { - ce.User.Connected = true - ce.Reply("You were already connected, but the bridge hadn't noticed. Fixed that now.") + ce.Reply("You are not logged in.") + return } - } else if err != nil { + } + if err != nil { ce.User.log.Warnln("Error while reconnecting:", err) - ce.Reply("Error while reconnecting (see logs for details)") + if err == whatsapp.ErrAlreadyLoggedIn { + if ce.User.Connected { + ce.Reply("You were already connected.") + } else { + ce.User.Connected = true + ce.Reply("You were already connected, but the bridge hadn't noticed. Fixed that now.") + } + } else if err.Error() == "restore session connection timed out" { + ce.Reply("Reconnection timed out. Is WhatsApp on your phone reachable?") + } else { + ce.Reply("Unknown error while reconnecting: %v", err) + } return } ce.User.Connected = true @@ -174,7 +193,7 @@ func (handler *CommandHandler) CommandDisconnect(ce *CommandEvent) { return } else if err != nil { ce.User.log.Warnln("Error while disconnecting:", err) - ce.Reply("Error while disconnecting (see logs for details)") + ce.Reply("Unknown error while disconnecting: %v", err) return } ce.User.SetSession(&sess) diff --git a/example-config.yaml b/example-config.yaml index 1b66bf7..20bf56d 100644 --- a/example-config.yaml +++ b/example-config.yaml @@ -54,6 +54,9 @@ bridge: # {{.Short}} - short display name from contact list displayname_template: "{{if .Notify}}{{.Notify}}{{else}}{{.Jid}}{{end}} (WA)" + # WhatsApp connection timeout in seconds. + connection_timeout: 20 + # The prefix for commands. Only required in non-management rooms. command_prefix: "!wa" diff --git a/user.go b/user.go index d3f0d88..d02fa13 100644 --- a/user.go +++ b/user.go @@ -162,6 +162,10 @@ func (user *User) RestoreSession() bool { sess, err := user.Conn.RestoreWithSession(*user.Session) if err != nil { user.log.Errorln("Failed to restore session:", err) + msg := format.RenderMarkdown(fmt.Sprintf("\u26a0 Failed to connect to WhatsApp. Make sure WhatsApp "+ + "on your phone is reachable and use `%s reconnect` to try connecting again.", + user.bridge.Config.Bridge.CommandPrefix)) + _, _ = user.bridge.Bot.SendMessageEvent(user.ManagementRoom, mautrix.EventMessage, msg) return false } user.Connected = true @@ -186,7 +190,7 @@ func (user *User) Login(ce *CommandEvent) { qrCode, err := qrcode.Encode(code, qrcode.Low, 256) if err != nil { user.log.Errorln("Failed to encode QR code:", err) - ce.Reply("Failed to encode QR code (see logs for details)") + ce.Reply("Failed to encode QR code: %v", err) return } @@ -195,7 +199,7 @@ func (user *User) Login(ce *CommandEvent) { resp, err := bot.UploadBytes(qrCode, "image/png") if err != nil { user.log.Errorln("Failed to upload QR code:", err) - ce.Reply("Failed to upload QR code (see logs for details)") + ce.Reply("Failed to upload QR code: %v", err) return } @@ -211,16 +215,17 @@ func (user *User) Login(ce *CommandEvent) { ce.Reply("You're already logged in.") } else if err == whatsapp.ErrLoginInProgress { ce.Reply("You have a login in progress already.") + } else if err.Error() == "qr code scan timed out" { + ce.Reply("QR code scan timed out. Please try again.") } else { user.log.Warnln("Failed to log in:", err) - ce.Reply("Failed to log in (see logs for details)") + ce.Reply("Failed to log in: %v", err) } return } user.Connected = true user.JID = strings.Replace(user.Conn.Info.Wid, whatsappExt.OldUserSuffix, whatsappExt.NewUserSuffix, 1) - user.Session = &session - user.Update() + user.SetSession(&session) ce.Reply("Successfully logged in. Now, you may ask for `sync [--create]`.") }