diff --git a/CHANGELOG.md b/CHANGELOG.md index 34f5ae9..1d45c8f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ * Added tracking for incoming events from the primary device to warn the user if their phone is offline for too long. +* (Re-)Added support for setting group avatar from Matrix. * Fixed some issues with read receipt bridging * Fixed `!wa open` not working with new-style group IDs. * Fixed panic in disappearing message handling code if a portal is deleted with diff --git a/ROADMAP.md b/ROADMAP.md index a86d8a3..18caacf 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -15,9 +15,9 @@ * [x] Invite * [x] Leave * [x] Kick - * [ ] Room metadata changes + * [x] Room metadata changes * [x] Name - * [ ] Avatar + * [x] Avatar * [x] Topic * [ ] Initial room metadata * WhatsApp → Matrix diff --git a/go.mod b/go.mod index ff177ad..a0133ce 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/prometheus/client_golang v1.11.0 github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e github.com/tidwall/gjson v1.13.0 - go.mau.fi/whatsmeow v0.0.0-20220204210537-a425ddb0b16c + go.mau.fi/whatsmeow v0.0.0-20220210104450-b05cf0cef136 golang.org/x/image v0.0.0-20211028202545-6944b10bf410 google.golang.org/protobuf v1.27.1 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b diff --git a/go.sum b/go.sum index 849f970..7cc3780 100644 --- a/go.sum +++ b/go.sum @@ -140,8 +140,8 @@ github.com/tidwall/sjson v1.2.4 h1:cuiLzLnaMeBhRmEv00Lpk3tkYrcxpmbU81tAY4Dw0tc= github.com/tidwall/sjson v1.2.4/go.mod h1:098SZ494YoMWPmMO6ct4dcFnqxwj9r/gF0Etp19pSNM= go.mau.fi/libsignal v0.0.0-20211109153248-a67163214910 h1:9FFhG0OmkuMau5UEaTgiUQ+7cSbtbOQ7hiWKdN8OI3I= go.mau.fi/libsignal v0.0.0-20211109153248-a67163214910/go.mod h1:AufGrvVh+00Nc07Jm4hTquh7yleZyn20tKJI2wCPAKg= -go.mau.fi/whatsmeow v0.0.0-20220204210537-a425ddb0b16c h1:hwuZ1W55J2uSwm029dREAr6crSVa+i5VsF91ltK389k= -go.mau.fi/whatsmeow v0.0.0-20220204210537-a425ddb0b16c/go.mod h1:8jUjOAi3xtGubxcZgG8uSHpAdyQXBRbWAfxkctX/4y4= +go.mau.fi/whatsmeow v0.0.0-20220210104450-b05cf0cef136 h1:AeE8izwMOwAbzNGC+GGOY821w6EWSpPxVmQcpRgyff4= +go.mau.fi/whatsmeow v0.0.0-20220210104450-b05cf0cef136/go.mod h1:8jUjOAi3xtGubxcZgG8uSHpAdyQXBRbWAfxkctX/4y4= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= diff --git a/portal.go b/portal.go index e86b859..b9437b9 100644 --- a/portal.go +++ b/portal.go @@ -202,6 +202,7 @@ type Portal struct { roomCreateLock sync.Mutex encryptLock sync.Mutex backfillLock sync.Mutex + avatarLock sync.Mutex recentlyHandled [recentlyHandledLength]recentlyHandledWrapper recentlyHandledLock sync.Mutex @@ -821,6 +822,8 @@ func (portal *Portal) SyncParticipants(source *User, metadata *types.GroupInfo) } func (portal *Portal) UpdateAvatar(user *User, setBy types.JID, updateInfo bool) bool { + portal.avatarLock.Lock() + defer portal.avatarLock.Unlock() avatar, err := user.Client.GetProfilePictureInfo(portal.Key.JID, false) if err != nil { if !errors.Is(err, whatsmeow.ErrProfilePictureUnauthorized) { @@ -2717,28 +2720,52 @@ func (portal *Portal) HandleMatrixInvite(sender *User, target *Puppet) { } func (portal *Portal) HandleMatrixMeta(sender *User, evt *event.Event) { - var err error switch content := evt.Content.Parsed.(type) { case *event.RoomNameEventContent: if content.Name == portal.Name { return } portal.Name = content.Name - err = sender.Client.SetGroupName(portal.Key.JID, content.Name) + err := sender.Client.SetGroupName(portal.Key.JID, content.Name) + if err != nil { + portal.log.Errorln("Failed to update group name:", err) + } case *event.TopicEventContent: if content.Topic == portal.Topic { return } portal.Topic = content.Topic - err = sender.Client.SetGroupTopic(portal.Key.JID, "", "", content.Topic) + err := sender.Client.SetGroupTopic(portal.Key.JID, "", "", content.Topic) + if err != nil { + portal.log.Errorln("Failed to update group description:", err) + } case *event.RoomAvatarEventContent: - // TODO implement - return - } - if err != nil { - portal.log.Errorln("Failed to update metadata:", err) - } else { - //out := <-resp - //portal.log.Debugln("Successfully updated metadata:", out) + portal.avatarLock.Lock() + defer portal.avatarLock.Unlock() + if content.URL == portal.AvatarURL || (content.URL.IsEmpty() && portal.Avatar == "remove") { + return + } + var data []byte + var err error + if !content.URL.IsEmpty() { + data, err = portal.MainIntent().DownloadBytes(content.URL) + if err != nil { + portal.log.Errorfln("Failed to download updated avatar %s: %v", content.URL, err) + return + } + portal.log.Debugfln("%s set the group avatar to %s", sender.MXID, content.URL) + } else { + portal.log.Debugfln("%s removed the group avatar", sender.MXID) + } + newID, err := sender.Client.SetGroupPhoto(portal.Key.JID, data) + if err != nil { + portal.log.Errorfln("Failed to update group avatar: %v", err) + return + } + portal.log.Debugfln("Successfully updated group avatar to %s", newID) + portal.Avatar = newID + portal.AvatarURL = content.URL + portal.UpdateBridgeInfo() + portal.Update() } }