From 29a76e342e5fe34ab73d4b9958c3526b578df990 Mon Sep 17 00:00:00 2001 From: Bohdan Horbeshko Date: Fri, 23 May 2025 13:56:12 -0400 Subject: [PATCH] Handle MUC exits --- telegram/utils.go | 19 ++++++++++++++++++ xmpp/handlers.go | 51 ++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 61 insertions(+), 9 deletions(-) diff --git a/telegram/utils.go b/telegram/utils.go index ae66953..d10810d 100644 --- a/telegram/utils.go +++ b/telegram/utils.go @@ -539,6 +539,8 @@ func (c *Client) JoinMUC(chatId int64, resource string, limit *MessageLimit) { } c.locks.mucCacheLock.Unlock() + log.Debugf("Resources in MUC %v: %v", chatId, mucState.Resources) + c.sendMUCStatuses(chatId) messages, err := c.getNLastMessages(chatId, limit) @@ -549,6 +551,23 @@ func (c *Client) JoinMUC(chatId int64, resource string, limit *MessageLimit) { c.sendMUCSubject(chatId, resource) } +// LeaveMUC removes MUC date from the cache +func (c *Client) LeaveMUC(chatId int64, resource string) { + c.locks.mucCacheLock.Lock() + defer c.locks.mucCacheLock.Unlock() + + mucState, ok := c.mucCache[chatId] + if !ok || mucState == nil { + return + } + delete(mucState.Resources, resource) + log.Debugf("Resources in MUC %v: %v", chatId, mucState.Resources) + + if len(mucState.Resources) == 0 { + delete(c.mucCache, chatId) + } +} + func (c *Client) getFullName(user *client.User) string { fullName := user.FirstName if user.LastName != "" { diff --git a/xmpp/handlers.go b/xmpp/handlers.go index 1991d78..a914214 100644 --- a/xmpp/handlers.go +++ b/xmpp/handlers.go @@ -379,7 +379,7 @@ func HandlePresence(s xmpp.Sender, p stanza.Packet) { handleMUCPresence(s, prs, mucExt) return } - tryHandleMUCNicknameChange(s, prs) + tryHandleMUCPresence(s, prs) } func handleSubscription(s xmpp.Sender, p stanza.Presence) { @@ -567,11 +567,7 @@ func handleMUCPresence(s xmpp.Sender, p stanza.Presence, mucExt stanza.MucPresen } } -func tryHandleMUCNicknameChange(s xmpp.Sender, p stanza.Presence) { - if p.Type != "" { - return - } - +func tryHandleMUCPresence(s xmpp.Sender, p stanza.Presence) { toBare, nickname, ok := gateway.SplitJID(p.To) if !ok || nickname == "" { return @@ -608,16 +604,25 @@ func tryHandleMUCNicknameChange(s xmpp.Sender, p stanza.Presence) { return } - log.Warn("🗿 Yes") - component, ok := s.(*xmpp.Component) if !ok { log.Error("Not a component") return } + switch p.Type { + case "": + handleMUCNicknameChange(component, p, session, chatId, toBare) + case stanza.PresenceTypeUnavailable: + handleMUCUnavailable(component, p, session, chatId, fromResource) + } +} + +func handleMUCNicknameChange(component *xmpp.Component, p stanza.Presence, session *telegram.Client, chatId int64, toBare string) { + log.Warn("🗿 Yes") + from := toBare - nickname, ok = session.GetMyMUCNickname(chatId) + nickname, ok := session.GetMyMUCNickname(chatId) if ok { from = from+"/"+nickname } @@ -638,6 +643,34 @@ func tryHandleMUCNicknameChange(s xmpp.Sender, p stanza.Presence) { gateway.ResumableSend(component, reply) } +func handleMUCUnavailable(component *xmpp.Component, p stanza.Presence, session *telegram.Client, chatId int64, resource string) { + log.Warn("No, it's a MUC exit") + + session.LeaveMUC(chatId, resource) + + reply := &stanza.Presence{ + Attrs: stanza.Attrs{ + From: p.To, + To: p.From, + Id: p.Id, + Type: stanza.PresenceTypeUnavailable, + }, + Extensions: []stanza.PresExtension{ + extensions.PresenceXMucUserExtension{ + Item: extensions.PresenceXMucUserItem{ + Affiliation: "member", + Jid: p.From, + Role: "none", + }, + Statuses: []extensions.PresenceXMucUserStatus{ + extensions.PresenceXMucUserStatus{Code: 110}, + }, + }, + }, + } + gateway.ResumableSend(component, reply) +} + func handleGetVcardIq(s xmpp.Sender, iq *stanza.IQ, typ byte) { log.WithFields(log.Fields{ "from": iq.From,