Reflect MUC member affiliation/role changes in Telegram

This commit is contained in:
Bohdan Horbeshko 2025-06-14 13:20:02 -04:00
parent 26eafbba3d
commit ebdf180ce5
6 changed files with 234 additions and 102 deletions

View file

@ -31,6 +31,7 @@ type MUCState struct {
type MUCMember struct { type MUCMember struct {
Nickname string Nickname string
Affiliation string Affiliation string
Role string
} }
func NewMUCState() *MUCState { func NewMUCState() *MUCState {

View file

@ -855,7 +855,7 @@ func (c *Client) ProcessChatCommand(chatID int64, cmdline string) (string, bool,
return "Contact not found", true, false return "Contact not found", true, false
} }
err = c.Kick(chatID, contact.Id, "") err = c.SetChatMemberStatus(chatID, contact.Id, ChatMemberStatusKicked, 0, "", "")
if err != nil { if err != nil {
return err.Error(), true, false return err.Error(), true, false
} }
@ -878,15 +878,7 @@ func (c *Client) ProcessChatCommand(chatID int64, cmdline string) (string, bool,
} }
} }
_, err = c.client.SetChatMemberStatus(&client.SetChatMemberStatusRequest{ err = c.SetChatMemberStatus(chatID, contact.Id, ChatMemberStatusMuted, hours, "", "")
ChatId: chatID,
MemberId: &client.MessageSenderUser{UserId: contact.Id},
Status: &client.ChatMemberStatusRestricted{
IsMember: true,
RestrictedUntilDate: c.formatBantime(hours),
Permissions: &permissionsReadonly,
},
})
if err != nil { if err != nil {
return err.Error(), true, false return err.Error(), true, false
} }
@ -907,15 +899,7 @@ func (c *Client) ProcessChatCommand(chatID int64, cmdline string) (string, bool,
return "Contact not found", true, false return "Contact not found", true, false
} }
_, err = c.client.SetChatMemberStatus(&client.SetChatMemberStatusRequest{ err = c.SetChatMemberStatus(chatID, contact.Id, ChatMemberStatusUnmuted, 0, "", "")
ChatId: chatID,
MemberId: &client.MessageSenderUser{UserId: contact.Id},
Status: &client.ChatMemberStatusRestricted{
IsMember: true,
RestrictedUntilDate: 0,
Permissions: &permissionsMember,
},
})
if err != nil { if err != nil {
return err.Error(), true, false return err.Error(), true, false
} }
@ -943,13 +927,7 @@ func (c *Client) ProcessChatCommand(chatID int64, cmdline string) (string, bool,
} }
} }
_, err = c.client.SetChatMemberStatus(&client.SetChatMemberStatusRequest{ err = c.SetChatMemberStatus(chatID, contact.Id, ChatMemberStatusBanned, hours, "", "")
ChatId: chatID,
MemberId: &client.MessageSenderUser{UserId: contact.Id},
Status: &client.ChatMemberStatusBanned{
BannedUntilDate: c.formatBantime(hours),
},
})
if err != nil { if err != nil {
return err.Error(), true, false return err.Error(), true, false
} }
@ -963,11 +941,7 @@ func (c *Client) ProcessChatCommand(chatID int64, cmdline string) (string, bool,
return "Contact not found", true, false return "Contact not found", true, false
} }
_, err = c.client.SetChatMemberStatus(&client.SetChatMemberStatusRequest{ err = c.SetChatMemberStatus(chatID, contact.Id, ChatMemberStatusUnbanned, 0, "", "")
ChatId: chatID,
MemberId: &client.MessageSenderUser{UserId: contact.Id},
Status: &client.ChatMemberStatusMember{},
})
if err != nil { if err != nil {
return err.Error(), true, false return err.Error(), true, false
} }
@ -981,21 +955,13 @@ func (c *Client) ProcessChatCommand(chatID int64, cmdline string) (string, bool,
return "Contact not found", true, false return "Contact not found", true, false
} }
// clone the permissions var customTitle string
status := client.ChatMemberStatusAdministrator{
CanBeEdited: true,
Rights: &permissionsAdmin,
}
if len(args) > 1 { if len(args) > 1 {
status.CustomTitle = args[1] customTitle = args[1]
} }
_, err = c.client.SetChatMemberStatus(&client.SetChatMemberStatusRequest{ // clone the permissions
ChatId: chatID, err = c.SetChatMemberStatus(chatID, contact.Id, ChatMemberStatusPromoted, 0, customTitle, "")
MemberId: &client.MessageSenderUser{UserId: contact.Id},
Status: &status,
})
if err != nil { if err != nil {
return err.Error(), true, false return err.Error(), true, false
} }

