summaryrefslogtreecommitdiff
path: root/teleirc/matterbridge/vendor/go.mau.fi/whatsmeow/presence.go
diff options
context:
space:
mode:
Diffstat (limited to 'teleirc/matterbridge/vendor/go.mau.fi/whatsmeow/presence.go')
-rw-r--r--teleirc/matterbridge/vendor/go.mau.fi/whatsmeow/presence.go139
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,
+ })
+}