]> git.giacomolli.uk - onechat/blobdiff - whatsapp.go
Write private data archives with safe extraction
[onechat] / whatsapp.go
index 6e1e1e62211926da5257877f16f1ef21c71f6cfa..95e1d54ea01e80f8216f29e38d63a56a479cc07a 100644 (file)
@@ -4,7 +4,7 @@ import (
        "context"
        "errors"
        "fmt"
-       "log"
+       "log/slog"
        "net/url"
        "os"
        "path/filepath"
@@ -103,7 +103,7 @@ type WhatsAppClient interface {
 // the account, so a file that another user can read is an error. The clock
 // gives the times of the status, logger gets the failures, and newClient makes
 // the client of a device with its event handler.
-func openWhatsApp(ctx context.Context, dir string, clock func() time.Time, logger *log.Logger, newClient func(device *store.Device, handle func(event any) bool) WhatsAppClient) (*WhatsApp, error) {
+func openWhatsApp(ctx context.Context, dir string, clock func() time.Time, logger *slog.Logger, newClient func(device *store.Device, handle func(event any) bool) WhatsAppClient) (*WhatsApp, error) {
        w := &WhatsApp{
                dir:         filepath.Join(dir, whatsappDirName),
                clock:       clock,
@@ -179,7 +179,7 @@ func openWhatsApp(ctx context.Context, dir string, clock func() time.Time, logge
 type WhatsApp struct {
        dir         string
        clock       func() time.Time
-       logger      *log.Logger
+       logger      *slog.Logger
        newClient   func(device *store.Device, handle func(event any) bool) WhatsAppClient
        noticeDelay time.Duration
        requests    chan WhatsAppRequest
@@ -487,7 +487,7 @@ func (w *WhatsApp) connect(ctx context.Context) bool {
        w.mutex.Unlock()
 
        if first {
-               w.logger.Printf("first connect failed, retrying: %s", cause)
+               w.logger.Warn("first connect failed, retrying", "err", cause)
        }
 
        return true
@@ -538,7 +538,7 @@ func (w *WhatsApp) loggedOut(ctx context.Context, l *TurnLoop) error {
                return nil
        }
 
-       w.logger.Print("logged out by the phone, run /whatsapp pair PHONE")
+       w.logger.Error("logged out by the phone, run /whatsapp pair PHONE")
 
        err := w.inbox.deliver(ctx, l, w.link(), true)
        if err != nil {
@@ -547,12 +547,12 @@ func (w *WhatsApp) loggedOut(ctx context.Context, l *TurnLoop) error {
 
        err = w.removeSession()
        if err != nil {
-               w.logger.Printf("session delete failed: %v", err)
+               w.logger.Error("session delete failed", "err", err)
        }
 
        err = l.note("WhatsApp was unlinked from the phone.")
        if err != nil {
-               w.logger.Printf("chat note failed: %v", err)
+               w.logger.Error("chat note failed", "err", err)
        }
 
        w.broadcast("WhatsApp was unlinked from the phone. Run /whatsapp pair PHONE to link it again.")
@@ -599,11 +599,11 @@ func (w *WhatsApp) unlink(ctx context.Context, l *TurnLoop, answer func(text str
                return nil
        }
 
-       w.logger.Print("unlinked")
+       w.logger.Info("unlinked")
 
        err = l.note("WhatsApp is unlinked.")
        if err != nil {
-               w.logger.Printf("chat note failed: %v", err)
+               w.logger.Error("chat note failed", "err", err)
        }
 
        if client == nil || logoutErr != nil {
@@ -751,11 +751,11 @@ func (w *WhatsApp) pair(ctx, runCtx context.Context, l *TurnLoop, phone string,
                        linked = true
 
                        w.linkedBy(client)
-                       w.logger.Print("linked")
+                       w.logger.Info("linked")
 
                        err = l.note("WhatsApp is linked.")
                        if err != nil {
-                               w.logger.Printf("chat note failed: %v", err)
+                               w.logger.Error("chat note failed", "err", err)
                        }
 
                        answer("WhatsApp is linked to +" + phone + ".")
@@ -848,6 +848,10 @@ func (w *WhatsApp) handle(event any) bool {
 
        var notice, line string
 
+       level := slog.LevelInfo
+
+       var attrs []any
+
        w.mutex.Lock()
 
        switch event := event.(type) {
@@ -859,7 +863,8 @@ func (w *WhatsApp) handle(event any) bool {
                case w.disconnectedAt.IsZero():
                        line = "connected"
                default:
-                       line = "connected again after " + durationText(w.clock().Sub(w.disconnectedAt))
+                       line = "connected again"
+                       attrs = append(attrs, "after", w.clock().Sub(w.disconnectedAt))
                }
 
                w.connected = true
@@ -876,6 +881,7 @@ func (w *WhatsApp) handle(event any) bool {
        case *events.Disconnected:
                connected := w.connected
                if w.startOutage() {
+                       level = slog.LevelWarn
                        line = "disconnected, retrying"
                        if !connected {
                                line = "first connect failed, retrying"
@@ -893,7 +899,9 @@ 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 = "disconnected for good, restart to retry: " + whatsappRedact(w.own, event.PermanentDisconnectDescription())
+                       level = slog.LevelError
+                       line = "disconnected for good, restart to retry"
+                       attrs = append(attrs, "err", whatsappRedact(w.own, event.PermanentDisconnectDescription()))
                }
        }
 
@@ -904,7 +912,7 @@ func (w *WhatsApp) handle(event any) bool {
        w.mutex.Unlock()
 
        if line != "" {
-               w.logger.Print(line)
+               w.logger.Log(context.Background(), level, line, attrs...)
        }
 
        if notice != "" {