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
129
130
131
132
|
/*
Description: Allows calling client to change their current nickname
*/
// module support functions
const verifyNickname = (nick) => /^[a-zA-Z0-9_]{1,24}$/.test(nick);
// module main
export async function run(core, server, socket, data) {
if (server.police.frisk(socket.address, 6)) {
return server.reply({
cmd: 'warn',
text: 'You are changing nicknames too fast. Wait a moment before trying again.',
}, socket);
}
// verify user data is string
if (typeof data.nick !== 'string') {
return true;
}
// make sure requested nickname meets standards
const newNick = data.nick.trim();
if (!verifyNickname(newNick)) {
return server.reply({
cmd: 'warn',
text: 'Nickname must consist of up to 24 letters, numbers, and underscores',
}, socket);
}
// prevent admin impersonation
// TODO: prevent mod impersonation
if (newNick.toLowerCase() === core.config.adminName.toLowerCase()) {
server.police.frisk(socket.address, 4);
return server.reply({
cmd: 'warn',
text: 'You are not the admin, liar!',
}, socket);
}
// find any sockets that have the same nickname
const userExists = server.findSockets({
channel: socket.channel,
nick: (targetNick) => targetNick.toLowerCase() === newNick.toLowerCase(),
});
// return error if found
if (userExists.length > 0) {
// That nickname is already in that channel
return server.reply({
cmd: 'warn',
text: 'Nickname taken',
}, socket);
}
// build join and leave notices
// TODO: this is a legacy client holdover, name changes in the future will
// have thieir own event
const leaveNotice = {
cmd: 'onlineRemove',
nick: socket.nick,
};
const joinNotice = {
cmd: 'onlineAdd',
nick: newNick,
trip: socket.trip || 'null',
hash: socket.hash,
};
// broadcast remove event and join event with new name, this is to support legacy clients and bots
server.broadcast(leaveNotice, { channel: socket.channel });
server.broadcast(joinNotice, { channel: socket.channel });
// notify channel that the user has changed their name
server.broadcast({
cmd: 'info',
text: `${socket.nick} is now ${newNick}`,
}, { channel: socket.channel });
// commit change to nickname
socket.nick = newNick;
return true;
}
// module hook functions
export function initHooks(server) {
server.registerHook('in', 'chat', this.nickCheck.bind(this), 29);
}
// hooks chat commands checking for /nick
export function nickCheck(core, server, socket, payload) {
if (typeof payload.text !== 'string') {
return false;
}
if (payload.text.startsWith('/nick')) {
const input = payload.text.split(' ');
// If there is no nickname target parameter
if (input[1] === undefined) {
server.reply({
cmd: 'warn',
text: 'Refer to `/help nick` for instructions on how to use this command.',
}, socket);
return false;
}
const newNick = input[1].replace(/@/g, '');
this.run(core, server, socket, {
cmd: 'changenick',
nick: newNick,
});
return false;
}
return payload;
}
export const requiredData = ['nick'];
export const info = {
name: 'changenick',
description: 'This will change your current connections nickname',
usage: `
API: { cmd: 'changenick', nick: '<new nickname>' }
Text: /nick <new nickname>`,
};
|