diff --git a/public/css/main.css b/public/css/main.css index 7ea4cfc..b9f43da 100644 --- a/public/css/main.css +++ b/public/css/main.css @@ -455,7 +455,8 @@ body { .message.m_join { color: #008000; } -.message.m_topic .content { +.message.m_topic .content, +.message.m_names .content { color: #03a9f4; font-weight: bold; } diff --git a/public/js/main.js b/public/js/main.js index 98669c7..7ed4141 100644 --- a/public/js/main.js +++ b/public/js/main.js @@ -367,7 +367,7 @@ let commands = { } else if(buffer.type != "channel") { handler.commandError(buffer, listargs[0].toUpperCase()+': Buffer is not a channel.'); } else if(listargs[1]) { - if(listargs[1].indexOf('#')) { + if(listargs[1].indexOf('#') != -1) { let msg = ""; if(listargs[2]) msg = listargs.slice(2).join(" "); @@ -382,17 +382,46 @@ let commands = { } }, description: "[<#channel>|] [message] - Leave the channel. If no channel specified, leave the current buffer.", aliases: ['leave']}, + topic: {execute: function(buffer, handler, command, message, listargs) { + if (!listargs[1] && buffer.type == "channel") { + irc.socket.emit("userinput", {command: "topic", server: buffer.server, message: "", arguments: [buffer.name]}); + } else if(buffer.type != "channel") { + handler.commandError(buffer, listargs[0].toUpperCase()+': Buffer is not a channel.'); + } else if(listargs[1]) { + if(listargs[1].indexOf('#') != -1) { + let msg = ""; + if(listargs[2]) + msg = listargs.slice(2).join(" "); + irc.socket.emit("userinput", {command: "topic", server: buffer.server, message: msg, arguments: [listargs[1]]}); + } else { + if(buffer.type == "channel") { + irc.socket.emit("userinput", {command: "topic", server: buffer.server, message: listargs.slice(1).join(" "), arguments: [buffer.name]}); + } else { + handler.commandError(buffer, listargs[0].toUpperCase()+': Buffer is not a channel.'); + } + } + } + }, description: "[<#channel>|] [topic] - Sets/prints the current topic of the channel.", aliases: ['t']}, + + kick: {execute: function(buffer, handler, command, message, listargs) { + if(buffer.type != "channel") + return handler.commandError(buffer, listargs[0].toUpperCase()+': Buffer is not a channel!'); + if(!listargs[1]) + return handler.commandError(buffer, listargs[0].toUpperCase()+': Missing parameter !'); + irc.socket.emit("userinput", {command: "kick", server: buffer.server, message: listargs.slice(2).join(" "), arguments: [buffer.name, listargs[1]]}); + }, description: " - Kick the following user from the channel."}, + quit: {execute: function(buffer, handler, command, message, listargs) { irc.socket.emit("userinput", {command: "quit", server: buffer.server, message: listargs.slice(1).join(" "), arguments: []}); }, description: "[] - Quit the current server with message.", aliases: ['exit']}, - privmsg: {execute: function(buffer, handler, command, message, listargs) { + msg: {execute: function(buffer, handler, command, message, listargs) { if(!listargs[1] || !listargs[2]) return handler.commandError(buffer, listargs[0].toUpperCase()+': Missing parameters!'); if(listargs[1] == '*') listargs[1] = buffer.name; irc.socket.emit("userinput", {command: "privmsg", server: buffer.server, message: listargs.slice(2).join(" "), arguments: [listargs[1]]}); - }, description: " - Sends a message to target.", aliases: ['msg', 'q', 'query', 'say']}, + }, description: " - Sends a message to target.", aliases: ['privmsg', 'q', 'query', 'say']}, notice: {execute: function(buffer, handler, command, message, listargs) { if(!listargs[1] || !listargs[2]) @@ -410,6 +439,32 @@ let commands = { irc.socket.emit("userinput", {command: "list", server: buffer.server, message: "", arguments: listargs.splice(1)}); }, description: "- List all channels on the current server."}, + nick: {execute: function(buffer, handler, command, message, listargs) { + if(!listargs[1]) { + if(buffer.server != '') { + let mynick = irc.serverData[buffer.server].my_nick; + buffer.addMessage("Your nickname is: "+mynick+"", null, "help"); + } + return; + } + irc.socket.emit("userinput", {command: "nick", server: buffer.server, message: "", arguments: listargs.splice(1)}); + }, description: "- List all channels on the current server.", aliases: ['nickname']}, + + names: {execute: function(buffer, handler, command, message, listargs) { + let channel = ""; + if(!listargs[1]) { + if(buffer.type == 'channel') + channel = buffer.name; + else + return handler.commandError(buffer, '/'+cmd.toUpperCase()+': Buffer is not a channel!'); + } else if(listargs[1].indexOf('#') == 0) { + channel = listargs[1]; + } else { + return handler.commandError(buffer, '/'+cmd.toUpperCase()+': Invalid channel name!'); + } + irc.socket.emit("userinput", {command: "names", server: buffer.server, message: "", arguments: [channel]}); + }, description: "- List all users on the current channel.", aliases: ['nicknames']}, + quote: {execute: function(buffer, handler, command, message, listargs) { irc.socket.emit("userinput", {command: listargs[1], server: buffer.server, message: listargs.slice(2).join(" "), arguments: listargs.splice(2)}); }, description: " [args] - Send a raw command to the server.", aliases: ['raw']}, @@ -457,7 +512,11 @@ let commands = { handler.commandError(buffer, '/'+cmd.toUpperCase()+': Unknown command!'); } } - }, description: " - Display help for command"} + }, description: " - Display help for command"}, + + clear: {execute: function(buffer, handler, command, message, listargs) { + buffer.clearMessages(); + }, description: "- Clears the current buffer."} } /*********************\ @@ -781,12 +840,20 @@ class Buffer { } } + clearMessages() { + this.messages = []; + + if(this.active) + clientdom.letterbox.innerHTML = ""; + } + appendMessage(meta) { let mesgConstr = composer.message[irc.chatType](meta.time, meta.sender, meta.message, meta.type); if(irc.serverData[this.server]) { + let mynick = irc.serverData[this.server].my_nick; if((meta.type == "privmsg" || meta.type == "notice" || meta.type == "action") && - meta.message.indexOf(irc.serverData[this.server].my_nick) != -1) + meta.message.toLowerCase().indexOf(mynick.toLowerCase()) != -1 && meta.sender != mynick) addClass(mesgConstr, "mentioned"); } @@ -819,8 +886,9 @@ class Buffer { } else { this.unreadCount += 1; if(irc.serverData[this.server]) { + let mynick = irc.serverData[this.server].my_nick; if((type == "privmsg" || type == "notice" || type == "action") && - message.indexOf(irc.serverData[this.server].my_nick) != -1) + message.toLowerCase().indexOf(mynick.toLowerCase()) != -1 && sender != mynick) console.log("TODO: notify user of mentioned"); } } @@ -1120,10 +1188,9 @@ class InputHandler { this.historyCaret = 0; this.searchNicknames = []; - this.i = -1; + this.index = -1; this.words = []; this.last = ""; - this.backspace = false; clientdom.input.onkeyup = (evt) => { let key = evt.keyCode || evt.which || evt.charCode || 0; @@ -1161,12 +1228,9 @@ class InputHandler { if (clientdom.input.selectionStart == input.length && word.length) { // Call the match() function to filter the words. this.tabWords = match(word, this.searchNicknames); - for(let n in this.tabWords) - this.tabWords[n] += ": "; - } - - if (this.backspace) { - this.backspace = false; + if(input.indexOf(word) == 0) + for(let n in this.tabWords) + this.tabWords[n] += ": "; } } @@ -1236,8 +1300,7 @@ class InputHandler { } else if(key == 8) { this.index = -1; this.lastWord = ""; - this.backspace = true; - + return; } } @@ -1480,6 +1543,8 @@ class IRCChatWindow { if(buf == null) return; + let channelSendNicks = []; + for(let n in nicks) { let nick = {nickname: "", prefix: "", modes: []}; @@ -1487,13 +1552,17 @@ class IRCChatWindow { nick.prefix = nicks[n].substring(0, 1); nick.nickname = nicks[n].substring(1); nick.modes = [objectGetKey(irc.serverData[buf.server].modeTranslation, nick.prefix)]; + channelSendNicks.push("{0}{1}".format(nick.prefix, nick.nickname)); } else { nick.nickname = nicks[n]; + channelSendNicks.push("{1}".format(nick.prefix, nick.nickname)); } buf.nicklist.nickAddObject(nick); } + buf.addMessage("Nicks {0}: {1}".format(channel, channelSendNicks.join(', ')), null, "names"); + if(buf.active) buf.nicklist.render(); } @@ -1518,7 +1587,7 @@ class IRCChatWindow { if(buffer.nicklist.getNickIndex(oldNick) == null) continue; buffer.nicklist.nickChange(oldNick, newNick); - buffer.addMessage(oldNick+" is now known as "+newNick, null, "nick"); + buffer.addMessage("{0} is now known as {1}".format(oldNick, newNick), null, "nick"); } } @@ -1529,9 +1598,10 @@ class IRCChatWindow { buf.topicChange(topic); if(changer) - buf.addMessage(changer+" set the topic of "+channel+ " to \""+topic+"\"", null, "topic"); + buf.addMessage("{0} has changed the topic of {1} to \"{2}\"".format(changer, channel, topic), + null, "topic"); else - buf.addMessage("Topic of "+channel+ " is \""+topic+"\"", null, "topic"); + buf.addMessage("Topic of {0} is \"{1}\"".format(channel, topic), null, "topic"); } handleQuit(server, user, reason) { @@ -1544,8 +1614,8 @@ class IRCChatWindow { if(buffer.nicklist.getNickIndex(user.nickname) == null) continue; buffer.nicklist.nickRemove(user.nickname); - buffer.addMessage(""+user.username+"@"+user.hostname+ - " has quit "+reason+"", user.nickname, "quit"); + buffer.addMessage("{0}@{1} has quit {2}".format(user.username, + user.hostname, reason), user.nickname, "quit"); } } @@ -1557,7 +1627,8 @@ class IRCChatWindow { if(user.nickname == irc.serverData[server].my_nick) buffer.setAliveStatus(true); - buffer.addMessage(""+user.username+"@"+user.hostname+" has joined "+channel, user.nickname, "join"); + buffer.addMessage("{0}@{1} has joined {2}".format(user.username, + user.hostname, channel), user.nickname, "join"); buffer.nicklist.nickAdd(user.nickname); } @@ -1575,10 +1646,10 @@ class IRCChatWindow { } if(kicker) - buffer.addMessage("has kicked "+user+" "+reason+"", kicker.nickname, "part"); + buffer.addMessage("has kicked {0} {1}".format(user, reason), kicker.nickname, "part"); else - buffer.addMessage(""+user.username+"@"+user.hostname+" has left "+ - channel+(reason != null ? " "+reason+"" : ""), user.nickname, "part"); + buffer.addMessage("{0}@{1} has left {2}{3}".format(user.username, + user.hostname, (reason != null ? " "+reason+"" : "")), user.nickname, "part"); if(kicker) buffer.nicklist.nickRemove(user); else @@ -1596,15 +1667,15 @@ class IRCChatWindow { if(data.type == "mode_add") { buf.nicklist.modeAdded(data.modeTarget, data.mode); - buf.addMessage("set mode "+data.target+" +"+data.mode+" "+ - data.modeTarget+"", data.user.nickname, "mode"); + buf.addMessage("set mode {0} +{1} {2}".format(data.target, + data.mode, data.modeTarget), data.user.nickname, "mode"); } else if(data.type == "mode_del") { buf.nicklist.modeRemoved(data.modeTarget, data.mode); - buf.addMessage("set mode "+data.target+" -"+data.mode+" "+ - data.modeTarget+"", data.user.nickname, "mode"); + buf.addMessage("set mode {0} -{1} {2}".format(data.target, + data.mode, data.modeTarget), data.user.nickname, "mode"); } else { - buf.addMessage("set mode "+data.target+" "+data.message+"", - data.user.nickname, "mode"); + buf.addMessage("set mode {0} {1}".format(data.target, + data.message), data.user.nickname, "mode"); } } diff --git a/public/main.styl b/public/main.styl index a507c71..e00761a 100644 --- a/public/main.styl +++ b/public/main.styl @@ -383,7 +383,7 @@ body color: red; &.m_join color: green; - &.m_topic .content + &.m_topic .content, &.m_names .content color: #03A9F4; font-weight: bold; &.m_motd .content diff --git a/server/irc.js b/server/irc.js index 2fb76f4..01fc57b 100644 --- a/server/irc.js +++ b/server/irc.js @@ -21,13 +21,19 @@ class IRCConnectionHandler { handleUserLine(data) { switch(data.command) { + case "topic": + this.conn.write(('{0} {1}'+(data.message != '' ? ' :'+data.message : '')).format(data.command.toUpperCase(), data.arguments[0])); + break; case "kick": + this.conn.write('{0} {1} :{2}'.format(data.command.toUpperCase(), data.arguments.join(' '), data.message)); + break; case "part": this.conn.write('{0} {1} :{2}'.format(data.command.toUpperCase(), data.arguments[0], data.message)); break; case "nick": case "whois": case "who": + case "names": case "join": this.conn.write('{0} {1}'.format(data.command.toUpperCase(), data.arguments[0])); break; @@ -214,6 +220,15 @@ class IRCConnectionHandler { case "042": this.conn.emit('pass_to_client', {type: "server_message", messageType: "regular", message: line.arguments[1] +" "+ line.trailing, server: serverName, from: realServerName}); break; + case "401": + case "402": + case "421": + case "482": + case "331": + case "432": + this.conn.emit('pass_to_client', {type: "message", to: null, message: line.arguments[1]+': '+line.trailing, + server: serverName, user: {nickname: realServerName}, messageType: "error"}); + break; case "MODE": let isChannelMode = false; let method = '+'; @@ -247,13 +262,6 @@ class IRCConnectionHandler { this.conn.write('NICK '+newNick); this.conn.config.nickname = newNick; break; - case "401": - case "402": - case "421": - case "432": - this.conn.emit('pass_to_client', {type: "message", to: null, message: line.arguments[1]+': '+line.trailing, - server: serverName, user: {nickname: realServerName}, messageType: "error"}); - break; case "311": // start whois queue list = {