Close socket to IRC server on websocket disconnect
[KiwiIRC.git] / server / client.js
1 var util = require('util'),
2 events = require('events'),
3 IRCConnection = require('./irc-connection.js').IRCConnection;
4 IRCCommands = require('./irc-commands.js');
5
6 var Client = function (websocket) {
7 var c = this;
8
9 events.EventEmitter.call(this);
10 this.websocket = websocket;
11
12 this.IRC_connections = [];
13 this.next_connection = 0;
14
15 this.buffer = {
16 list: [],
17 motd: ''
18 };
19
20 websocket.on('irc', function () {
21 IRC_command.apply(c, arguments);
22 });
23 websocket.on('kiwi', function () {
24 kiwi_command.apply(c, arguments);
25 });
26 websocket.on('disconnect', function () {
27 disconnect.apply(c, arguments);
28 });
29 websocket.on('error', function () {
30 error.apply(c, arguments);
31 });
32 };
33 util.inherits(Client, events.EventEmitter);
34
35 module.exports.Client = Client;
36
37 // Callback API:
38 // Callbacks SHALL accept 2 arguments, error and response, in that order.
39 // error MUST be null where the command is successul.
40 // error MUST otherwise be a truthy value and SHOULD be a string where the cause of the error is known.
41 // response MAY be given even if error is truthy
42
43 Client.prototype.sendIRCCommand = function (command, data, callback) {
44 var c = {command: command, data: data};
45 console.log('C<--', c);
46 this.websocket.emit('irc', c, callback);
47 };
48
49 Client.prototype.sendKiwiCommand = function (command, callback) {
50 this.websocket.emit('kiwi', command, callback);
51 };
52
53 var IRC_command = function (command, callback) {
54 console.log('C-->', command);
55 var method, str = '';
56 if (typeof callback !== 'function') {
57 callback = function () {};
58 }
59 if ((command.server === null) || (typeof command.server !== 'number')) {
60 return callback('server not specified');
61 } else if (!this.IRC_connections[command.server]) {
62 return callback('not connected to server');
63 }
64
65 command.data = JSON.parse(command.data);
66
67 if (command.data.method === 'ctcp') {
68 if (command.data.args.request) {
69 str += 'PRIVMSG ';
70 } else {
71 str += 'NOTICE ';
72 }
73 str += command.data.args.target + ' :'
74 str += String.fromCharCode(1) + command.data.args.type + ' ';
75 str += command.data.args.params + String.fromCharCode(1);
76 this.IRC_connections[command.server].write(str);
77 } else if (command.data.method === 'raw') {
78 this.IRC_connections[command.server].write(command.data.args.data);
79 } else if (command.data.method === 'kiwi') {
80 // do special Kiwi stuff here
81 } else {
82 method = command.data.method;
83 command.data = command.data.args;
84 this.IRC_connections[command.server].write(method + ((command.data.params) ? ' ' + command.data.params.join(' ') : '') + ((command.data.trailing) ? ' :' + command.data.trailing : ''), callback);
85 }
86 };
87
88 var kiwi_command = function (command, callback) {
89 var that = this;
90 console.log(typeof callback);
91 if (typeof callback !== 'function') {
92 callback = function () {};
93 }
94 switch (command.command) {
95 case 'connect':
96 if ((command.hostname) && (command.port) && (command.nick)) {
97 var con = new IRCConnection(command.hostname, command.port, command.ssl,
98 command.nick, {hostname: this.websocket.handshake.revdns, address: this.websocket.handshake.address.address},
99 command.password, null);
100
101 var con_num = this.next_connection++;
102 this.IRC_connections[con_num] = con;
103
104 var binder = new IRCCommands.Binder(con, con_num, this);
105 binder.bind_irc_commands();
106
107 con.on('connected', function () {
108 console.log("con.on('connected')");
109 return callback(null, con_num);
110 });
111
112 con.on('error', function (err) {
113 this.websocket.sendKiwiCommand('error', {server: con_num, error: err});
114 });
115
116 con.on('close', function () {
117 that.IRC_connections[con_num] = null;
118 });
119 } else {
120 return callback('Hostname, port and nickname must be specified');
121 }
122 break;
123 default:
124 callback();
125 }
126 };
127
128 var extension_command = function (command, callback) {
129 if (typeof callback === 'function') {
130 callback('not implemented');
131 }
132 };
133
134 var disconnect = function () {
135 _.each(this.IRC_connections, function (irc_connection, i, cons) {
136 if (irc_connection) {
137 irc_connection.end('QUIT :Kiwi IRC');
138 cons[i] = null;
139 }
140 });
141 this.emit('destroy');
142 };
143
144 var error = function () {
145 this.emit('destroy');
146 };