mirror of
https://dev.narayana.im/narayana/telegabber.git
synced 2026-08-05 04:07:07 +00:00
Upgrade MUC occupants map to LRU
This commit is contained in:
parent
a909b86831
commit
f3eeba7273
5 changed files with 618 additions and 39 deletions
|
|
@ -21,27 +21,6 @@ type DelayedStatus struct {
|
||||||
TimestampExpired int64
|
TimestampExpired int64
|
||||||
}
|
}
|
||||||
|
|
||||||
// MUCState holds MUC metadata
|
|
||||||
type MUCState struct {
|
|
||||||
Resources map[string]bool
|
|
||||||
Occupants map[int64]*MUCOccupant
|
|
||||||
}
|
|
||||||
|
|
||||||
// MUCOccupant represents a MUC occupant
|
|
||||||
type MUCOccupant struct {
|
|
||||||
Nickname string
|
|
||||||
Affiliation string
|
|
||||||
Role string
|
|
||||||
Status client.ChatMemberStatus
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewMUCState() *MUCState {
|
|
||||||
return &MUCState{
|
|
||||||
Resources: make(map[string]bool),
|
|
||||||
Occupants: make(map[int64]*MUCOccupant),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// HashedAvatar stores a SHA-1 hash and a Telegram file ID
|
// HashedAvatar stores a SHA-1 hash and a Telegram file ID
|
||||||
type HashedAvatar struct {
|
type HashedAvatar struct {
|
||||||
Hash string
|
Hash string
|
||||||
|
|
|
||||||
|
|
@ -506,7 +506,7 @@ func (c *Client) updateBasicGroupFullInfo(update *client.UpdateBasicGroupFullInf
|
||||||
|
|
||||||
mucState, ok := c.mucCache[chatID]
|
mucState, ok := c.mucCache[chatID]
|
||||||
if ok && mucState != nil {
|
if ok && mucState != nil {
|
||||||
mucState.Occupants = make(map[int64]*MUCOccupant)
|
mucState.Occupants.Clear()
|
||||||
c.updateMUCOccupants(mucState, chatID, update.BasicGroupFullInfo.Members)
|
c.updateMUCOccupants(mucState, chatID, update.BasicGroupFullInfo.Members)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -528,7 +528,7 @@ func (c *Client) updateChatPermissions(update *client.UpdateChatPermissions) {
|
||||||
mucState, ok := c.mucCache[update.ChatId]
|
mucState, ok := c.mucCache[update.ChatId]
|
||||||
if ok && mucState != nil {
|
if ok && mucState != nil {
|
||||||
_, toJids := c.getMUCJoinedJIDs(update.ChatId, mucState, false)
|
_, toJids := c.getMUCJoinedJIDs(update.ChatId, mucState, false)
|
||||||
for memberID, occupant := range mucState.Occupants {
|
for occupant := range mucState.Occupants.Range() {
|
||||||
affiliation, role := c.memberStatusToAffiliationAndRole(occupant.Status, chat)
|
affiliation, role := c.memberStatusToAffiliationAndRole(occupant.Status, chat)
|
||||||
if affiliation != occupant.Affiliation || role != occupant.Role {
|
if affiliation != occupant.Affiliation || role != occupant.Role {
|
||||||
occupant.Affiliation = affiliation
|
occupant.Affiliation = affiliation
|
||||||
|
|
@ -538,7 +538,7 @@ func (c *Client) updateChatPermissions(update *client.UpdateChatPermissions) {
|
||||||
gateway.SPFrom(gateway.MUCNODE(update.ChatId)),
|
gateway.SPFrom(gateway.MUCNODE(update.ChatId)),
|
||||||
gateway.SPResource(occupant.Nickname),
|
gateway.SPResource(occupant.Nickname),
|
||||||
gateway.SPImmed(true),
|
gateway.SPImmed(true),
|
||||||
gateway.SPMUCJid(gateway.CHATJID(memberID, true)),
|
gateway.SPMUCJid(gateway.CHATJID(occupant.key, true)),
|
||||||
gateway.SPMUCAffiliation(affiliation),
|
gateway.SPMUCAffiliation(affiliation),
|
||||||
gateway.SPMUCRole(role),
|
gateway.SPMUCRole(role),
|
||||||
gateway.SPToJids(toJids),
|
gateway.SPToJids(toJids),
|
||||||
|
|
|
||||||
181
telegram/muc.go
Normal file
181
telegram/muc.go
Normal file
|
|
@ -0,0 +1,181 @@
|
||||||
|
package telegram
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/zelenin/go-tdlib/client"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
const MUCOccupantsLimit int32 = 200
|
||||||
|
|
||||||
|
// MUCState holds MUC metadata
|
||||||
|
type MUCState struct {
|
||||||
|
Resources map[string]bool
|
||||||
|
Occupants *MUCOccupantsLRU
|
||||||
|
}
|
||||||
|
|
||||||
|
// MUCOccupant represents a MUC occupant
|
||||||
|
type MUCOccupant struct {
|
||||||
|
Nickname string
|
||||||
|
Affiliation string
|
||||||
|
Role string
|
||||||
|
Status client.ChatMemberStatus
|
||||||
|
prev *MUCOccupant
|
||||||
|
next *MUCOccupant
|
||||||
|
key int64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *MUCOccupant) cutOut() (prev, next *MUCOccupant) {
|
||||||
|
prev = o.prev
|
||||||
|
next = o.next
|
||||||
|
|
||||||
|
// -- * --- * -X- * -X- * --- * --
|
||||||
|
o.prev = nil
|
||||||
|
o.next = nil
|
||||||
|
if prev != nil {
|
||||||
|
prev.next = next
|
||||||
|
}
|
||||||
|
if next != nil {
|
||||||
|
next.prev = prev
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMUCState() *MUCState {
|
||||||
|
return &MUCState{
|
||||||
|
Resources: make(map[string]bool),
|
||||||
|
Occupants: NewMUCOccupantsLRU(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type MUCOccupantsLRU struct {
|
||||||
|
m map[int64]*MUCOccupant
|
||||||
|
oldest *MUCOccupant
|
||||||
|
newest *MUCOccupant
|
||||||
|
lock sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMUCOccupantsLRU() *MUCOccupantsLRU {
|
||||||
|
return &MUCOccupantsLRU{
|
||||||
|
m: make(map[int64]*MUCOccupant),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lru *MUCOccupantsLRU) Get(key int64) (*MUCOccupant, bool) {
|
||||||
|
lru.lock.Lock()
|
||||||
|
defer lru.lock.Unlock()
|
||||||
|
|
||||||
|
occupant, ok := lru.m[key]
|
||||||
|
return occupant, ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lru *MUCOccupantsLRU) cutOut(oldOccupant *MUCOccupant) (prev, next *MUCOccupant) {
|
||||||
|
prev, next = oldOccupant.cutOut()
|
||||||
|
if lru.oldest == oldOccupant {
|
||||||
|
lru.oldest = next
|
||||||
|
}
|
||||||
|
if lru.newest == oldOccupant {
|
||||||
|
lru.newest = prev
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lru *MUCOccupantsLRU) insertNewest(occupant *MUCOccupant) {
|
||||||
|
lru.newest.next = occupant
|
||||||
|
occupant.prev = lru.newest
|
||||||
|
occupant.next = nil
|
||||||
|
lru.newest = occupant
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lru *MUCOccupantsLRU) Set(key int64, occupant *MUCOccupant) {
|
||||||
|
lru.lock.Lock()
|
||||||
|
defer lru.lock.Unlock()
|
||||||
|
|
||||||
|
occupant.key = key
|
||||||
|
|
||||||
|
oldOccupant, oldOk := lru.m[key]
|
||||||
|
lru.m[key] = occupant
|
||||||
|
|
||||||
|
if oldOk {
|
||||||
|
lru.cutOut(oldOccupant)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lru.oldest == nil) != (lru.newest == nil) {
|
||||||
|
log.Fatal("MRD MUDAQ")
|
||||||
|
}
|
||||||
|
|
||||||
|
if lru.oldest == nil && lru.newest == nil {
|
||||||
|
lru.oldest = occupant
|
||||||
|
lru.newest = occupant
|
||||||
|
occupant.prev = nil
|
||||||
|
occupant.next = nil
|
||||||
|
} else {
|
||||||
|
lru.insertNewest(occupant)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(lru.m) > int(MUCOccupantsLimit) && lru.oldest != nil {
|
||||||
|
delete(lru.m, lru.oldest.key)
|
||||||
|
lru.cutOut(lru.oldest)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lru *MUCOccupantsLRU) Delete(key int64) {
|
||||||
|
lru.lock.Lock()
|
||||||
|
defer lru.lock.Unlock()
|
||||||
|
|
||||||
|
oldOccupant, oldOk := lru.m[key]
|
||||||
|
delete(lru.m, key)
|
||||||
|
|
||||||
|
if oldOk {
|
||||||
|
lru.cutOut(oldOccupant)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lru *MUCOccupantsLRU) Bump(occupant *MUCOccupant) {
|
||||||
|
lru.lock.Lock()
|
||||||
|
defer lru.lock.Unlock()
|
||||||
|
|
||||||
|
if lru.newest == occupant {
|
||||||
|
// already at the top, nothing to do
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
lru.cutOut(occupant)
|
||||||
|
lru.insertNewest(occupant)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lru *MUCOccupantsLRU) Range() chan *MUCOccupant {
|
||||||
|
lru.lock.Lock()
|
||||||
|
|
||||||
|
occupantChan := make(chan *MUCOccupant, 1)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
defer func() {
|
||||||
|
lru.lock.Unlock()
|
||||||
|
close(occupantChan)
|
||||||
|
}()
|
||||||
|
|
||||||
|
for _, occupant := range lru.m {
|
||||||
|
occupantChan <- occupant
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
return occupantChan
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lru *MUCOccupantsLRU) Clear() {
|
||||||
|
lru.lock.Lock()
|
||||||
|
defer lru.lock.Unlock()
|
||||||
|
|
||||||
|
for _, occupant := range lru.m {
|
||||||
|
occupant.prev = nil
|
||||||
|
occupant.next = nil
|
||||||
|
}
|
||||||
|
lru.m = make(map[int64]*MUCOccupant)
|
||||||
|
|
||||||
|
lru.oldest = nil
|
||||||
|
lru.newest = nil
|
||||||
|
}
|
||||||
419
telegram/muc_test.go
Normal file
419
telegram/muc_test.go
Normal file
|
|
@ -0,0 +1,419 @@
|
||||||
|
package telegram
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
// -x->[]-x-> +(.)
|
||||||
|
func TestSetMUCOccupantsLRUSetInitiallyEmpty(t *testing.T) {
|
||||||
|
// init
|
||||||
|
occupants := NewMUCOccupantsLRU()
|
||||||
|
|
||||||
|
// addition
|
||||||
|
newOccupant := &MUCOccupant{}
|
||||||
|
occupants.Set(1, newOccupant)
|
||||||
|
|
||||||
|
// checks
|
||||||
|
if occupants.oldest != newOccupant || newOccupant.prev != nil || newOccupant.next != nil || occupants.newest != newOccupant {
|
||||||
|
t.Error("Broken")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testMUCOccupantsLRUChainOfOne() (occupants *MUCOccupantsLRU, occupant1 *MUCOccupant) {
|
||||||
|
occupants = NewMUCOccupantsLRU()
|
||||||
|
occupant1 = &MUCOccupant{}
|
||||||
|
occupants.m[1] = occupant1
|
||||||
|
occupants.oldest = occupant1
|
||||||
|
occupants.newest = occupant1
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func testMUCOccupantsLRUChainOfThree() (occupants *MUCOccupantsLRU, occupant1, occupant2, occupant3 *MUCOccupant) {
|
||||||
|
occupants = NewMUCOccupantsLRU()
|
||||||
|
occupant1 = &MUCOccupant{}
|
||||||
|
occupant2 = &MUCOccupant{}
|
||||||
|
occupant3 = &MUCOccupant{}
|
||||||
|
occupants.m[1] = occupant1
|
||||||
|
occupants.m[2] = occupant2
|
||||||
|
occupants.m[3] = occupant3
|
||||||
|
occupants.oldest = occupant1
|
||||||
|
occupants.newest = occupant3
|
||||||
|
occupant1.next = occupant2
|
||||||
|
occupant2.prev = occupant1
|
||||||
|
occupant2.next = occupant3
|
||||||
|
occupant3.prev = occupant2
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// ->[]->()-> +(.)
|
||||||
|
func TestSetMUCOccupantsLRUSetOneOther(t *testing.T) {
|
||||||
|
// init
|
||||||
|
occupants, occupant1 := testMUCOccupantsLRUChainOfOne()
|
||||||
|
|
||||||
|
// addition
|
||||||
|
newOccupant := &MUCOccupant{}
|
||||||
|
occupants.Set(2, newOccupant)
|
||||||
|
|
||||||
|
// checks
|
||||||
|
if occupants.oldest != occupant1 || occupant1.prev != nil || occupant1.next != newOccupant || newOccupant.prev != occupant1 || newOccupant.next != nil || occupants.newest != newOccupant {
|
||||||
|
t.Error("Broken")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ->[]->()->()->()-> +(.)
|
||||||
|
func TestSetMUCOccupantsLRUSetThreeOthers(t *testing.T) {
|
||||||
|
// init
|
||||||
|
occupants, occupant1, occupant2, occupant3 := testMUCOccupantsLRUChainOfThree()
|
||||||
|
|
||||||
|
// addition
|
||||||
|
newOccupant := &MUCOccupant{}
|
||||||
|
occupants.Set(4, newOccupant)
|
||||||
|
|
||||||
|
// checks
|
||||||
|
if occupants.oldest != occupant1 ||
|
||||||
|
occupant1.prev != nil ||
|
||||||
|
occupant1.next != occupant2 ||
|
||||||
|
occupant2.prev != occupant1 ||
|
||||||
|
occupant2.next != occupant3 ||
|
||||||
|
occupant3.prev != occupant2 ||
|
||||||
|
occupant3.next != newOccupant ||
|
||||||
|
newOccupant.prev != occupant3 ||
|
||||||
|
newOccupant.next != nil ||
|
||||||
|
occupants.newest != newOccupant {
|
||||||
|
t.Error("Broken")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ->[]->(.)->()->()-> +(.)
|
||||||
|
func TestSetMUCOccupantsLRUSetReplaceFirst(t *testing.T) {
|
||||||
|
// init
|
||||||
|
occupants, occupant1, occupant2, occupant3 := testMUCOccupantsLRUChainOfThree()
|
||||||
|
|
||||||
|
// addition
|
||||||
|
newOccupant := &MUCOccupant{}
|
||||||
|
occupants.Set(1, newOccupant)
|
||||||
|
|
||||||
|
// checks
|
||||||
|
if occupants.oldest != occupant2 ||
|
||||||
|
occupant2.prev != nil ||
|
||||||
|
occupant2.next != occupant3 ||
|
||||||
|
occupant3.prev != occupant2 ||
|
||||||
|
occupant3.next != newOccupant ||
|
||||||
|
newOccupant.prev != occupant3 ||
|
||||||
|
newOccupant.next != nil ||
|
||||||
|
occupants.newest != newOccupant ||
|
||||||
|
occupant1.prev != nil ||
|
||||||
|
occupant1.next != nil {
|
||||||
|
t.Error("Broken")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ->[]->()->(.)->()-> +(.)
|
||||||
|
func TestSetMUCOccupantsLRUSetReplaceMiddle(t *testing.T) {
|
||||||
|
// init
|
||||||
|
occupants, occupant1, occupant2, occupant3 := testMUCOccupantsLRUChainOfThree()
|
||||||
|
|
||||||
|
// addition
|
||||||
|
newOccupant := &MUCOccupant{}
|
||||||
|
occupants.Set(2, newOccupant)
|
||||||
|
|
||||||
|
// checks
|
||||||
|
if occupants.oldest != occupant1 ||
|
||||||
|
occupant1.prev != nil ||
|
||||||
|
occupant1.next != occupant3 ||
|
||||||
|
occupant3.prev != occupant1 ||
|
||||||
|
occupant3.next != newOccupant ||
|
||||||
|
newOccupant.prev != occupant3 ||
|
||||||
|
newOccupant.next != nil ||
|
||||||
|
occupants.newest != newOccupant ||
|
||||||
|
occupant2.prev != nil ||
|
||||||
|
occupant2.next != nil {
|
||||||
|
t.Error("Broken")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ->[]->()->()->(.)-> +(.)
|
||||||
|
func TestSetMUCOccupantsLRUSetReplaceLast(t *testing.T) {
|
||||||
|
// init
|
||||||
|
occupants, occupant1, occupant2, occupant3 := testMUCOccupantsLRUChainOfThree()
|
||||||
|
|
||||||
|
// addition
|
||||||
|
newOccupant := &MUCOccupant{}
|
||||||
|
occupants.Set(3, newOccupant)
|
||||||
|
|
||||||
|
// checks
|
||||||
|
if occupants.oldest != occupant1 ||
|
||||||
|
occupant1.prev != nil ||
|
||||||
|
occupant1.next != occupant2 ||
|
||||||
|
occupant2.prev != occupant1 ||
|
||||||
|
occupant2.next != newOccupant ||
|
||||||
|
newOccupant.prev != occupant2 ||
|
||||||
|
newOccupant.next != nil ||
|
||||||
|
occupants.newest != newOccupant ||
|
||||||
|
occupant3.prev != nil ||
|
||||||
|
occupant3.next != nil {
|
||||||
|
t.Error("Broken")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ->[]->(.)-> +(.)
|
||||||
|
func TestSetMUCOccupantsLRUSetReplaceOnly(t *testing.T) {
|
||||||
|
// init
|
||||||
|
occupants, occupant1 := testMUCOccupantsLRUChainOfOne()
|
||||||
|
|
||||||
|
// addition
|
||||||
|
newOccupant := &MUCOccupant{}
|
||||||
|
occupants.Set(1, newOccupant)
|
||||||
|
|
||||||
|
// checks
|
||||||
|
if occupants.oldest != newOccupant ||
|
||||||
|
occupants.newest != newOccupant ||
|
||||||
|
newOccupant.prev != nil ||
|
||||||
|
newOccupant.next != nil ||
|
||||||
|
occupant1.prev != nil ||
|
||||||
|
occupant1.next != nil {
|
||||||
|
t.Error("Broken")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ->[]->(.)->()->()-> +s(.)
|
||||||
|
func TestSetMUCOccupantsLRUSetReplaceFirstWithSame(t *testing.T) {
|
||||||
|
// init
|
||||||
|
occupants, occupant1, occupant2, occupant3 := testMUCOccupantsLRUChainOfThree()
|
||||||
|
|
||||||
|
// addition
|
||||||
|
occupants.Set(1, occupant1)
|
||||||
|
|
||||||
|
// checks
|
||||||
|
if occupants.oldest != occupant2 ||
|
||||||
|
occupant2.prev != nil ||
|
||||||
|
occupant2.next != occupant3 ||
|
||||||
|
occupant3.prev != occupant2 ||
|
||||||
|
occupant3.next != occupant1 ||
|
||||||
|
occupant1.prev != occupant3 ||
|
||||||
|
occupant1.next != nil ||
|
||||||
|
occupants.newest != occupant1 {
|
||||||
|
t.Error("Broken")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ->[]->()->(.)->()-> +s(.)
|
||||||
|
func TestSetMUCOccupantsLRUSetReplaceMiddleWithSame(t *testing.T) {
|
||||||
|
// init
|
||||||
|
occupants, occupant1, occupant2, occupant3 := testMUCOccupantsLRUChainOfThree()
|
||||||
|
|
||||||
|
// addition
|
||||||
|
occupants.Set(2, occupant2)
|
||||||
|
|
||||||
|
// checks
|
||||||
|
if occupants.oldest != occupant1 ||
|
||||||
|
occupant1.prev != nil ||
|
||||||
|
occupant1.next != occupant3 ||
|
||||||
|
occupant3.prev != occupant1 ||
|
||||||
|
occupant3.next != occupant2 ||
|
||||||
|
occupant2.prev != occupant3 ||
|
||||||
|
occupant2.next != nil ||
|
||||||
|
occupants.newest != occupant2 {
|
||||||
|
t.Error("Broken")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ->[]->()->()->(.)-> +s(.)
|
||||||
|
func TestSetMUCOccupantsLRUSetReplaceLastWithSame(t *testing.T) {
|
||||||
|
// init
|
||||||
|
occupants, occupant1, occupant2, occupant3 := testMUCOccupantsLRUChainOfThree()
|
||||||
|
|
||||||
|
// addition
|
||||||
|
occupants.Set(3, occupant3)
|
||||||
|
|
||||||
|
// checks
|
||||||
|
if occupants.oldest != occupant1 ||
|
||||||
|
occupant1.prev != nil ||
|
||||||
|
occupant1.next != occupant2 ||
|
||||||
|
occupant2.prev != occupant1 ||
|
||||||
|
occupant2.next != occupant3 ||
|
||||||
|
occupant3.prev != occupant2 ||
|
||||||
|
occupant3.next != nil ||
|
||||||
|
occupants.newest != occupant3 {
|
||||||
|
t.Error("Broken")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ->[]->(.)-> +(.)
|
||||||
|
func TestSetMUCOccupantsLRUSetReplaceOnlyWithSame(t *testing.T) {
|
||||||
|
// init
|
||||||
|
occupants, occupant1 := testMUCOccupantsLRUChainOfOne()
|
||||||
|
|
||||||
|
// addition
|
||||||
|
occupants.Set(1, occupant1)
|
||||||
|
|
||||||
|
// checks
|
||||||
|
if occupants.oldest != occupant1 ||
|
||||||
|
occupants.newest != occupant1 ||
|
||||||
|
occupant1.prev != nil ||
|
||||||
|
occupant1.next != nil {
|
||||||
|
t.Error("Broken")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ->[]->(X)->
|
||||||
|
func TestSetMUCOccupantsLRUDeleteOnly(t *testing.T) {
|
||||||
|
// init
|
||||||
|
occupants, occupant1 := testMUCOccupantsLRUChainOfOne()
|
||||||
|
|
||||||
|
// deletion
|
||||||
|
occupants.Delete(1)
|
||||||
|
|
||||||
|
// checks
|
||||||
|
if occupants.oldest != nil ||
|
||||||
|
occupants.newest != nil ||
|
||||||
|
occupant1.prev != nil ||
|
||||||
|
occupant1.next != nil {
|
||||||
|
t.Error("Broken")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ->[]->(X)->()->()->
|
||||||
|
func TestSetMUCOccupantsLRUDeleteFirst(t *testing.T) {
|
||||||
|
// init
|
||||||
|
occupants, occupant1, occupant2, occupant3 := testMUCOccupantsLRUChainOfThree()
|
||||||
|
|
||||||
|
// deletion
|
||||||
|
occupants.Delete(1)
|
||||||
|
|
||||||
|
// checks
|
||||||
|
if occupants.oldest != occupant2 ||
|
||||||
|
occupant2.prev != nil ||
|
||||||
|
occupant2.next != occupant3 ||
|
||||||
|
occupant3.prev != occupant2 ||
|
||||||
|
occupant3.next != nil ||
|
||||||
|
occupants.newest != occupant3 ||
|
||||||
|
occupant1.prev != nil ||
|
||||||
|
occupant1.next != nil {
|
||||||
|
t.Error("Broken")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ->[]->()->(X)->()->
|
||||||
|
func TestSetMUCOccupantsLRUDeleteMiddle(t *testing.T) {
|
||||||
|
// init
|
||||||
|
occupants, occupant1, occupant2, occupant3 := testMUCOccupantsLRUChainOfThree()
|
||||||
|
|
||||||
|
// deletion
|
||||||
|
occupants.Delete(2)
|
||||||
|
|
||||||
|
// checks
|
||||||
|
if occupants.oldest != occupant1 ||
|
||||||
|
occupant1.prev != nil ||
|
||||||
|
occupant1.next != occupant3 ||
|
||||||
|
occupant3.prev != occupant1 ||
|
||||||
|
occupant3.next != nil ||
|
||||||
|
occupants.newest != occupant3 ||
|
||||||
|
occupant2.prev != nil ||
|
||||||
|
occupant2.next != nil {
|
||||||
|
t.Error("Broken")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ->[]->()->()->(X)->
|
||||||
|
func TestSetMUCOccupantsLRUDeleteLast(t *testing.T) {
|
||||||
|
// init
|
||||||
|
occupants, occupant1, occupant2, occupant3 := testMUCOccupantsLRUChainOfThree()
|
||||||
|
|
||||||
|
// deletion
|
||||||
|
occupants.Delete(3)
|
||||||
|
|
||||||
|
// checks
|
||||||
|
if occupants.oldest != occupant1 ||
|
||||||
|
occupant1.prev != nil ||
|
||||||
|
occupant1.next != occupant2 ||
|
||||||
|
occupant2.prev != occupant1 ||
|
||||||
|
occupant2.next != nil ||
|
||||||
|
occupants.newest != occupant2 ||
|
||||||
|
occupant3.prev != nil ||
|
||||||
|
occupant3.next != nil {
|
||||||
|
t.Error("Broken")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ->[]->(.)->
|
||||||
|
func TestSetMUCOccupantsLRUBumpOnly(t *testing.T) {
|
||||||
|
// init
|
||||||
|
occupants, occupant1 := testMUCOccupantsLRUChainOfOne()
|
||||||
|
|
||||||
|
// bump
|
||||||
|
occupants.Bump(occupant1)
|
||||||
|
|
||||||
|
// checks
|
||||||
|
if occupants.oldest != occupant1 ||
|
||||||
|
occupant1.prev != nil ||
|
||||||
|
occupant1.next != nil ||
|
||||||
|
occupants.newest != occupant1 {
|
||||||
|
t.Error("Broken")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ->[]->(.)->()->()->
|
||||||
|
func TestSetMUCOccupantsLRUBumpFirst(t *testing.T) {
|
||||||
|
// init
|
||||||
|
occupants, occupant1, occupant2, occupant3 := testMUCOccupantsLRUChainOfThree()
|
||||||
|
|
||||||
|
// bump
|
||||||
|
occupants.Bump(occupant1)
|
||||||
|
|
||||||
|
// checks
|
||||||
|
if occupants.oldest != occupant2 ||
|
||||||
|
occupant2.prev != nil ||
|
||||||
|
occupant2.next != occupant3 ||
|
||||||
|
occupant3.prev != occupant2 ||
|
||||||
|
occupant3.next != occupant1 ||
|
||||||
|
occupant1.prev != occupant3 ||
|
||||||
|
occupant1.next != nil ||
|
||||||
|
occupants.newest != occupant1 {
|
||||||
|
t.Error("Broken")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ->[]->()->(.)->()->
|
||||||
|
func TestSetMUCOccupantsLRUBumpMiddle(t *testing.T) {
|
||||||
|
// init
|
||||||
|
occupants, occupant1, occupant2, occupant3 := testMUCOccupantsLRUChainOfThree()
|
||||||
|
|
||||||
|
// bump
|
||||||
|
occupants.Bump(occupant2)
|
||||||
|
|
||||||
|
// checks
|
||||||
|
if occupants.oldest != occupant1 ||
|
||||||
|
occupant1.prev != nil ||
|
||||||
|
occupant1.next != occupant3 ||
|
||||||
|
occupant3.prev != occupant1 ||
|
||||||
|
occupant3.next != occupant2 ||
|
||||||
|
occupant2.prev != occupant3 ||
|
||||||
|
occupant2.next != nil ||
|
||||||
|
occupants.newest != occupant2 {
|
||||||
|
t.Error("Broken")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ->[]->()->()->(.)->
|
||||||
|
func TestSetMUCOccupantsLRUBumpLast(t *testing.T) {
|
||||||
|
// init
|
||||||
|
occupants, occupant1, occupant2, occupant3 := testMUCOccupantsLRUChainOfThree()
|
||||||
|
|
||||||
|
// bump
|
||||||
|
occupants.Bump(occupant3)
|
||||||
|
|
||||||
|
// checks
|
||||||
|
if occupants.oldest != occupant1 ||
|
||||||
|
occupant1.prev != nil ||
|
||||||
|
occupant1.next != occupant2 ||
|
||||||
|
occupant2.prev != occupant1 ||
|
||||||
|
occupant2.next != occupant3 ||
|
||||||
|
occupant3.prev != occupant2 ||
|
||||||
|
occupant3.next != nil ||
|
||||||
|
occupants.newest != occupant3 {
|
||||||
|
t.Error("Broken")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -565,7 +565,7 @@ func (c *Client) ProcessStatusUpdate(chatID int64, status string, show string, o
|
||||||
c.locks.mucCacheLock.Lock()
|
c.locks.mucCacheLock.Lock()
|
||||||
chatJid := gateway.CHATJID(chatID, true)
|
chatJid := gateway.CHATJID(chatID, true)
|
||||||
for mucId, state := range c.mucCache {
|
for mucId, state := range c.mucCache {
|
||||||
occupant, ok := state.Occupants[chatID]
|
occupant, ok := state.Occupants.Get(chatID)
|
||||||
if ok {
|
if ok {
|
||||||
_, toJids := c.getMUCJoinedJIDs(mucId, state, false)
|
_, toJids := c.getMUCJoinedJIDs(mucId, state, false)
|
||||||
newMucArgs := append(
|
newMucArgs := append(
|
||||||
|
|
@ -682,7 +682,7 @@ func (c *Client) sendMUCStatuses(chatID int64) {
|
||||||
|
|
||||||
members, err := c.client.SearchChatMembers(&client.SearchChatMembersRequest{
|
members, err := c.client.SearchChatMembers(&client.SearchChatMembersRequest{
|
||||||
ChatId: chatID,
|
ChatId: chatID,
|
||||||
Limit: 200,
|
Limit: MUCOccupantsLimit,
|
||||||
Filter: &client.ChatMembersFilterMembers{},
|
Filter: &client.ChatMembersFilterMembers{},
|
||||||
})
|
})
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
|
@ -707,12 +707,12 @@ func (c *Client) updateMUCOccupants(mucState *MUCState, chatID int64, members []
|
||||||
|
|
||||||
for _, member := range members {
|
for _, member := range members {
|
||||||
senderId, nickname, affiliation, role := c.TgMemberToMUCOccupant(member, chat)
|
senderId, nickname, affiliation, role := c.TgMemberToMUCOccupant(member, chat)
|
||||||
mucState.Occupants[senderId] = &MUCOccupant{
|
mucState.Occupants.Set(senderId, &MUCOccupant{
|
||||||
Nickname: nickname,
|
Nickname: nickname,
|
||||||
Affiliation: affiliation,
|
Affiliation: affiliation,
|
||||||
Role: role,
|
Role: role,
|
||||||
Status: member.Status,
|
Status: member.Status,
|
||||||
}
|
})
|
||||||
|
|
||||||
if c.me != nil && senderId == c.me.Id {
|
if c.me != nil && senderId == c.me.Id {
|
||||||
myNickname = nickname
|
myNickname = nickname
|
||||||
|
|
@ -753,7 +753,7 @@ func (c *Client) mucCacheHasOccupant(mucID int64, memberID int64) bool {
|
||||||
return false // no MUC to be added to
|
return false // no MUC to be added to
|
||||||
}
|
}
|
||||||
|
|
||||||
_, ok = mucState.Occupants[memberID]
|
_, ok = mucState.Occupants.Get(memberID)
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -780,12 +780,12 @@ func (c *Client) addMUCOccupant(mucID int64, memberID int64, affiliation, role s
|
||||||
)
|
)
|
||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
mucState.Occupants[memberID] = &MUCOccupant{
|
mucState.Occupants.Set(memberID, &MUCOccupant{
|
||||||
Nickname: nickname,
|
Nickname: nickname,
|
||||||
Affiliation: affiliation,
|
Affiliation: affiliation,
|
||||||
Role: role,
|
Role: role,
|
||||||
Status: status,
|
Status: status,
|
||||||
}
|
})
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -830,14 +830,14 @@ func (c *Client) updateMUCsNickname(memberID int64, newNickname string) {
|
||||||
|
|
||||||
realJid := gateway.CHATJID(memberID, true)
|
realJid := gateway.CHATJID(memberID, true)
|
||||||
for mucId, state := range c.mucCache {
|
for mucId, state := range c.mucCache {
|
||||||
oldOccupant, ok := state.Occupants[memberID]
|
oldOccupant, ok := state.Occupants.Get(memberID)
|
||||||
if ok {
|
if ok {
|
||||||
state.Occupants[memberID] = &MUCOccupant{
|
state.Occupants.Set(memberID, &MUCOccupant{
|
||||||
Nickname: newNickname,
|
Nickname: newNickname,
|
||||||
Affiliation: oldOccupant.Affiliation,
|
Affiliation: oldOccupant.Affiliation,
|
||||||
Role: oldOccupant.Role,
|
Role: oldOccupant.Role,
|
||||||
Status: oldOccupant.Status,
|
Status: oldOccupant.Status,
|
||||||
}
|
})
|
||||||
|
|
||||||
sMucId := gateway.MUCNODE(mucId)
|
sMucId := gateway.MUCNODE(mucId)
|
||||||
unavailableStatusCodes := []uint16{303, 210}
|
unavailableStatusCodes := []uint16{303, 210}
|
||||||
|
|
@ -921,7 +921,7 @@ func (c *Client) GetMyMUCNickname(chatID int64) (string, bool) {
|
||||||
if !ok || mucState == nil {
|
if !ok || mucState == nil {
|
||||||
return "", false
|
return "", false
|
||||||
}
|
}
|
||||||
occupant, ok := mucState.Occupants[c.me.Id]
|
occupant, ok := mucState.Occupants.Get(c.me.Id)
|
||||||
if !ok {
|
if !ok {
|
||||||
return "", false
|
return "", false
|
||||||
}
|
}
|
||||||
|
|
@ -938,9 +938,9 @@ func (c *Client) GetMUCMemberIdByNickname(chatID int64, nickname string) int64 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
for memberId, occupant := range mucState.Occupants {
|
for occupant := range mucState.Occupants.Range() {
|
||||||
if occupant.Nickname == nickname {
|
if occupant.Nickname == nickname {
|
||||||
return memberId
|
return occupant.key
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3068,9 +3068,9 @@ func (c *Client) mucOccupantRolePresence(chatID, userID int64, status ChatMember
|
||||||
mucState, ok := c.mucCache[chatID]
|
mucState, ok := c.mucCache[chatID]
|
||||||
if ok && mucState != nil {
|
if ok && mucState != nil {
|
||||||
if status == ChatMemberStatusKicked || status == ChatMemberStatusBanned {
|
if status == ChatMemberStatusKicked || status == ChatMemberStatusBanned {
|
||||||
delete(mucState.Occupants, userID)
|
mucState.Occupants.Delete(userID)
|
||||||
} else {
|
} else {
|
||||||
occupant, ok := mucState.Occupants[userID]
|
occupant, ok := mucState.Occupants.Get(userID)
|
||||||
if ok {
|
if ok {
|
||||||
occupant.Affiliation = newAffiliation
|
occupant.Affiliation = newAffiliation
|
||||||
occupant.Role = newRole
|
occupant.Role = newRole
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue