Prioritize user modes properly serverside

This commit is contained in:
Ken-Håvard Lieng 2017-05-10 05:44:59 +02:00
parent 2b5a468079
commit 71177254b4
2 changed files with 110 additions and 41 deletions

View File

@ -6,16 +6,69 @@ import (
) )
type ChannelStore struct { type ChannelStore struct {
users map[string]map[string][]string users map[string]map[string][]*ChannelStoreUser
userLock sync.Mutex userLock sync.Mutex
topic map[string]map[string]string topic map[string]map[string]string
topicLock sync.Mutex topicLock sync.Mutex
} }
const userModePrefixes = "~&@%+"
const userModeChars = "qaohv"
type ChannelStoreUser struct {
nick string
modes string
prefix string
}
func NewChannelStoreUser(nick string) *ChannelStoreUser {
user := &ChannelStoreUser{nick: nick}
if i := strings.IndexAny(nick, userModePrefixes); i == 0 {
i = strings.Index(userModePrefixes, string(nick[0]))
user.modes = string(userModeChars[i])
user.nick = nick[1:]
user.updatePrefix()
}
return user
}
func (c *ChannelStoreUser) String() string {
return c.prefix + c.nick
}
func (c *ChannelStoreUser) addModes(modes string) {
for _, mode := range modes {
if strings.Contains(c.modes, string(mode)) {
continue
}
c.modes += string(mode)
}
c.updatePrefix()
}
func (c *ChannelStoreUser) removeModes(modes string) {
for _, mode := range modes {
c.modes = strings.Replace(c.modes, string(mode), "", 1)
}
c.updatePrefix()
}
func (c *ChannelStoreUser) updatePrefix() {
for i, mode := range userModeChars {
if strings.Contains(c.modes, string(mode)) {
c.prefix = string(userModePrefixes[i])
return
}
}
c.prefix = ""
}
func NewChannelStore() *ChannelStore { func NewChannelStore() *ChannelStore {
return &ChannelStore{ return &ChannelStore{
users: make(map[string]map[string][]string), users: make(map[string]map[string][]*ChannelStoreUser),
topic: make(map[string]map[string]string), topic: make(map[string]map[string]string),
} }
} }
@ -24,7 +77,9 @@ func (c *ChannelStore) GetUsers(server, channel string) []string {
c.userLock.Lock() c.userLock.Lock()
users := make([]string, len(c.users[server][channel])) users := make([]string, len(c.users[server][channel]))
copy(users, c.users[server][channel]) for i, user := range c.users[server][channel] {
users[i] = user.String()
}
c.userLock.Unlock() c.userLock.Unlock()
@ -35,10 +90,13 @@ func (c *ChannelStore) SetUsers(users []string, server, channel string) {
c.userLock.Lock() c.userLock.Lock()
if _, ok := c.users[server]; !ok { if _, ok := c.users[server]; !ok {
c.users[server] = make(map[string][]string) c.users[server] = make(map[string][]*ChannelStoreUser)
}
for _, nick := range users {
c.users[server][channel] = append(c.users[server][channel], NewChannelStoreUser(nick))
} }
c.users[server][channel] = users
c.userLock.Unlock() c.userLock.Unlock()
} }
@ -46,20 +104,20 @@ func (c *ChannelStore) AddUser(user, server, channel string) {
c.userLock.Lock() c.userLock.Lock()
if _, ok := c.users[server]; !ok { if _, ok := c.users[server]; !ok {
c.users[server] = make(map[string][]string) c.users[server] = make(map[string][]*ChannelStoreUser)
} }
if users, ok := c.users[server][channel]; ok { if users, ok := c.users[server][channel]; ok {
for _, nick := range users { for _, u := range users {
if nick == user { if u.nick == user {
c.userLock.Unlock() c.userLock.Unlock()
return return
} }
} }
c.users[server][channel] = append(users, user) c.users[server][channel] = append(users, NewChannelStoreUser(user))
} else { } else {
c.users[server][channel] = []string{user} c.users[server][channel] = []*ChannelStoreUser{NewChannelStoreUser(user)}
} }
c.userLock.Unlock() c.userLock.Unlock()
@ -90,12 +148,14 @@ func (c *ChannelStore) RenameUser(oldNick, newNick, server string) {
func (c *ChannelStore) SetMode(server, channel, user, add, remove string) { func (c *ChannelStore) SetMode(server, channel, user, add, remove string) {
c.userLock.Lock() c.userLock.Lock()
if strings.Contains(add, "o") { for _, u := range c.users[server][channel] {
c.setPrefix(server, channel, user, "@") if u.nick == user {
} else if strings.Contains(add, "v") { u.addModes(add)
c.setPrefix(server, channel, user, "+") u.removeModes(remove)
} else if strings.IndexAny(remove, "ov") > -1 {
c.setPrefix(server, channel, user, "") c.userLock.Unlock()
return
}
} }
c.userLock.Unlock() c.userLock.Unlock()
@ -103,9 +163,9 @@ func (c *ChannelStore) SetMode(server, channel, user, add, remove string) {
func (c *ChannelStore) GetTopic(server, channel string) string { func (c *ChannelStore) GetTopic(server, channel string) string {
c.topicLock.Lock() c.topicLock.Lock()
defer c.topicLock.Unlock() topic := c.topic[server][channel]
c.topicLock.Unlock()
return c.topic[server][channel] return topic
} }
func (c *ChannelStore) SetTopic(topic, server, channel string) { func (c *ChannelStore) SetTopic(topic, server, channel string) {
@ -120,22 +180,9 @@ func (c *ChannelStore) SetTopic(topic, server, channel string) {
} }
func (c *ChannelStore) rename(server, channel, oldNick, newNick string) { func (c *ChannelStore) rename(server, channel, oldNick, newNick string) {
for i, nick := range c.users[server][channel] { for _, user := range c.users[server][channel] {
if strings.TrimLeft(nick, "@+") == oldNick { if user.nick == oldNick {
if nick[0] == '@' || nick[0] == '+' { user.nick = newNick
newNick = nick[:1] + newNick
}
c.users[server][channel][i] = newNick
return
}
}
}
func (c *ChannelStore) setPrefix(server, channel, user, prefix string) {
for i, nick := range c.users[server][channel] {
if strings.TrimLeft(nick, "@+") == user {
c.users[server][channel][i] = prefix + user
return return
} }
} }
@ -148,8 +195,8 @@ func (c *ChannelStore) renameAll(server, oldNick, newNick string) {
} }
func (c *ChannelStore) removeUser(user, server, channel string) { func (c *ChannelStore) removeUser(user, server, channel string) {
for i, nick := range c.users[server][channel] { for i, u := range c.users[server][channel] {
if strings.TrimLeft(nick, "@+") == user { if u.nick == user {
users := c.users[server][channel] users := c.users[server][channel]
c.users[server][channel] = append(users[:i], users[i+1:]...) c.users[server][channel] = append(users[:i], users[i+1:]...)
return return

View File

@ -8,9 +8,9 @@ import (
func TestGetSetUsers(t *testing.T) { func TestGetSetUsers(t *testing.T) {
channelStore := NewChannelStore() channelStore := NewChannelStore()
users := []string{"a,b"} users := []string{"a", "b"}
channelStore.SetUsers(users, "srv", "#chan") channelStore.SetUsers(users, "srv", "#chan")
assert.Equal(t, channelStore.GetUsers("srv", "#chan"), users) assert.Equal(t, users, channelStore.GetUsers("srv", "#chan"))
} }
func TestAddRemoveUser(t *testing.T) { func TestAddRemoveUser(t *testing.T) {
@ -52,9 +52,11 @@ func TestMode(t *testing.T) {
channelStore.SetMode("srv", "#chan", "user", "o", "v") channelStore.SetMode("srv", "#chan", "user", "o", "v")
assert.Equal(t, []string{"@user"}, channelStore.GetUsers("srv", "#chan")) assert.Equal(t, []string{"@user"}, channelStore.GetUsers("srv", "#chan"))
channelStore.SetMode("srv", "#chan", "user", "v", "") channelStore.SetMode("srv", "#chan", "user", "v", "")
assert.Equal(t, []string{"@user"}, channelStore.GetUsers("srv", "#chan"))
channelStore.SetMode("srv", "#chan", "user", "", "o")
assert.Equal(t, []string{"+user"}, channelStore.GetUsers("srv", "#chan")) assert.Equal(t, []string{"+user"}, channelStore.GetUsers("srv", "#chan"))
channelStore.SetMode("srv", "#chan", "user", "", "v") channelStore.SetMode("srv", "#chan", "user", "q", "")
assert.Equal(t, []string{"user"}, channelStore.GetUsers("srv", "#chan")) assert.Equal(t, []string{"~user"}, channelStore.GetUsers("srv", "#chan"))
} }
func TestTopic(t *testing.T) { func TestTopic(t *testing.T) {
@ -63,3 +65,23 @@ func TestTopic(t *testing.T) {
channelStore.SetTopic("the topic", "srv", "#chan") channelStore.SetTopic("the topic", "srv", "#chan")
assert.Equal(t, "the topic", channelStore.GetTopic("srv", "#chan")) assert.Equal(t, "the topic", channelStore.GetTopic("srv", "#chan"))
} }
func TestChannelUserMode(t *testing.T) {
user := NewChannelStoreUser("&test")
assert.Equal(t, "test", user.nick)
assert.Equal(t, "a", string(user.modes[0]))
assert.Equal(t, "&test", user.String())
user.removeModes("a")
assert.Equal(t, "test", user.String())
user.addModes("o")
assert.Equal(t, "@test", user.String())
user.addModes("q")
assert.Equal(t, "~test", user.String())
user.addModes("v")
assert.Equal(t, "~test", user.String())
user.removeModes("qo")
assert.Equal(t, "+test", user.String())
user.removeModes("v")
assert.Equal(t, "test", user.String())
}