Added basic mode support with op/voice and userlist sorting

This commit is contained in:
khlieng 2015-01-25 02:35:46 +01:00
parent 0c2250b268
commit 721971cbb3
8 changed files with 170 additions and 11 deletions

View File

@ -11,6 +11,7 @@ var channelActions = Reflux.createActions([
'removeUserAll', 'removeUserAll',
'setUsers', 'setUsers',
'setTopic', 'setTopic',
'setMode',
'load' 'load'
]); ]);
@ -48,6 +49,10 @@ socket.on('topic', function(data) {
channelActions.setTopic(data.topic, data.server, data.channel); channelActions.setTopic(data.topic, data.server, data.channel);
}); });
socket.on('mode', function(data) {
channelActions.setMode(data);
});
socket.on('channels', function(data) { socket.on('channels', function(data) {
channelActions.load(data); channelActions.load(data);
}); });

View File

@ -14,7 +14,7 @@ var Chat = React.createClass({
<MessageInput /> <MessageInput />
<UserList /> <UserList />
</div> </div>
) );
} }
}); });

View File

@ -11,7 +11,7 @@ function dispatchCommand(cmd, channel, server) {
switch (params[0].toLowerCase()) { switch (params[0].toLowerCase()) {
case 'join': case 'join':
if (params[1]) { if (params[1]) {
channelActions.join(params[1], server); channelActions.join([params[1]], server);
} }
break; break;

View File

@ -26,7 +26,7 @@ var UserList = React.createClass({
var channel = this.state.channels[tab.server][tab.channel]; var channel = this.state.channels[tab.server][tab.channel];
if (channel) { if (channel) {
users = _.map(channel.users, function(user) { users = _.map(channel.users, function(user) {
return <p>{user}</p>; return <p>{user.renderName}</p>;
}); });
} }
} }

View File

@ -14,6 +14,54 @@ function initChannel(server, channel) {
} }
} }
function createUser(nick, mode) {
return updateRenderName({
nick: nick,
renderName: nick,
mode: mode || ''
});
}
function loadUser(users, nick) {
var mode;
if (nick[0] === '@') {
mode = 'o';
} else if (nick[0] === '+') {
mode = 'v';
}
if (mode) {
nick = nick.slice(1);
}
users.push(createUser(nick, mode));
}
function updateRenderName(user) {
if (user.mode.indexOf('o') !== -1) {
user.renderName = '@' + user.nick;
} else if (user.mode.indexOf('v') !== -1) {
user.renderName = '+' + user.nick;
} else {
user.renderName = user.nick;
}
return user;
}
function sortUsers(server, channel) {
channels[server][channel].users.sort(function(a, b) {
if (a.renderName < b.renderName) {
return -1;
}
if (a.renderName > b.renderName) {
return 1;
}
return 0;
});
}
var channelStore = Reflux.createStore({ var channelStore = Reflux.createStore({
init: function() { init: function() {
this.listenToMany(actions); this.listenToMany(actions);
@ -28,25 +76,34 @@ var channelStore = Reflux.createStore({
addUser: function(user, server, channel) { addUser: function(user, server, channel) {
initChannel(server, channel); initChannel(server, channel);
channels[server][channel].users.push(user); channels[server][channel].users.push(createUser(user));
sortUsers(server, channel);
this.trigger(channels); this.trigger(channels);
}, },
removeUser: function(user, server, channel) { removeUser: function(user, server, channel) {
_.pull(channels[server][channel].users, user); _.remove(channels[server][channel].users, { nick: user });
this.trigger(channels); this.trigger(channels);
}, },
removeUserAll: function(user, server) { removeUserAll: function(user, server) {
_.each(channels[server], function(channel) { _.each(channels[server], function(channel) {
_.pull(channel.users, user); _.remove(channel.users, { nick: user });
}); });
this.trigger(channels); this.trigger(channels);
}, },
setUsers: function(users, server, channel) { setUsers: function(users, server, channel) {
initChannel(server, channel); initChannel(server, channel);
channels[server][channel].users = users; var chan = channels[server][channel];
chan.users = [];
_.each(users, function(user) {
loadUser(chan.users, user);
});
sortUsers(server, channel);
this.trigger(channels); this.trigger(channels);
}, },
@ -55,12 +112,37 @@ var channelStore = Reflux.createStore({
this.trigger(channels); this.trigger(channels);
}, },
setMode: function(mode) {
var user = _.find(channels[mode.server][mode.channel].users, { nick: mode.user });
if (user) {
_.each(mode.remove, function(mode) {
user.mode = user.mode.replace(mode, '');
});
_.each(mode.add, function(mode) {
user.mode += mode;
});
updateRenderName(user);
sortUsers(mode.server, mode.channel);
this.trigger(channels);
}
},
load: function(storedChannels) { load: function(storedChannels) {
_.each(storedChannels, function(channel) { _.each(storedChannels, function(channel) {
initChannel(channel.server, channel.name); initChannel(channel.server, channel.name);
channels[channel.server][channel.name].users = channel.users; var chan = channels[channel.server][channel.name];
channels[channel.server][channel.name].topic = channel.topic;
chan.users = [];
chan.topic = channel.topic;
_.each(channel.users, function(user) {
loadUser(chan.users, user);
}); });
sortUsers(channel.server, channel.name);
});
this.trigger(channels); this.trigger(channels);
}, },

View File

@ -26,6 +26,14 @@ type Join struct {
Channels []string `json:"channels"` Channels []string `json:"channels"`
} }
type Mode struct {
Server string `json:"server"`
Channel string `json:"channel"`
User string `json:"user"`
Add string `json:"add"`
Remove string `json:"remove"`
}
type Quit struct { type Quit struct {
Server string `json:"server"` Server string `json:"server"`
User string `json:"user"` User string `json:"user"`

View File

@ -48,6 +48,19 @@ func handleMessages(irc *IRC, session *Session) {
session.user.RemoveChannel(irc.Host, msg.Params[0]) session.user.RemoveChannel(irc.Host, msg.Params[0])
} }
case MODE:
target := msg.Params[0]
if len(msg.Params) > 2 && isChannel(target) {
mode := parseMode(msg.Params[1])
mode.Server = irc.Host
mode.Channel = target
mode.User = msg.Params[2]
session.sendJSON("mode", mode)
channelStore.SetMode(irc.Host, target, msg.Params[2], mode.Add, mode.Remove)
}
case PRIVMSG, NOTICE: case PRIVMSG, NOTICE:
if msg.Params[0] == irc.nick { if msg.Params[0] == irc.nick {
session.sendJSON("pm", Chat{ session.sendJSON("pm", Chat{
@ -100,9 +113,9 @@ func handleMessages(irc *IRC, session *Session) {
case RPL_NAMREPLY: case RPL_NAMREPLY:
users := strings.Split(msg.Trailing, " ") users := strings.Split(msg.Trailing, " ")
for i, user := range users { /*for i, user := range users {
users[i] = strings.TrimLeft(user, "@+") users[i] = strings.TrimLeft(user, "@+")
} }*/
userBuffer := userBuffers[msg.Params[2]] userBuffer := userBuffers[msg.Params[2]]
userBuffers[msg.Params[2]] = append(userBuffer, users...) userBuffers[msg.Params[2]] = append(userBuffer, users...)
@ -142,6 +155,29 @@ func handleMessages(irc *IRC, session *Session) {
} }
} }
func parseMode(mode string) *Mode {
m := Mode{}
add := false
for _, c := range mode {
if c == '+' {
add = true
} else if c == '-' {
add = false
} else if add {
m.Add += string(c)
} else {
m.Remove += string(c)
}
}
return &m
}
func isChannel(s string) bool {
return strings.IndexAny(s, "&#+!") == 0
}
func printMessage(msg *Message, irc *IRC) { func printMessage(msg *Message, irc *IRC) {
log.Println(irc.nick+":", msg.Prefix, msg.Command, msg.Params, msg.Trailing) log.Println(irc.nick+":", msg.Prefix, msg.Command, msg.Params, msg.Trailing)
} }

View File

@ -1,6 +1,7 @@
package storage package storage
import ( import (
"strings"
"sync" "sync"
) )
@ -74,6 +75,20 @@ func (c *ChannelStore) RemoveUserAll(user, server string) {
c.userLock.Unlock() c.userLock.Unlock()
} }
func (c *ChannelStore) SetMode(server, channel, user, add, remove string) {
c.userLock.Lock()
if strings.Contains(add, "o") {
c.rename(server, channel, user, "@"+user)
} else if strings.Contains(add, "v") {
c.rename(server, channel, user, "+"+user)
} else if strings.IndexAny(remove, "ov") > -1 {
c.rename(server, channel, user, user)
}
c.userLock.Unlock()
}
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() defer c.topicLock.Unlock()
@ -92,8 +107,21 @@ func (c *ChannelStore) SetTopic(topic, server, channel string) {
c.topicLock.Unlock() c.topicLock.Unlock()
} }
func (c *ChannelStore) rename(server, channel, oldNick, newNick string) {
for i, u := range c.users[server][channel] {
u = strings.TrimLeft(u, "@+")
if u == oldNick {
c.users[server][channel][i] = newNick
return
}
}
}
func (c *ChannelStore) removeUser(user, server, channel string) { func (c *ChannelStore) removeUser(user, server, channel string) {
for i, u := range c.users[server][channel] { for i, u := range c.users[server][channel] {
u = strings.TrimLeft(u, "@+")
if u == user { if u == 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:]...)