Process MUC deletion

This commit is contained in:
Bohdan Horbeshko 2025-06-22 10:37:20 -04:00
parent f18fded3e9
commit 0b1e204912
5 changed files with 152 additions and 78 deletions

View file

@ -980,9 +980,7 @@ func (c *Client) ProcessChatCommand(chatID int64, cmdline string) (string, bool,
}
// leave current chat (for owners)
case "leave!":
_, err := c.client.DeleteChat(&client.DeleteChatRequest{
ChatId: chatID,
})
err := c.DeleteChat(chatID)
if err != nil {
return err.Error(), true, false
}

View file

@ -588,6 +588,39 @@ func (c *Client) LeaveMUC(chatId int64, resource string) {
}
}
// DestroyMUC removes everyone from the MUC
func (c *Client) DestroyMUC(chatId int64) error {
err := c.DeleteChat(chatId)
if err != nil {
return err
}
c.locks.mucCacheLock.Lock()
defer c.locks.mucCacheLock.Unlock()
mucState, ok := c.mucCache[chatId]
if !ok || mucState == nil {
return nil
}
var toResources []string
for resource := range mucState.Resources {
toResources = append(toResources, resource)
}
c.sendPresence(
gateway.SPFrom(gateway.MUCNODE(chatId)),
gateway.SPResource(c.GetMUCNickname(0)),
gateway.SPToResources(toResources),
gateway.SPMUCAffiliation("none"),
gateway.SPMUCRole("none"),
gateway.SPMUCDestroy(""),
)
delete(c.mucCache, chatId)
return nil
}
func (c *Client) getFullName(user *client.User) string {
fullName := user.FirstName
if user.LastName != "" {
@ -2710,6 +2743,14 @@ func (c *Client) SetChatPermissions(chatID int64, permissions *client.ChatPermis
return err
}
// DeleteChat is a handy wrapper for the following TDLib method
func (c *Client) DeleteChat(chatID int64) error {
_, err := c.client.DeleteChat(&client.DeleteChatRequest{
ChatId: chatID,
})
return err
}
// CloneChatPermissions makes a copy of ChatPermissions structure
func CloneChatPermissions(permissions *client.ChatPermissions) *client.ChatPermissions {
return &client.ChatPermissions{

View file

@ -244,6 +244,7 @@ type MessageXMucUserInviteContinue struct {
type PresenceXMucUserExtension struct {
XMLName xml.Name `xml:"http://jabber.org/protocol/muc#user x"`
Item PresenceXMucUserItem
Destroy *MucDestroy
Statuses []PresenceXMucUserStatus
}
@ -327,10 +328,18 @@ type QueryMucAdminItem struct {
// QueryMucOwner is from XEP-0045
type QueryMucOwner struct {
XMLName xml.Name `xml:"http://jabber.org/protocol/muc#owner query"`
Form *stanza.Form `xml:"jabber:x:data x`
Form *stanza.Form `xml:"jabber:x:data x,omitempty"`
Destroy *MucDestroy `xml:"destroy,omitempty"`
ResultSet *stanza.ResultSet `xml:"set,omitempty"`
}
// MucDestroy is a child element from XEP-0045
type MucDestroy struct {
XMLName xml.Name `xml:"destroy"`
Jid string `xml:"jid,attr,omitempty"`
Reason string `xml:"reason,omitempty"`
}
// Namespace is a namespace!
func (c PresenceNickExtension) Namespace() string {
return c.XMLName.Space

View file

@ -450,6 +450,12 @@ var SPMUCJid = args.NewString()
// SPMUCStatusCodes is a set of XEP-0045 MUC status codes
var SPMUCStatusCodes = args.New()
// SPMUCDestroy is a XEP-0045 room destruction element
var SPMUCDestroy = args.NewString()
// SPToResources achieves to send the presence to certain resources only
var SPToResources = args.New()
func newPresence(bareJid string, to string, args ...args.V) stanza.Presence {
var presenceFrom string
if SPFrom.IsSet(args) {
@ -534,6 +540,12 @@ func newPresence(bareJid string, to string, args ...args.V) stanza.Presence {
})
}
}
if SPMUCDestroy.IsSet(args) {
userExt.Destroy = &extensions.MucDestroy{
Jid: SPMUCDestroy.Get(args),
Reason: "Group was deleted",
}
}
presence.Extensions = append(presence.Extensions, userExt)
}
}
@ -557,6 +569,15 @@ func SendPresence(component *xmpp.Component, to string, args ...args.V) error {
"to": to,
}).Info("Got presence")
var tos []string
if SPToResources.IsSet(args) {
for _, toResource := range SPToResources.Get(args).([]string) {
tos = append(tos, to + "/" + toResource)
}
} else {
tos = []string{to}
}
for _, to := range tos {
presence := newPresence(bareJid, to, args...)
// explicit check, as marshalling is expensive
@ -581,6 +602,7 @@ func SendPresence(component *xmpp.Component, to string, args ...args.V) error {
Queue[presence.From+presence.To] = &presence
QueueLock.Unlock()
}
}
return nil
}

View file

@ -1899,11 +1899,7 @@ func handleSetQueryMucOwner(s xmpp.Sender, iq *stanza.IQ, query *extensions.Quer
return
}
if query.Form == nil {
iqAnswerSetError(answer, 400)
return
}
if query.Form != nil {
switch query.Form.Type {
case stanza.FormTypeSubmit:
// okay, noop
@ -1963,6 +1959,13 @@ func handleSetQueryMucOwner(s xmpp.Sender, iq *stanza.IQ, query *extensions.Quer
}
}
}
} else if query.Destroy != nil {
err = session.DestroyMUC(toID)
} else {
// per 1.0 spec version, it also could be a destruction, but too dangerous to cover probably
iqAnswerSetError(answer, 400)
return
}
if err != nil {
code, ok := telegram.GetErrorCode(err)
@ -1973,6 +1976,7 @@ func handleSetQueryMucOwner(s xmpp.Sender, iq *stanza.IQ, query *extensions.Quer
answer.Error.Text = err.Error()
return
}
}
func iqAnswerSetError(answer *stanza.IQ, code int) {