]> git.giacomolli.uk - onechat/blobdiff - whatsapp_inbox.go
Submit root events through the local socket
[onechat] / whatsapp_inbox.go
index 7d4e9e4c7b3920a303d35628b290a60676df9e7a..8bf8a97eaee2dfa431012a539d9af667d4829952 100644 (file)
@@ -32,23 +32,6 @@ const (
        whatsappCatchupTimeout = time.Minute
 )
 
        whatsappCatchupTimeout = time.Minute
 )
 
-// newWhatsAppInbox returns the inbox of the batches in state, with clock for
-// the times of the batch texts and groups for the names of the groups. images
-// holds shared images, and logger gets image failures.
-func newWhatsAppInbox(state *WhatsAppState, clock func() time.Time, groups *WhatsAppGroups, images *ImageStore, logger *slog.Logger) *WhatsAppInbox {
-       return &WhatsAppInbox{
-               state:    state,
-               clock:    clock,
-               groups:   groups,
-               images:   images,
-               voices:   &VoiceStore{dir: filepath.Join(filepath.Dir(filepath.Dir(state.path)), voiceDirName)},
-               voice:    &VoiceTranscriber{},
-               logger:   logger,
-               wake:     make(chan struct{}, 1),
-               failures: make(chan error, 1),
-       }
-}
-
 // WhatsAppInbox puts messages into batches, one chat at a time, as
 // WhatsAppState says. deliver logs each closed batch as a work message that
 // starts with [WhatsApp], and a batch that needs the user wakes the turn loop.
 // WhatsAppInbox puts messages into batches, one chat at a time, as
 // WhatsAppState says. deliver logs each closed batch as a work message that
 // starts with [WhatsApp], and a batch that needs the user wakes the turn loop.
@@ -89,6 +72,24 @@ type WhatsAppInbox struct {
        catchupTimer *time.Timer
 }
 
        catchupTimer *time.Timer
 }
 
+// newWhatsAppInbox returns the inbox of the batches in state, with clock for
+// the times of the batch texts and groups for the names of the groups. images
+// holds shared images, and logger gets image failures. Audio shares the data
+// directory of state.
+func newWhatsAppInbox(state *WhatsAppState, clock func() time.Time, groups *WhatsAppGroups, images *ImageStore, logger *slog.Logger) *WhatsAppInbox {
+       return &WhatsAppInbox{
+               state:    state,
+               clock:    clock,
+               groups:   groups,
+               images:   images,
+               voices:   &VoiceStore{dir: filepath.Join(filepath.Dir(filepath.Dir(state.path)), voiceDirName)},
+               voice:    &VoiceTranscriber{},
+               logger:   logger,
+               wake:     make(chan struct{}, 1),
+               failures: make(chan error, 1),
+       }
+}
+
 // due returns a channel that gets a value when the next open batch is due, or
 // nil when no batch is open.
 func (i *WhatsAppInbox) due() <-chan time.Time {
 // due returns a channel that gets a value when the next open batch is due, or
 // nil when no batch is open.
 func (i *WhatsAppInbox) due() <-chan time.Time {
@@ -128,7 +129,7 @@ func (i *WhatsAppInbox) deliver(ctx context.Context, l *TurnLoop, link WhatsAppL
        }
 
        if err != nil {
        }
 
        if err != nil {
-               return err
+               return fmt.Errorf("close due WhatsApp batches: %w", err)
        }
 
        batches := i.state.Closed()
        }
 
        batches := i.state.Closed()
@@ -182,7 +183,7 @@ func (i *WhatsAppInbox) deliver(ctx context.Context, l *TurnLoop, link WhatsAppL
 
                err = i.state.Remove(batch.Number)
                if err != nil {
 
                err = i.state.Remove(batch.Number)
                if err != nil {
-                       return err
+                       return fmt.Errorf("remove delivered WhatsApp batch: %w", err)
                }
 
                if batch.Turn() {
                }
 
                if batch.Turn() {
@@ -229,10 +230,40 @@ func (i *WhatsAppInbox) startCatchup() {
        })
 }
 
        })
 }
 
