fix: surface QR pairing failures
This commit is contained in:
parent
3077e626a3
commit
9568cbfb42
@ -22,6 +22,7 @@
|
||||
|
||||
### Fixed
|
||||
|
||||
- Auth: propagate QR channel setup errors and surface actionable QR pairing failures. (#100 — thanks @pmatheus)
|
||||
- Groups: hide groups after `groups leave`, mark missing joined groups as left during refresh, and show them again if a later refresh reports membership. (#125, #129 — thanks @SeifBenayed and @ImLukeF)
|
||||
- History: cap on-demand backfill at 500 messages per request and 100 requests per run.
|
||||
- Messages: normalize device-specific `@s.whatsapp.net` JIDs before storing chats, contacts, and senders.
|
||||
|
||||
@ -94,7 +94,10 @@ func (c *Client) Connect(ctx context.Context, opts ConnectOptions) error {
|
||||
|
||||
var qrChan <-chan whatsmeow.QRChannelItem
|
||||
if !authed {
|
||||
ch, _ := cli.GetQRChannel(ctx)
|
||||
ch, err := cli.GetQRChannel(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("get QR channel: %w", err)
|
||||
}
|
||||
qrChan = ch
|
||||
}
|
||||
|
||||
@ -115,24 +118,44 @@ func (c *Client) Connect(ctx context.Context, opts ConnectOptions) error {
|
||||
if !ok {
|
||||
return fmt.Errorf("QR channel closed")
|
||||
}
|
||||
switch evt.Event {
|
||||
case "code":
|
||||
switch {
|
||||
case evt.Event == whatsmeow.QRChannelEventCode:
|
||||
if opts.OnQRCode != nil {
|
||||
opts.OnQRCode(evt.Code)
|
||||
} else {
|
||||
qrterminal.GenerateHalfBlock(evt.Code, qrterminal.M, os.Stdout)
|
||||
}
|
||||
case "success":
|
||||
case evt == whatsmeow.QRChannelSuccess:
|
||||
return nil
|
||||
case "timeout":
|
||||
return fmt.Errorf("QR code timed out")
|
||||
case "error":
|
||||
return fmt.Errorf("QR error")
|
||||
default:
|
||||
if err := qrChannelEventError(evt); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func qrChannelEventError(evt whatsmeow.QRChannelItem) error {
|
||||
switch {
|
||||
case evt == whatsmeow.QRChannelTimeout:
|
||||
return fmt.Errorf("QR code timed out; run `wacli auth` again to get a new code")
|
||||
case evt == whatsmeow.QRChannelClientOutdated:
|
||||
return fmt.Errorf("WhatsApp client outdated; update wacli and try again")
|
||||
case evt == whatsmeow.QRChannelScannedWithoutMultidevice:
|
||||
return fmt.Errorf("QR scanned, but multi-device is not enabled on the phone")
|
||||
case evt == whatsmeow.QRChannelErrUnexpectedEvent:
|
||||
return fmt.Errorf("unexpected QR pairing state; run `wacli auth` again")
|
||||
case evt.Event == whatsmeow.QRChannelEventError:
|
||||
if evt.Error != nil {
|
||||
return fmt.Errorf("QR pairing failed: %w", evt.Error)
|
||||
}
|
||||
return fmt.Errorf("QR pairing failed")
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) AddEventHandler(handler func(interface{})) uint32 {
|
||||
c.mu.Lock()
|
||||
cli := c.client
|
||||
|
||||
@ -1,9 +1,12 @@
|
||||
package wa
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"go.mau.fi/whatsmeow"
|
||||
"go.mau.fi/whatsmeow/types"
|
||||
)
|
||||
|
||||
@ -68,6 +71,28 @@ func TestParseUserOrJID(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestQRChannelEventError(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
evt whatsmeow.QRChannelItem
|
||||
want string
|
||||
}{
|
||||
{name: "timeout", evt: whatsmeow.QRChannelTimeout, want: "QR code timed out"},
|
||||
{name: "client outdated", evt: whatsmeow.QRChannelClientOutdated, want: "WhatsApp client outdated"},
|
||||
{name: "multidevice disabled", evt: whatsmeow.QRChannelScannedWithoutMultidevice, want: "multi-device is not enabled"},
|
||||
{name: "unexpected state", evt: whatsmeow.QRChannelErrUnexpectedEvent, want: "unexpected QR pairing state"},
|
||||
{name: "pair error", evt: whatsmeow.QRChannelItem{Event: whatsmeow.QRChannelEventError, Error: errors.New("bad code")}, want: "bad code"},
|
||||
}
|
||||
for _, tt := range cases {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
err := qrChannelEventError(tt.evt)
|
||||
if err == nil || !strings.Contains(err.Error(), tt.want) {
|
||||
t.Fatalf("error = %v, want substring %q", err, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBestContactName(t *testing.T) {
|
||||
if BestContactName(types.ContactInfo{Found: false, FullName: "x"}) != "" {
|
||||
t.Fatalf("expected empty for not found")
|
||||
|
||||
Loading…
Reference in New Issue
Block a user