Commit | Line | Data |
---|---|---|
f4f7781b JA |
1 | /*jslint regexp: true, confusion: true, undef: false, node: true, sloppy: true, nomen: true, plusplus: true, maxerr: 50, indent: 4 */ |
2 | ||
68ad40c6 | 3 | var tls = require('tls'), |
c6b5e668 | 4 | net = require('net'), |
68ad40c6 | 5 | http = require('http'), |
09365139 | 6 | https = require('https'), |
1eaf214f | 7 | fs = require('fs'), |
7d1c3ee9 | 8 | url = require('url'), |
c6b5e668 | 9 | ws = require('socket.io'), |
4136eb38 JA |
10 | _ = require('./lib/underscore.min.js'), |
11 | starttls = require('./lib/starttls.js'); | |
c6b5e668 | 12 | |
4a30a583 | 13 | |
14 | /* | |
15 | * Find a config file in the following order: | |
16 | * - /etc/kiwi/config.json | |
17 | * - ./config.json | |
18 | */ | |
19 | var config = null, config_filename = 'config.json'; | |
20 | var config_dirs = ['/etc/kiwiirc/', __dirname + '/']; | |
21 | for(var i in config_dirs){ | |
22 | try { | |
23 | if(fs.lstatSync(config_dirs[i] + config_filename).isDirectory() === false){ | |
24 | config = JSON.parse(fs.readFileSync(config_dirs[i] + config_filename, 'ascii')); | |
25 | console.log('Using config file ' + config_dirs[i] + config_filename); | |
26 | break; | |
27 | } | |
28 | } catch(e){ | |
29 | continue; | |
30 | } | |
31 | } | |
32 | ||
33 | if(config === null){ | |
34 | console.log('Couldn\'t find a config file!'); | |
35 | process.exit(0); | |
36 | } | |
37 | ||
38 | ||
39 | ||
40 | ||
41 | /* | |
42 | * Some process changes | |
43 | */ | |
44 | process.title = 'kiwiirc'; | |
45 | function changeUser(){ | |
46 | if(typeof config.group !== 'undefined' && config.group !== ''){ | |
47 | try { | |
48 | process.setgid(config.group); | |
49 | } | |
50 | catch (err) { | |
51 | console.log('Failed to set gid: ' + err); | |
52 | process.exit(); | |
53 | } | |
54 | } | |
55 | ||
56 | if(typeof config.user !== 'undefined' && config.user !== ''){ | |
57 | try { | |
58 | process.setuid(config.user); | |
59 | } | |
60 | catch (err) { | |
61 | console.log('Failed to set uid: ' + err); | |
62 | process.exit(); | |
63 | } | |
64 | } | |
65 | } | |
66 | ||
67 | ||
68 | /* | |
69 | * And now KiwiIRC, the server :) | |
70 | */ | |
1eaf214f | 71 | |
c6b5e668 | 72 | var ircNumerics = { |
bad1ea63 JA |
73 | RPL_WELCOME: '001', |
74 | RPL_ISUPPORT: '005', | |
75 | RPL_WHOISUSER: '311', | |
76 | RPL_WHOISSERVER: '312', | |
77 | RPL_WHOISOPERATOR: '313', | |
78 | RPL_WHOISIDLE: '317', | |
79 | RPL_ENDOFWHOIS: '318', | |
80 | RPL_WHOISCHANNELS: '319', | |
81 | RPL_TOPIC: '332', | |
82 | RPL_NAMEREPLY: '353', | |
83 | RPL_ENDOFNAMES: '366', | |
84 | RPL_MOTD: '372', | |
85 | RPL_WHOISMODES: '379', | |
86 | ERR_NOSUCHNICK: '401', | |
4136eb38 JA |
87 | ERR_LINKCHANNEL: '470', |
88 | RPL_STARTTLS: '670' | |
c6b5e668 JA |
89 | }; |
90 | ||
91 | ||
92 | var parseIRCMessage = function (websocket, ircSocket, data) { | |
4136eb38 | 93 | /*global ircSocketDataHandler */ |
0c5e2aaa | 94 | var msg, regex, opts, options, opt, i, j, matches, nick, users, chan, params, prefix, prefixes, nicklist, caps, rtn; |
c6b5e668 JA |
95 | regex = /^(?::(?:([a-z0-9\x5B-\x60\x7B-\x7D\.\-]+)|([a-z0-9\x5B-\x60\x7B-\x7D\.\-]+)!([a-z0-9~\.\-_|]+)@([a-z0-9\.\-:]+)) )?([a-z0-9]+)(?:(?: ([^:]+))?(?: :(.+))?)$/i; |
96 | msg = regex.exec(data); | |
97 | if (msg) { | |
98 | msg = { | |
99 | prefix: msg[1], | |
100 | nick: msg[2], | |
101 | ident: msg[3], | |
102 | hostname: msg[4], | |
103 | command: msg[5], | |
104 | params: msg[6] || '', | |
105 | trailing: (msg[7]) ? msg[7].trim() : '' | |
106 | }; | |
107 | switch (msg.command.toUpperCase()) { | |
108 | case 'PING': | |
109 | ircSocket.write('PONG ' + msg.trailing + '\r\n'); | |
110 | break; | |
bad1ea63 | 111 | case ircNumerics.RPL_WELCOME: |
4136eb38 JA |
112 | if (ircSocket.IRC.CAP.negotiating) { |
113 | ircSocket.IRC.CAP.negotiating = false; | |
114 | ircSocket.IRC.CAP.enabled = []; | |
115 | ircSocket.IRC.CAP.requested = []; | |
116 | } | |
c6b5e668 JA |
117 | websocket.emit('message', {event: 'connect', connected: true, host: null}); |
118 | break; | |
bad1ea63 | 119 | case ircNumerics.RPL_ISUPPORT: |
c6b5e668 JA |
120 | opts = msg.params.split(" "); |
121 | options = []; | |
122 | for (i = 0; i < opts.length; i++) { | |
123 | opt = opts[i].split("=", 2); | |
124 | opt[0] = opt[0].toUpperCase(); | |
bad1ea63 | 125 | ircSocket.IRC.options[opt[0]] = opt[1] || true; |
c6b5e668 JA |
126 | if (_.include(['NETWORK', 'PREFIX', 'CHANTYPES'], opt[0])) { |
127 | if (opt[0] === 'PREFIX') { | |
128 | regex = /\(([^)]*)\)(.*)/; | |
129 | matches = regex.exec(opt[1]); | |
130 | if ((matches) && (matches.length === 3)) { | |
020ec63b | 131 | ircSocket.IRC.options[opt[0]] = []; |
c6b5e668 | 132 | for (j = 0; j < matches[2].length; j++) { |
020ec63b | 133 | //ircSocket.IRC.options[opt[0]][matches[2].charAt(j)] = matches[1].charAt(j); |
134 | ircSocket.IRC.options[opt[0]].push({symbol: matches[2].charAt(j), mode: matches[1].charAt(j)}); | |
135 | //console.log({symbol: matches[2].charAt(j), mode: matches[1].charAt(j)}); | |
c6b5e668 | 136 | } |
020ec63b | 137 | console.log(ircSocket.IRC.options); |
c6b5e668 JA |
138 | } |
139 | } | |
140 | } | |
141 | } | |
0417bcfa | 142 | websocket.emit('message', {event: 'options', server: '', "options": ircSocket.IRC.options}); |
c6b5e668 JA |
143 | break; |
144 | case ircNumerics.RPL_WHOISUSER: | |
145 | case ircNumerics.RPL_WHOISSERVER: | |
146 | case ircNumerics.RPL_WHOISOPERATOR: | |
c6b5e668 JA |
147 | case ircNumerics.RPL_ENDOFWHOIS: |
148 | case ircNumerics.RPL_WHOISCHANNELS: | |
149 | case ircNumerics.RPL_WHOISMODES: | |
150 | websocket.emit('message', {event: 'whois', server: '', nick: msg.params.split(" ", 3)[1], "msg": msg.trailing}); | |
151 | break; | |
eedf3f38 | 152 | case ircNumerics.RPL_WHOISIDLE: |
0c5e2aaa JA |
153 | params = msg.params.split(" ", 4); |
154 | rtn = {event: 'whois', server: '', nick: params[1], idle: params[2]}; | |
155 | if (params[3]) { | |
156 | rtn.logon = params[3]; | |
157 | } | |
158 | websocket.emit('message', rtn); | |
159 | break; | |
c6b5e668 JA |
160 | case ircNumerics.RPL_MOTD: |
161 | websocket.emit('message', {event: 'motd', server: '', "msg": msg.trailing}); | |
162 | break; | |
163 | case ircNumerics.RPL_NAMEREPLY: | |
164 | params = msg.params.split(" "); | |
165 | nick = params[0]; | |
166 | chan = params[2]; | |
167 | users = msg.trailing.split(" "); | |
bad1ea63 JA |
168 | prefixes = _.values(ircSocket.IRC.options.PREFIX); |
169 | nicklist = {}; | |
170 | i = 0; | |
c6b5e668 JA |
171 | _.each(users, function (user) { |
172 | if (_.include(prefix, user.charAt(0))) { | |
173 | prefix = user.charAt(0); | |
174 | user = user.substring(1); | |
175 | nicklist[user] = prefix; | |
bad1ea63 JA |
176 | } else { |
177 | nicklist[user] = ''; | |
c6b5e668 | 178 | } |
bad1ea63 | 179 | if (i++ >= 50) { |
c6b5e668 JA |
180 | websocket.emit('message', {event: 'userlist', server: '', "users": nicklist, channel: chan}); |
181 | nicklist = {}; | |
182 | i = 0; | |
183 | } | |
c6b5e668 | 184 | }); |
bad1ea63 | 185 | if (i > 0) { |
c6b5e668 | 186 | websocket.emit('message', {event: 'userlist', server: '', "users": nicklist, channel: chan}); |
bad1ea63 JA |
187 | } else { |
188 | console.log("oops"); | |
c6b5e668 JA |
189 | } |
190 | break; | |
bad1ea63 JA |
191 | case ircNumerics.RPL_ENDOFNAMES: |
192 | websocket.emit('message', {event: 'userlist_end', server: '', channel: msg.params.split(" ")[1]}); | |
193 | break; | |
194 | case ircNumerics.ERR_LINKCHANNEL: | |
195 | params = msg.params.split(" "); | |
196 | websocket.emit('message', {event: 'channel_redirect', from: params[1], to: params[2]}); | |
197 | break; | |
198 | case ircNumerics.ERR_NOSUCHNICK: | |
199 | //TODO: shit | |
200 | break; | |
201 | case 'JOIN': | |
202 | websocket.emit('message', {event: 'join', nick: msg.nick, ident: msg.ident, hostname: msg.hostname, channel: msg.trailing}); | |
203 | if (msg.nick === ircSocket.IRC.nick) { | |
204 | ircSocket.write('NAMES ' + msg.trailing + '\r\n'); | |
205 | } | |
206 | break; | |
207 | case 'PART': | |
208 | websocket.emit('message', {event: 'part', nick: msg.nick, ident: msg.ident, hostname: msg.hostname, channel: msg.params.trim(), message: msg.trailing}); | |
209 | break; | |
210 | case 'KICK': | |
211 | params = msg.params.split(" "); | |
212 | websocket.emit('message', {event: 'kick', kicked: params[1], nick: msg.nick, ident: msg.ident, hostname: msg.hostname, channel: params[0].trim(), message: msg.trailing}); | |
213 | break; | |
214 | case 'QUIT': | |
215 | websocket.emit('message', {event: 'quit', nick: msg.nick, ident: msg.ident, hostname: msg.hostname, message: msg.trailing}); | |
216 | break; | |
217 | case 'NOTICE': | |
423a590e JA |
218 | if ((msg.trailing.charAt(0) === '\001') && (msg.trailing.charAt(msg.trailing.length - 1) === '\001')) { |
219 | // It's a CTCP response | |
220 | websocket.emit('message', {event: 'ctcp_response', nick: msg.nick, ident: msg.ident, hostname: msg.hostname, channel: msg.params.trim(), msg: msg.trailing.substr(1, msg.trailing.length - 2)}); | |
221 | } else { | |
222 | websocket.emit('message', {event: 'notice', nick: msg.nick, ident: msg.ident, hostname: msg.hostname, channel: msg.params.trim(), msg: msg.trailing}); | |
223 | } | |
bad1ea63 JA |
224 | break; |
225 | case 'NICK': | |
226 | websocket.emit('message', {event: 'nick', nick: msg.nick, ident: msg.ident, hostname: msg.hostname, newnick: msg.trailing}); | |
227 | break; | |
228 | case 'TOPIC': | |
229 | websocket.emit('message', {event: 'topic', nick: msg.nick, channel: msg.params, topic: msg.trailing}); | |
230 | break; | |
231 | case ircNumerics.RPL_TOPIC: | |
232 | websocket.emit('message', {event: 'topic', nick: '', channel: msg.params.split(" ")[1], topic: msg.trailing}); | |
233 | break; | |
234 | case 'MODE': | |
235 | opts = msg.params.split(" "); | |
236 | params = {event: 'mode', nick: msg.nick}; | |
237 | switch (opts.length) { | |
238 | case 1: | |
239 | params.effected_nick = opts[0]; | |
240 | params.mode = msg.trailing; | |
241 | break; | |
242 | case 2: | |
243 | params.channel = opts[0]; | |
244 | params.mode = opts[1]; | |
245 | break; | |
246 | default: | |
247 | params.channel = opts[0]; | |
248 | params.mode = opts[1]; | |
249 | params.effected_nick = opts[2]; | |
250 | break; | |
251 | } | |
252 | websocket.emit('message', params); | |
253 | break; | |
254 | case 'PRIVMSG': | |
423a590e JA |
255 | if ((msg.trailing.charAt(0) === '\001') && (msg.trailing.charAt(msg.trailing.length - 1) === '\001')) { |
256 | // It's a CTCP request | |
257 | if (msg.trailing.substr(1, 6) === 'ACTION') { | |
020ec63b | 258 | websocket.emit('message', {event: 'action', nick: msg.nick, ident: msg.ident, hostname: msg.hostname, channel: msg.params.trim(), msg: msg.trailing.substr(7, msg.trailing.length - 2)}); |
423a590e | 259 | } else if (msg.trailing.substr(1, 7) === 'VERSION') { |
d8568ae2 | 260 | ircSocket.write('NOTICE ' + msg.nick + ' :\001VERSION KiwiIRC\001\r\n'); |
423a590e JA |
261 | } else { |
262 | websocket.emit('message', {event: 'ctcp_request', nick: msg.nick, ident: msg.ident, hostname: msg.hostname, channel: msg.params.trim(), msg: msg.trailing.substr(1, msg.trailing.length - 2)}); | |
263 | } | |
264 | } else { | |
265 | websocket.emit('message', {event: 'msg', nick: msg.nick, ident: msg.ident, hostname: msg.hostname, channel: msg.params.trim(), msg: msg.trailing}); | |
266 | } | |
c6b5e668 | 267 | break; |
4136eb38 | 268 | case 'CAP': |
1eaf214f | 269 | caps = config.cap_options; |
4136eb38 JA |
270 | options = msg.trailing.split(" "); |
271 | switch (_.first(msg.params.split(" "))) { | |
272 | case 'LS': | |
273 | opts = ''; | |
274 | _.each(_.intersect(caps, options), function (cap) { | |
275 | if (opts !== '') { | |
276 | opts += " "; | |
277 | } | |
278 | opts += cap; | |
279 | ircSocket.IRC.CAP.requested.push(cap); | |
280 | }); | |
281 | if (opts.length > 0) { | |
282 | ircSocket.write('CAP REQ :' + opts + '\r\n'); | |
283 | } else { | |
284 | ircSocket.write('CAP END\r\n'); | |
285 | } | |
286 | // TLS is special | |
287 | /*if (_.include(options, 'tls')) { | |
288 | ircSocket.write('STARTTLS\r\n'); | |
289 | ircSocket.IRC.CAP.requested.push('tls'); | |
290 | }*/ | |
291 | break; | |
292 | case 'ACK': | |
293 | _.each(options, function (cap) { | |
294 | ircSocket.IRC.CAP.enabled.push(cap); | |
295 | }); | |
296 | if (_.last(msg.params.split(" ")) !== '*') { | |
297 | ircSocket.IRC.CAP.requested = []; | |
298 | ircSocket.IRC.CAP.negotiating = false; | |
299 | ircSocket.write('CAP END\r\n'); | |
300 | } | |
301 | break; | |
302 | case 'NAK': | |
303 | ircSocket.IRC.CAP.requested = []; | |
304 | ircSocket.IRC.CAP.negotiating = false; | |
305 | ircSocket.write('CAP END\r\n'); | |
306 | break; | |
307 | } | |
308 | break; | |
309 | /*case ircNumerics.RPL_STARTTLS: | |
310 | try { | |
311 | IRC = ircSocket.IRC; | |
312 | listeners = ircSocket.listeners('data'); | |
313 | ircSocket.removeAllListeners('data'); | |
314 | ssl_socket = starttls(ircSocket, {}, function () { | |
315 | ssl_socket.on("data", function (data) { | |
316 | ircSocketDataHandler(data, websocket, ssl_socket); | |
317 | }); | |
318 | ircSocket = ssl_socket; | |
319 | ircSocket.IRC = IRC; | |
320 | _.each(listeners, function (listener) { | |
321 | ircSocket.addListener('data', listener); | |
322 | }); | |
323 | }); | |
324 | //console.log(ircSocket); | |
325 | } catch (e) { | |
326 | console.log(e); | |
327 | } | |
328 | break;*/ | |
c6b5e668 JA |
329 | } |
330 | } else { | |
331 | console.log("Unknown command.\r\n"); | |
332 | } | |
333 | }; | |
68ad40c6 | 334 | |
4136eb38 JA |
335 | var ircSocketDataHandler = function (data, websocket, ircSocket) { |
336 | var i; | |
1eaf214f JA |
337 | if ((ircSocket.holdLast) && (ircSocket.held !== '')) { |
338 | data = ircSocket.held + data; | |
339 | ircSocket.holdLast = false; | |
340 | ircSocket.held = ''; | |
341 | } | |
0417bcfa | 342 | if (data.substr(-2) === '\r\n') { |
1eaf214f JA |
343 | ircSocket.holdLast = true; |
344 | } | |
345 | data = data.split("\r\n"); | |
4136eb38 JA |
346 | for (i = 0; i < data.length; i++) { |
347 | if (data[i]) { | |
ca5ea123 | 348 | if ((ircSocket.holdLast) && (i === data.length - 1)) { |
1eaf214f JA |
349 | ircSocket.held = data[i]; |
350 | break; | |
351 | } | |
4136eb38 JA |
352 | console.log("->" + data[i]); |
353 | parseIRCMessage(websocket, ircSocket, data[i]); | |
354 | } | |
355 | } | |
356 | }; | |
357 | ||
ceec0f93 | 358 | if (config.handle_http) { |
0c5e2aaa JA |
359 | var fileServer = new (require('node-static').Server)(__dirname + config.public_http); |
360 | var jade = require('jade'); | |
ceec0f93 | 361 | } |
7d1c3ee9 JA |
362 | |
363 | var httpHandler = function (request, response) { | |
364 | var uri, subs, useragent, agent, server_set, server, nick, debug, touchscreen; | |
365 | if (config.handle_http) { | |
366 | uri = url.parse(request.url); | |
367 | subs = uri.pathname.substr(0, 4); | |
368 | if ((subs === '/js/') || (subs === '/css') || (subs === '/img')) { | |
369 | request.addListener('end', function () { | |
370 | fileServer.serve(request, response); | |
371 | }); | |
372 | } else if (uri.pathname === '/') { | |
373 | useragent = (response.headers) ? response.headers['user-agent']: ''; | |
374 | if (useragent.indexOf('android') !== -1) { | |
375 | agent = 'android'; | |
376 | touchscreen = true; | |
377 | } else if (useragent.indexOf('iphone') !== -1) { | |
378 | agent = 'iphone'; | |
379 | touchscreen = true; | |
380 | } else if (useragent.indexOf('ipad') !== -1) { | |
381 | agent = 'ipad'; | |
382 | touchscreen = true; | |
383 | } else if (useragent.indexOf('ipod') !== -1) { | |
384 | agent = 'ipod'; | |
385 | touchscreen = true; | |
386 | } else { | |
387 | agent = 'normal'; | |
388 | touchscreen = false; | |
389 | } | |
390 | if (uri.query) { | |
391 | server_set = (uri.query.server !== ''); | |
392 | server = uri.query.server || 'irc.anonnet.org'; | |
393 | nick = uri.query.nick || ''; | |
394 | debug = (uri.query.debug !== ''); | |
395 | } else { | |
396 | server = 'irc.anonnet.org'; | |
397 | nick = ''; | |
398 | } | |
399 | response.setHeader('Connection', 'close'); | |
400 | response.setHeader('X-Generated-By', 'KiwiIRC'); | |
401 | jade.renderFile(__dirname + '/client/index.html.jade', { locals: { "touchscreen": touchscreen, "debug": debug, "server_set": server_set, "server": server, "nick": nick, "agent": agent, "config": config }}, function (err, html) { | |
402 | if (!err) { | |
403 | response.write(html); | |
404 | } else { | |
405 | response.statusCode = 500; | |
406 | } | |
407 | response.end(); | |
408 | }); | |
409 | } else if (uri.pathname.substr(0, 10) === '/socket.io') { | |
410 | // Do nothing! | |
411 | } else { | |
412 | response.statusCode = 404; | |
413 | response.end(); | |
414 | } | |
415 | } | |
416 | }; | |
417 | ||
68ad40c6 | 418 | //setup websocket listener |
1eaf214f | 419 | if (config.listen_ssl) { |
7d1c3ee9 | 420 | var httpServer = https.createServer({key: fs.readFileSync(__dirname + '/' + config.ssl_key), cert: fs.readFileSync(__dirname + '/' + config.ssl_cert)}, httpHandler); |
09365139 JA |
421 | var io = ws.listen(httpServer, {secure: true}); |
422 | httpServer.listen(config.port, config.bind_address); | |
1eaf214f | 423 | } else { |
7d1c3ee9 | 424 | var httpServer = http.createServer(httpHandler); |
09365139 JA |
425 | var io = ws.listen(httpServer, {secure: false}); |
426 | httpServer.listen(config.port, config.bind_address); | |
1eaf214f | 427 | } |
4a30a583 | 428 | |
429 | // Now we're listening on the network, set our UID/GIDs if required | |
430 | changeUser(); | |
431 | ||
7d1c3ee9 | 432 | io.of('/kiwi').on('connection', function (websocket) { |
c6b5e668 | 433 | websocket.on('irc connect', function (nick, host, port, ssl, callback) { |
4136eb38 | 434 | var ircSocket; |
68ad40c6 | 435 | //setup IRC connection |
c6b5e668 JA |
436 | if (!ssl) { |
437 | ircSocket = net.createConnection(port, host); | |
438 | } else { | |
439 | ircSocket = tls.connect(port, host); | |
68ad40c6 JA |
440 | } |
441 | ircSocket.setEncoding('ascii'); | |
4136eb38 | 442 | ircSocket.IRC = {options: {}, CAP: {negotiating: true, requested: [], enabled: []}}; |
bad1ea63 | 443 | websocket.ircSocket = ircSocket; |
0417bcfa JA |
444 | ircSocket.holdLast = false; |
445 | ircSocket.held = ''; | |
68ad40c6 | 446 | |
c6b5e668 | 447 | ircSocket.on('data', function (data) { |
4136eb38 | 448 | ircSocketDataHandler(data, websocket, ircSocket); |
68ad40c6 JA |
449 | }); |
450 | ||
bad1ea63 | 451 | ircSocket.IRC.nick = nick; |
68ad40c6 | 452 | // Send the login data |
4136eb38 | 453 | ircSocket.write('CAP LS\r\n'); |
c6b5e668 JA |
454 | ircSocket.write('NICK ' + nick + '\r\n'); |
455 | ircSocket.write('USER ' + nick + '_kiwi 0 0 :' + nick + '\r\n'); | |
68ad40c6 | 456 | |
c6b5e668 | 457 | if ((callback) && (typeof (callback) === 'function')) { |
68ad40c6 JA |
458 | callback(); |
459 | } | |
460 | }); | |
c6b5e668 | 461 | websocket.on('message', function (msg, callback) { |
bad1ea63 | 462 | var args; |
f4f7781b JA |
463 | try { |
464 | msg.data = JSON.parse(msg.data); | |
465 | args = msg.data.args; | |
466 | switch (msg.data.method) { | |
467 | case 'msg': | |
468 | if ((args.target) && (args.msg)) { | |
469 | websocket.ircSocket.write('PRIVMSG ' + args.target + ' :' + args.msg + '\r\n'); | |
470 | } | |
471 | break; | |
472 | case 'action': | |
473 | if ((args.target) && (args.msg)) { | |
474 | websocket.ircSocket.write('PRIVMSG ' + args.target + ' :\ 1ACTION ' + args.msg + '\ 1\r\n'); | |
475 | } | |
476 | break; | |
477 | case 'raw': | |
478 | websocket.ircSocket.write(args.data + '\r\n'); | |
479 | break; | |
480 | case 'join': | |
481 | if (args.channel) { | |
482 | _.each(args.channel.split(","), function (chan) { | |
483 | websocket.ircSocket.write('JOIN ' + chan + '\r\n'); | |
484 | }); | |
485 | } | |
486 | break; | |
487 | case 'quit': | |
488 | websocket.ircSocket.end('QUIT :' + args.message + '\r\n'); | |
489 | websocket.sentQUIT = true; | |
490 | websocket.ircSocket.destroySoon(); | |
491 | websocket.disconnect(); | |
492 | break; | |
e36e767b D |
493 | case 'notice': |
494 | if ((args.target) && (args.msg)) { | |
495 | websocket.ircSocket.write('NOTICE ' + args.target + ' :' + args.msg + '\r\n'); | |
496 | } | |
497 | break; | |
f4f7781b | 498 | default: |
bad1ea63 | 499 | } |
f4f7781b JA |
500 | if ((callback) && (typeof (callback) === 'function')) { |
501 | callback(); | |
bad1ea63 | 502 | } |
f4f7781b JA |
503 | } catch (e) { |
504 | console.log("Caught error: " + e); | |
bad1ea63 | 505 | } |
f4f7781b JA |
506 | }); |
507 | websocket.on('disconnect', function () { | |
508 | if ((!websocket.sentQUIT) && (websocket.ircSocket)) { | |
02a9f7e8 | 509 | websocket.ircSocket.end('QUIT :' + config.quit_message + '\r\n'); |
f4f7781b JA |
510 | websocket.sentQUIT = true; |
511 | websocket.ircSocket.destroySoon(); | |
68ad40c6 JA |
512 | } |
513 | }); | |
514 | }); | |
c6b5e668 | 515 |