aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBohdan Horbeshko <bodqhrohro@gmail.com>2023-09-18 06:21:57 +0300
committerBohdan Horbeshko <bodqhrohro@gmail.com>2023-09-18 06:21:57 +0300
commitf99f4f6acc6734ecbd0da80015285e6b3d39fdd8 (patch)
tree1edb75e85dab67337cc4d795cb66677242df1d55
parent776993894ad780f1500c139aff85378c8a1d22f5 (diff)
Send memberlist on MUC join, suppress PM statuses for MUC JIDs
-rw-r--r--telegram/utils.go55
-rw-r--r--xmpp/extensions/extensions.go24
-rw-r--r--xmpp/gateway/gateway.go24
-rw-r--r--xmpp/handlers.go86
4 files changed, 189 insertions, 0 deletions
diff --git a/telegram/utils.go b/telegram/utils.go
index 08c45d2..3ab6b88 100644
--- a/telegram/utils.go
+++ b/telegram/utils.go
@@ -217,6 +217,10 @@ func (c *Client) ProcessStatusUpdate(chatID int64, status string, show string, o
return err
}
+ if chat != nil && c.Session.MUC && c.IsGroup(chat) {
+ return nil
+ }
+
var photo string
if chat != nil && chat.Photo != nil {
file, path, err := c.ForceOpenFile(chat.Photo.Small, 1)
@@ -290,6 +294,35 @@ func (c *Client) ProcessStatusUpdate(chatID int64, status string, show string, o
)
}
+func (c *Client) SendMUCStatuses(chatID int64) {
+ members, err := c.client.SearchChatMembers(&client.SearchChatMembersRequest{
+ ChatId: chatID,
+ Limit: 200,
+ Filter: &client.ChatMembersFilterMembers{},
+ })
+ if err == nil {
+ for _, member := range members.Members {
+ var senderId int64
+ switch member.MemberId.MessageSenderType() {
+ case client.TypeMessageSenderUser:
+ memberUser, _ := member.MemberId.(*client.MessageSenderUser)
+ senderId = memberUser.UserId
+ case client.TypeMessageSenderChat:
+ memberChat, _ := member.MemberId.(*client.MessageSenderChat)
+ senderId = memberChat.ChatId
+ }
+ gateway.SendPresence(
+ c.xmpp,
+ c.jid,
+ gateway.SPFrom(strconv.FormatInt(chatID, 10)),
+ gateway.SPResource(c.formatContact(senderId)),
+ gateway.SPImmed(true),
+ gateway.SPAffiliation(c.memberStatusToAffiliation(member.Status)),
+ )
+ }
+ }
+}
+
func (c *Client) formatContact(chatID int64) string {
if chatID == 0 {
return ""
@@ -1434,6 +1467,10 @@ func (c *Client) UpdateChatNicknames() {
for _, id := range c.cache.ChatsKeys() {
chat, ok := c.cache.GetChat(id)
if ok {
+ if c.Session.MUC && c.IsGroup(chat) {
+ continue
+ }
+
newArgs := []args.V{
gateway.SPFrom(strconv.FormatInt(id, 10)),
gateway.SPNickname(chat.Title),
@@ -1560,3 +1597,21 @@ func (c *Client) usernamesToString(usernames []string) string {
}
return strings.Join(atUsernames, ", ")
}
+
+func (c *Client) memberStatusToAffiliation(memberStatus client.ChatMemberStatus) string {
+ switch memberStatus.ChatMemberStatusType() {
+ case client.TypeChatMemberStatusCreator:
+ return "owner"
+ case client.TypeChatMemberStatusAdministrator:
+ return "admin"
+ case client.TypeChatMemberStatusMember:
+ return "member"
+ case client.TypeChatMemberStatusRestricted:
+ return "outcast"
+ case client.TypeChatMemberStatusLeft:
+ return "none"
+ case client.TypeChatMemberStatusBanned:
+ return "outcast"
+ }
+ return "member"
+}
diff --git a/xmpp/extensions/extensions.go b/xmpp/extensions/extensions.go
index 8e2f743..0b7269f 100644
--- a/xmpp/extensions/extensions.go
+++ b/xmpp/extensions/extensions.go
@@ -213,6 +213,19 @@ type QueryRegisterRemove struct {
XMLName xml.Name `xml:"remove"`
}
+// PresenceXMucUserExtension is from XEP-0045
+type PresenceXMucUserExtension struct {
+ XMLName xml.Name `xml:"http://jabber.org/protocol/muc#user x"`
+ Item PresenceXMucUserItem
+}
+
+// PresenceXMucUserItem is from XEP-0045
+type PresenceXMucUserItem struct {
+ XMLName xml.Name `xml:"item"`
+ Affiliation string `xml:"affiliation,attr"`
+ Role string `xml:"role,attr"`
+}
+
// Namespace is a namespace!
func (c PresenceNickExtension) Namespace() string {
return c.XMLName.Space
@@ -278,6 +291,11 @@ func (c QueryRegister) GetSet() *stanza.ResultSet {
return c.ResultSet
}
+// Namespace is a namespace!
+func (c PresenceXMucUserExtension) Namespace() string {
+ return c.XMLName.Space
+}
+
// Name is a packet name
func (ClientMessage) Name() string {
return "message"
@@ -362,4 +380,10 @@ func init() {
"jabber:iq:register",
"query",
}, QueryRegister{})
+
+ // presence muc user
+ stanza.TypeRegistry.MapExtension(stanza.PKTPresence, xml.Name{
+ "http://jabber.org/protocol/muc#user",
+ "x",
+ }, PresenceXMucUserExtension{})
}
diff --git a/xmpp/gateway/gateway.go b/xmpp/gateway/gateway.go
index dfe2ebf..c09a061 100644
--- a/xmpp/gateway/gateway.go
+++ b/xmpp/gateway/gateway.go
@@ -240,6 +240,9 @@ var SPResource = args.NewString()
// SPImmed skips queueing
var SPImmed = args.NewBool(args.Default(true))
+// SPAffiliation is a XEP-0045 MUC affiliation
+var SPAffiliation = args.NewString()
+
func newPresence(bareJid string, to string, args ...args.V) stanza.Presence {
var presenceFrom string
if SPFrom.IsSet(args) {
@@ -295,6 +298,17 @@ func newPresence(bareJid string, to string, args ...args.V) stanza.Presence {
})
}
}
+ if SPAffiliation.IsSet(args) {
+ affiliation := SPAffiliation.Get(args)
+ if affiliation != "" {
+ presence.Extensions = append(presence.Extensions, extensions.PresenceXMucUserExtension{
+ Item: extensions.PresenceXMucUserItem{
+ Affiliation: affiliation,
+ Role: affilationToRole(affiliation),
+ },
+ })
+ }
+ }
return presence
}
@@ -377,3 +391,13 @@ func SplitJID(from string) (string, string, bool) {
}
return fromJid.Bare(), fromJid.Resource, true
}
+
+func affilationToRole(affilation string) string {
+ switch affilation {
+ case "owner", "admin":
+ return "moderator"
+ case "member":
+ return "participant"
+ }
+ return "none"
+}
diff --git a/xmpp/handlers.go b/xmpp/handlers.go
index 6f51427..a1f6d74 100644
--- a/xmpp/handlers.go
+++ b/xmpp/handlers.go
@@ -287,6 +287,12 @@ func HandlePresence(s xmpp.Sender, p stanza.Packet) {
}
if prs.To == gateway.Jid.Bare() {
handlePresence(s, prs)
+ return
+ }
+ var mucExt stanza.MucPresence
+ prs.Get(&mucExt)
+ if mucExt.XMLName.Space != "" {
+ handleMUCPresence(s, prs)
}
}
@@ -397,6 +403,64 @@ func handlePresence(s xmpp.Sender, p stanza.Presence) {
}
}
+func handleMUCPresence(s xmpp.Sender, p stanza.Presence) {
+ log.WithFields(log.Fields{
+ "type": p.Type,
+ "from": p.From,
+ "to": p.To,
+ }).Warn("MUC presence")
+ log.Debugf("%#v", p)
+
+ if p.Type == "" {
+ toBare, nickname, ok := gateway.SplitJID(p.To)
+ if ok {
+ component, ok := s.(*xmpp.Component)
+ if !ok {
+ log.Error("Not a component")
+ return
+ }
+
+ reply := stanza.Presence{Attrs: stanza.Attrs{
+ From: toBare,
+ To: p.From,
+ Id: p.Id,
+ }}
+ defer gateway.ResumableSend(component, reply)
+
+ if nickname == "" {
+ presenceReplySetError(&reply, 400)
+ return
+ }
+
+ chatId, ok := toToID(toBare)
+ if !ok {
+ presenceReplySetError(&reply, 404)
+ return
+ }
+
+ fromBare, _, ok := gateway.SplitJID(p.From)
+ if !ok {
+ presenceReplySetError(&reply, 400)
+ return
+ }
+
+ session, ok := sessions[fromBare]
+ if !ok || !session.Session.MUC {
+ presenceReplySetError(&reply, 401)
+ return
+ }
+
+ chat, _, err := session.GetContactByID(chatId, nil)
+ if err != nil || !session.IsGroup(chat) {
+ presenceReplySetError(&reply, 404)
+ return
+ }
+
+ session.SendMUCStatuses(chatId)
+ }
+ }
+}
+
func handleGetVcardIq(s xmpp.Sender, iq *stanza.IQ, typ byte) {
log.WithFields(log.Fields{
"from": iq.From,
@@ -711,6 +775,28 @@ func iqAnswerSetError(answer *stanza.IQ, payload *extensions.QueryRegister, code
}
}
+func presenceReplySetError(reply *stanza.Presence, code int) {
+ reply.Type = stanza.PresenceTypeError
+ reply.Error = stanza.Err{
+ Code: code,
+ }
+ switch code {
+ case 400:
+ reply.Error.Type = stanza.ErrorTypeModify
+ reply.Error.Reason = "jid-malformed"
+ case 401:
+ reply.Error.Type = stanza.ErrorTypeAuth
+ reply.Error.Reason = "not-authorized"
+ case 404:
+ reply.Error.Type = stanza.ErrorTypeCancel
+ reply.Error.Reason = "item-not-found"
+ default:
+ log.Error("Unknown error code, falling back with empty reason")
+ reply.Error.Type = stanza.ErrorTypeCancel
+ reply.Error.Reason = "undefined-condition"
+ }
+}
+
func toToID(to string) (int64, bool) {
toParts := strings.Split(to, "@")
if len(toParts) < 2 {