View file

@ -131,6 +131,17 @@ func NewMessageLimitSince(since int64) *MessageLimit {
const AVATAR_SIZE_LIMIT int64 = 128 * 1024 const AVATAR_SIZE_LIMIT int64 = 128 * 1024
const (
ChatMemberStatusIllegal = iota
ChatMemberStatusKicked
ChatMemberStatusMuted
ChatMemberStatusUnmuted
ChatMemberStatusBanned
ChatMemberStatusUnbanned
ChatMemberStatusPromoted
)
type ChatMemberStatus int
// GetContactByUsername resolves username to user id retrieves user and chat information // GetContactByUsername resolves username to user id retrieves user and chat information
func (c *Client) GetContactByUsername(username string) (*client.Chat, *client.User, error) { func (c *Client) GetContactByUsername(username string) (*client.Chat, *client.User, error) {
if !c.Online() { if !c.Online() {
@ -512,6 +523,7 @@ func (c *Client) ProcessStatusUpdate(chatID int64, status string, show string, o
gateway.SPFrom(gateway.MUCNODE(mucId)), gateway.SPFrom(gateway.MUCNODE(mucId)),
gateway.SPResource(member.Nickname), gateway.SPResource(member.Nickname),
gateway.SPMUCAffiliation(member.Affiliation), gateway.SPMUCAffiliation(member.Affiliation),
gateway.SPMUCRole(member.Role),
gateway.SPMUCJid(chatJid), gateway.SPMUCJid(chatJid),
) )
err := c.sendPresence(newMucArgs...) err := c.sendPresence(newMucArgs...)
@ -597,6 +609,7 @@ func (c *Client) sendMUCStatuses(chatID int64) {
myNickname = c.getFullName(c.me) myNickname = c.getFullName(c.me)
} }
myAffiliation := "member" myAffiliation := "member"
myRole := "participant"
members, err := c.client.SearchChatMembers(&client.SearchChatMembersRequest{ members, err := c.client.SearchChatMembers(&client.SearchChatMembersRequest{
ChatId: chatID, ChatId: chatID,
@ -616,15 +629,17 @@ func (c *Client) sendMUCStatuses(chatID int64) {
} }
nickname := c.GetMUCNickname(senderId) nickname := c.GetMUCNickname(senderId)
affiliation := c.memberStatusToAffiliation(member.Status) affiliation, role := c.memberStatusToAffiliationAndRole(member.Status)
mucState.Members[senderId] = &MUCMember{ mucState.Members[senderId] = &MUCMember{
Nickname: nickname, Nickname: nickname,
Affiliation: affiliation, Affiliation: affiliation,
Role: role,
} }
if c.me != nil && senderId == c.me.Id { if c.me != nil && senderId == c.me.Id {
myNickname = nickname myNickname = nickname
myAffiliation = affiliation myAffiliation = affiliation
myRole = role
continue continue
} }
@ -633,6 +648,7 @@ func (c *Client) sendMUCStatuses(chatID int64) {
gateway.SPResource(nickname), gateway.SPResource(nickname),
gateway.SPImmed(true), gateway.SPImmed(true),
gateway.SPMUCAffiliation(affiliation), gateway.SPMUCAffiliation(affiliation),
gateway.SPMUCRole(affiliation),
gateway.SPMUCJid(gateway.CHATJID(senderId, true)), gateway.SPMUCJid(gateway.CHATJID(senderId, true)),
) )
} }
@ -644,6 +660,7 @@ func (c *Client) sendMUCStatuses(chatID int64) {
gateway.SPResource(myNickname), gateway.SPResource(myNickname),
gateway.SPImmed(true), gateway.SPImmed(true),
gateway.SPMUCAffiliation(myAffiliation), gateway.SPMUCAffiliation(myAffiliation),
gateway.SPMUCRole(myRole),
gateway.SPMUCStatusCodes([]uint16{100, 110, 210}), gateway.SPMUCStatusCodes([]uint16{100, 110, 210}),
) )
} }
@ -660,7 +677,7 @@ func (c *Client) mucCacheHasMember(mucID int64, memberID int64) bool {
return ok return ok
} }
func (c *Client) addMUCMember(mucID int64, memberID int64, affiliation string) bool { func (c *Client) addMUCMember(mucID int64, memberID int64, affiliation, role string) bool {
c.locks.mucCacheLock.Lock() c.locks.mucCacheLock.Lock()
defer c.locks.mucCacheLock.Unlock() defer c.locks.mucCacheLock.Unlock()
mucState, ok := c.mucCache[mucID] mucState, ok := c.mucCache[mucID]
@ -675,6 +692,7 @@ func (c *Client) addMUCMember(mucID int64, memberID int64, affiliation string) b
gateway.SPResource(nickname), gateway.SPResource(nickname),
gateway.SPImmed(true), gateway.SPImmed(true),
gateway.SPMUCAffiliation(affiliation), gateway.SPMUCAffiliation(affiliation),
gateway.SPMUCRole(role),
gateway.SPMUCJid(gateway.CHATJID(memberID, true)), gateway.SPMUCJid(gateway.CHATJID(memberID, true)),
) )
@ -682,6 +700,7 @@ func (c *Client) addMUCMember(mucID int64, memberID int64, affiliation string) b
mucState.Members[memberID] = &MUCMember{ mucState.Members[memberID] = &MUCMember{
Nickname: nickname, Nickname: nickname,
Affiliation: affiliation, Affiliation: affiliation,
Role: role,
} }
return true return true
} }
@ -747,6 +766,7 @@ func (c *Client) updateMUCsNickname(memberID int64, newNickname string) {
gateway.SPResource(oldMember.Nickname), gateway.SPResource(oldMember.Nickname),
gateway.SPImmed(true), gateway.SPImmed(true),
gateway.SPMUCAffiliation(oldMember.Affiliation), gateway.SPMUCAffiliation(oldMember.Affiliation),
gateway.SPMUCRole(oldMember.Role),
gateway.SPMUCNick(newNickname), gateway.SPMUCNick(newNickname),
gateway.SPMUCStatusCodes(unavailableStatusCodes), gateway.SPMUCStatusCodes(unavailableStatusCodes),
gateway.SPMUCJid(realJid), gateway.SPMUCJid(realJid),
@ -756,6 +776,7 @@ func (c *Client) updateMUCsNickname(memberID int64, newNickname string) {
gateway.SPResource(newNickname), gateway.SPResource(newNickname),
gateway.SPImmed(true), gateway.SPImmed(true),
gateway.SPMUCAffiliation(oldMember.Affiliation), gateway.SPMUCAffiliation(oldMember.Affiliation),
gateway.SPMUCRole(oldMember.Role),
gateway.SPMUCStatusCodes(availableStatusCodes), gateway.SPMUCStatusCodes(availableStatusCodes),
gateway.SPMUCJid(realJid), gateway.SPMUCJid(realJid),
) )
@ -1618,7 +1639,7 @@ func (c *Client) ProcessIncomingMessage(chatId int64, message *client.Message) {
if c.Session.MUC && c.IsGroup(chat) { if c.Session.MUC && c.IsGroup(chat) {
if message.Content.MessageContentType() == client.TypeMessageChatDeleteMember { if message.Content.MessageContentType() == client.TypeMessageChatDeleteMember {
deleteMember, _ := message.Content.(*client.MessageChatDeleteMember) deleteMember, _ := message.Content.(*client.MessageChatDeleteMember)
c.kickMemberFromMUC(chatId, deleteMember.UserId, c.GetMUCNickname(deleteMember.UserId)) c.mucMemberRolePresence(chatId, deleteMember.UserId, ChatMemberStatusKicked, c.GetMUCNickname(deleteMember.UserId))
} }
senderId := c.getMessageSenderId(message) senderId := c.getMessageSenderId(message)
@ -1636,7 +1657,8 @@ func (c *Client) ProcessIncomingMessage(chatId int64, message *client.Message) {
if err == nil { if err == nil {
status = chatMember.Status status = chatMember.Status
} }
safeToSend = c.addMUCMember(chatId, senderId, c.memberStatusToAffiliation(status)) affiliation, role := c.memberStatusToAffiliationAndRole(status)
safeToSend = c.addMUCMember(chatId, senderId, affiliation, role)
} }
groupChatFrom = gateway.MUCJID(chatId) + "/" + c.GetMUCNickname(senderId) groupChatFrom = gateway.MUCJID(chatId) + "/" + c.GetMUCNickname(senderId)
@ -2441,24 +2463,28 @@ func (c *Client) usernamesToString(usernames []string) string {
return strings.Join(atUsernames, ", ") return strings.Join(atUsernames, ", ")
} }
func (c *Client) memberStatusToAffiliation(memberStatus client.ChatMemberStatus) string { func (c *Client) memberStatusToAffiliationAndRole(memberStatus client.ChatMemberStatus) (string, string) {
if memberStatus != nil { if memberStatus != nil {
switch memberStatus.ChatMemberStatusType() { switch memberStatus.ChatMemberStatusType() {
case client.TypeChatMemberStatusCreator: case client.TypeChatMemberStatusCreator:
return "owner" return "owner", "moderator"
case client.TypeChatMemberStatusAdministrator: case client.TypeChatMemberStatusAdministrator:
return "admin" return "admin", "moderator"
case client.TypeChatMemberStatusMember: case client.TypeChatMemberStatusMember:
return "member" return "member", "participant"
case client.TypeChatMemberStatusRestricted: case client.TypeChatMemberStatusRestricted:
return "outcast" restricted, _ := memberStatus.(*client.ChatMemberStatusRestricted)
if restricted.Permissions != nil && !restricted.Permissions.CanSendBasicMessages {
return "member", "visitor"
}
return "member", "participant"
case client.TypeChatMemberStatusLeft: case client.TypeChatMemberStatusLeft:
return "none" return "none", "none"
case client.TypeChatMemberStatusBanned: case client.TypeChatMemberStatusBanned:
return "outcast" return "outcast", "none"
} }
} }
return "member" return "member", "participant"
} }
func (c *Client) sendMessagesReverse(chatID int64, messages []*client.Message, plain bool, toJid string) { func (c *Client) sendMessagesReverse(chatID int64, messages []*client.Message, plain bool, toJid string) {
@ -2598,38 +2624,114 @@ func (c *Client) MigrateToMUCs() {
} }
} }
// Kick kicks // SetChatMemberStatus is a handy wrapper for the following TDLib method
func (c *Client) Kick(chatID, userID int64, nickname string) error { func (c *Client) SetChatMemberStatus(chatID, userID int64, status ChatMemberStatus, numericPayload int64, stringPayload, nickname string) error {
var chatMemberStatus client.ChatMemberStatus
switch status {
case ChatMemberStatusKicked:
chatMemberStatus = &client.ChatMemberStatusLeft{}
case ChatMemberStatusMuted:
chatMemberStatus = &client.ChatMemberStatusRestricted{
IsMember: true,
RestrictedUntilDate: c.formatBantime(numericPayload),
Permissions: &permissionsReadonly,
}
case ChatMemberStatusUnmuted:
chatMemberStatus = &client.ChatMemberStatusRestricted{
IsMember: true,
RestrictedUntilDate: 0,
Permissions: &permissionsMember,
}
case ChatMemberStatusBanned:
chatMemberStatus = &client.ChatMemberStatusBanned{
BannedUntilDate: c.formatBantime(numericPayload),
}
case ChatMemberStatusUnbanned:
chatMemberStatus = &client.ChatMemberStatusMember{}
case ChatMemberStatusPromoted:
chatMemberStatus = &client.ChatMemberStatusAdministrator{
CanBeEdited: true,
Rights: &permissionsAdmin,
CustomTitle: stringPayload,
}
}
_, err := c.client.SetChatMemberStatus(&client.SetChatMemberStatusRequest{ _, err := c.client.SetChatMemberStatus(&client.SetChatMemberStatusRequest{
ChatId: chatID, ChatId: chatID,
MemberId: &client.MessageSenderUser{UserId: userID}, MemberId: &client.MessageSenderUser{UserId: userID},
Status: &client.ChatMemberStatusLeft{}, Status: chatMemberStatus,
}) })
if err != nil && nickname != "" { if err == nil && nickname != "" {
c.kickMemberFromMUC(chatID, userID, nickname) c.mucMemberRolePresence(chatID, userID, status, nickname)
} }
return err return err
} }
func (c *Client) kickMemberFromMUC(chatID, userID int64, nickname string) { func (c *Client) mucMemberRolePresence(chatID, userID int64, status ChatMemberStatus, nickname string) {
unavailableStatusCodes := []uint16{307} args := []args.V{
if c.me != nil && userID == c.me.Id {
unavailableStatusCodes = append(unavailableStatusCodes, 110)
}
c.sendPresence(
gateway.SPType("unavailable"),
gateway.SPFrom(gateway.MUCNODE(chatID)), gateway.SPFrom(gateway.MUCNODE(chatID)),
gateway.SPResource(nickname), gateway.SPResource(nickname),
gateway.SPImmed(true), gateway.SPImmed(true),
gateway.SPMUCAffiliation("none"),
gateway.SPMUCStatusCodes(unavailableStatusCodes),
gateway.SPMUCJid(gateway.CHATJID(userID, true)), gateway.SPMUCJid(gateway.CHATJID(userID, true)),
}
var statusCodes []uint16
var newAffiliation, newRole string
switch status {
case ChatMemberStatusKicked:
args = append(args, gateway.SPType("unavailable"))
newAffiliation = "none"
newRole = "none"
statusCodes = append(statusCodes, 307)
if c.me != nil && userID == c.me.Id {
statusCodes = append(statusCodes, 110)
}
case ChatMemberStatusMuted:
newAffiliation = "member"
newRole = "visitor"
case ChatMemberStatusUnmuted, ChatMemberStatusUnbanned:
newAffiliation = "member"
newRole = "participant"
case ChatMemberStatusBanned:
args = append(args, gateway.SPType("unavailable"))
newAffiliation = "outcast"
newRole = "none"
statusCodes = append(statusCodes, 301)
case ChatMemberStatusPromoted:
newAffiliation = "admin"
newRole = "moderator"
}
args = append(
args,
gateway.SPMUCAffiliation(newAffiliation),
gateway.SPMUCRole(newRole),
gateway.SPMUCStatusCodes(statusCodes),
) )
c.sendPresence(args...)
c.locks.mucCacheLock.Lock() c.locks.mucCacheLock.Lock()
mucState, ok := c.mucCache[chatID] mucState, ok := c.mucCache[chatID]
if ok && mucState != nil { if ok && mucState != nil {
delete(mucState.Members, userID) if status == ChatMemberStatusKicked || status == ChatMemberStatusBanned {
delete(mucState.Members, userID)
} else {
member, ok := mucState.Members[userID]
if ok {
member.Affiliation = newAffiliation
member.Role = newRole
}
}
} }
c.locks.mucCacheLock.Unlock() c.locks.mucCacheLock.Unlock()
} }
// GetErrorCode obtains an error code from a Telegram response error
func GetErrorCode(err error) (int32, bool) {
responseError, ok := err.(client.ResponseError)
if !ok || responseError.Err == nil {
return 0, false
}
return responseError.Err.Code, true
}

