Send memberlist on MUC join, suppress PM statuses for MUC JIDs
This commit is contained in:
parent
776993894a
commit
f99f4f6acc
|
@ -217,6 +217,10 @@ func (c *Client) ProcessStatusUpdate(chatID int64, status string, show string, o
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if chat != nil && c.Session.MUC && c.IsGroup(chat) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
var photo string
|
var photo string
|
||||||
if chat != nil && chat.Photo != nil {
|
if chat != nil && chat.Photo != nil {
|
||||||
file, path, err := c.ForceOpenFile(chat.Photo.Small, 1)
|
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 {
|
func (c *Client) formatContact(chatID int64) string {
|
||||||
if chatID == 0 {
|
if chatID == 0 {
|
||||||
return ""
|
return ""
|
||||||
|
@ -1434,6 +1467,10 @@ func (c *Client) UpdateChatNicknames() {
|
||||||
for _, id := range c.cache.ChatsKeys() {
|
for _, id := range c.cache.ChatsKeys() {
|
||||||
chat, ok := c.cache.GetChat(id)
|
chat, ok := c.cache.GetChat(id)
|
||||||
if ok {
|
if ok {
|
||||||
|
if c.Session.MUC && c.IsGroup(chat) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
newArgs := []args.V{
|
newArgs := []args.V{
|
||||||
gateway.SPFrom(strconv.FormatInt(id, 10)),
|
gateway.SPFrom(strconv.FormatInt(id, 10)),
|
||||||
gateway.SPNickname(chat.Title),
|
gateway.SPNickname(chat.Title),
|
||||||
|
@ -1560,3 +1597,21 @@ func (c *Client) usernamesToString(usernames []string) string {
|
||||||
}
|
}
|
||||||
return strings.Join(atUsernames, ", ")
|
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"
|
||||||
|
}
|
||||||
|
|
|
@ -213,6 +213,19 @@ type QueryRegisterRemove struct {
|
||||||
XMLName xml.Name `xml:"remove"`
|
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!
|
// Namespace is a namespace!
|
||||||
func (c PresenceNickExtension) Namespace() string {
|
func (c PresenceNickExtension) Namespace() string {
|
||||||
return c.XMLName.Space
|
return c.XMLName.Space
|
||||||
|
@ -278,6 +291,11 @@ func (c QueryRegister) GetSet() *stanza.ResultSet {
|
||||||
return c.ResultSet
|
return c.ResultSet
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Namespace is a namespace!
|
||||||
|
func (c PresenceXMucUserExtension) Namespace() string {
|
||||||
|
return c.XMLName.Space
|
||||||
|
}
|
||||||
|
|
||||||
// Name is a packet name
|
// Name is a packet name
|
||||||
func (ClientMessage) Name() string {
|
func (ClientMessage) Name() string {
|
||||||
return "message"
|
return "message"
|
||||||
|
@ -362,4 +380,10 @@ func init() {
|
||||||
"jabber:iq:register",
|
"jabber:iq:register",
|
||||||
"query",
|
"query",
|
||||||
}, QueryRegister{})
|
}, QueryRegister{})
|
||||||
|
|
||||||
|
// presence muc user
|
||||||
|
stanza.TypeRegistry.MapExtension(stanza.PKTPresence, xml.Name{
|
||||||
|
"http://jabber.org/protocol/muc#user",
|
||||||
|
"x",
|
||||||
|
}, PresenceXMucUserExtension{})
|
||||||
}
|
}
|
||||||
|
|
|
@ -240,6 +240,9 @@ var SPResource = args.NewString()
|
||||||
// SPImmed skips queueing
|
// SPImmed skips queueing
|
||||||
var SPImmed = args.NewBool(args.Default(true))
|
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 {
|
func newPresence(bareJid string, to string, args ...args.V) stanza.Presence {
|
||||||
var presenceFrom string
|
var presenceFrom string
|
||||||
if SPFrom.IsSet(args) {
|
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
|
return presence
|
||||||
}
|
}
|
||||||
|
@ -377,3 +391,13 @@ func SplitJID(from string) (string, string, bool) {
|
||||||
}
|
}
|
||||||
return fromJid.Bare(), fromJid.Resource, true
|
return fromJid.Bare(), fromJid.Resource, true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func affilationToRole(affilation string) string {
|
||||||
|
switch affilation {
|
||||||
|
case "owner", "admin":
|
||||||
|
return "moderator"
|
||||||
|
case "member":
|
||||||
|
return "participant"
|
||||||
|
}
|
||||||
|
return "none"
|
||||||
|
}
|
||||||
|
|
|
@ -287,6 +287,12 @@ func HandlePresence(s xmpp.Sender, p stanza.Packet) {
|
||||||
}
|
}
|
||||||
if prs.To == gateway.Jid.Bare() {
|
if prs.To == gateway.Jid.Bare() {
|
||||||
handlePresence(s, prs)
|
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) {
|
func handleGetVcardIq(s xmpp.Sender, iq *stanza.IQ, typ byte) {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
"from": iq.From,
|
"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) {
|
func toToID(to string) (int64, bool) {
|
||||||
toParts := strings.Split(to, "@")
|
toParts := strings.Split(to, "@")
|
||||||
if len(toParts) < 2 {
|
if len(toParts) < 2 {
|
||||||
|
|
Loading…
Reference in a new issue