Improve connection error handling

This commit is contained in:
Tulir Asokan 2022-02-17 14:09:40 +02:00
parent 79648ea9ec
commit 1a1fd68812
5 changed files with 32 additions and 11 deletions

2
go.mod
View file

@ -10,7 +10,7 @@ require (
github.com/prometheus/client_golang v1.11.1 github.com/prometheus/client_golang v1.11.1
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
github.com/tidwall/gjson v1.14.0 github.com/tidwall/gjson v1.14.0
go.mau.fi/whatsmeow v0.0.0-20220215120744-a1550ccceb70 go.mau.fi/whatsmeow v0.0.0-20220217120518-0bf6c8fb0ce5
golang.org/x/image v0.0.0-20211028202545-6944b10bf410 golang.org/x/image v0.0.0-20211028202545-6944b10bf410
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd
google.golang.org/protobuf v1.27.1 google.golang.org/protobuf v1.27.1

4
go.sum
View file

@ -120,8 +120,8 @@ github.com/tidwall/sjson v1.2.4 h1:cuiLzLnaMeBhRmEv00Lpk3tkYrcxpmbU81tAY4Dw0tc=
github.com/tidwall/sjson v1.2.4/go.mod h1:098SZ494YoMWPmMO6ct4dcFnqxwj9r/gF0Etp19pSNM= github.com/tidwall/sjson v1.2.4/go.mod h1:098SZ494YoMWPmMO6ct4dcFnqxwj9r/gF0Etp19pSNM=
go.mau.fi/libsignal v0.0.0-20211109153248-a67163214910 h1:9FFhG0OmkuMau5UEaTgiUQ+7cSbtbOQ7hiWKdN8OI3I= go.mau.fi/libsignal v0.0.0-20211109153248-a67163214910 h1:9FFhG0OmkuMau5UEaTgiUQ+7cSbtbOQ7hiWKdN8OI3I=
go.mau.fi/libsignal v0.0.0-20211109153248-a67163214910/go.mod h1:AufGrvVh+00Nc07Jm4hTquh7yleZyn20tKJI2wCPAKg= go.mau.fi/libsignal v0.0.0-20211109153248-a67163214910/go.mod h1:AufGrvVh+00Nc07Jm4hTquh7yleZyn20tKJI2wCPAKg=
go.mau.fi/whatsmeow v0.0.0-20220215120744-a1550ccceb70 h1:6APIMrOUeLr1KZmi9ToqA/mZ6s2fSmpyVdi++hSA9a4= go.mau.fi/whatsmeow v0.0.0-20220217120518-0bf6c8fb0ce5 h1:hv2cBvttHOiRA/6JUt+yRMAX7CjjER6c+xO2WYqwtA0=
go.mau.fi/whatsmeow v0.0.0-20220215120744-a1550ccceb70/go.mod h1:NNI4Ah/B27mfQNChJMD1iSO8+HS+fQ4WqNuQ8Mh2/XI= go.mau.fi/whatsmeow v0.0.0-20220217120518-0bf6c8fb0ce5/go.mod h1:NNI4Ah/B27mfQNChJMD1iSO8+HS+fQ4WqNuQ8Mh2/XI=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=

View file

@ -2819,7 +2819,7 @@ func (portal *Portal) canBridgeFrom(sender *User, evtType string) bool {
if portal.HasRelaybot() { if portal.HasRelaybot() {
return true return true
} else if sender.Session != nil { } else if sender.Session != nil {
portal.log.Debugln("Ignoring %s from %s as user is not connected", evtType, sender.MXID) portal.log.Debugfln("Ignoring %s from %s as user is not connected", evtType, sender.MXID)
msg := format.RenderMarkdown(fmt.Sprintf("\u26a0 You are not connected to WhatsApp, so your %s was not bridged.", evtType), true, false) msg := format.RenderMarkdown(fmt.Sprintf("\u26a0 You are not connected to WhatsApp, so your %s was not bridged.", evtType), true, false)
msg.MsgType = event.MsgNotice msg.MsgType = event.MsgNotice
_, err := portal.sendMainIntentMessage(&msg) _, err := portal.sendMainIntentMessage(&msg)

View file

@ -204,6 +204,9 @@ func (puppet *Puppet) UpdateAvatar(source *User) bool {
if err != nil { if err != nil {
if !errors.Is(err, whatsmeow.ErrProfilePictureUnauthorized) { if !errors.Is(err, whatsmeow.ErrProfilePictureUnauthorized) {
puppet.log.Warnln("Failed to get avatar URL:", err) puppet.log.Warnln("Failed to get avatar URL:", err)
} else if puppet.Avatar == "" {
puppet.Avatar = "unauthorized"
return true
} }
return false return false
} else if avatar == nil { } else if avatar == nil {

32
user.go
View file

@ -520,7 +520,7 @@ func (user *User) sendPhoneOfflineWarning() {
func (user *User) HandleEvent(event interface{}) { func (user *User) HandleEvent(event interface{}) {
switch v := event.(type) { switch v := event.(type) {
case *events.LoggedOut: case *events.LoggedOut:
go user.handleLoggedOut(v.OnConnect) go user.handleLoggedOut(v.OnConnect, v.Reason)
user.bridge.Metrics.TrackConnectionState(user.JID, false) user.bridge.Metrics.TrackConnectionState(user.JID, false)
user.bridge.Metrics.TrackLoginState(user.JID, false) user.bridge.Metrics.TrackLoginState(user.JID, false)
case *events.Connected: case *events.Connected:
@ -577,8 +577,22 @@ func (user *User) HandleEvent(event interface{}) {
user.JID = v.ID user.JID = v.ID
user.addToJIDMap() user.addToJIDMap()
user.Update() user.Update()
case *events.ConnectFailure, *events.StreamError: case *events.StreamError:
go user.sendBridgeState(BridgeState{StateEvent: StateUnknownError}) var message string
if v.Code != "" {
message = fmt.Sprintf("Unknown stream error with code %s", v.Code)
} else if children := v.Raw.GetChildren(); len(children) > 0 {
message = fmt.Sprintf("Unknown stream error (contains %s node)", children[0].Tag)
} else {
message = "Unknown stream error"
}
go user.sendBridgeState(BridgeState{StateEvent: StateUnknownError, Message: message})
user.bridge.Metrics.TrackConnectionState(user.JID, false)
case *events.ConnectFailure:
go user.sendBridgeState(BridgeState{StateEvent: StateUnknownError, Message: fmt.Sprintf("Unknown connection failure: %s", v.Reason)})
user.bridge.Metrics.TrackConnectionState(user.JID, false)
case *events.TemporaryBan:
go user.sendBridgeState(BridgeState{StateEvent: StateBadCredentials, Message: v.String()})
user.bridge.Metrics.TrackConnectionState(user.JID, false) user.bridge.Metrics.TrackConnectionState(user.JID, false)
case *events.Disconnected: case *events.Disconnected:
go user.sendBridgeState(BridgeState{StateEvent: StateTransientDisconnect}) go user.sendBridgeState(BridgeState{StateEvent: StateTransientDisconnect})
@ -825,12 +839,12 @@ func (user *User) UpdateDirectChats(chats map[id.UserID][]id.RoomID) {
} }
} }
func (user *User) handleLoggedOut(onConnect bool) { func (user *User) handleLoggedOut(onConnect bool, reason events.ConnectFailureReason) {
user.sendBridgeState(BridgeState{StateEvent: StateBadCredentials, Error: WALoggedOut}) user.sendBridgeState(BridgeState{StateEvent: StateBadCredentials, Error: WALoggedOut, Message: reason.String()})
user.JID = types.EmptyJID user.JID = types.EmptyJID
user.Update() user.Update()
if onConnect { if onConnect {
user.sendMarkdownBridgeAlert("Connecting to WhatsApp failed as the device was logged out. Please link the bridge to your phone again.") user.sendMarkdownBridgeAlert("Connecting to WhatsApp failed as the device was unlinked (error %s). Please link the bridge to your phone again.", reason)
} else { } else {
user.sendMarkdownBridgeAlert("You were logged out from another device. Please link the bridge to your phone again.") user.sendMarkdownBridgeAlert("You were logged out from another device. Please link the bridge to your phone again.")
} }
@ -867,7 +881,11 @@ func (user *User) ResyncContacts() error {
user.log.Infofln("Resyncing displaynames with %d contacts", len(contacts)) user.log.Infofln("Resyncing displaynames with %d contacts", len(contacts))
for jid, contact := range contacts { for jid, contact := range contacts {
puppet := user.bridge.GetPuppetByJID(jid) puppet := user.bridge.GetPuppetByJID(jid)
puppet.Sync(user, contact) if puppet != nil {
puppet.Sync(user, contact)
} else {
user.log.Warnfln("Got a nil puppet for %s while syncing contacts", jid)
}
} }
return nil return nil
} }