mautrix-whatsapp/vendor/maunium.net/go/mautrix-appservice/statestore.go
2018-08-27 00:48:32 +03:00

178 lines
5.1 KiB
Go

package appservice
import (
"maunium.net/go/gomatrix"
"strings"
"sync"
"time"
)
type StateStore interface {
IsRegistered(userID string) bool
MarkRegistered(userID string)
IsTyping(roomID, userID string) bool
SetTyping(roomID, userID string, timeout int64)
IsInRoom(roomID, userID string) bool
SetMembership(roomID, userID, membership string)
SetPowerLevels(roomID string, levels *gomatrix.PowerLevels)
GetPowerLevels(roomID string) *gomatrix.PowerLevels
GetPowerLevel(roomID, userID string) int
GetPowerLevelRequirement(roomID string, eventType gomatrix.EventType, isState bool) int
HasPowerLevel(roomID, userID string, eventType gomatrix.EventType, isState bool) bool
}
func (as *AppService) UpdateState(evt *gomatrix.Event) {
switch evt.Type {
case gomatrix.StateMember:
as.StateStore.SetMembership(evt.RoomID, evt.GetStateKey(), evt.Content.Membership)
}
}
type BasicStateStore struct {
registrationsLock sync.RWMutex `json:"-"`
Registrations map[string]bool `json:"registrations"`
membershipsLock sync.RWMutex `json:"-"`
Memberships map[string]map[string]string `json:"memberships"`
powerLevelsLock sync.RWMutex `json:"-"`
PowerLevels map[string]*gomatrix.PowerLevels `json:"power_levels"`
Typing map[string]map[string]int64 `json:"-"`
typingLock sync.RWMutex `json:"-"`
}
func NewBasicStateStore() StateStore {
return &BasicStateStore{
Registrations: make(map[string]bool),
Memberships: make(map[string]map[string]string),
PowerLevels: make(map[string]*gomatrix.PowerLevels),
Typing: make(map[string]map[string]int64),
}
}
func (store *BasicStateStore) IsRegistered(userID string) bool {
store.registrationsLock.RLock()
defer store.registrationsLock.RUnlock()
registered, ok := store.Registrations[userID]
return ok && registered
}
func (store *BasicStateStore) MarkRegistered(userID string) {
store.registrationsLock.Lock()
defer store.registrationsLock.Unlock()
store.Registrations[userID] = true
}
func (store *BasicStateStore) IsTyping(roomID, userID string) bool {
store.typingLock.RLock()
defer store.typingLock.RUnlock()
roomTyping, ok := store.Typing[roomID]
if !ok {
return false
}
typingEndsAt, _ := roomTyping[userID]
return typingEndsAt >= time.Now().Unix()
}
func (store *BasicStateStore) SetTyping(roomID, userID string, timeout int64) {
store.typingLock.Lock()
defer store.typingLock.Unlock()
roomTyping, ok := store.Typing[roomID]
if !ok {
if timeout >= 0 {
roomTyping = map[string]int64{
userID: time.Now().Unix() + timeout,
}
} else {
roomTyping = make(map[string]int64)
}
} else {
if timeout >= 0 {
roomTyping[userID] = time.Now().Unix() + timeout
} else {
delete(roomTyping, userID)
}
}
store.Typing[roomID] = roomTyping
}
func (store *BasicStateStore) GetRoomMemberships(roomID string) map[string]string {
store.membershipsLock.RLock()
memberships, ok := store.Memberships[roomID]
store.membershipsLock.RUnlock()
if !ok {
memberships = make(map[string]string)
store.membershipsLock.Lock()
store.Memberships[roomID] = memberships
store.membershipsLock.Unlock()
}
return memberships
}
func (store *BasicStateStore) GetMembership(roomID, userID string) string {
store.membershipsLock.RLock()
defer store.membershipsLock.RUnlock()
memberships, ok := store.Memberships[roomID]
if !ok {
return "leave"
}
membership, ok := memberships[userID]
if !ok {
return "leave"
}
return membership
}
func (store *BasicStateStore) IsInRoom(roomID, userID string) bool {
return store.GetMembership(roomID, userID) == "join"
}
func (store *BasicStateStore) SetMembership(roomID, userID, membership string) {
store.membershipsLock.Lock()
memberships, ok := store.Memberships[roomID]
if !ok {
memberships = map[string]string{
userID: strings.ToLower(membership),
}
} else {
memberships[userID] = strings.ToLower(membership)
}
store.Memberships[roomID] = memberships
store.membershipsLock.Unlock()
}
func (store *BasicStateStore) SetPowerLevels(roomID string, levels *gomatrix.PowerLevels) {
store.powerLevelsLock.Lock()
store.PowerLevels[roomID] = levels
store.powerLevelsLock.Unlock()
}
func (store *BasicStateStore) GetPowerLevels(roomID string) (levels *gomatrix.PowerLevels) {
store.powerLevelsLock.RLock()
levels, _ = store.PowerLevels[roomID]
store.powerLevelsLock.RUnlock()
return
}
func (store *BasicStateStore) GetPowerLevel(roomID, userID string) int {
return store.GetPowerLevels(roomID).GetUserLevel(userID)
}
func (store *BasicStateStore) GetPowerLevelRequirement(roomID string, eventType gomatrix.EventType, isState bool) int {
levels := store.GetPowerLevels(roomID)
switch eventType {
case "kick":
return levels.Kick()
case "invite":
return levels.Invite()
case "redact":
return levels.Redact()
}
return levels.GetEventLevel(eventType, isState)
}
func (store *BasicStateStore) HasPowerLevel(roomID, userID string, eventType gomatrix.EventType, isState bool) bool {
return store.GetPowerLevel(roomID, userID) >= store.GetPowerLevelRequirement(roomID, eventType, isState)
}