|
@@ -4,12 +4,16 @@ 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)
|
|
|
|
|
@@ -28,33 +32,70 @@ func (as *AppService) UpdateState(evt *gomatrix.Event) {
|
|
|
}
|
|
|
|
|
|
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:"-"`
|
|
|
+ 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() *BasicStateStore {
|
|
|
+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]
|
|
|
- store.registrationsLock.RUnlock()
|
|
|
return ok && registered
|
|
|
}
|
|
|
|
|
|
func (store *BasicStateStore) MarkRegistered(userID string) {
|
|
|
store.registrationsLock.Lock()
|
|
|
+ defer store.registrationsLock.Unlock()
|
|
|
store.Registrations[userID] = true
|
|
|
- store.registrationsLock.Unlock()
|
|
|
+}
|
|
|
+
|
|
|
+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 {
|
|
@@ -88,12 +129,13 @@ func (store *BasicStateStore) SetMembership(roomID, userID, membership string) {
|
|
|
store.membershipsLock.Lock()
|
|
|
memberships, ok := store.Memberships[roomID]
|
|
|
if !ok {
|
|
|
- store.Memberships[roomID] = map[string]string{
|
|
|
+ memberships = map[string]string{
|
|
|
userID: strings.ToLower(membership),
|
|
|
}
|
|
|
} else {
|
|
|
memberships[userID] = strings.ToLower(membership)
|
|
|
}
|
|
|
+ store.Memberships[roomID] = memberships
|
|
|
store.membershipsLock.Unlock()
|
|
|
}
|
|
|
|