X-Git-Url: https://git.giacomolli.uk/onechat/blobdiff_plain/33aa709aa4e59e05ada6940a1c055f5e5646a418..5b778ad04422dd456b7d673fb653f0353c47b0fe:/whatsapp.go?ds=inline diff --git a/whatsapp.go b/whatsapp.go index b883496..2c1b6cb 100644 --- a/whatsapp.go +++ b/whatsapp.go @@ -14,6 +14,7 @@ import ( "time" "go.mau.fi/whatsmeow" + "go.mau.fi/whatsmeow/proto/waCompanionReg" "go.mau.fi/whatsmeow/proto/waE2E" "go.mau.fi/whatsmeow/store" "go.mau.fi/whatsmeow/store/sqlstore" @@ -404,7 +405,7 @@ func (w *WhatsApp) connect(ctx context.Context) { err := client.ConnectContext(ctx) if err != nil { - w.logger.Printf("connect: %s", w.redact(err.Error())) + w.logger.Printf("WhatsApp messages do not come, because the connection failed, and it is tried again only at a restart of the daemon: %s", w.redact(err.Error())) } } @@ -434,6 +435,7 @@ func (w *WhatsApp) loggedOut(ctx context.Context, l *TurnLoop) error { return nil } + w.logger.Print("WhatsApp messages stop, because the phone logged out this device (run /whatsapp pair PHONE to link it again)") err := w.inbox.deliver(ctx, l, w.link(), true) if err != nil { return err @@ -441,12 +443,12 @@ func (w *WhatsApp) loggedOut(ctx context.Context, l *TurnLoop) error { err = w.removeSession() if err != nil { - w.logger.Printf("delete the session after the logout: %v", err) + w.logger.Printf("the session of the logged out device stays on the disk, because its delete failed: %v", err) } err = l.note("WhatsApp was unlinked from the phone.") if err != nil { - w.logger.Printf("note the logout: %v", err) + w.logger.Printf("the chat has no note of the logout, because its write failed: %v", err) } w.broadcast("WhatsApp was unlinked from the phone. Run /whatsapp pair PHONE to link it again.") @@ -489,9 +491,10 @@ func (w *WhatsApp) unlink(ctx context.Context, l *TurnLoop, answer func(text str return nil } + w.logger.Print("WhatsApp messages stop, because the user unlinked WhatsApp") err = l.note("WhatsApp is unlinked.") if err != nil { - w.logger.Printf("note the unlink: %v", err) + w.logger.Printf("the chat has no note of the unlink, because its write failed: %v", err) } if client == nil || logoutErr != nil { @@ -513,6 +516,7 @@ func (w *WhatsApp) removeSession() error { w.linked = false w.own = nil w.connected = false + w.disconnectedAt = time.Time{} if w.timer != nil { w.timer.Stop() } @@ -594,6 +598,8 @@ func (w *WhatsApp) pair(ctx, runCtx context.Context, l *TurnLoop, phone string, return } + // The server accepts only a display name of the form "Browser (OS)" + // with a common browser and OS, and refuses the pairing otherwise. code, err := client.PairPhone(ctx, phone, true, whatsmeow.PairClientChrome, "Chrome (Linux)") if err != nil { answer("WhatsApp refused the pairing: " + err.Error() + ". Check the phone number and run /whatsapp pair PHONE again.") @@ -625,10 +631,11 @@ func (w *WhatsApp) pair(ctx, runCtx context.Context, l *TurnLoop, phone string, case item.Event == whatsmeow.QRChannelSuccess.Event: linked = true w.linkedBy(client) + w.logger.Print("WhatsApp is linked") err = l.note("WhatsApp is linked.") if err != nil { - w.logger.Printf("note the link: %v", err) + w.logger.Printf("the chat has no note of the link, because its write failed: %v", err) } answer("WhatsApp is linked to +" + phone + ".") @@ -691,6 +698,11 @@ func (w *WhatsApp) linkedBy(client WhatsAppClient) { // the library tries again. After noticeDelay of a disconnection, all clients // get one notice, and they get one more when the connection comes back. A // disconnection that the library does not try again gives a notice at once. +// +// The log of the daemon gets one line for each change of the connection of the +// linked device: connected, a failed first connection, a lost connection, and +// connected again with the length of the outage. The retries of the library +// between them log nothing. func (w *WhatsApp) handle(event any) bool { switch event := event.(type) { case *events.Message: @@ -711,12 +723,20 @@ func (w *WhatsApp) handle(event any) bool { w.inbox.startCatchup() } - var notice string + var notice, line string w.mutex.Lock() switch event := event.(type) { case *events.PairSuccess: w.own = whatsappOwnIDs(event.ID.User, event.LID.User) case *events.Connected: + switch { + case !w.linked || w.connected: + case w.disconnectedAt.IsZero(): + line = "WhatsApp is connected, and new messages come in" + default: + line = "WhatsApp is connected again, after " + durationText(w.clock().Sub(w.disconnectedAt)) + } + w.connected = true w.connectedAt = w.clock() if w.timer != nil { @@ -729,6 +749,11 @@ func (w *WhatsApp) handle(event any) bool { } case *events.Disconnected: if w.linked && (w.connected || w.disconnectedAt.IsZero()) { + line = "new WhatsApp messages wait, because the connection is lost (the next try is automatic)" + if !w.connected { + line = "new WhatsApp messages wait, because the first connection failed (the next try is automatic)" + } + w.disconnectedAt = w.clock() w.disconnections++ disconnections := w.disconnections @@ -748,10 +773,20 @@ func (w *WhatsApp) handle(event any) bool { w.connected = false w.noticed = true notice = "WhatsApp is disconnected and does not connect again by itself: " + event.PermanentDisconnectDescription() + ". Restart the daemon to try again." + line = "WhatsApp messages do not come, because the connection is lost and it is tried again only at a restart of the daemon: " + whatsappRedact(w.own, event.PermanentDisconnectDescription()) } } + + if w.closed { + line = "" + } + w.mutex.Unlock() + if line != "" { + w.logger.Print(line) + } + if notice != "" { w.broadcast(notice) } @@ -817,12 +852,20 @@ type WhatsAppRequest struct { answer func(text string) } +// whatsappSetDeviceProps sets the device properties that the library sends at +// the pairing. They are global values of the library, so the daemon sets them +// once before any client exists. The phone shows the linked device with the +// name OneChat and a desktop icon only when the platform type is known. +func whatsappSetDeviceProps() { + store.SetOSInfo("OneChat", [3]uint32{0, 1, 0}) + store.DeviceProps.PlatformType = waCompanionReg.DeviceProps_DESKTOP.Enum() +} + // whatsappNewClient returns the client of the library for device, with handle // as its event handler. The client tries again after a failed first connection, // acknowledges a message only after handle returns true, and downloads no old -// history. The phone shows the device with the name OneChat. +// history. func whatsappNewClient(device *store.Device, handle func(event any) bool) WhatsAppClient { - store.SetOSInfo("OneChat", [3]uint32{0, 1, 0}) client := whatsmeow.NewClient(device, waLog.Noop) client.InitialAutoReconnect = true client.SynchronousAck = true