diff --git a/config/bridge.go b/config/bridge.go index 1278c43..2b1b2a7 100644 --- a/config/bridge.go +++ b/config/bridge.go @@ -73,6 +73,7 @@ type BridgeConfig struct { ResendBridgeInfo bool `yaml:"resend_bridge_info"` MuteBridging bool `yaml:"mute_bridging"` ArchiveTag string `yaml:"archive_tag"` + PinnedTag string `yaml:"pinned_tag"` WhatsappThumbnail bool `yaml:"whatsapp_thumbnail"` diff --git a/example-config.yaml b/example-config.yaml index 71a7564..8dc03ff 100644 --- a/example-config.yaml +++ b/example-config.yaml @@ -189,6 +189,8 @@ bridge: # Note that WhatsApp unarchives chats when a message is received, which will also be mirrored to Matrix. # This can be set to a tag (e.g. m.lowpriority), or null to disable. archive_tag: null + # Same as above, but for pinned chats. The favorite tag is called m.favourite + pinned_tag: null # Whether or not thumbnails from WhatsApp should be sent. # They're disabled by default due to very low resolution. diff --git a/go.mod b/go.mod index 9996bf6..0495da8 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( gopkg.in/yaml.v2 v2.3.0 maunium.net/go/mauflag v1.0.0 maunium.net/go/maulogger/v2 v2.2.4 - maunium.net/go/mautrix v0.9.7 + maunium.net/go/mautrix v0.9.8 ) -replace github.com/Rhymen/go-whatsapp => github.com/tulir/go-whatsapp v0.4.4 +replace github.com/Rhymen/go-whatsapp => github.com/tulir/go-whatsapp v0.4.5 diff --git a/go.sum b/go.sum index c4ebb5a..4b2c885 100644 --- a/go.sum +++ b/go.sum @@ -325,6 +325,8 @@ github.com/tulir/go-whatsapp v0.4.3 h1:rQBBT40JHE4eLk5idQ3r/6jNj46nqjLyMnlJTKwyH github.com/tulir/go-whatsapp v0.4.3/go.mod h1:rwwuTh1bKqhgrRvOBAr8hDqtuz8Cc1Quqw/0BeXb+/E= github.com/tulir/go-whatsapp v0.4.4 h1:69AIE/CbmVYpBbug75meWFOS8lilzoafZFctt2JzRek= github.com/tulir/go-whatsapp v0.4.4/go.mod h1:rwwuTh1bKqhgrRvOBAr8hDqtuz8Cc1Quqw/0BeXb+/E= +github.com/tulir/go-whatsapp v0.4.5 h1:rLPm1Hnn5KGnbRwlL3Fwn1dMqb6mFI4hyeS1fNYiVFM= +github.com/tulir/go-whatsapp v0.4.5/go.mod h1:rwwuTh1bKqhgrRvOBAr8hDqtuz8Cc1Quqw/0BeXb+/E= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= @@ -526,5 +528,7 @@ maunium.net/go/mautrix v0.9.7-0.20210419142435-ba8ea0c90b98 h1:FXg4JcsKHtoYGo/bS maunium.net/go/mautrix v0.9.7-0.20210419142435-ba8ea0c90b98/go.mod h1:mckyHSKKyI0PQF2K9MgWMMDUWH1meCNggE28ILTLuMg= maunium.net/go/mautrix v0.9.7 h1:PnRJuH2hhLmQ7arxph1ICXC5H1kGsnD+ldI1LsbCvlo= maunium.net/go/mautrix v0.9.7/go.mod h1:mckyHSKKyI0PQF2K9MgWMMDUWH1meCNggE28ILTLuMg= +maunium.net/go/mautrix v0.9.8 h1:s/0XbkM6ui8P2SX9el79osKjMlmxh/IKdK1RilEmo2A= +maunium.net/go/mautrix v0.9.8/go.mod h1:mckyHSKKyI0PQF2K9MgWMMDUWH1meCNggE28ILTLuMg= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= diff --git a/user.go b/user.go index f05a19c..0d41bf7 100644 --- a/user.go +++ b/user.go @@ -626,7 +626,12 @@ func (user *User) HandleEvent(event interface{}) { case whatsapp.ArchiveMessage: portal := user.bridge.GetPortalByJID(user.PortalKey(v.JID)) if portal != nil { - go user.updateChatArchive(nil, portal, v.IsArchived) + go user.updateChatTag(nil, portal, user.bridge.Config.Bridge.ArchiveTag, v.IsArchived) + } + case whatsapp.PinMessage: + portal := user.bridge.GetPortalByJID(user.PortalKey(v.JID)) + if portal != nil { + go user.updateChatTag(nil, portal, user.bridge.Config.Bridge.PinnedTag, v.IsPinned) } case json.RawMessage: user.HandleJSONMessage(v) @@ -699,8 +704,17 @@ func (user *User) updateChatMute(intent *appservice.IntentAPI, portal *Portal, m } } -func (user *User) updateChatArchive(intent *appservice.IntentAPI, portal *Portal, archived bool) { - if len(portal.MXID) == 0 || len(user.bridge.Config.Bridge.ArchiveTag) == 0 { +type CustomTagData struct { + Order json.Number `json:"order"` + DoublePuppet bool `json:"net.maunium.whatsapp.puppet"` +} + +type CustomTagEventContent struct { + Tags map[string]CustomTagData `json:"tags"` +} + +func (user *User) updateChatTag(intent *appservice.IntentAPI, portal *Portal, tag string, active bool) { + if len(portal.MXID) == 0 || len(tag) == 0 { return } else if intent == nil { doublePuppet := user.bridge.GetPuppetByCustomMXID(user.MXID) @@ -709,16 +723,24 @@ func (user *User) updateChatArchive(intent *appservice.IntentAPI, portal *Portal } intent = doublePuppet.CustomIntent() } - var err error - if archived { - user.log.Debugln("Adding tag", user.bridge.Config.Bridge.ArchiveTag, "to", portal.MXID) - err = intent.AddTag(portal.MXID, user.bridge.Config.Bridge.ArchiveTag, 0.5) + var existingTags CustomTagEventContent + err := intent.GetTagsWithCustomData(portal.MXID, &existingTags) + if err != nil && !errors.Is(err, mautrix.MNotFound) { + user.log.Warnfln("Failed to get tags of %s: %v", portal.MXID, err) + } + currentTag, ok := existingTags.Tags[tag] + if active && !ok { + user.log.Debugln("Adding tag", tag, "to", portal.MXID) + data := CustomTagData{"0.5", true} + err = intent.AddTagWithCustomData(portal.MXID, tag, &data) + } else if !active && ok && currentTag.DoublePuppet { + user.log.Debugln("Removing tag", tag, "from", portal.MXID) + err = intent.RemoveTag(portal.MXID, tag) } else { - user.log.Debugln("Removing tag", user.bridge.Config.Bridge.ArchiveTag, "from", portal.MXID) - err = intent.RemoveTag(portal.MXID, user.bridge.Config.Bridge.ArchiveTag) + err = nil } if err != nil { - user.log.Warnfln("Failed to update tag for %s through double puppet: %v", portal.MXID, err) + user.log.Warnfln("Failed to update tag %s for %s through double puppet: %v", tag, portal.MXID, err) } } @@ -737,7 +759,8 @@ func (user *User) syncChatDoublePuppetDetails(doublePuppet *Puppet, chat Chat) { } } user.updateChatMute(intent, chat.Portal, chat.MutedUntil) - user.updateChatArchive(intent, chat.Portal, chat.IsArchived) + user.updateChatTag(intent, chat.Portal, user.bridge.Config.Bridge.ArchiveTag, chat.IsArchived) + user.updateChatTag(intent, chat.Portal, user.bridge.Config.Bridge.PinnedTag, chat.IsPinned) } func (user *User) syncPortal(chat Chat) {