diff --git a/Gopkg.lock b/Gopkg.lock index 9873696..d782b12 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -123,7 +123,7 @@ ".", "format" ] - revision = "3bc65810c93810440c0a053b9fe5009bb01521c5" + revision = "692bae934fcd3b7f4379e89d7271220f1d81f318" [[projects]] branch = "master" @@ -141,7 +141,7 @@ branch = "master" name = "maunium.net/go/mautrix-appservice" packages = ["."] - revision = "7873866d1709943d6e2ac2d889c845eeca2e7686" + revision = "62ccd06944c74b6e526b493ef66fc736d23b1cf2" [solve-meta] analyzer-name = "dep" diff --git a/statestore.go b/statestore.go index e60bf0d..aaaffae 100644 --- a/statestore.go +++ b/statestore.go @@ -26,19 +26,19 @@ import ( ) type AutosavingStateStore struct { - *appservice.BasicStateStore + appservice.StateStore Path string } func NewAutosavingStateStore(path string) *AutosavingStateStore { return &AutosavingStateStore{ - BasicStateStore: appservice.NewBasicStateStore(), - Path: path, + StateStore: appservice.NewBasicStateStore(), + Path: path, } } func (store *AutosavingStateStore) Save() error { - data, err := json.Marshal(store.BasicStateStore) + data, err := json.Marshal(store.StateStore) if err != nil { return err } @@ -55,20 +55,20 @@ func (store *AutosavingStateStore) Load() error { return err } - return json.Unmarshal(data, store.BasicStateStore) + return json.Unmarshal(data, store.StateStore) } func (store *AutosavingStateStore) MarkRegistered(userID string) { - store.BasicStateStore.MarkRegistered(userID) + store.StateStore.MarkRegistered(userID) store.Save() } func (store *AutosavingStateStore) SetMembership(roomID, userID, membership string) { - store.BasicStateStore.SetMembership(roomID, userID, membership) + store.StateStore.SetMembership(roomID, userID, membership) store.Save() } func (store *AutosavingStateStore) SetPowerLevels(roomID string, levels *gomatrix.PowerLevels) { - store.BasicStateStore.SetPowerLevels(roomID, levels) + store.StateStore.SetPowerLevels(roomID, levels) store.Save() } diff --git a/vendor/maunium.net/go/gomatrix/events.go b/vendor/maunium.net/go/gomatrix/events.go index ca577b6..fcd0538 100644 --- a/vendor/maunium.net/go/gomatrix/events.go +++ b/vendor/maunium.net/go/gomatrix/events.go @@ -231,8 +231,8 @@ func (pl *PowerLevels) StateDefault() int { func (pl *PowerLevels) GetUserLevel(userID string) int { pl.usersLock.RLock() + defer pl.usersLock.RUnlock() level, ok := pl.Users[userID] - pl.usersLock.RUnlock() if !ok { return pl.UsersDefault } @@ -241,12 +241,12 @@ func (pl *PowerLevels) GetUserLevel(userID string) int { func (pl *PowerLevels) SetUserLevel(userID string, level int) { pl.usersLock.Lock() + defer pl.usersLock.Unlock() if level == pl.UsersDefault { delete(pl.Users, userID) } else { pl.Users[userID] = level } - pl.usersLock.Unlock() } func (pl *PowerLevels) EnsureUserLevel(userID string, level int) bool { @@ -260,8 +260,8 @@ func (pl *PowerLevels) EnsureUserLevel(userID string, level int) bool { func (pl *PowerLevels) GetEventLevel(eventType EventType, isState bool) int { pl.eventsLock.RLock() + defer pl.eventsLock.RUnlock() level, ok := pl.Events[eventType] - pl.eventsLock.RUnlock() if !ok { if isState { return pl.StateDefault() @@ -273,12 +273,12 @@ func (pl *PowerLevels) GetEventLevel(eventType EventType, isState bool) int { func (pl *PowerLevels) SetEventLevel(eventType EventType, isState bool, level int) { pl.eventsLock.Lock() + defer pl.eventsLock.Unlock() if (isState && level == pl.StateDefault()) || (!isState && level == pl.EventsDefault) { delete(pl.Events, eventType) } else { pl.Events[eventType] = level } - pl.eventsLock.Unlock() } func (pl *PowerLevels) EnsureEventLevel(eventType EventType, isState bool, level int) bool { diff --git a/vendor/maunium.net/go/mautrix-appservice/appservice.go b/vendor/maunium.net/go/mautrix-appservice/appservice.go index cc7c2ec..1ae68a2 100644 --- a/vendor/maunium.net/go/mautrix-appservice/appservice.go +++ b/vendor/maunium.net/go/mautrix-appservice/appservice.go @@ -24,7 +24,7 @@ func Create() *AppService { LogConfig: CreateLogConfig(), clients: make(map[string]*gomatrix.Client), intents: make(map[string]*IntentAPI), - StateStore: &BasicStateStore{}, + StateStore: NewBasicStateStore(), } } diff --git a/vendor/maunium.net/go/mautrix-appservice/intent.go b/vendor/maunium.net/go/mautrix-appservice/intent.go index 9436a5b..957d529 100644 --- a/vendor/maunium.net/go/mautrix-appservice/intent.go +++ b/vendor/maunium.net/go/mautrix-appservice/intent.go @@ -150,6 +150,21 @@ func (intent *IntentAPI) SetPowerLevel(roomID, userID string, level int) (*gomat return nil, nil } +func (intent *IntentAPI) UserTyping(roomID string, typing bool, timeout int64) (resp *gomatrix.RespTyping, err error) { + if intent.as.StateStore.IsTyping(roomID, intent.UserID) == typing { + return + } + resp, err = intent.Client.UserTyping(roomID, typing, timeout) + if err != nil { + return + } + if !typing { + timeout = -1 + } + intent.as.StateStore.SetTyping(roomID, intent.UserID, timeout) + return +} + func (intent *IntentAPI) SendText(roomID, text string) (*gomatrix.RespSendEvent, error) { if err := intent.EnsureJoined(roomID); err != nil { return nil, err diff --git a/vendor/maunium.net/go/mautrix-appservice/statestore.go b/vendor/maunium.net/go/mautrix-appservice/statestore.go index 5c723f7..173a3f3 100644 --- a/vendor/maunium.net/go/mautrix-appservice/statestore.go +++ b/vendor/maunium.net/go/mautrix-appservice/statestore.go @@ -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() }