From 233a9aef72f969d6c146164329b957d6f6ff2f67 Mon Sep 17 00:00:00 2001 From: Sheogorath Date: Wed, 17 Jul 2019 12:14:05 +0200 Subject: [PATCH 1/2] Add concept of channels and allow users to create them --- src/channel.js | 11 +++++++++++ src/server.js | 8 ++++++++ src/user.js | 3 +++ test/command_join.js | 28 ++++++++++++++++++++++++++++ 4 files changed, 50 insertions(+) create mode 100644 src/channel.js create mode 100644 test/command_join.js diff --git a/src/channel.js b/src/channel.js new file mode 100644 index 0000000..4eab6ae --- /dev/null +++ b/src/channel.js @@ -0,0 +1,11 @@ +function Channel(name) { + this.name = name + this.userlist = [] + + this.join = function(user) { + this.userlist.push(user) + user.sendRaw(`:${user.nickname} JOIN ${this.name}`) + } +} + +module.exports = Channel diff --git a/src/server.js b/src/server.js index 988abd9..46d25fb 100644 --- a/src/server.js +++ b/src/server.js @@ -1,5 +1,6 @@ const net = require("net") const User = require("../src/user.js") +const Channel = require("../src/channel.js") const RPL_WELCOME = '001' const ERR_NOSUCHNICK = '401' @@ -20,6 +21,7 @@ server.create = function create(config = {}) { password = config.password } let userlist = {} + let channellist = {} let server = net.createServer((socket) => { const user = new User(socket) if (!config.password) { @@ -85,6 +87,12 @@ server.create = function create(config = {}) { } break; + case "JOIN": + let channelname = tokenized[1] + let channel = new Channel(channelname) + channel.join(user) + channellist[channelname] = channel + break; case "QUIT": server.closeConnection(user.nickname) break; diff --git a/src/user.js b/src/user.js index b54678e..a9b454f 100644 --- a/src/user.js +++ b/src/user.js @@ -44,6 +44,9 @@ function User(socket) { this.sendMsg = function (from, message) { this.connection.write(`:${from.nickname} PRIVMSG ${this.nickname} :${message}\r\n`, "ascii") } + this.sendRaw = function(message) { + this.connection.write(`${message}\r\n`, "ascii") + } } module.exports = User diff --git a/test/command_join.js b/test/command_join.js new file mode 100644 index 0000000..da2a65a --- /dev/null +++ b/test/command_join.js @@ -0,0 +1,28 @@ +const assert = require('assert'); +const EventEmitter = require('events'); +const IRCServer = require("../src/server.js"); + +describe("JOIN OK", function () { + it("should handle a JOIN command -> JOIN #testchan", function (done) { + const server = IRCServer.create() + let mockedSock = new EventEmitter() + mockedSock.address = function () { + return {port: 12346, family: 'IPv4', address: '127.0.0.1'} + } + mockedSock.write = function (data) { + let answer = data.toString("ascii") + if (answer.indexOf("JOIN") >= 0) { + assert.equal(answer, ":some_nick JOIN #testchan\r\n") + done() + } + } + mockedSock.destroy = function () { + done("Destroyed socket without answering") + } + + server.emit("connection", mockedSock) + mockedSock.emit('data', Buffer.from("NICK some_nick\r\n", "ascii")) + mockedSock.emit('data', Buffer.from("USER guest tolmoon tolsun :Ronnie Reagan\r\n", "ascii")) + mockedSock.emit('data', Buffer.from("JOIN #testchan\r\n", "ascii")) + }) +}) From 394384689b7d8467c5b4a96cd187499bebb33d3e Mon Sep 17 00:00:00 2001 From: Sheogorath Date: Wed, 17 Jul 2019 12:39:19 +0200 Subject: [PATCH 2/2] Add ability to join channel with multiple users Joining channels allone is nice, but defeats the purpose of channels. This patch adds the ability to join a channel with multiple users. --- src/channel.js | 5 ++++- src/server.js | 11 ++++++++--- test/command_join.js | 44 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 4 deletions(-) diff --git a/src/channel.js b/src/channel.js index 4eab6ae..f4d82f3 100644 --- a/src/channel.js +++ b/src/channel.js @@ -3,8 +3,11 @@ function Channel(name) { this.userlist = [] this.join = function(user) { + let channel = this this.userlist.push(user) - user.sendRaw(`:${user.nickname} JOIN ${this.name}`) + this.userlist.forEach(function(item) { + item.sendRaw(`:${user.nickname} JOIN ${channel.name}`) + }) } } diff --git a/src/server.js b/src/server.js index 46d25fb..63e8fc3 100644 --- a/src/server.js +++ b/src/server.js @@ -89,9 +89,14 @@ server.create = function create(config = {}) { break; case "JOIN": let channelname = tokenized[1] - let channel = new Channel(channelname) - channel.join(user) - channellist[channelname] = channel + if (Object.keys(channellist).includes(channelname)) { + channellist[channelname].join(user) + } else { + let channel = new Channel(channelname) + channel.join(user) + channellist[channelname] = channel + } + break; case "QUIT": server.closeConnection(user.nickname) diff --git a/test/command_join.js b/test/command_join.js index da2a65a..6ea8ac3 100644 --- a/test/command_join.js +++ b/test/command_join.js @@ -25,4 +25,48 @@ describe("JOIN OK", function () { mockedSock.emit('data', Buffer.from("USER guest tolmoon tolsun :Ronnie Reagan\r\n", "ascii")) mockedSock.emit('data', Buffer.from("JOIN #testchan\r\n", "ascii")) }) + + it("should handle a JOIN command for more than one user -> JOIN #testchan and send join events to all channel members", function (done) { + const server = IRCServer.create() + // helper to count join messages for channel + // we should see 2 of them + let counter = 0 + let mockedSock1 = new EventEmitter() + mockedSock1.address = function () { + return {port: 12346, family: 'IPv4', address: '127.0.0.1'} + } + mockedSock1.write = function (data) { + let answer = data.toString("ascii") + if (answer.indexOf("JOIN") >= 0 && counter === 1) { + assert.equal(answer, ":other_nick JOIN #testchan\r\n") + done() + } + if (answer === ":some_nick JOIN #testchan\r\n") { + counter++ + } + } + mockedSock1.destroy = function () { + done("Destroyed socket without answering") + } + + let mockedSock2 = new EventEmitter() + mockedSock2.address = function () { + return {port: 12346, family: 'IPv4', address: '127.0.0.1'} + } + mockedSock2.write = function (data) { + return + } + mockedSock2.destroy = function () { + done("Destroyed socket without answering") + } + + server.emit("connection", mockedSock1) + server.emit("connection", mockedSock2) + mockedSock1.emit('data', Buffer.from("NICK some_nick\r\n", "ascii")) + mockedSock1.emit('data', Buffer.from("USER guest tolmoon tolsun :Ronnie Reagan\r\n", "ascii")) + mockedSock1.emit('data', Buffer.from("JOIN #testchan\r\n", "ascii")) + mockedSock2.emit('data', Buffer.from("NICK other_nick\r\n", "ascii")) + mockedSock2.emit('data', Buffer.from("USER guest tolmoon tolsun :Ronnie Reagan\r\n", "ascii")) + mockedSock2.emit('data', Buffer.from("JOIN #testchan\r\n", "ascii")) + }) })