Update stuff and move pushrules to mautrix-go
This commit is contained in:
@ -27,6 +27,8 @@ import (
|
||||
sync "github.com/sasha-s/go-deadlock"
|
||||
|
||||
"maunium.net/go/mautrix"
|
||||
"maunium.net/go/mautrix/event"
|
||||
"maunium.net/go/mautrix/id"
|
||||
|
||||
"maunium.net/go/gomuks/debug"
|
||||
)
|
||||
@ -54,25 +56,27 @@ type RoomTag struct {
|
||||
}
|
||||
|
||||
type UnreadMessage struct {
|
||||
EventID string
|
||||
EventID id.EventID
|
||||
Counted bool
|
||||
Highlight bool
|
||||
}
|
||||
|
||||
type Member struct {
|
||||
mautrix.Member
|
||||
event.Member
|
||||
|
||||
// The user who sent the membership event
|
||||
Sender string `json:"-"`
|
||||
Sender id.UserID `json:"-"`
|
||||
}
|
||||
|
||||
// Room represents a single Matrix room.
|
||||
type Room struct {
|
||||
// The room ID.
|
||||
ID string
|
||||
ID id.RoomID
|
||||
|
||||
// Whether or not the user has left the room.
|
||||
HasLeft bool
|
||||
// Whether or not the room is encrypted.
|
||||
Encrypted bool
|
||||
|
||||
// The first batch of events that has been fetched for this room.
|
||||
// Used for fetching additional history.
|
||||
@ -80,14 +84,14 @@ type Room struct {
|
||||
// The last_batch field from the most recent sync. Used for fetching member lists.
|
||||
LastPrevBatch string
|
||||
// The MXID of the user whose session this room was created for.
|
||||
SessionUserID string
|
||||
SessionUserID id.UserID
|
||||
SessionMember *Member
|
||||
|
||||
// The number of unread messages that were notified about.
|
||||
UnreadMessages []UnreadMessage
|
||||
unreadCountCache *int
|
||||
highlightCache *bool
|
||||
lastMarkedRead string
|
||||
lastMarkedRead id.EventID
|
||||
// Whether or not this room is marked as a direct chat.
|
||||
IsDirect bool
|
||||
|
||||
@ -101,10 +105,10 @@ type Room struct {
|
||||
// Whether or not the members for this room have been fetched from the server.
|
||||
MembersFetched bool
|
||||
// Room state cache.
|
||||
state map[mautrix.EventType]map[string]*mautrix.Event
|
||||
state map[event.Type]map[string]*event.Event
|
||||
// MXID -> Member cache calculated from membership events.
|
||||
memberCache map[string]*Member
|
||||
exMemberCache map[string]*Member
|
||||
memberCache map[id.UserID]*Member
|
||||
exMemberCache map[id.UserID]*Member
|
||||
// The first two non-SessionUserID members in the room. Calculated at
|
||||
// the same time as memberCache.
|
||||
firstMemberCache *Member
|
||||
@ -117,11 +121,11 @@ type Room struct {
|
||||
// The topic of the room. Directly fetched from the m.room.topic state event.
|
||||
topicCache string
|
||||
// The canonical alias of the room. Directly fetched from the m.room.canonical_alias state event.
|
||||
CanonicalAliasCache string
|
||||
CanonicalAliasCache id.RoomAlias
|
||||
// Whether or not the room has been tombstoned.
|
||||
replacedCache bool
|
||||
// The room ID that replaced this room.
|
||||
replacedByCache *string
|
||||
replacedByCache *id.RoomID
|
||||
|
||||
// Path for state store file.
|
||||
path string
|
||||
@ -174,7 +178,7 @@ func (room *Room) load() {
|
||||
return
|
||||
}
|
||||
debug.Print("Loading state for room", room.ID, "from disk")
|
||||
room.state = make(map[mautrix.EventType]map[string]*mautrix.Event)
|
||||
room.state = make(map[event.Type]map[string]*event.Event)
|
||||
file, err := os.OpenFile(room.path, os.O_RDONLY, 0600)
|
||||
if err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
@ -265,7 +269,7 @@ func (room *Room) Save() {
|
||||
}
|
||||
|
||||
// MarkRead clears the new message statuses on this room.
|
||||
func (room *Room) MarkRead(eventID string) bool {
|
||||
func (room *Room) MarkRead(eventID id.EventID) bool {
|
||||
room.lock.Lock()
|
||||
defer room.lock.Unlock()
|
||||
if room.lastMarkedRead == eventID {
|
||||
@ -319,7 +323,7 @@ func (room *Room) HasNewMessages() bool {
|
||||
return len(room.UnreadMessages) > 0
|
||||
}
|
||||
|
||||
func (room *Room) AddUnread(eventID string, counted, highlight bool) {
|
||||
func (room *Room) AddUnread(eventID id.EventID, counted, highlight bool) {
|
||||
room.lock.Lock()
|
||||
defer room.lock.Unlock()
|
||||
room.UnreadMessages = append(room.UnreadMessages, UnreadMessage{
|
||||
@ -341,18 +345,25 @@ func (room *Room) AddUnread(eventID string, counted, highlight bool) {
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
tagDirect = RoomTag{"net.maunium.gomuks.fake.direct", "0.5"}
|
||||
tagInvite = RoomTag{"net.maunium.gomuks.fake.invite", "0.5"}
|
||||
tagDefault = RoomTag{"", "0.5"}
|
||||
tagLeave = RoomTag{"net.maunium.gomuks.fake.leave", "0.5"}
|
||||
)
|
||||
|
||||
func (room *Room) Tags() []RoomTag {
|
||||
room.lock.RLock()
|
||||
defer room.lock.RUnlock()
|
||||
if len(room.RawTags) == 0 {
|
||||
if room.IsDirect {
|
||||
return []RoomTag{{"net.maunium.gomuks.fake.direct", "0.5"}}
|
||||
} else if room.SessionMember != nil && room.SessionMember.Membership == mautrix.MembershipInvite {
|
||||
return []RoomTag{{"net.maunium.gomuks.fake.invite", "0.5"}}
|
||||
} else if room.SessionMember != nil && room.SessionMember.Membership != mautrix.MembershipJoin {
|
||||
return []RoomTag{{"net.maunium.gomuks.fake.leave", "0.5"}}
|
||||
return []RoomTag{tagDirect}
|
||||
} else if room.SessionMember != nil && room.SessionMember.Membership == event.MembershipInvite {
|
||||
return []RoomTag{tagInvite}
|
||||
} else if room.SessionMember != nil && room.SessionMember.Membership != event.MembershipJoin {
|
||||
return []RoomTag{tagLeave}
|
||||
}
|
||||
return []RoomTag{{"", "0.5"}}
|
||||
return []RoomTag{tagDefault}
|
||||
}
|
||||
return room.RawTags
|
||||
}
|
||||
@ -374,46 +385,46 @@ func (room *Room) UpdateSummary(summary mautrix.LazyLoadSummary) {
|
||||
|
||||
// UpdateState updates the room's current state with the given Event. This will clobber events based
|
||||
// on the type/state_key combination.
|
||||
func (room *Room) UpdateState(event *mautrix.Event) {
|
||||
if event.StateKey == nil {
|
||||
func (room *Room) UpdateState(evt *event.Event) {
|
||||
if evt.StateKey == nil {
|
||||
panic("Tried to UpdateState() event with no state key.")
|
||||
}
|
||||
room.Load()
|
||||
room.lock.Lock()
|
||||
defer room.lock.Unlock()
|
||||
room.changed = true
|
||||
_, exists := room.state[event.Type]
|
||||
_, exists := room.state[evt.Type]
|
||||
if !exists {
|
||||
room.state[event.Type] = make(map[string]*mautrix.Event)
|
||||
room.state[evt.Type] = make(map[string]*event.Event)
|
||||
}
|
||||
switch event.Type {
|
||||
case mautrix.StateRoomName:
|
||||
room.NameCache = event.Content.Name
|
||||
switch evt.Type {
|
||||
case event.StateRoomName:
|
||||
room.NameCache = evt.Content.Name
|
||||
room.nameCacheSource = ExplicitRoomName
|
||||
case mautrix.StateCanonicalAlias:
|
||||
case event.StateCanonicalAlias:
|
||||
if room.nameCacheSource <= CanonicalAliasRoomName {
|
||||
room.NameCache = event.Content.Alias
|
||||
room.NameCache = string(evt.Content.Alias)
|
||||
room.nameCacheSource = CanonicalAliasRoomName
|
||||
}
|
||||
room.CanonicalAliasCache = event.Content.Alias
|
||||
case mautrix.StateMember:
|
||||
room.CanonicalAliasCache = evt.Content.Alias
|
||||
case event.StateMember:
|
||||
if room.nameCacheSource <= MemberRoomName {
|
||||
room.NameCache = ""
|
||||
}
|
||||
room.updateMemberState(event)
|
||||
case mautrix.StateTopic:
|
||||
room.topicCache = event.Content.Topic
|
||||
room.updateMemberState(evt)
|
||||
case event.StateTopic:
|
||||
room.topicCache = evt.Content.Topic
|
||||
}
|
||||
|
||||
if event.Type != mautrix.StateMember {
|
||||
debug.Printf("Updating state %s#%s for %s", event.Type.String(), event.GetStateKey(), room.ID)
|
||||
if evt.Type != event.StateMember {
|
||||
debug.Printf("Updating state %s#%s for %s", evt.Type.String(), evt.GetStateKey(), room.ID)
|
||||
}
|
||||
|
||||
room.state[event.Type][*event.StateKey] = event
|
||||
room.state[evt.Type][*evt.StateKey] = evt
|
||||
}
|
||||
|
||||
func (room *Room) updateMemberState(event *mautrix.Event) {
|
||||
userID := event.GetStateKey()
|
||||
func (room *Room) updateMemberState(event *event.Event) {
|
||||
userID := id.UserID(event.GetStateKey())
|
||||
if userID == room.SessionUserID {
|
||||
debug.Print("Updating session user state:", string(event.Content.VeryRaw))
|
||||
room.SessionMember = room.eventToMember(userID, event.Sender, &event.Content)
|
||||
@ -442,7 +453,7 @@ func (room *Room) updateMemberState(event *mautrix.Event) {
|
||||
}
|
||||
|
||||
// GetStateEvent returns the state event for the given type/state_key combo, or nil.
|
||||
func (room *Room) GetStateEvent(eventType mautrix.EventType, stateKey string) *mautrix.Event {
|
||||
func (room *Room) GetStateEvent(eventType event.Type, stateKey string) *event.Event {
|
||||
room.Load()
|
||||
room.lock.RLock()
|
||||
defer room.lock.RUnlock()
|
||||
@ -452,7 +463,7 @@ func (room *Room) GetStateEvent(eventType mautrix.EventType, stateKey string) *m
|
||||
}
|
||||
|
||||
// getStateEvents returns the state events for the given type.
|
||||
func (room *Room) getStateEvents(eventType mautrix.EventType) map[string]*mautrix.Event {
|
||||
func (room *Room) getStateEvents(eventType event.Type) map[string]*event.Event {
|
||||
stateEventMap, _ := room.state[eventType]
|
||||
return stateEventMap
|
||||
}
|
||||
@ -460,7 +471,7 @@ func (room *Room) getStateEvents(eventType mautrix.EventType) map[string]*mautri
|
||||
// GetTopic returns the topic of the room.
|
||||
func (room *Room) GetTopic() string {
|
||||
if len(room.topicCache) == 0 {
|
||||
topicEvt := room.GetStateEvent(mautrix.StateTopic, "")
|
||||
topicEvt := room.GetStateEvent(event.StateTopic, "")
|
||||
if topicEvt != nil {
|
||||
room.topicCache = topicEvt.Content.Topic
|
||||
}
|
||||
@ -468,9 +479,9 @@ func (room *Room) GetTopic() string {
|
||||
return room.topicCache
|
||||
}
|
||||
|
||||
func (room *Room) GetCanonicalAlias() string {
|
||||
func (room *Room) GetCanonicalAlias() id.RoomAlias {
|
||||
if len(room.CanonicalAliasCache) == 0 {
|
||||
canonicalAliasEvt := room.GetStateEvent(mautrix.StateCanonicalAlias, "")
|
||||
canonicalAliasEvt := room.GetStateEvent(event.StateCanonicalAlias, "")
|
||||
if canonicalAliasEvt != nil {
|
||||
room.CanonicalAliasCache = canonicalAliasEvt.Content.Alias
|
||||
} else {
|
||||
@ -485,7 +496,7 @@ func (room *Room) GetCanonicalAlias() string {
|
||||
|
||||
// updateNameFromNameEvent updates the room display name to be the name set in the name event.
|
||||
func (room *Room) updateNameFromNameEvent() {
|
||||
nameEvt := room.GetStateEvent(mautrix.StateRoomName, "")
|
||||
nameEvt := room.GetStateEvent(event.StateRoomName, "")
|
||||
if nameEvt != nil {
|
||||
room.NameCache = nameEvt.Content.Name
|
||||
}
|
||||
@ -528,7 +539,7 @@ func (room *Room) updateNameCache() {
|
||||
room.nameCacheSource = ExplicitRoomName
|
||||
}
|
||||
if len(room.NameCache) == 0 {
|
||||
room.NameCache = room.GetCanonicalAlias()
|
||||
room.NameCache = string(room.GetCanonicalAlias())
|
||||
room.nameCacheSource = CanonicalAliasRoomName
|
||||
}
|
||||
if len(room.NameCache) == 0 {
|
||||
@ -548,8 +559,8 @@ func (room *Room) GetTitle() string {
|
||||
|
||||
func (room *Room) IsReplaced() bool {
|
||||
if room.replacedByCache == nil {
|
||||
evt := room.GetStateEvent(mautrix.StateTombstone, "")
|
||||
var replacement string
|
||||
evt := room.GetStateEvent(event.StateTombstone, "")
|
||||
var replacement id.RoomID
|
||||
if evt != nil {
|
||||
replacement = evt.Content.ReplacementRoom
|
||||
}
|
||||
@ -559,18 +570,18 @@ func (room *Room) IsReplaced() bool {
|
||||
return room.replacedCache
|
||||
}
|
||||
|
||||
func (room *Room) ReplacedBy() string {
|
||||
func (room *Room) ReplacedBy() id.RoomID {
|
||||
if room.replacedByCache == nil {
|
||||
room.IsReplaced()
|
||||
}
|
||||
return *room.replacedByCache
|
||||
}
|
||||
|
||||
func (room *Room) eventToMember(userID string, sender string, content *mautrix.Content) *Member {
|
||||
func (room *Room) eventToMember(userID, sender id.UserID, content *event.Content) *Member {
|
||||
member := content.Member
|
||||
member.Membership = content.Membership
|
||||
if len(member.Displayname) == 0 {
|
||||
member.Displayname = userID
|
||||
member.Displayname = string(userID)
|
||||
}
|
||||
return &Member{
|
||||
Member: member,
|
||||
@ -578,7 +589,7 @@ func (room *Room) eventToMember(userID string, sender string, content *mautrix.C
|
||||
}
|
||||
}
|
||||
|
||||
func (room *Room) updateNthMemberCache(userID string, member *Member) {
|
||||
func (room *Room) updateNthMemberCache(userID id.UserID, member *Member) {
|
||||
if userID != room.SessionUserID {
|
||||
if room.firstMemberCache == nil {
|
||||
room.firstMemberCache = member
|
||||
@ -589,19 +600,20 @@ func (room *Room) updateNthMemberCache(userID string, member *Member) {
|
||||
}
|
||||
|
||||
// createMemberCache caches all member events into a easily processable MXID -> *Member map.
|
||||
func (room *Room) createMemberCache() map[string]*Member {
|
||||
func (room *Room) createMemberCache() map[id.UserID]*Member {
|
||||
if len(room.memberCache) > 0 {
|
||||
return room.memberCache
|
||||
}
|
||||
cache := make(map[string]*Member)
|
||||
exCache := make(map[string]*Member)
|
||||
cache := make(map[id.UserID]*Member)
|
||||
exCache := make(map[id.UserID]*Member)
|
||||
room.lock.RLock()
|
||||
events := room.getStateEvents(mautrix.StateMember)
|
||||
memberEvents := room.getStateEvents(event.StateMember)
|
||||
room.firstMemberCache = nil
|
||||
room.secondMemberCache = nil
|
||||
if events != nil {
|
||||
for userID, event := range events {
|
||||
member := room.eventToMember(userID, event.Sender, &event.Content)
|
||||
if memberEvents != nil {
|
||||
for userIDStr, evt := range memberEvents {
|
||||
userID := id.UserID(userIDStr)
|
||||
member := room.eventToMember(userID, evt.Sender, &evt.Content)
|
||||
if member.Membership.IsInviteOrJoin() {
|
||||
cache[userID] = member
|
||||
room.updateNthMemberCache(userID, member)
|
||||
@ -631,7 +643,7 @@ func (room *Room) createMemberCache() map[string]*Member {
|
||||
//
|
||||
// The members are returned from the cache.
|
||||
// If the cache is empty, it is updated first.
|
||||
func (room *Room) GetMembers() map[string]*Member {
|
||||
func (room *Room) GetMembers() map[id.UserID]*Member {
|
||||
room.Load()
|
||||
room.createMemberCache()
|
||||
return room.memberCache
|
||||
@ -639,7 +651,7 @@ func (room *Room) GetMembers() map[string]*Member {
|
||||
|
||||
// GetMember returns the member with the given MXID.
|
||||
// If the member doesn't exist, nil is returned.
|
||||
func (room *Room) GetMember(userID string) *Member {
|
||||
func (room *Room) GetMember(userID id.UserID) *Member {
|
||||
if userID == room.SessionUserID && room.SessionMember != nil {
|
||||
return room.SessionMember
|
||||
}
|
||||
@ -660,16 +672,27 @@ func (room *Room) GetMember(userID string) *Member {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (room *Room) GetMemberCount() int {
|
||||
if room.memberCache == nil && room.Summary.JoinedMemberCount != nil {
|
||||
return *room.Summary.JoinedMemberCount
|
||||
}
|
||||
return len(room.GetMembers())
|
||||
}
|
||||
|
||||
// GetSessionOwner returns the ID of the user whose session this room was created for.
|
||||
func (room *Room) GetSessionOwner() string {
|
||||
return room.SessionUserID
|
||||
func (room *Room) GetOwnDisplayname() string {
|
||||
member := room.GetMember(room.SessionUserID)
|
||||
if member != nil {
|
||||
return member.Displayname
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// NewRoom creates a new Room with the given ID
|
||||
func NewRoom(roomID string, cache *RoomCache) *Room {
|
||||
func NewRoom(roomID id.RoomID, cache *RoomCache) *Room {
|
||||
return &Room{
|
||||
ID: roomID,
|
||||
state: make(map[mautrix.EventType]map[string]*mautrix.Event),
|
||||
state: make(map[event.Type]map[string]*event.Event),
|
||||
path: cache.roomPath(roomID),
|
||||
cache: cache,
|
||||
|
||||
|
@ -1,237 +0,0 @@
|
||||
// gomuks - A terminal Matrix client written in Go.
|
||||
// Copyright (C) 2019 Tulir Asokan
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package rooms_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"maunium.net/go/gomuks/matrix/rooms"
|
||||
"maunium.net/go/mautrix"
|
||||
)
|
||||
|
||||
func TestNewRoom_DefaultValues(t *testing.T) {
|
||||
room := rooms.NewRoom("!test:maunium.net", "@tulir:maunium.net")
|
||||
assert.Equal(t, "!test:maunium.net", room.ID)
|
||||
assert.Equal(t, "@tulir:maunium.net", room.SessionUserID)
|
||||
assert.Empty(t, room.GetMembers())
|
||||
assert.Equal(t, "Empty room", room.GetTitle())
|
||||
assert.Empty(t, room.GetAliases())
|
||||
assert.Empty(t, room.GetCanonicalAlias())
|
||||
assert.Empty(t, room.GetTopic())
|
||||
assert.Nil(t, room.GetMember(room.GetSessionOwner()))
|
||||
}
|
||||
|
||||
func TestRoom_GetCanonicalAlias(t *testing.T) {
|
||||
room := rooms.NewRoom("!test:maunium.net", "@tulir:maunium.net")
|
||||
room.UpdateState(&mautrix.Event{
|
||||
Type: mautrix.StateCanonicalAlias,
|
||||
Content: mautrix.Content{
|
||||
Alias: "#foo:maunium.net",
|
||||
},
|
||||
})
|
||||
assert.Equal(t, "#foo:maunium.net", room.GetCanonicalAlias())
|
||||
}
|
||||
|
||||
func TestRoom_GetTopic(t *testing.T) {
|
||||
room := rooms.NewRoom("!test:maunium.net", "@tulir:maunium.net")
|
||||
room.UpdateState(&mautrix.Event{
|
||||
Type: mautrix.StateTopic,
|
||||
Content: mautrix.Content{
|
||||
Topic: "test topic",
|
||||
},
|
||||
})
|
||||
assert.Equal(t, "test topic", room.GetTopic())
|
||||
}
|
||||
|
||||
func TestRoom_Tags_Empty(t *testing.T) {
|
||||
room := rooms.NewRoom("!test:maunium.net", "@tulir:maunium.net")
|
||||
assert.Empty(t, room.RawTags)
|
||||
tags := room.Tags()
|
||||
assert.Len(t, tags, 1)
|
||||
assert.Equal(t, "", tags[0].Tag)
|
||||
assert.Equal(t, "0.5", tags[0].Order)
|
||||
}
|
||||
|
||||
func TestRoom_Tags_NotEmpty(t *testing.T) {
|
||||
room := rooms.NewRoom("!test:maunium.net", "@tulir:maunium.net")
|
||||
room.RawTags = []rooms.RoomTag{{Tag: "foo", Order: "1"}, {Tag: "bar", Order: "1"}}
|
||||
tags := room.Tags()
|
||||
assert.Equal(t, room.RawTags, tags)
|
||||
}
|
||||
|
||||
func TestRoom_GetAliases(t *testing.T) {
|
||||
room := rooms.NewRoom("!test:maunium.net", "@tulir:maunium.net")
|
||||
addAliases(room)
|
||||
|
||||
aliases := room.GetAliases()
|
||||
assert.Contains(t, aliases, "#bar:maunium.net")
|
||||
assert.Contains(t, aliases, "#test:maunium.net")
|
||||
assert.Contains(t, aliases, "#foo:matrix.org")
|
||||
assert.Contains(t, aliases, "#test:matrix.org")
|
||||
}
|
||||
|
||||
func addName(room *rooms.Room) {
|
||||
room.UpdateState(&mautrix.Event{
|
||||
Type: mautrix.StateRoomName,
|
||||
Content: mautrix.Content{
|
||||
Name: "Test room",
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func addCanonicalAlias(room *rooms.Room) {
|
||||
room.UpdateState(&mautrix.Event{
|
||||
Type: mautrix.StateCanonicalAlias,
|
||||
Content: mautrix.Content{
|
||||
Alias: "#foo:maunium.net",
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func addAliases(room *rooms.Room) {
|
||||
server1 := "maunium.net"
|
||||
room.UpdateState(&mautrix.Event{
|
||||
Type: mautrix.StateAliases,
|
||||
StateKey: &server1,
|
||||
Content: mautrix.Content{
|
||||
Aliases: []string{"#bar:maunium.net", "#test:maunium.net", "#foo:maunium.net"},
|
||||
},
|
||||
})
|
||||
|
||||
server2 := "matrix.org"
|
||||
room.UpdateState(&mautrix.Event{
|
||||
Type: mautrix.StateAliases,
|
||||
StateKey: &server2,
|
||||
Content: mautrix.Content{
|
||||
Aliases: []string{"#foo:matrix.org", "#test:matrix.org"},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func addMembers(room *rooms.Room, count int) {
|
||||
user1 := "@tulir:maunium.net"
|
||||
room.UpdateState(&mautrix.Event{
|
||||
Type: mautrix.StateMember,
|
||||
StateKey: &user1,
|
||||
Content: mautrix.Content{
|
||||
Member: mautrix.Member{
|
||||
Displayname: "tulir",
|
||||
Membership: mautrix.MembershipJoin,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
for i := 1; i < count; i++ {
|
||||
userN := fmt.Sprintf("@user_%d:matrix.org", i+1)
|
||||
content := mautrix.Content{
|
||||
Member: mautrix.Member{
|
||||
Membership: mautrix.MembershipJoin,
|
||||
},
|
||||
}
|
||||
if i%2 == 1 {
|
||||
content.Displayname = fmt.Sprintf("User #%d", i+1)
|
||||
}
|
||||
if i%5 == 0 {
|
||||
content.Membership = mautrix.MembershipInvite
|
||||
}
|
||||
room.UpdateState(&mautrix.Event{
|
||||
Type: mautrix.StateMember,
|
||||
StateKey: &userN,
|
||||
Content: content,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRoom_GetMembers(t *testing.T) {
|
||||
room := rooms.NewRoom("!test:maunium.net", "@tulir:maunium.net")
|
||||
addMembers(room, 6)
|
||||
|
||||
members := room.GetMembers()
|
||||
assert.Len(t, members, 6)
|
||||
}
|
||||
|
||||
func TestRoom_GetMember(t *testing.T) {
|
||||
room := rooms.NewRoom("!test:maunium.net", "@tulir:maunium.net")
|
||||
addMembers(room, 6)
|
||||
|
||||
assert.NotNil(t, room.GetMember("@user_2:matrix.org"))
|
||||
assert.NotNil(t, room.GetMember("@tulir:maunium.net"))
|
||||
assert.Equal(t, "@tulir:maunium.net", room.GetSessionOwner())
|
||||
}
|
||||
|
||||
func TestRoom_GetTitle_ExplicitName(t *testing.T) {
|
||||
room := rooms.NewRoom("!test:maunium.net", "@tulir:maunium.net")
|
||||
addMembers(room, 4)
|
||||
addName(room)
|
||||
addCanonicalAlias(room)
|
||||
addAliases(room)
|
||||
assert.Equal(t, "Test room", room.GetTitle())
|
||||
}
|
||||
|
||||
func TestRoom_GetTitle_CanonicalAlias(t *testing.T) {
|
||||
room := rooms.NewRoom("!test:maunium.net", "@tulir:maunium.net")
|
||||
addMembers(room, 4)
|
||||
addCanonicalAlias(room)
|
||||
addAliases(room)
|
||||
assert.Equal(t, "#foo:maunium.net", room.GetTitle())
|
||||
}
|
||||
|
||||
func TestRoom_GetTitle_FirstAlias(t *testing.T) {
|
||||
room := rooms.NewRoom("!test:maunium.net", "@tulir:maunium.net")
|
||||
addMembers(room, 2)
|
||||
addAliases(room)
|
||||
assert.Equal(t, "#bar:maunium.net", room.GetTitle())
|
||||
}
|
||||
|
||||
func TestRoom_GetTitle_Members_Empty(t *testing.T) {
|
||||
room := rooms.NewRoom("!test:maunium.net", "@tulir:maunium.net")
|
||||
addMembers(room, 1)
|
||||
assert.Equal(t, "Empty room", room.GetTitle())
|
||||
}
|
||||
|
||||
func TestRoom_GetTitle_Members_OneToOne(t *testing.T) {
|
||||
room := rooms.NewRoom("!test:maunium.net", "@tulir:maunium.net")
|
||||
addMembers(room, 2)
|
||||
assert.Equal(t, "User #2", room.GetTitle())
|
||||
}
|
||||
|
||||
func TestRoom_GetTitle_Members_GroupChat(t *testing.T) {
|
||||
room := rooms.NewRoom("!test:maunium.net", "@tulir:maunium.net")
|
||||
addMembers(room, 76)
|
||||
assert.Contains(t, room.GetTitle(), " and 74 others")
|
||||
}
|
||||
|
||||
func TestRoom_MarkRead(t *testing.T) {
|
||||
room := rooms.NewRoom("!test:maunium.net", "@tulir:maunium.net")
|
||||
|
||||
room.AddUnread("foo", true, false)
|
||||
assert.Equal(t, 1, room.UnreadCount())
|
||||
assert.False(t, room.Highlighted())
|
||||
|
||||
room.AddUnread("bar", true, false)
|
||||
assert.Equal(t, 2, room.UnreadCount())
|
||||
assert.False(t, room.Highlighted())
|
||||
|
||||
room.AddUnread("asd", false, true)
|
||||
assert.Equal(t, 2, room.UnreadCount())
|
||||
assert.True(t, room.Highlighted())
|
||||
|
||||
room.MarkRead("asd")
|
||||
assert.Empty(t, room.UnreadMessages)
|
||||
}
|
@ -27,6 +27,7 @@ import (
|
||||
sync "github.com/sasha-s/go-deadlock"
|
||||
|
||||
"maunium.net/go/gomuks/debug"
|
||||
"maunium.net/go/mautrix/id"
|
||||
)
|
||||
|
||||
// RoomCache contains room state info in a hashmap and linked list.
|
||||
@ -37,15 +38,15 @@ type RoomCache struct {
|
||||
directory string
|
||||
maxSize int
|
||||
maxAge int64
|
||||
getOwner func() string
|
||||
getOwner func() id.UserID
|
||||
|
||||
Map map[string]*Room
|
||||
Map map[id.RoomID]*Room
|
||||
head *Room
|
||||
tail *Room
|
||||
size int
|
||||
}
|
||||
|
||||
func NewRoomCache(listPath, directory string, maxSize int, maxAge int64, getOwner func() string) *RoomCache {
|
||||
func NewRoomCache(listPath, directory string, maxSize int, maxAge int64, getOwner func() id.UserID) *RoomCache {
|
||||
return &RoomCache{
|
||||
listPath: listPath,
|
||||
directory: directory,
|
||||
@ -53,7 +54,7 @@ func NewRoomCache(listPath, directory string, maxSize int, maxAge int64, getOwne
|
||||
maxAge: maxAge,
|
||||
getOwner: getOwner,
|
||||
|
||||
Map: make(map[string]*Room),
|
||||
Map: make(map[id.RoomID]*Room),
|
||||
}
|
||||
}
|
||||
|
||||
@ -88,7 +89,7 @@ func (cache *RoomCache) LoadList() error {
|
||||
}
|
||||
|
||||
// Read list
|
||||
cache.Map = make(map[string]*Room, size)
|
||||
cache.Map = make(map[id.RoomID]*Room, size)
|
||||
for i := 0; i < size; i++ {
|
||||
room := &Room{}
|
||||
err = dec.Decode(room)
|
||||
@ -147,7 +148,7 @@ func (cache *RoomCache) SaveList() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cache *RoomCache) Touch(roomID string) {
|
||||
func (cache *RoomCache) Touch(roomID id.RoomID) {
|
||||
cache.Lock()
|
||||
node, ok := cache.Map[roomID]
|
||||
if !ok || node == nil {
|
||||
@ -174,14 +175,14 @@ func (cache *RoomCache) touch(node *Room) {
|
||||
node.touch = time.Now().Unix()
|
||||
}
|
||||
|
||||
func (cache *RoomCache) Get(roomID string) *Room {
|
||||
func (cache *RoomCache) Get(roomID id.RoomID) *Room {
|
||||
cache.Lock()
|
||||
node := cache.get(roomID)
|
||||
cache.Unlock()
|
||||
return node
|
||||
}
|
||||
|
||||
func (cache *RoomCache) GetOrCreate(roomID string) *Room {
|
||||
func (cache *RoomCache) GetOrCreate(roomID id.RoomID) *Room {
|
||||
cache.Lock()
|
||||
node := cache.get(roomID)
|
||||
if node == nil {
|
||||
@ -192,7 +193,7 @@ func (cache *RoomCache) GetOrCreate(roomID string) *Room {
|
||||
return node
|
||||
}
|
||||
|
||||
func (cache *RoomCache) get(roomID string) *Room {
|
||||
func (cache *RoomCache) get(roomID id.RoomID) *Room {
|
||||
node, ok := cache.Map[roomID]
|
||||
if ok && node != nil {
|
||||
return node
|
||||
@ -215,11 +216,11 @@ func (cache *RoomCache) Put(room *Room) {
|
||||
node.Save()
|
||||
}
|
||||
|
||||
func (cache *RoomCache) roomPath(roomID string) string {
|
||||
return filepath.Join(cache.directory, roomID+".gob.gz")
|
||||
func (cache *RoomCache) roomPath(roomID id.RoomID) string {
|
||||
return filepath.Join(cache.directory, string(roomID)+".gob.gz")
|
||||
}
|
||||
|
||||
func (cache *RoomCache) Load(roomID string) *Room {
|
||||
func (cache *RoomCache) Load(roomID id.RoomID) *Room {
|
||||
cache.Lock()
|
||||
defer cache.Unlock()
|
||||
node, ok := cache.Map[roomID]
|
||||
@ -312,7 +313,7 @@ func (cache *RoomCache) Unload(node *Room) {
|
||||
}
|
||||
}
|
||||
|
||||
func (cache *RoomCache) newRoom(roomID string) *Room {
|
||||
func (cache *RoomCache) newRoom(roomID id.RoomID) *Room {
|
||||
node := NewRoom(roomID, cache)
|
||||
cache.Map[node.ID] = node
|
||||
return node
|
||||
|
Reference in New Issue
Block a user