diff --git a/README.textile b/README.textile index d3d2437..e4d611a 100644 --- a/README.textile +++ b/README.textile @@ -21,6 +21,7 @@ Done: * PASS (connection password) * PING/PONG * PRIVMSG +* NOTICE * MODE * JOIN * TOPIC @@ -50,7 +51,7 @@ Planned: * Server-to-server messages for JOIN, NJOIN, MODE, PRIVSG and NOTICE * SQUIT and QUIT for links * Server to server communication -* More basic commands: NOTICE, LINKS, TRACE, ADMIN, INFO +* More basic commands: LINKS, TRACE, ADMIN, INFO * Log files and logging options * Local ops (+O) * Stats command diff --git a/lib/commands.js b/lib/commands.js index 00b54d4..1819b7e 100644 --- a/lib/commands.js +++ b/lib/commands.js @@ -202,6 +202,37 @@ Commands.prototype = { } }, + // TODO: The RFC says the sender nick and actual user nick should be checked + // TODO: Message validation + NOTICE: function(user, target, message) { + // ERR_NOTOPLEVEL + // ERR_WILDTOPLEVEL + // ERR_TOOMANYTARGETS + // ERR_NOSUCHNICK + // RPL_AWAY + if (!target || target.length === 0) { + user.send(this.server.host, irc.errors.noRecipient, ':No recipient given'); + } else if (!message || message.length === 0) { + user.send(this.server.host, irc.errors.noTextToSend, ':No text to send'); + } else if (this.server.channelTarget(target)) { + var channel = this.server.channels.find(target); + if (!channel) { + user.send(this.server.host, irc.errors.noSuchNick, user.nick, target, ':No such nick/channel'); + } else if (channel.isModerated && !user.isVoiced(channel)) { + user.send(this.server.host, irc.errors.cannotSend, channel.name, ':Cannot send to channel'); + } else if (user.channels.indexOf(channel) === -1) { + if (channel.modes.indexOf('n') !== -1) { + user.send(this.server.host, irc.errors.cannotSend, channel.name, ':Cannot send to channel'); + return; + } + } else { + this.server.channels.notice(user, channel, message); + } + } else { + user.notice(target, message); + } + }, + INVITE: function(user, nick, channelName) { var channel = this.server.channels.find(channelName), targetUser = this.server.users.find(nick); diff --git a/lib/storage.js b/lib/storage.js index e0d13ce..64fea6c 100644 --- a/lib/storage.js +++ b/lib/storage.js @@ -79,6 +79,15 @@ ChannelDatabase.prototype = { }); }, + notice: function(user, channel, message) { + if (!channel) return; + channel.users.forEach(function(channelUser) { + if (channelUser !== user) { + channelUser.send(user.mask, 'NOTICE', channel.name, ':' + message); + } + }); + }, + expandMask: function(mask) { return mask.replace(/\./g, '\\.'). replace(/\*/g, '.*'); diff --git a/lib/user.js b/lib/user.js index 1971ede..2927c0e 100644 --- a/lib/user.js +++ b/lib/user.js @@ -232,6 +232,20 @@ User.prototype = { } }, + notice: function(nick, message) { + var user = this.server.users.find(nick); + this.updated = new Date(); + + if (user) { + if (user.isAway) { + this.send(this.server.host, irc.reply.away, this.nick, user.nick, ':' + user.awayMessage); + } + user.send(this.mask, 'NOTICE', user.nick, ':' + message); + } else { + this.send(this.server.host, irc.errors.noSuchNick, this.nick, nick, ':No such nick/channel'); + } + }, + addModes: function(user, modes, arg) { var thisUser = this; modes.slice(1).split('').forEach(function(mode) {