ctx, cancel := context.WithTimeout(context.Background(), whatsappLookupTime)
defer cancel()
- chat, message, found := w.message(ctx, event)
+ w.mutex.Lock()
+ device := w.device
+ own := slices.Clone(w.own)
+ w.mutex.Unlock()
+
+ chat, message, found := whatsappMessage(ctx, device, own, event)
if !found {
return true
}
return true
}
-// message returns the chat and the batch message of event, or false when the
-// batches do not take it. They take the text of a private chat or a group, from
-// another person or from the user. They do not take media, reactions, edits,
-// deletions, view-once and disappearing messages, old history, status
-// broadcasts, channels, and the chat of the user with itself.
-//
-// A mention of the user becomes @you, another mention @NAME when the name is
-// known, and the own number and LID become OWN, so that they never go to the
-// log.
-func (w *WhatsApp) message(ctx context.Context, event *events.Message) (WhatsAppChat, WhatsAppMessage, bool) {
- w.mutex.Lock()
- device := w.device
- own := slices.Clone(w.own)
- w.mutex.Unlock()
-
- info := event.Info
- chatJID := info.Chat.ToNonAD()
- switch {
- case device == nil:
- case event.IsEdit, info.Edit != "", event.IsEphemeral, event.IsViewOnce, event.SourceWebMsg != nil:
- case chatJID.Server != types.DefaultUserServer && chatJID.Server != types.HiddenUserServer && chatJID.Server != types.GroupServer:
- case slices.Contains(own, chatJID.User):
- default:
- return w.text(ctx, device, own, event)
- }
-
- return WhatsAppChat{}, WhatsAppMessage{}, false
-}
-
-// text returns the chat and the batch message of event, a message that the
-// batches take when it has text.
-func (w *WhatsApp) text(ctx context.Context, device *store.Device, own []string, event *events.Message) (WhatsAppChat, WhatsAppMessage, bool) {
- info := event.Info
- text := event.Message.GetConversation()
- extended := event.Message.GetExtendedTextMessage()
- if text == "" {
- text = extended.GetText()
- }
-
- if strings.TrimSpace(text) == "" {
- return WhatsAppChat{}, WhatsAppMessage{}, false
- }
-
- contextInfo := extended.GetContextInfo()
- message := WhatsAppMessage{
- ID: info.ID,
- Time: info.Timestamp,
- Mine: info.IsFromMe,
- }
-
- if !message.Mine {
- message.Sender = whatsappContactName(ctx, device, info.Sender, info.PushName)
- }
-
- for _, mentioned := range contextInfo.GetMentionedJID() {
- jid, err := types.ParseJID(mentioned)
- switch {
- case err != nil:
- case slices.Contains(own, jid.User):
- message.Mention = true
- text = strings.ReplaceAll(text, "@"+jid.User, "@you")
- default:
- text = strings.ReplaceAll(text, "@"+jid.User, "@"+whatsappContactName(ctx, device, jid, ""))
- }
- }
-
- participant, err := types.ParseJID(contextInfo.GetParticipant())
- message.Reply = err == nil && slices.Contains(own, participant.User)
-
- for _, id := range own {
- text = strings.ReplaceAll(text, id, "OWN")
- }
-
- message.Text = text
- chatJID := info.Chat.ToNonAD()
- chat := WhatsAppChat{
- ID: chatJID.String(),
- Group: chatJID.Server == types.GroupServer,
- }
-
- if !chat.Group {
- push := info.PushName
- if message.Mine {
- push = ""
- }
-
- chat.Name = whatsappContactName(ctx, device, chatJID, push)
- }
-
- return chat, message, true
-}
-
// caughtUpBy ends the catch-up of the connection with the number catchups, when
// no later connection started a new one.
func (w *WhatsApp) caughtUpBy(catchups int) {
w.mutex.Lock()
defer w.mutex.Unlock()
- for _, id := range w.own {
- text = strings.ReplaceAll(text, id, "OWN")
- }
-
- return text
+ return whatsappRedact(w.own, text)
}
// Send sends text to chat, the ID of a private chat or a group, and returns the
return client
}
+// whatsappMessage returns the chat and the batch message of event, or false
+// when the batches do not take it. device is the linked device, and own holds
+// the own IDs. The batches take the text of a private chat or a group, from
+// another person or from the user. They do not take media, reactions, edits,
+// deletions, view-once and disappearing messages, old history, status
+// broadcasts, channels, and the chat of the user with itself.
+//
+// A mention of the user becomes @you, another mention @NAME when the name is
+// known, and the own number and LID become OWN, so that they never go to the
+// log.
+func whatsappMessage(ctx context.Context, device *store.Device, own []string, event *events.Message) (WhatsAppChat, WhatsAppMessage, bool) {
+ info := event.Info
+ chatJID := info.Chat.ToNonAD()
+ switch {
+ case device == nil:
+ case event.IsEdit, info.Edit != "", event.IsEphemeral, event.IsViewOnce, event.SourceWebMsg != nil:
+ case chatJID.Server != types.DefaultUserServer && chatJID.Server != types.HiddenUserServer && chatJID.Server != types.GroupServer:
+ case slices.Contains(own, chatJID.User):
+ default:
+ return whatsappText(ctx, device, own, event)
+ }
+
+ return WhatsAppChat{}, WhatsAppMessage{}, false
+}
+
+// whatsappText returns the chat and the batch message of event, a message that
+// the batches take when it has text.
+func whatsappText(ctx context.Context, device *store.Device, own []string, event *events.Message) (WhatsAppChat, WhatsAppMessage, bool) {
+ info := event.Info
+ text := event.Message.GetConversation()
+ extended := event.Message.GetExtendedTextMessage()
+ if text == "" {
+ text = extended.GetText()
+ }
+
+ if strings.TrimSpace(text) == "" {
+ return WhatsAppChat{}, WhatsAppMessage{}, false
+ }
+
+ contextInfo := extended.GetContextInfo()
+ message := WhatsAppMessage{
+ ID: info.ID,
+ Time: info.Timestamp,
+ Mine: info.IsFromMe,
+ }
+
+ if !message.Mine {
+ message.Sender = whatsappContactName(ctx, device, info.Sender, info.PushName)
+ }
+
+ for _, mentioned := range contextInfo.GetMentionedJID() {
+ jid, err := types.ParseJID(mentioned)
+ switch {
+ case err != nil:
+ case slices.Contains(own, jid.User):
+ message.Mention = true
+ text = strings.ReplaceAll(text, "@"+jid.User, "@you")
+ default:
+ text = strings.ReplaceAll(text, "@"+jid.User, "@"+whatsappContactName(ctx, device, jid, ""))
+ }
+ }
+
+ participant, err := types.ParseJID(contextInfo.GetParticipant())
+ message.Reply = err == nil && slices.Contains(own, participant.User)
+
+ message.Text = whatsappRedact(own, text)
+ chatJID := info.Chat.ToNonAD()
+ chat := WhatsAppChat{
+ ID: chatJID.String(),
+ Group: chatJID.Server == types.GroupServer,
+ }
+
+ if !chat.Group {
+ push := info.PushName
+ if message.Mine {
+ push = ""
+ }
+
+ chat.Name = whatsappContactName(ctx, device, chatJID, push)
+ }
+
+ return chat, message, true
+}
+
// whatsappContactName returns the name of the person jid: the full name, the
// first name, the business name, or the push name of the contact in the session
// of device, then push, the push name of a message, then the phone number. A
return own
}
+// whatsappRedact replaces each of the own IDs own in text with OWN.
+func whatsappRedact(own []string, text string) string {
+ for _, id := range own {
+ text = strings.ReplaceAll(text, id, "OWN")
+ }
+
+ return text
+}
+
// whatsappSessionAddress returns the SQLite address of the session database at
// path, with foreign keys on, as the library needs, and a wait for a busy
// database.