IRCd reconnection only when registered for 10+ secs
[KiwiIRC.git] / server / irc / commands / registration.js
CommitLineData
138d8d17
D
1var _ = require('lodash');
2
3module.exports = function AddCommandHandlers(command_controller) {
4 _.each(handlers, function(handler, handler_command) {
5 command_controller.addHandler(handler_command, handler);
6 });
7};
8
9
10var handlers = {
11 RPL_WELCOME: function (command) {
12 var nick = command.params[0];
138d8d17
D
13 this.cap_negotiation = false;
14 this.emit('server ' + this.irc_connection.irc_host.hostname + ' connect', {
15 nick: nick
16 });
17 },
18
19
20 RPL_ISUPPORT: function (command) {
21 var options, i, option, matches, j;
22 options = command.params;
23 for (i = 1; i < options.length; i++) {
24 option = options[i].split("=", 2);
25 option[0] = option[0].toUpperCase();
26 this.irc_connection.options[option[0]] = (typeof option[1] !== 'undefined') ? option[1] : true;
27 if (_.include(['NETWORK', 'PREFIX', 'CHANTYPES', 'CHANMODES', 'NAMESX'], option[0])) {
28 if (option[0] === 'PREFIX') {
29 matches = /\(([^)]*)\)(.*)/.exec(option[1]);
30 if ((matches) && (matches.length === 3)) {
31 this.irc_connection.options.PREFIX = [];
32 for (j = 0; j < matches[2].length; j++) {
33 this.irc_connection.options.PREFIX.push({symbol: matches[2].charAt(j), mode: matches[1].charAt(j)});
34 }
35 }
36 } else if (option[0] === 'CHANTYPES') {
37 this.irc_connection.options.CHANTYPES = this.irc_connection.options.CHANTYPES.split('');
38 } else if (option[0] === 'CHANMODES') {
39 this.irc_connection.options.CHANMODES = option[1].split(',');
40 } else if ((option[0] === 'NAMESX') && (!_.contains(this.irc_connection.cap.enabled, 'multi-prefix'))) {
41 this.irc_connection.write('PROTOCTL NAMESX');
42 }
43 }
44 }
45 this.emit('server ' + this.irc_connection.irc_host.hostname + ' options', {
46 options: this.irc_connection.options,
47 cap: this.irc_connection.cap.enabled
48 });
49 },
50
51
52 CAP: function (command) {
53 // TODO: capability modifiers
54 // i.e. - for disable, ~ for requires ACK, = for sticky
55 var capabilities = command.params[command.params.length - 1].replace(/(?:^| )[\-~=]/, '').split(' ');
56 var request;
57
58 // Which capabilities we want to enable
59 var want = ['multi-prefix', 'away-notify', 'server-time', 'znc.in/server-time-iso', 'znc.in/server-time'];
60
61 if (this.irc_connection.password) {
62 want.push('sasl');
63 }
64
65 switch (command.params[1]) {
66 case 'LS':
67 // Compute which of the available capabilities we want and request them
68 request = _.intersection(capabilities, want);
69 if (request.length > 0) {
70 this.irc_connection.cap.requested = request;
71 this.irc_connection.write('CAP REQ :' + request.join(' '));
72 } else {
73 this.irc_connection.write('CAP END');
74 this.irc_connection.cap_negotiation = false;
75 }
76 break;
77 case 'ACK':
78 if (capabilities.length > 0) {
79 // Update list of enabled capabilities
80 this.irc_connection.cap.enabled = capabilities;
81 // Update list of capabilities we would like to have but that aren't enabled
82 this.irc_connection.cap.requested = _.difference(this.irc_connection.cap.requested, capabilities);
83 }
84 if (this.irc_connection.cap.enabled.length > 0) {
85 if (_.contains(this.irc_connection.cap.enabled, 'sasl')) {
86 this.irc_connection.sasl = true;
87 this.irc_connection.write('AUTHENTICATE PLAIN');
88 } else {
89 this.irc_connection.write('CAP END');
90 this.irc_connection.cap_negotiation = false;
91 }
92 }
93 break;
94 case 'NAK':
95 if (capabilities.length > 0) {
96 this.irc_connection.cap.requested = _.difference(this.irc_connection.cap.requested, capabilities);
97 }
98 if (this.irc_connection.cap.requested.length > 0) {
99 this.irc_connection.write('CAP END');
100 this.irc_connection.cap_negotiation = false;
101 }
102 break;
103 case 'LIST':
104 // should we do anything here?
105 break;
106 }
107 },
108
109
110 AUTHENTICATE: function (command) {
111 var b = new Buffer(this.irc_connection.nick + "\0" + this.irc_connection.nick + "\0" + this.irc_connection.password, 'utf8');
112 var b64 = b.toString('base64');
113 if (command.params[0] === '+') {
114 while (b64.length >= 400) {
115 this.irc_connection.write('AUTHENTICATE ' + b64.slice(0, 399));
116 b64 = b64.slice(399);
117 }
118 if (b64.length > 0) {
119 this.irc_connection.write('AUTHENTICATE ' + b64);
120 } else {
121 this.irc_connection.write('AUTHENTICATE +');
122 }
123 } else {
124 this.irc_connection.write('CAP END');
125 this.irc_connection.cap_negotiation = false;
126 }
127 },
128
129
130 RPL_SASLAUTHENTICATED: function (command) {
131 this.irc_connection.write('CAP END');
132 this.irc_connection.cap_negotiation = false;
133 this.irc_connection.sasl = true;
134 },
135
136
137 RPL_SASLLOGGEDIN: function (command) {
138 if (this.irc_connection.cap_negotiation === true) {
139 this.irc_connection.write('CAP END');
140 this.irc_connection.cap_negotiation = false;
141 }
142 },
143
144 ERR_SASLNOTAUTHORISED: function (command) {
145 this.irc_connection.write('CAP END');
146 this.irc_connection.cap_negotiation = false;
147 },
148
149
150 ERR_SASLABORTED: function (command) {
151 this.irc_connection.write('CAP END');
152 this.irc_connection.cap_negotiation = false;
153 },
154
155
156 ERR_SASLALREADYAUTHED: function (command) {
157 // noop
158 }
159};