1
0
mirror of https://github.com/hack-chat/main.git synced 2024-03-22 13:20:33 +08:00
hack-chat-main/server/src/commands/core/join.js

171 lines
4.7 KiB
JavaScript
Raw Normal View History

2020-09-17 13:44:32 +08:00
/* eslint no-param-reassign: 0 */
2018-03-10 15:47:00 +08:00
/*
Description: Adds requested channel into the calling clients "subscribed channels"
2018-03-10 15:47:00 +08:00
*/
// import * as UAC from '../utility/UAC/_info';
import {
canJoinChannel,
} from '../utility/_Channels';
import {
Errors,
} from '../utility/_Constants';
import {
upgradeLegacyJoin,
legacyLevelToLabel,
} from '../utility/_LegacyFunctions';
import {
verifyNickname,
getUserPerms,
} from '../utility/_UAC';
// module main
2020-09-17 13:44:32 +08:00
export async function run({
core, server, socket, payload,
}) { // check for spam
2019-11-07 15:35:23 +08:00
if (server.police.frisk(socket.address, 3)) {
return server.reply({
cmd: 'warn',
2019-11-07 15:35:23 +08:00
text: 'You are joining channels too fast. Wait a moment and try again.',
id: Errors.Join.RATELIMIT,
2020-10-10 13:34:59 +08:00
channel: false, // @todo Multichannel, false for global event
}, socket);
}
// `join` is the legacy entry point, check if it needs to be upgraded
if (typeof socket.hcProtocol === 'undefined') {
payload = upgradeLegacyJoin(server, socket, payload);
}
// store payload values
const { channel, nick, pass } = payload;
// check if a client is able to join target channel
const mayJoin = canJoinChannel(channel, socket);
if (mayJoin !== true) {
return server.reply({
cmd: 'warn',
text: 'You may not join that channel.',
id: mayJoin,
2020-10-10 13:34:59 +08:00
channel: false, // @todo Multichannel, false for global event
2018-03-10 15:47:00 +08:00
}, socket);
}
2018-06-04 15:07:24 +08:00
// calling socket already in a channel
// @todo multichannel update, will remove
2018-03-10 15:47:00 +08:00
if (typeof socket.channel !== 'undefined') {
2020-09-08 12:51:47 +08:00
return server.reply({
cmd: 'warn', // @todo Remove this
text: 'Joining more than one channel is not currently supported',
id: Errors.Join.ALREADY_JOINED,
2020-10-10 13:34:59 +08:00
channel: false, // @todo Multichannel, false for global event
2020-09-08 12:51:47 +08:00
}, socket);
2018-03-10 15:47:00 +08:00
}
// end todo
2018-03-10 15:47:00 +08:00
// validates the user input for `nick`
const validName = verifyNickname(nick, socket);
if (validName !== true) {
return server.reply({
cmd: 'warn',
text: 'Nickname must consist of up to 24 letters, numbers, and underscores',
id: Errors.Join.INVALID_NICK,
2020-10-10 13:34:59 +08:00
channel: false, // @todo Multichannel, false for global event
}, socket);
}
// get trip and level
const { trip, level } = getUserPerms(pass, core.config, channel);
// store the user values
const userInfo = {
nick,
trip,
uType: legacyLevelToLabel(level),
hash: socket.hash,
level,
userid: socket.userid,
channel,
};
2018-03-10 15:47:00 +08:00
// prevent admin impersonation
if (nick.toLowerCase() === core.config.adminName.toLowerCase()) {
if (userInfo.trip !== 'Admin') {
userInfo.nick = `Fake${userInfo.nick}`;
}
2018-03-10 15:47:00 +08:00
}
2018-06-04 15:07:24 +08:00
// check if the nickname already exists in the channel
2019-11-07 15:35:23 +08:00
const userExists = server.findSockets({
channel,
2019-11-07 15:35:23 +08:00
nick: (targetNick) => targetNick.toLowerCase() === userInfo.nick.toLowerCase(),
2018-04-29 13:29:38 +08:00
});
2018-03-10 15:47:00 +08:00
2018-04-29 13:29:38 +08:00
if (userExists.length > 0) {
2018-06-04 15:07:24 +08:00
// that nickname is already in that channel
return server.reply({
cmd: 'warn',
2019-11-07 15:35:23 +08:00
text: 'Nickname taken',
id: Errors.Join.NAME_TAKEN,
2020-10-10 13:34:59 +08:00
channel: false, // @todo Multichannel, false for global event
2018-04-29 13:29:38 +08:00
}, socket);
2018-03-10 15:47:00 +08:00
}
2018-06-04 15:07:24 +08:00
// prepare to notify channel peers
const newPeerList = server.findSockets({ channel });
2020-03-13 02:28:20 +08:00
const nicks = []; /* @legacy */
const users = [];
const joinAnnouncement = { ...{ cmd: 'onlineAdd' }, ...userInfo };
2018-06-04 15:07:24 +08:00
// send join announcement and prep online set reply
2019-11-07 15:35:23 +08:00
for (let i = 0, l = newPeerList.length; i < l; i += 1) {
2018-04-29 13:29:38 +08:00
server.reply(joinAnnouncement, newPeerList[i]);
2020-03-13 02:28:20 +08:00
nicks.push(newPeerList[i].nick); /* @legacy */
users.push({
nick: newPeerList[i].nick,
trip: newPeerList[i].trip,
uType: newPeerList[i].uType, /* @legacy */
2020-03-14 02:40:12 +08:00
hash: newPeerList[i].hash,
2020-03-13 02:28:20 +08:00
level: newPeerList[i].level,
userid: newPeerList[i].userid,
channel,
2020-03-13 02:28:20 +08:00
isme: false,
2020-10-15 12:43:38 +08:00
isBot: newPeerList[i].isBot,
2020-03-13 02:28:20 +08:00
});
2018-04-29 13:29:38 +08:00
}
2018-03-10 15:47:00 +08:00
2018-06-04 15:07:24 +08:00
// store user info
socket.nick = userInfo.nick;
2020-03-13 02:28:20 +08:00
socket.trip = userInfo.trip;
socket.level = userInfo.level;
socket.uType = userInfo.uType; /* @legacy */
socket.channel = channel; /* @legacy */
// @todo multi-channel patch
// socket.channels.push(channel);
2020-03-13 02:28:20 +08:00
nicks.push(userInfo.nick); /* @legacy */
2020-10-15 12:43:38 +08:00
users.push({ ...{ isme: true, isBot: socket.isBot }, ...userInfo });
2018-03-10 15:47:00 +08:00
2018-06-04 15:07:24 +08:00
// reply with channel peer list
2018-03-10 15:47:00 +08:00
server.reply({
cmd: 'onlineSet',
2020-03-13 02:28:20 +08:00
nicks, /* @legacy */
users,
2020-10-10 13:34:59 +08:00
channel, // @todo Multichannel (?)
2018-03-10 15:47:00 +08:00
}, socket);
2018-06-04 15:07:24 +08:00
// stats are fun
2019-03-19 14:36:21 +08:00
core.stats.increment('users-joined');
2018-03-10 15:47:00 +08:00
2019-11-07 15:35:23 +08:00
return true;
}
2020-09-17 13:44:32 +08:00
export const requiredData = []; // ['channel', 'nick'];
2019-11-07 15:35:23 +08:00
export const info = {
2018-05-13 18:33:22 +08:00
name: 'join',
description: 'Join the target channel using the supplied nick and password',
usage: `
2020-09-08 12:51:47 +08:00
API: { cmd: 'join', nick: '<your nickname>', pass: '<optional password>', channel: '<target channel>' }`,
};