-// receive stores an image before its batch and wakes Run. link gives the device
-// and the own IDs. It returns false when the state file cannot hold the
-// message, so that the library does not acknowledge it, and Run stops the
-// daemon. An image that cannot be downloaded or stored gets a text marker. A
+// caughtUpBy ends the catch-up of the connection with the number catchups, when
+// no later connection started a new one.
+func (i *WhatsAppInbox) caughtUpBy(catchups int) {
+       i.mutex.Lock()
+       defer i.mutex.Unlock()
+
+       if i.catchups == catchups {
+               i.finishCatchup()
+       }
+}
+
+// finishCatchup ends a running catch-up and wakes Run, which logs all batches.
+// The caller holds the mutex.
+func (i *WhatsAppInbox) finishCatchup() {
+       if !i.catchingUp {
+               return
+       }
+
+       i.catchingUp = false
+       i.caughtUp = true
+       if i.catchupTimer != nil {
+               i.catchupTimer.Stop()
+       }
+
+       select {
+       case i.wake <- struct{}{}:
+       default:
+       }
+}
+
+// receive stores images and transcribed voice notes before their batches and
+// wakes Run. link gives the device and the own IDs. It returns false when the
+// state file cannot hold the message, so that the library does not acknowledge
+// it, and Run stops the daemon. Failed media input gets a text marker. A
 // message that the batches do not take is handled with nothing to do.
 func (i *WhatsAppInbox) receive(ctx context.Context, link WhatsAppLink, event *events.Message) bool {
        lookupCtx, cancel := context.WithTimeout(ctx, whatsappContactLookupTimeout)
 // message that the batches do not take is handled with nothing to do.
 func (i *WhatsAppInbox) receive(ctx context.Context, link WhatsAppLink, event *events.Message) bool {
        lookupCtx, cancel := context.WithTimeout(ctx, whatsappContactLookupTimeout)
@@ -291,36 +322,6 @@ func (i *WhatsAppInbox) imageText(ctx context.Context, link WhatsAppLink, event
        return imageText([]string{name}, caption)
 }
 
        return imageText([]string{name}, caption)
 }
 
-// caughtUpBy ends the catch-up of the connection with the number catchups, when
-// no later connection started a new one.
-func (i *WhatsAppInbox) caughtUpBy(catchups int) {
-       i.mutex.Lock()
-       defer i.mutex.Unlock()
-
-       if i.catchups == catchups {
-               i.finishCatchup()
-       }
-}
-
-// finishCatchup ends a running catch-up and wakes Run, which logs all batches.
-// The caller holds the mutex.
-func (i *WhatsAppInbox) finishCatchup() {
-       if !i.catchingUp {
-               return
-       }
-
-       i.catchingUp = false
-       i.caughtUp = true
-       if i.catchupTimer != nil {
-               i.catchupTimer.Stop()
-       }
-
-       select {
-       case i.wake <- struct{}{}:
-       default:
-       }
-}
-
 // endCatchup ends a running catch-up at OfflineSyncCompleted.
 func (i *WhatsAppInbox) endCatchup() {
        i.mutex.Lock()
 // endCatchup ends a running catch-up at OfflineSyncCompleted.
 func (i *WhatsAppInbox) endCatchup() {
        i.mutex.Lock()
@@ -374,7 +375,8 @@ func whatsappMessage(ctx context.Context, device *store.Device, own []string, ev
 }
 
 // whatsappText returns the chat and the batch message of event, a message that
 }
 
 // whatsappText returns the chat and the batch message of event, a message that
-// the batches take. An image returns its caption until receive stores it.
+// the batches take. An image returns its caption until receive stores it. A
+// voice note returns a marker until receive transcribes it.
 func whatsappText(ctx context.Context, device *store.Device, own []string, event *events.Message) (WhatsAppChat, WhatsAppMessage, bool) {
        info := event.Info
        text := event.Message.GetConversation()
 func whatsappText(ctx context.Context, device *store.Device, own []string, event *events.Message) (WhatsAppChat, WhatsAppMessage, bool) {
        info := event.Info
        text := event.Message.GetConversation()