mirror of
https://dev.narayana.im/narayana/telegabber.git
synced 2026-08-05 04:07:07 +00:00
189 lines
3.5 KiB
Go
189 lines
3.5 KiB
Go
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
|
|
id 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(id int64) (*MUCOccupant, bool) {
|
|
lru.lock.Lock()
|
|
defer lru.lock.Unlock()
|
|
|
|
occupant, ok := lru.m[id]
|
|
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
|
|
}
|
|
|
|
// Set adds or replaces an occupant and possibly returns an occupant removed instead because of overflow
|
|
func (lru *MUCOccupantsLRU) Set(id int64, occupant *MUCOccupant) (deleted *MUCOccupant) {
|
|
lru.lock.Lock()
|
|
defer lru.lock.Unlock()
|
|
|
|
occupant.id = id
|
|
|
|
oldOccupant, oldOk := lru.m[id]
|
|
lru.m[id] = 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 {
|
|
deleted = lru.oldest
|
|
delete(lru.m, lru.oldest.id)
|
|
lru.cutOut(lru.oldest)
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
// Delete occupant by member ID
|
|
func (lru *MUCOccupantsLRU) Delete(id int64) {
|
|
lru.lock.Lock()
|
|
defer lru.lock.Unlock()
|
|
|
|
oldOccupant, oldOk := lru.m[id]
|
|
delete(lru.m, id)
|
|
|
|
if oldOk {
|
|
lru.cutOut(oldOccupant)
|
|
}
|
|
}
|
|
|
|
// Bump raises the occupant in LRU
|
|
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)
|
|
}
|
|
|
|
// Range loops over all occupants
|
|
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
|
|
}
|
|
|
|
// Clear properly removes all occupants and their possible mutual references (not necessary in Golang, yet still)
|
|
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
|
|
}
|