-// Send sends text to chat, the ID of a private chat or a group, and returns the
-// answer of the tool. id names the send: a call with an id that has a record
-// gives the answer of the record and sends nothing, and the same id with
-// another chat or text is an error. The record "sending" is durable before the
-// send, so a stop of the daemon during the send gives an answer that the result
-// is unknown, and not a second send. A disconnected WhatsApp sends nothing and
-// makes no record.
-func (w *WhatsApp) Send(ctx context.Context, id, chat, text string) (string, error) {
- w.mutex.Lock()
- linked := w.linked
- device := w.device
- client := w.client
- connected := w.connected
- own := slices.Clone(w.own)
- w.mutex.Unlock()
-
- if !linked {
- return whatsappNotLinked, nil
- }
-
- jid, err := whatsappSendCheck(id, chat, text, own)
- if err != nil {
- return "", err
- }
-
- digest := sha256.Sum256([]byte(text))
- record := WhatsAppSend{
- ID: id,
- Chat: chat,
- Digest: hex.EncodeToString(digest[:]),
- State: whatsappSending,
- Time: w.clock(),
- }
-
- held, found := w.state.Send(id)
- switch {
- case found && (held.Chat != record.Chat || held.Digest != record.Digest):
- return "", fmt.Errorf("the id %s belongs to another message: give a new id for each message", id)
- case found && held.State == whatsappSending:
- return "The send with this id started, but its result is unknown, because the daemon stopped during it. Ask the user to look at the chat in WhatsApp before you send the message again with a new id.", nil
- case found:
- return held.Answer + " This is the answer of the first call with this id: nothing was sent again.", nil
- case client == nil || !connected:
- return "", errors.New("WhatsApp is disconnected, so nothing was sent: try again later")
- }
-
- record.MessageID = client.GenerateMessageID()
- err = w.state.PutSend(record)
- if err != nil {
- return "", err
- }
-
- sendCtx, cancel := context.WithTimeout(ctx, whatsappSendTime)
- defer cancel()
-
- response, err := client.SendMessage(sendCtx, jid, &waE2E.Message{
- Conversation: new(text),
- }, whatsmeow.SendRequestExtra{
- ID: record.MessageID,
- })
-
- record.State = whatsappSent
- if err != nil {
- record.State = whatsappFailed
- record.Answer = "The send failed: " + w.redact(err.Error()) + "."
- } else {
- name := w.groups.name(ctx, w.link(), jid.String())
- if jid.Server != types.GroupServer {
- name = whatsappContactName(ctx, device, jid, "")
- }
-
- record.Answer = "Sent to " + name + " at " + response.Timestamp.In(w.clock().Location()).Format("15:04") + "."
- }
-
- err = w.state.PutSend(record)
- if err != nil {
- return "", err
- }
-
- return record.Answer, nil
-}
-