diff options
Diffstat (limited to 'teleirc/matterbridge/vendor/go.mau.fi/whatsmeow/presence.go')
| -rw-r--r-- | teleirc/matterbridge/vendor/go.mau.fi/whatsmeow/presence.go | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/teleirc/matterbridge/vendor/go.mau.fi/whatsmeow/presence.go b/teleirc/matterbridge/vendor/go.mau.fi/whatsmeow/presence.go new file mode 100644 index 0000000..0ce94a7 --- /dev/null +++ b/teleirc/matterbridge/vendor/go.mau.fi/whatsmeow/presence.go @@ -0,0 +1,139 @@ +// Copyright (c) 2021 Tulir Asokan +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +package whatsmeow + +import ( + "fmt" + "sync/atomic" + + waBinary "go.mau.fi/whatsmeow/binary" + "go.mau.fi/whatsmeow/types" + "go.mau.fi/whatsmeow/types/events" +) + +func (cli *Client) handleChatState(node *waBinary.Node) { + source, err := cli.parseMessageSource(node, true) + if err != nil { + cli.Log.Warnf("Failed to parse chat state update: %v", err) + } else if len(node.GetChildren()) != 1 { + cli.Log.Warnf("Failed to parse chat state update: unexpected number of children in element (%d)", len(node.GetChildren())) + } else { + child := node.GetChildren()[0] + presence := types.ChatPresence(child.Tag) + if presence != types.ChatPresenceComposing && presence != types.ChatPresencePaused { + cli.Log.Warnf("Unrecognized chat presence state %s", child.Tag) + } + media := types.ChatPresenceMedia(child.AttrGetter().OptionalString("media")) + cli.dispatchEvent(&events.ChatPresence{ + MessageSource: source, + State: presence, + Media: media, + }) + } +} + +func (cli *Client) handlePresence(node *waBinary.Node) { + var evt events.Presence + ag := node.AttrGetter() + evt.From = ag.JID("from") + presenceType := ag.OptionalString("type") + if presenceType == "unavailable" { + evt.Unavailable = true + } else if presenceType != "" { + cli.Log.Debugf("Unrecognized presence type '%s' in presence event from %s", presenceType, evt.From) + } + lastSeen := ag.OptionalString("last") + if lastSeen != "" && lastSeen != "deny" { + evt.LastSeen = ag.UnixTime("last") + } + if !ag.OK() { + cli.Log.Warnf("Error parsing presence event: %+v", ag.Errors) + } else { + cli.dispatchEvent(&evt) + } +} + +// SendPresence updates the user's presence status on WhatsApp. +// +// You should call this at least once after connecting so that the server has your pushname. +// Otherwise, other users will see "-" as the name. +func (cli *Client) SendPresence(state types.Presence) error { + if len(cli.Store.PushName) == 0 { + return ErrNoPushName + } + if state == types.PresenceAvailable { + atomic.CompareAndSwapUint32(&cli.sendActiveReceipts, 0, 1) + } else { + atomic.CompareAndSwapUint32(&cli.sendActiveReceipts, 1, 0) + } + return cli.sendNode(waBinary.Node{ + Tag: "presence", + Attrs: waBinary.Attrs{ + "name": cli.Store.PushName, + "type": string(state), + }, + }) +} + +// SubscribePresence asks the WhatsApp servers to send presence updates of a specific user to this client. +// +// After subscribing to this event, you should start receiving *events.Presence for that user in normal event handlers. +// +// Also, it seems that the WhatsApp servers require you to be online to receive presence status from other users, +// so you should mark yourself as online before trying to use this function: +// +// cli.SendPresence(types.PresenceAvailable) +func (cli *Client) SubscribePresence(jid types.JID) error { + privacyToken, err := cli.Store.PrivacyTokens.GetPrivacyToken(jid) + if err != nil { + return fmt.Errorf("failed to get privacy token: %w", err) + } else if privacyToken == nil { + if cli.ErrorOnSubscribePresenceWithoutToken { + return fmt.Errorf("%w for %v", ErrNoPrivacyToken, jid.ToNonAD()) + } else { + cli.Log.Debugf("Trying to subscribe to presence of %s without privacy token", jid) + } + } + req := waBinary.Node{ + Tag: "presence", + Attrs: waBinary.Attrs{ + "type": "subscribe", + "to": jid, + }, + } + if privacyToken != nil { + req.Content = []waBinary.Node{{ + Tag: "tctoken", + Content: privacyToken.Token, + }} + } + return cli.sendNode(req) +} + +// SendChatPresence updates the user's typing status in a specific chat. +// +// The media parameter can be set to indicate the user is recording media (like a voice message) rather than typing a text message. +func (cli *Client) SendChatPresence(jid types.JID, state types.ChatPresence, media types.ChatPresenceMedia) error { + ownID := cli.getOwnID() + if ownID.IsEmpty() { + return ErrNotLoggedIn + } + content := []waBinary.Node{{Tag: string(state)}} + if state == types.ChatPresenceComposing && len(media) > 0 { + content[0].Attrs = waBinary.Attrs{ + "media": string(media), + } + } + return cli.sendNode(waBinary.Node{ + Tag: "chatstate", + Attrs: waBinary.Attrs{ + "from": ownID, + "to": jid, + }, + Content: content, + }) +} |
