1 var util
= require('util'),
2 events
= require('events'),
3 crypto
= require('crypto'),
5 State
= require('./irc/state.js');
6 IrcConnection
= require('./irc/connection.js').IrcConnection
,
7 ClientCommands
= require('./clientcommands.js');
10 var Client = function (websocket
) {
13 events
.EventEmitter
.call(this);
14 this.websocket
= websocket
;
17 this.real_address
= this.websocket
.handshake
.real_address
;
19 // A hash to identify this client instance
20 this.hash
= crypto
.createHash('sha256')
21 .update(this.real_address
)
22 .update('' + Date
.now())
23 .update(Math
.floor(Math
.random() * 100000).toString())
26 this.state
= new State(this);
33 // Handler for any commands sent from the client
34 this.client_commands
= new ClientCommands(this);
36 websocket
.on('irc', function () {
37 handleClientMessage
.apply(that
, arguments
);
39 websocket
.on('kiwi', function () {
40 kiwiCommand
.apply(that
, arguments
);
42 websocket
.on('disconnect', function () {
43 websocketDisconnect
.apply(that
, arguments
);
45 websocket
.on('error', function () {
46 websocketError
.apply(that
, arguments
);
49 util
.inherits(Client
, events
.EventEmitter
);
51 module
.exports
.Client
= Client
;
54 // Callbacks SHALL accept 2 arguments, error and response, in that order.
55 // error MUST be null where the command is successul.
56 // error MUST otherwise be a truthy value and SHOULD be a string where the cause of the error is known.
57 // response MAY be given even if error is truthy
59 Client
.prototype.sendIrcCommand = function (command
, data
, callback
) {
60 var c
= {command
: command
, data
: data
};
61 this.websocket
.emit('irc', c
, callback
);
64 Client
.prototype.sendKiwiCommand = function (command
, data
, callback
) {
65 var c
= {command
: command
, data
: data
};
66 this.websocket
.emit('kiwi', c
, callback
);
69 Client
.prototype.dispose = function () {
71 this.removeAllListeners();
74 function handleClientMessage(msg
, callback
) {
75 var server
, args
, obj
, channels
, keys
;
77 // Make sure we have a server number specified
78 if ((msg
.server
=== null) || (typeof msg
.server
!== 'number')) {
79 return (typeof callback
=== 'function') ? callback('server not specified') : undefined;
80 } else if (!this.state
.irc_connections
[msg
.server
]) {
81 return (typeof callback
=== 'function') ? callback('not connected to server') : undefined;
84 // The server this command is directed to
85 server
= this.state
.irc_connections
[msg
.server
];
87 if (typeof callback
!== 'function') {
92 msg
.data
= JSON
.parse(msg
.data
);
94 kiwi
.log('[handleClientMessage] JSON parsing error ' + msg
.data
);
98 // Run the client command
99 this.client_commands
.run(msg
.data
.method
, msg
.data
.args
, server
, callback
);
105 function kiwiCommand(command
, callback
) {
108 if (typeof callback
!== 'function') {
109 callback = function () {};
111 switch (command
.command
) {
113 if (command
.hostname
&& command
.port
&& command
.nick
) {
117 (global
.config
.restrict_server
|| command
.hostname
),
118 (global
.config
.restrict_server_port
|| command
.port
),
119 (global
.config
.restrict_server_ssl
|| command
.ssl
),
121 {hostname
: this.websocket
.handshake
.revdns
, address
: this.websocket
.handshake
.real_address
},
122 (global
.config
.restrict_server_password
|| command
.password
),
125 return callback('Hostname, port and nickname must be specified');
134 // Websocket has disconnected, so quit all the IRC connections
135 function websocketDisconnect() {
136 this.emit('disconnect');
142 // TODO: Should this close all the websocket connections too?
143 function websocketError() {