X-Git-Url: https://git.giacomolli.uk/onechat/blobdiff_plain/723f6e18adc6482ed913e1618c8a76e981720c2b..3b2bf881d484ba1a33ff77a342564b8195a75c80:/whatsapp.go?ds=sidebyside diff --git a/whatsapp.go b/whatsapp.go index 851cfd1..be1acc6 100644 --- a/whatsapp.go +++ b/whatsapp.go @@ -95,6 +95,7 @@ type WhatsAppClient interface { PairPhone(ctx context.Context, phone string, showPushNotification bool, clientType whatsmeow.PairClientType, clientDisplayName string) (string, error) Logout(ctx context.Context) error GetJoinedGroups(ctx context.Context) ([]*types.GroupInfo, error) + Download(ctx context.Context, message whatsmeow.DownloadableMessage) ([]byte, error) GenerateMessageID() types.MessageID SendMessage(ctx context.Context, to types.JID, message *waE2E.Message, extra ...whatsmeow.SendRequestExtra) (whatsmeow.SendResponse, error) } @@ -106,6 +107,7 @@ type WhatsAppClient interface { // the client of a device with its event handler. 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{ + ctx: ctx, dir: filepath.Join(dir, whatsappDirName), clock: clock, logger: logger, @@ -123,7 +125,7 @@ func openWhatsApp(ctx context.Context, dir string, clock func() time.Time, logge return nil, err } - w.inbox = newWhatsAppInbox(w.state, clock, w.groups) + w.inbox = newWhatsAppInbox(w.state, clock, w.groups, &ImageStore{dir: filepath.Join(dir, imageDirName)}, logger) info, err := os.Stat(w.sessionPath()) if errors.Is(err, os.ErrNotExist) { @@ -168,9 +170,12 @@ func openWhatsApp(ctx context.Context, dir string, clock func() time.Time, logge // creation, close, removal, and snapshots. It is held before mutex, and stays // held when removal releases mutex for client callbacks. // -// The inbox puts the text messages into batches and logs them, and groups -// holds the names of the groups. Both get a WhatsAppLink from link for each -// call, so they use the current device and client. +// ctx is the caller context until Run sets its context for library callbacks. +// The mutex protects it, so callbacks follow daemon cancellation. +// +// The inbox puts messages into batches and logs them, and groups holds the +// names of the groups. Both get a WhatsAppLink from link for each call, so they +// use the current device and client. // // The library logs nothing, because its log lines hold the ID of the own // account, which is the phone number of the user. The own number and the own @@ -180,6 +185,7 @@ func openWhatsApp(ctx context.Context, dir string, clock func() time.Time, logge // log, and those of private chats hold phone numbers, because the agent needs // them to send. type WhatsApp struct { + ctx context.Context dir string clock func() time.Time logger *slog.Logger @@ -223,6 +229,7 @@ type WhatsApp struct { func (w *WhatsApp) Run(ctx context.Context, l *TurnLoop, notify func(Event)) error { w.mutex.Lock() + w.ctx = ctx w.notify = notify linked := w.linked w.retrying = linked @@ -899,9 +906,14 @@ func (w *WhatsApp) linkedBy(client WhatsAppClient) { // connected again with the length of the outage. The retries of the library and // Run between them log nothing. func (w *WhatsApp) handle(event any) bool { + w.mutex.Lock() + + ctx := w.ctx + w.mutex.Unlock() + switch event := event.(type) { case *events.Message: - return w.inbox.receive(w.link(), event) + return w.inbox.receive(ctx, w.link(), event) case *events.GroupInfo: if event.Name != nil { w.groups.set(event.JID.String(), event.Name.Name) @@ -986,7 +998,7 @@ func (w *WhatsApp) handle(event any) bool { w.mutex.Unlock() if line != "" { - w.logger.Log(context.Background(), level, line, attrs...) + w.logger.Log(ctx, level, line, attrs...) } if notice != "" {