View file

@ -316,10 +316,12 @@ type QueryMucAdmin struct {
// QueryMucAdminItem is a child element from XEP-0045 // QueryMucAdminItem is a child element from XEP-0045
type QueryMucAdminItem struct { type QueryMucAdminItem struct {
XMLName xml.Name `xml:"item"` XMLName xml.Name `xml:"item"`
Nick string `xml:"nick,attr"` Jid string `xml:"jid,attr,omitempty"`
Role string `xml:"role,attr"` Nick string `xml:"nick,attr,omitempty"`
Reason string `xml:"reason,omitempty"` Role string `xml:"role,attr,omitempty"`
Affiliation string `xml:"affiliation,attr,omitempty"`
Reason string `xml:"reason,omitempty"`
} }
// Namespace is a namespace! // Namespace is a namespace!

View file

@ -438,6 +438,9 @@ var SPImmed = args.NewBool(args.Default(true))
// SPMUCAffiliation is a XEP-0045 MUC affiliation // SPMUCAffiliation is a XEP-0045 MUC affiliation
var SPMUCAffiliation = args.NewString() var SPMUCAffiliation = args.NewString()
// SPMUCRole is a XEP-0045 MUC role
var SPMUCRole = args.NewString()
// SPMUCNick is a XEP-0045 MUC user nick // SPMUCNick is a XEP-0045 MUC user nick
var SPMUCNick = args.NewString() var SPMUCNick = args.NewString()
@ -505,10 +508,16 @@ func newPresence(bareJid string, to string, args ...args.V) stanza.Presence {
if SPMUCAffiliation.IsSet(args) { if SPMUCAffiliation.IsSet(args) {
affiliation := SPMUCAffiliation.Get(args) affiliation := SPMUCAffiliation.Get(args)
if affiliation != "" { if affiliation != "" {
var role string
if SPMUCRole.IsSet(args) {
role = SPMUCRole.Get(args)
} else {
role = affiliationToRole(affiliation)
}
userExt := extensions.PresenceXMucUserExtension{ userExt := extensions.PresenceXMucUserExtension{
Item: extensions.PresenceXMucUserItem{ Item: extensions.PresenceXMucUserItem{
Affiliation: affiliation, Affiliation: affiliation,
Role: affilationToRole(affiliation), Role: role,
}, },
} }
if SPMUCNick.IsSet(args) { if SPMUCNick.IsSet(args) {
@ -625,7 +634,7 @@ func SplitJID(from string) (string, string, bool) {
return fromJid.Bare(), fromJid.Resource, true return fromJid.Bare(), fromJid.Resource, true
} }
func affilationToRole(affilation string) string { func affiliationToRole(affilation string) string {
switch affilation { switch affilation {
case "owner", "admin": case "owner", "admin":
return "moderator" return "moderator"

View file

@ -1602,37 +1602,84 @@ func handleSetQueryMucAdmin(s xmpp.Sender, iq *stanza.IQ, query *extensions.Quer
} }
defer gateway.ResumableSend(component, answer) defer gateway.ResumableSend(component, answer)
if query.Item.Role == "none" { bare, _, fromOk := gateway.SplitJID(iq.From)
bare, _, fromOk := gateway.SplitJID(iq.From) if !fromOk {
if !fromOk { iqAnswerSetError(answer, 400)
iqAnswerSetError(answer, 400) return
return }
}
session, sessionOk := sessions[bare] session, sessionOk := sessions[bare]
if !sessionOk || !session.Session.MUC { if !sessionOk || !session.Session.MUC {
iqAnswerSetError(answer, 401) iqAnswerSetError(answer, 403)
return return
} }
toID, toOk, toIsGroup := toToID(iq.To) toID, toOk, toIsGroup := toToID(iq.To)
if !toOk || !toIsGroup { if !toOk || !toIsGroup {
iqAnswerSetError(answer, 406) iqAnswerSetError(answer, 406)
return return
} }
userID := session.GetMUCMemberIdByNickname(toID, query.Item.Nick) var userID int64
if userID == 0 { if query.Item.Jid != "" {
iqAnswerSetError(answer, 404) userID, _, _ = toToID(query.Item.Jid)
return } else if query.Item.Nick != "" {
} userID = session.GetMUCMemberIdByNickname(toID, query.Item.Nick)
}
if userID == 0 {
iqAnswerSetError(answer, 404)
return
}
err := session.Kick(toID, userID, query.Item.Nick) nick := query.Item.Nick
if err != nil { if nick == "" {
iqAnswerSetError(answer, 500) nick = session.GetMUCNickname(userID)
answer.Error.Text = err.Error() }
return
var status telegram.ChatMemberStatus
var integerPayload int64
var stringPayload string
switch query.Item.Role {
case "none":
status = telegram.ChatMemberStatusKicked
case "visitor":
status = telegram.ChatMemberStatusMuted
case "participant":
status = telegram.ChatMemberStatusUnmuted
case "moderator":
status = telegram.ChatMemberStatusPromoted
}
// affiliations have a higher priority over roles
switch query.Item.Affiliation {
case "none":
status = telegram.ChatMemberStatusKicked
case "outcast":
status = telegram.ChatMemberStatusBanned
case "member":
status = telegram.ChatMemberStatusUnmuted
case "admin":
status = telegram.ChatMemberStatusPromoted
case "owner":
iqAnswerSetError(answer, 403)
return
}
// nothing has been detected
if status == telegram.ChatMemberStatusIllegal {
iqAnswerSetError(answer, 400)
return
}
err := session.SetChatMemberStatus(toID, userID, status, integerPayload, stringPayload, nick)
if err != nil {
code, ok := telegram.GetErrorCode(err)
if !ok {
code = 500
} }
iqAnswerSetError(answer, int(code))
answer.Error.Text = err.Error()
return
} }
} }
@ -1658,6 +1705,11 @@ func iqAnswerSetErrorInternal(answer *stanza.IQ, code int, registerMode bool) {
Type: stanza.ErrorTypeAuth, Type: stanza.ErrorTypeAuth,
Reason: "not-authorized", Reason: "not-authorized",
} }
case 403:
answer.Error = &stanza.Err{
Type: stanza.ErrorTypeAuth,
Reason: "forbidden",
}
case 404: case 404:
answer.Error = &stanza.Err{ answer.Error = &stanza.Err{
Type: stanza.ErrorTypeCancel, Type: stanza.ErrorTypeCancel,