Correctly using /quit command without reconnecting #567
[KiwiIRC.git] / server / clientcommands.js
CommitLineData
f9ff7686 1var _ = require('lodash');\r
f3dbbd91
D
2\r
3\r
4\r
5\r
2a8e95d1 6var ClientCommands = function (client) {\r
f3dbbd91
D
7 this.client = client;\r
8};\r
2a8e95d1 9module.exports = ClientCommands;\r
f3dbbd91 10\r
2a8e95d1 11ClientCommands.prototype.run = function (command, args, irc_connection, callback) {\r
f3dbbd91
D
12 // Do we have a function to handle this command?\r
13 if (!listeners[command.toUpperCase()]) {\r
14 return;\r
15 }\r
16\r
17 return listeners[command.toUpperCase()](args, irc_connection, callback);\r
18};\r
19\r
ac102e9d
D
20ClientCommands.prototype.addRpcEvents = function(client, rpc) {\r
21 // Called for each RPC call\r
22 // addRpcMethod() below prepends the incoming RPC call with the method name and\r
23 // the listener that handles this call, and passes that argument list to moduleEventWrap().\r
24 // This gives us the chance to wrap all calls with connection_id checks and passing\r
25 // them off to the module system.\r
26\r
27 var moduleEventWrap = function(rpc_method, the_fn, callback, connection_id) {\r
28 var connection, rpc_args, fn_args;\r
29\r
30 // Make sure we have a connection_id specified\r
31 if (!connection_id && connection_id !== 0) {\r
32 return callback('server not specified');\r
33\r
34 } else if (!client.state.irc_connections[connection_id]) {\r
35 return callback('not connected to server');\r
36 }\r
37\r
38 // The server this command is directed to\r
39 connection = client.state.irc_connections[connection_id];\r
40\r
41 // Get the arguments for the RPC call only (starts at 4)\r
42 rpc_args = Array.prototype.slice.call(arguments, 4);\r
43\r
44 global.modules.emit('rpc ' + rpc_method, {\r
45 arguments: rpc_args,\r
46 client: client,\r
47 connection: connection\r
48 })\r
49 .done(function() {\r
50 // Listeners expect arguments in a (connection, callback, args..n) format, so preppend\r
51 // the connection + callback\r
52 fn_args = rpc_args.slice(0);\r
53 fn_args.unshift(connection, callback);\r
54\r
55 the_fn.apply(client, fn_args);\r
56 })\r
57 .prevented(function() {\r
58 // The RPC call was prevented from running by a module\r
59 });\r
60 };\r
61\r
62 // Quick + easier way to call the above function\r
63 var addRpcMethod = function(rpc_method, fn) {\r
64 rpc.on(rpc_method, _.partial(moduleEventWrap, rpc_method, fn));\r
65 };\r
66\r
67 addRpcMethod('irc.privmsg', listeners.privmsg);\r
68 addRpcMethod('irc.ctcp', listeners.ctcp);\r
69 addRpcMethod('irc.raw', listeners.raw);\r
70 addRpcMethod('irc.join', listeners.join);\r
71 addRpcMethod('irc.channel_info', listeners.channel_info);\r
72 addRpcMethod('irc.part', listeners.part);\r
73 addRpcMethod('irc.topic', listeners.topic);\r
74 addRpcMethod('irc.kick', listeners.kick);\r
75 addRpcMethod('irc.quit', listeners.quit);\r
76 addRpcMethod('irc.notice', listeners.notice);\r
77 addRpcMethod('irc.mode', listeners.mode);\r
78 addRpcMethod('irc.nick', listeners.nick);\r
79 addRpcMethod('irc.kiwi', listeners.kiwi);\r
80 addRpcMethod('irc.encoding', listeners.encoding);\r
81};\r
82\r
f3dbbd91
D
83\r
84\r
85\r
0cd61eb7
D
86/**\r
87 * Truncate a string into blocks of a set size\r
88 */\r
89function truncateString(str, block_size) {\r
90 block_size = block_size || 350;\r
91\r
92 var blocks = [],\r
93 current_pos;\r
94\r
95 for (current_pos = 0; current_pos < str.length; current_pos = current_pos + block_size) {\r
96 blocks.push(str.substr(current_pos, block_size));\r
97 }\r
98\r
99 return blocks;\r
100}\r
101\r
102\r
103\r
104\r
f3dbbd91 105var listeners = {\r
ac102e9d 106 privmsg: function (irc_connection, callback, args) {\r
5328acca
JA
107 // Maximum length of target + message we can send to the IRC server is 500 characters\r
108 // but we need to leave extra room for the sender prefix so the entire message can\r
109 // be sent from the IRCd to the target without being truncated.\r
0cd61eb7 110 var blocks = truncateString(args.msg, 350);\r
ac102e9d 111\r
a22a69f3
D
112 blocks.forEach(function (block, idx) {\r
113 // Apply the callback on the last message only\r
114 var cb = (idx === blocks.length - 1) ?\r
115 callback :\r
116 undefined;\r
117\r
118 irc_connection.write('PRIVMSG ' + args.target + ' :' + block, cb);\r
0cd61eb7 119 });\r
f3dbbd91 120 },\r
72db27e4 121\r
f3dbbd91 122\r
ac102e9d 123 ctcp: function (irc_connection, callback, args) {\r
f3dbbd91 124 if ((args.target) && (args.type)) {\r
d07c8435 125 if (args.is_request) {\r
f3dbbd91
D
126 irc_connection.write('PRIVMSG ' + args.target + ' :' + String.fromCharCode(1) + args.type.toUpperCase() + ' ' + args.params + String.fromCharCode(1), callback);\r
127 } else {\r
128 irc_connection.write('NOTICE ' + args.target + ' :' + String.fromCharCode(1) + args.type.toUpperCase() + ' ' + args.params + String.fromCharCode(1), callback);\r
129 }\r
130 }\r
131 },\r
132\r
133\r
ac102e9d 134 raw: function (irc_connection, callback, args) {\r
f3dbbd91
D
135 irc_connection.write(args.data, callback);\r
136 },\r
137\r
138\r
ac102e9d
D
139 join: function (irc_connection, callback, args) {\r
140 var channels, keys;\r
f3dbbd91
D
141 if (args.channel) {\r
142 channels = args.channel.split(",");\r
143 keys = (args.key) ? args.key.split(",") : [];\r
144 _.each(channels, function (chan, index) {\r
145 irc_connection.write('JOIN ' + chan + ' ' + (keys[index] || ''), callback);\r
146 });\r
147 }\r
148 },\r
149\r
150\r
ac102e9d 151 channel_info: function (irc_connection, callback, args) {\r
72db27e4
D
152 if (args.channel) {\r
153 irc_connection.write('MODE ' + args.channel, callback);\r
154 }\r
155 },\r
156\r
157\r
ac102e9d 158 part: function (irc_connection, callback, args) {\r
f3dbbd91
D
159 if (args.channel) {\r
160 _.each(args.channel.split(","), function (chan) {\r
7f272ac9 161 irc_connection.write('PART ' + chan + (args.message ? ' :' + args.message : ''), callback);\r
f3dbbd91
D
162 });\r
163 }\r
164 },\r
165\r
166\r
ac102e9d 167 topic: function (irc_connection, callback, args) {\r
f3dbbd91
D
168 if (args.channel) {\r
169 if (args.topic) {\r
170 irc_connection.write('TOPIC ' + args.channel + ' :' + args.topic, callback);\r
171 } else {\r
172 irc_connection.write('TOPIC ' + args.channel, callback);\r
173 }\r
174 }\r
175 },\r
176\r
177\r
ac102e9d 178 kick: function (irc_connection, callback, args) {\r
f3dbbd91 179 if ((args.channel) && (args.nick)) {\r
fc677b4c 180 irc_connection.write('KICK ' + args.channel + ' ' + args.nick + ' :' + args.reason, callback);\r
f3dbbd91
D
181 }\r
182 },\r
183\r
184\r
ac102e9d 185 quit: function (irc_connection, callback, args) {\r
e32ff87b 186 irc_connection.end('QUIT :' + (args.message||''));\r
f3dbbd91
D
187 },\r
188\r
189\r
ac102e9d 190 notice: function (irc_connection, callback, args) {\r
5328acca
JA
191 // Maximum length of target + message we can send to the IRC server is 500 characters\r
192 // but we need to leave extra room for the sender prefix so the entire message can\r
193 // be sent from the IRCd to the target without being truncated.\r
0cd61eb7
D
194\r
195 var blocks = truncateString(args.msg, 350);\r
a22a69f3
D
196 blocks.forEach(function (block, idx) {\r
197 // Apply the callback on the last message only\r
198 var cb = (idx === blocks.length - 1) ?\r
199 callback :\r
200 undefined;\r
201\r
202 irc_connection.write('NOTICE ' + args.target + ' :' + block, cb);\r
0cd61eb7 203 });\r
f3dbbd91
D
204 },\r
205\r
206\r
ac102e9d 207 mode: function (irc_connection, callback, args) {\r
f3dbbd91
D
208 if ((args.target) && (args.mode)) {\r
209 irc_connection.write('MODE ' + args.target + ' ' + args.mode + ' ' + args.params, callback);\r
210 }\r
211 },\r
212\r
213\r
ac102e9d 214 nick: function (irc_connection, callback, args) {\r
f3dbbd91
D
215 if (args.nick) {\r
216 irc_connection.write('NICK ' + args.nick, callback);\r
217 }\r
218 },\r
219\r
220\r
ac102e9d 221 kiwi: function (irc_connection, callback, args) {\r
f3dbbd91
D
222 if ((args.target) && (args.data)) {\r
223 irc_connection.write('PRIVMSG ' + args.target + ': ' + String.fromCharCode(1) + 'KIWI ' + args.data + String.fromCharCode(1), callback);\r
224 }\r
d1b3e8b3
VDF
225 },\r
226\r
ac102e9d 227 encoding: function (irc_connection, callback, args) {\r
d1b3e8b3 228 if (args.encoding) {\r
3efb4f33 229 return callback(irc_connection.setEncoding(args.encoding));\r
d1b3e8b3 230 }\r
f3dbbd91
D
231 }\r
232};\r