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)
}
// 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,
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) {
// 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
// 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
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
// 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)
w.mutex.Unlock()
if line != "" {
- w.logger.Log(context.Background(), level, line, attrs...)
+ w.logger.Log(ctx, level, line, attrs...)
}
if notice != "" {