1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
/*
*/
'use strict';
const crypto = require('crypto');
function hash(password) {
var sha = crypto.createHash('sha256');
sha.update(password);
return sha.digest('base64').substr(0, 6);
}
function verifyNickname(nick) {
return /^[a-zA-Z0-9_]{1,24}$/.test(nick);
}
exports.run = async (core, server, socket, data) => {
if (server._police.frisk(socket.remoteAddress, 3)) {
server.reply({
cmd: 'warn',
text: 'You are joining channels too fast. Wait a moment and try again.'
}, socket);
return;
}
if (typeof socket.channel !== 'undefined') {
// Calling socket already in a channel
// TODO: allow changing of channel without reconnection
return;
}
let channel = String(data.channel).trim();
if (!channel) {
// Must join a non-blank channel
return;
}
// Process nickname
let nick = String(data.nick);
let nickArray = nick.split('#', 2);
nick = nickArray[0].trim();
if (!verifyNickname(nick)) {
server.reply({
cmd: 'warn',
text: 'Nickname must consist of up to 24 letters, numbers, and underscores'
}, socket);
return
}
for (let client of server.clients) {
if (client.channel === channel) {
if (client.nick.toLowerCase() === nick.toLowerCase()) {
server.reply({
cmd: 'warn',
text: 'Nickname taken'
}, socket);
return;
}
}
}
// TODO: Should we check for mod status first to prevent overwriting of admin status somehow? Meh, w/e, cba.
let uType = 'user';
let trip = null;
let password = nickArray[1];
if (nick.toLowerCase() == core.config.adminName.toLowerCase()) {
if (password != core.config.adminPass) {
server.reply({
cmd: 'warn',
text: 'Gtfo'
}, socket);
return;
} else {
uType = 'admin';
trip = hash(password + core.config.tripSalt);
}
} else if (password) {
trip = hash(password + core.config.tripSalt);
}
// TODO: Disallow moderator impersonation
for (let mod of core.config.mods) {
if (trip === mod.trip)
uType = 'mod';
}
// Announce the new user
server.broadcast({
cmd: 'onlineAdd',
nick: nick,
trip: trip || 'null'
}, { channel: channel });
socket.uType = uType;
socket.nick = nick;
socket.channel = channel;
if (trip !== null) socket.trip = trip;
// Reply with online user list
let nicks = [];
for (let client of server.clients) {
if (client.channel === channel) {
nicks.push(client.nick);
}
}
server.reply({
cmd: 'onlineSet',
nicks: nicks
}, socket);
core.managers.stats.increment('users-joined');
};
exports.requiredData = ['channel', 'nick'];
exports.info = {
name: 'join',
usage: 'join {channel} {nick}',
description: 'Place calling socket into target channel with target nick & broadcast event to channel'
};
|