1
0
mirror of https://github.com/hack-chat/main.git synced 2024-03-22 13:20:33 +08:00
This commit is contained in:
marzavec 2020-11-06 13:16:43 -08:00
parent 76b30c8553
commit b4553511f0
25 changed files with 370 additions and 238 deletions

View File

@ -18,6 +18,11 @@
"color-convert": "^2.0.1"
}
},
"ascii-captcha": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/ascii-captcha/-/ascii-captcha-0.0.3.tgz",
"integrity": "sha1-NAtO1oVYOHEHsJVzBC/kc4v0mPk="
},
"async": {
"version": "0.9.2",
"resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz",

View File

@ -18,6 +18,7 @@
"author": "Marzavec",
"license": "WTFPL",
"dependencies": {
"ascii-captcha": "0.0.3",
"chalk": "^3.0.0",
"common-tags": "^1.8.0",
"dateformat": "^3.0.3",

View File

@ -2,14 +2,19 @@
Description: Adds the target trip to the mod list then elevates the uType
*/
import * as UAC from '../utility/UAC/_info';
import {
isAdmin,
isModerator,
levels,
getUserDetails,
} from '../utility/_UAC';
// module main
export async function run({
core, server, socket, payload,
}) {
// increase rate limit chance and ignore if not admin
if (!UAC.isAdmin(socket.level)) {
if (!isAdmin(socket.level)) {
return server.police.frisk(socket.address, 20);
}
@ -19,10 +24,20 @@ export async function run({
// find targets current connections
const newMod = server.findSockets({ trip: payload.trip });
if (newMod.length !== 0) {
// build update notice with new privileges
const updateNotice = {
...getUserDetails(newMod[0]),
...{
cmd: 'updateUser',
uType: 'mod', // @todo use legacyLevelToLabel from _LegacyFunctions.js
level: levels.moderator,
},
};
for (let i = 0, l = newMod.length; i < l; i += 1) {
// upgrade privilages
newMod[i].uType = 'mod';
newMod[i].level = UAC.levels.moderator;
newMod[i].uType = 'mod'; // @todo use legacyLevelToLabel from _LegacyFunctions.js
newMod[i].level = levels.moderator;
// inform new mod
server.send({
@ -30,6 +45,14 @@ export async function run({
text: 'You are now a mod.',
channel: newMod[i].channel, // @todo Multichannel
}, newMod[i]);
// notify channel
server.broadcast({
...updateNotice,
...{
channel: newMod[i].channel,
},
}, { channel: newMod[i].channel });
}
}
@ -45,7 +68,7 @@ export async function run({
cmd: 'info',
text: `Added mod: ${payload.trip}`,
channel: false, // @todo Multichannel, false for global info
}, { level: UAC.isModerator });
}, { level: isModerator });
return true;
}

View File

@ -6,12 +6,14 @@
Description: Outputs all current channels and their user nicks
*/
import * as UAC from '../utility/UAC/_info';
import {
isAdmin,
} from '../utility/_UAC';
// module main
export async function run({ server, socket }) {
// increase rate limit chance and ignore if not admin
if (!UAC.isAdmin(socket.level)) {
if (!isAdmin(socket.level)) {
return server.police.frisk(socket.address, 20);
}

View File

@ -2,14 +2,17 @@
Description: Clears and resets the command modules, outputting any errors
*/
import * as UAC from '../utility/UAC/_info';
import {
isAdmin,
isModerator,
} from '../utility/_UAC';
// module main
export async function run({
core, server, socket, payload,
}) {
// increase rate limit chance and ignore if not admin
if (!UAC.isAdmin(socket.level)) {
if (!isAdmin(socket.level)) {
return server.police.frisk(socket.address, 20);
}
@ -37,7 +40,7 @@ export async function run({
cmd: 'info',
text: loadResult,
channel: false, // @todo Multichannel, false for global
}, { level: UAC.isModerator });
}, { level: isModerator });
return true;
}

View File

@ -2,14 +2,18 @@
Description: Removes target trip from the config as a mod and downgrades the socket type
*/
import * as UAC from '../utility/UAC/_info';
import {
isAdmin,
isModerator,
levels,
} from '../utility/_UAC';
// module main
export async function run({
core, server, socket, payload,
}) {
// increase rate limit chance and ignore if not admin
if (!UAC.isAdmin(socket.level)) {
if (!isAdmin(socket.level)) {
return server.police.frisk(socket.address, 20);
}
@ -23,7 +27,7 @@ export async function run({
for (let i = 0, l = targetMod.length; i < l; i += 1) {
// downgrade privilages
targetMod[i].uType = 'user';
targetMod[i].level = UAC.levels.default;
targetMod[i].level = levels.default;
// inform ex-mod
server.send({
@ -48,7 +52,7 @@ export async function run({
cmd: 'info',
text: `Removed mod: ${payload.trip}`,
channel: false, // @todo Multichannel, false for global
}, { level: UAC.isModerator });
}, { level: isModerator });
return true;
}

View File

@ -2,12 +2,15 @@
Description: Writes the current config to disk
*/
import * as UAC from '../utility/UAC/_info';
import {
isAdmin,
isModerator,
} from '../utility/_UAC';
// module main
export async function run({ core, server, socket }) {
// increase rate limit chance and ignore if not admin
if (!UAC.isAdmin(socket.level)) {
if (!isAdmin(socket.level)) {
return server.police.frisk(socket.address, 20);
}
@ -25,7 +28,7 @@ export async function run({ core, server, socket }) {
cmd: 'info',
text: 'Config saved!',
channel: false, // @todo Multichannel
}, { level: UAC.isModerator });
}, { level: isModerator });
return true;
}

View File

@ -2,12 +2,14 @@
Description: Emmits a server-wide message as `info`
*/
import * as UAC from '../utility/UAC/_info';
import {
isAdmin,
} from '../utility/_UAC';
// module main
export async function run({ server, socket, payload }) {
// increase rate limit chance and ignore if not admin
if (!UAC.isAdmin(socket.level)) {
if (!isAdmin(socket.level)) {
return server.police.frisk(socket.address, 20);
}

View File

@ -0,0 +1,111 @@
/*
Description: Allows calling client to change their nickname color
*/
// module support functions
const verifyColor = (color) => /(^[0-9A-F]{6}$)|(^[0-9A-F]{3}$)/i.test(color);
// module main
export async function run({
core, server, socket, payload,
}) {
const channel = socket.channel;
if (server.police.frisk(socket.address, 6)) {
return server.reply({
cmd: 'warn', // @todo Add numeric error code as `id`
text: 'You are changing colors too fast. Wait a moment before trying again.',
channel, // @todo Multichannel
}, socket);
}
// verify user data is string
if (typeof payload.color !== 'string') {
return true;
}
// make sure requested nickname meets standards
const newColor = payload.color.trim().toUpperCase().replace(/#/g, '');
if (newColor !== 'RESET' && !verifyColor(newColor)) {
return server.reply({
cmd: 'warn',
text: 'Invalid color! Color must be in hex value',
channel, // @todo Multichannel
}, socket);
}
if (newColor === 'RESET') {
socket.color = false;
} else {
socket.color = newColor;
}
// build update notice with new color
const updateNotice = {
...getUserDetails(socket),
...{
cmd: 'updateUser',
channel: socket.channel, // @todo Multichannel
}
};
// notify channel that the user has changed their name
// @todo this should be sent to every channel the user is in (multichannel)
server.broadcast(updateNotice, { channel: socket.channel });
return true;
}
// module hook functions
export function initHooks(server) {
server.registerHook('in', 'chat', this.colorCheck.bind(this), 29);
}
// hooks chat commands checking for /color
export function colorCheck({
core, server, socket, payload,
}) {
if (typeof payload.text !== 'string') {
return false;
}
if (payload.text.startsWith('/color ')) {
const input = payload.text.split(' ');
// If there is no color target parameter
if (input[1] === undefined) {
server.reply({
cmd: 'warn',
text: 'Refer to `/help changecolor` for instructions on how to use this command.',
channel: socket.channel, // @todo Multichannel
}, socket);
return false;
}
this.run({
core,
server,
socket,
payload: {
cmd: 'changecolor',
color: input[1],
},
});
return false;
}
return payload;
}
// module meta
export const requiredData = ['color'];
export const info = {
name: 'changecolor',
description: 'This will change your nickname color',
usage: `
API: { cmd: 'changecolor', color: '<new color as hex>' }
Text: /color <new color as hex>
Removal: /color reset`,
};

View File

@ -4,17 +4,22 @@
Description: Allows calling client to change their current nickname
*/
import * as UAC from '../utility/UAC/_info';
import {
verifyNickname,
getUserDetails,
} from '../utility/_UAC';
// module main
export async function run({
core, server, socket, payload,
}) {
const channel = socket.channel;
if (server.police.frisk(socket.address, 6)) {
return server.reply({
cmd: 'warn', // @todo Add numeric error code as `id`
text: 'You are changing nicknames too fast. Wait a moment before trying again.',
channel: socket.channel, // @todo Multichannel
channel, // @todo Multichannel
}, socket);
}
@ -27,11 +32,11 @@ export async function run({
// make sure requested nickname meets standards
const newNick = payload.nick.trim();
if (!UAC.verifyNickname(newNick)) {
if (!verifyNickname(newNick)) {
return server.reply({
cmd: 'warn', // @todo Add numeric error code as `id`
text: 'Nickname must consist of up to 24 letters, numbers, and underscores',
channel: socket.channel, // @todo Multichannel
channel, // @todo Multichannel
}, socket);
}
@ -43,7 +48,7 @@ export async function run({
return server.reply({
cmd: 'warn', // @todo Add numeric error code as `id`
text: 'You are not the admin, liar!',
channel: socket.channel, // @todo Multichannel
channel, // @todo Multichannel
}, socket);
}
@ -51,13 +56,13 @@ export async function run({
return server.reply({
cmd: 'warn', // @todo Add numeric error code as `id`
text: 'You already have that name',
channel: socket.channel, // @todo Multichannel
channel, // @todo Multichannel
}, socket);
}
// find any sockets that have the same nickname
const userExists = server.findSockets({
channel: socket.channel,
channel,
nick: (targetNick) => targetNick.toLowerCase() === newNick.toLowerCase()
// Allow them to rename themselves to a different case
&& targetNick != previousNick,
@ -69,37 +74,57 @@ export async function run({
return server.reply({
cmd: 'warn', // @todo Add numeric error code as `id`
text: 'Nickname taken',
channel: socket.channel, // @todo Multichannel
channel, // @todo Multichannel
}, socket);
}
// build join and leave notices
// @todo this is a legacy client holdover, name changes in the future will
// have thieir own event
// build update notice with new nickname
const updateNotice = {
...getUserDetails(socket),
...{
cmd: 'updateUser',
nick: newNick,
channel, // @todo Multichannel
}
};
// build join and leave notices for legacy clients
const leaveNotice = {
cmd: 'onlineRemove',
userid: socket.userid,
nick: socket.nick,
channel: socket.channel, // @todo Multichannel
channel, // @todo Multichannel
};
const joinNotice = {
cmd: 'onlineAdd',
nick: newNick,
trip: socket.trip || 'null',
hash: socket.hash,
channel: socket.channel, // @todo Multichannel
...getUserDetails(socket),
...{
cmd: 'onlineAdd',
nick: newNick,
channel, // @todo Multichannel
},
};
// 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 });
// gather channel peers
const peerList = server.findSockets({ channel });
for (let i = 0, l = peerList.length; i < l; i += 1) {
if (peerList[i].hcProtocol === 1) {
// send join/leave to legacy clients
server.send(leaveNotice, peerList[i]);
server.send(joinNotice, peerList[i]);
} else {
// send update info
// @todo this should be sent to every channel the client is in
server.send(updateNotice, peerList[i]);
}
}
// notify channel that the user has changed their name
server.broadcast({
cmd: 'info',
text: `${socket.nick} is now ${newNick}`,
channel: socket.channel, // @todo Multichannel
}, { channel: socket.channel });
channel, // @todo Multichannel
}, { channel });
// commit change to nickname
socket.nick = newNick; // eslint-disable-line no-param-reassign

View File

@ -2,7 +2,10 @@
Description: Rebroadcasts any `text` to all clients in a `channel`
*/
import * as UAC from '../utility/UAC/_info';
import {
isAdmin,
isModerator,
} from '../utility/_UAC';
// module support functions
const parseText = (text) => {
@ -54,9 +57,9 @@ export async function run({
level: socket.level,
};
if (UAC.isAdmin(socket.level)) {
if (isAdmin(socket.level)) {
outgoingPayload.admin = true;
} else if (UAC.isModerator(socket.level)) {
} else if (isModerator(socket.level)) {
outgoingPayload.mod = true;
}
@ -64,6 +67,10 @@ export async function run({
outgoingPayload.trip = socket.trip; /* @legacy */
}
if (socket.color) {
outgoingPayload.color = socket.color;
}
// broadcast to channel peers
server.broadcast(outgoingPayload, { channel: socket.channel });

View File

@ -4,7 +4,6 @@
Description: Adds requested channel into the calling clients "subscribed channels"
*/
// import * as UAC from '../utility/UAC/_info';
import {
canJoinChannel,
} from '../utility/_Channels';
@ -18,6 +17,7 @@ import {
import {
verifyNickname,
getUserPerms,
getUserDetails,
} from '../utility/_UAC';
// module main
@ -76,6 +76,7 @@ export async function run({
// get trip and level
const { trip, level } = getUserPerms(pass, core.config, channel);
// store the user values
const userInfo = {
nick,
@ -84,6 +85,8 @@ export async function run({
hash: socket.hash,
level,
userid: socket.userid,
isBot: socket.isBot,
color: socket.color,
channel,
};
@ -119,18 +122,14 @@ export async function run({
// send join announcement and prep online set reply
for (let i = 0, l = newPeerList.length; i < l; i += 1) {
server.reply(joinAnnouncement, newPeerList[i]);
nicks.push(newPeerList[i].nick); /* @legacy */
users.push({
nick: newPeerList[i].nick,
trip: newPeerList[i].trip,
uType: newPeerList[i].uType, /* @legacy */
hash: newPeerList[i].hash,
level: newPeerList[i].level,
userid: newPeerList[i].userid,
channel,
isme: false,
isBot: newPeerList[i].isBot,
...{
channel,
isme: false,
},
...getUserDetails(newPeerList[i]),
});
}

View File

@ -2,6 +2,11 @@
Description: Changes the current channel of the calling socket
@deprecated This module will be removed or replaced
*/
import {
verifyNickname,
getUserPerms,
getUserDetails,
} from '../utility/_UAC';
// module main
export async function run({ server, socket, payload }) {
@ -27,7 +32,7 @@ export async function run({ server, socket, payload }) {
}, socket);
}
if (payload.channel === socket.channel) {
if (payload.channel === socket.channel) { // @todo Multichannel update
// they are trying to rejoin the channel
return true;
}
@ -52,41 +57,61 @@ export async function run({ server, socket, payload }) {
server.reply({
cmd: 'onlineRemove',
nick: peerList[i].nick,
userid: peerList[i].userid,
channel: socket.channel, // @todo Multichannel
}, socket);
if (socket.nick !== peerList[i].nick) {
if (socket.userid !== peerList[i].userid) {
server.reply({
cmd: 'onlineRemove',
nick: socket.nick,
userid: socket.userid,
channel: socket.channel, // @todo Multichannel
}, peerList[i]);
}
}
}
// @todo import function from join module
// broadcast join notice to new peers
const newPeerList = server.findSockets({ channel: payload.channel });
const moveAnnouncement = {
cmd: 'onlineAdd',
nick: socket.nick,
trip: socket.trip || 'null',
hash: socket.hash,
...{
cmd: 'onlineAdd',
channel: payload.channel, // @todo Multichannel
},
...getUserDetails(socket),
};
const nicks = [];
const users = [];
for (let i = 0, l = newPeerList.length; i < l; i += 1) {
server.reply(moveAnnouncement, newPeerList[i]);
nicks.push(newPeerList[i].nick);
nicks.push(newPeerList[i].nick); /* @legacy */
users.push({
...{
channel: payload.channel,
isme: false,
},
...getUserDetails(newPeerList[i]),
});
}
nicks.push(socket.nick);
nicks.push(socket.nick); /* @legacy */
users.push({
...{
channel: payload.channel,
isme: true,
},
...getUserDetails(socket)
});
// reply with new user list
server.reply({
cmd: 'onlineSet',
nicks,
users,
channel: socket.channel, // @todo Multichannel (!)
}, socket);

View File

@ -55,6 +55,7 @@ export async function run({ server, socket, payload }) {
socket.userid = Math.floor(Math.random() * 9999999999999);
socket.hash = server.getSocketHash(socket);
socket.isBot = payload.isBot || false;
socket.color = false;
// dispatch info
server.reply({

View File

@ -90,6 +90,8 @@ export async function run({ server, socket, payload }) {
server.reply(outgoingPayload, socket);
}
targetUser.whisperReply = socket.nick;
return true;
}
@ -161,6 +163,7 @@ export function whisperCheck({
payload: {
cmd: 'whisper',
nick: socket.whisperReply,
channel: socket.channel, // @todo Multichannel
text: whisperText,
},
});

View File

@ -3,7 +3,11 @@
Description: Adds the target socket's ip to the ratelimiter
*/
import * as UAC from '../utility/UAC/_info';
import {
isModerator,
getUserDetails,
levels,
} from '../utility/_UAC';
import {
Errors,
} from '../utility/_Constants';
@ -16,7 +20,7 @@ export async function run({
core, server, socket, payload,
}) {
// increase rate limit chance and ignore if not admin or mod
if (!UAC.isModerator(socket.level)) {
if (!isModerator(socket.level)) {
return server.police.frisk(socket.address, 10);
}
@ -62,9 +66,9 @@ export async function run({
server.broadcast({
cmd: 'info',
text: `Banned ${targetNick}`,
user: UAC.getUserDetails(targetUser),
user: getUserDetails(targetUser),
channel: socket.channel, // @todo Multichannel
}, { channel: socket.channel, level: (level) => level < UAC.levels.moderator });
}, { channel: socket.channel, level: (level) => level < levels.moderator });
// notify mods
server.broadcast({
@ -72,9 +76,9 @@ export async function run({
text: `${socket.nick}#${socket.trip} banned ${targetNick} in ${payload.channel}, userhash: ${targetUser.hash}`,
channel: socket.channel, // @todo Multichannel
inChannel: payload.channel,
user: UAC.getUserDetails(targetUser),
banner: UAC.getUserDetails(socket),
}, { level: UAC.isModerator });
user: getUserDetails(targetUser),
banner: getUserDetails(socket),
}, { level: isModerator });
// force connection closed
targetUser.terminate();

View File

@ -6,7 +6,9 @@
* Author: simple
*/
import * as UAC from '../utility/UAC/_info';
import {
isModerator,
} from '../utility/_UAC';
import {
Errors,
} from '../utility/_Constants';
@ -26,7 +28,7 @@ export async function run({
core, server, socket, payload,
}) {
// increase rate limit chance and ignore if not admin or mod
if (!UAC.isModerator(socket.level)) {
if (!isModerator(socket.level)) {
return server.police.frisk(socket.address, 10);
}
@ -77,7 +79,7 @@ export async function run({
cmd: 'info',
text: `${socket.nick}#${socket.trip} muzzled ${targetUser.nick} in ${payload.channel}, userhash: ${targetUser.hash}`,
channel: false, // @todo Multichannel, false for global
}, { level: UAC.isModerator });
}, { level: isModerator });
return true;
}

View File

@ -4,7 +4,11 @@
Description: Forces a change on the target(s) socket's channel, then broadcasts event
*/
import * as UAC from '../utility/UAC/_info';
import {
isModerator,
levels,
getUserDetails,
} from '../utility/_UAC';
import {
Errors,
} from '../utility/_Constants';
@ -17,7 +21,7 @@ export async function run({
core, server, socket, payload,
}) {
// increase rate limit chance and ignore if not admin or mod
if (!UAC.isModerator(socket.level)) {
if (!isModerator(socket.level)) {
return server.police.frisk(socket.address, 10);
}
@ -76,17 +80,15 @@ export async function run({
// Announce the kicked clients arrival in destChannel and that they were kicked
// Before they arrive, so they don't see they got moved
for (let i = 0; i < kicked.length; i += 1) {
server.broadcast({
const moveAnnouncement = {
...getUserDetails(socket),
...{
cmd: 'onlineAdd',
nick: kicked[i].nick,
trip: kicked[i].trip || 'null',
uType: 'user',
hash: kicked[i].hash,
level: UAC.levels.default,
userid: kicked[i].userid,
channel: destChannel,
}, { channel: destChannel });
channel: destChannel, // @todo Multichannel
},
};
for (let i = 0; i < kicked.length; i += 1) {
server.broadcast(moveAnnouncement, { channel: destChannel });
}
// Move all kicked clients to the new channel
@ -98,7 +100,7 @@ export async function run({
cmd: 'info',
text: `${kicked[i].nick} was banished to ?${destChannel}`,
channel: socket.channel, // @todo Multichannel
}, { channel: socket.channel, level: UAC.isModerator });
}, { channel: socket.channel, level: isModerator });
console.log(`${socket.nick} [${socket.trip}] kicked ${kicked[i].nick} in ${socket.channel} to ${destChannel} `);
}
@ -118,7 +120,7 @@ export async function run({
cmd: 'info',
text: `Kicked ${kicked.map((k) => k.nick).join(', ')}`,
channel: socket.channel, // @todo Multichannel
}, { channel: socket.channel, level: (level) => level < UAC.levels.moderator });
}, { channel: socket.channel, level: (level) => level < levels.moderator });
// stats are fun
core.stats.increment('users-kicked', kicked.length);

View File

@ -3,12 +3,15 @@
@deprecated This module will be removed or replaced
*/
import * as UAC from '../utility/UAC/_info';
import {
isModerator,
getUserDetails,
} from '../utility/_UAC';
// module main
export async function run({ server, socket, payload }) {
// increase rate limit chance and ignore if not admin or mod
if (!UAC.isModerator(socket.level)) {
if (!isModerator(socket.level)) {
return server.police.frisk(socket.address, 10);
}
@ -59,6 +62,7 @@ export async function run({ server, socket, payload }) {
for (let i = 0, l = peerList.length; i < l; i += 1) {
server.reply({
cmd: 'onlineRemove',
userid: peerList[i].userid,
nick: peerList[i].nick,
channel: socket.channel, // @todo Multichannel
}, badClient);
@ -66,6 +70,7 @@ export async function run({ server, socket, payload }) {
if (badClient.nick !== peerList[i].nick) {
server.reply({
cmd: 'onlineRemove',
userid: badClient.userid,
nick: badClient.nick,
channel: socket.channel, // @todo Multichannel
}, peerList[i]);
@ -73,27 +78,43 @@ export async function run({ server, socket, payload }) {
}
}
// @todo import from join module
const newPeerList = server.findSockets({ channel: payload.channel });
const moveAnnouncement = {
cmd: 'onlineAdd',
nick: badClient.nick,
trip: badClient.trip || 'null',
hash: server.getSocketHash(badClient),
...getUserDetails(badClient),
...{
cmd: 'onlineAdd',
channel: payload.channel, // @todo Multichannel
},
};
const nicks = [];
const users = [];
for (let i = 0, l = newPeerList.length; i < l; i += 1) {
server.reply(moveAnnouncement, newPeerList[i]);
nicks.push(newPeerList[i].nick);
nicks.push(newPeerList[i].nick); /* @legacy */
users.push({
...{
channel,
isme: false,
},
...getUserDetails(newPeerList[i]),
});
}
nicks.push(badClient.nick);
nicks.push(badClient.nick); /* @legacy */
users.push({
...{
isme: true,
},
...getUserDetails(badClient),
});
server.reply({
cmd: 'onlineSet',
nicks,
channel: socket.channel, // @todo Multichannel (!)
nicks, /* @legacy */
users,
channel, // @todo Multichannel (?)
}, badClient);
badClient.channel = payload.channel;
@ -101,7 +122,7 @@ export async function run({ server, socket, payload }) {
server.broadcast({
cmd: 'info',
text: `${badClient.nick} was moved into ?${payload.channel}`,
channel: socket.channel, // @todo Multichannel
channel: payload.channel, // @todo Multichannel
}, { channel: payload.channel });
return true;

View File

@ -5,7 +5,9 @@
* Author: simple
*/
import * as UAC from '../utility/UAC/_info';
import {
isModerator,
} from '../utility/_UAC';
// module constructor
export function init(core) {
@ -19,7 +21,7 @@ export async function run({
core, server, socket, payload,
}) {
// increase rate limit chance and ignore if not admin or mod
if (!UAC.isModerator(socket.level)) {
if (!isModerator(socket.level)) {
return server.police.frisk(socket.address, 10);
}
@ -40,7 +42,7 @@ export async function run({
cmd: 'info',
text: `${socket.nick} unmuzzled all users`,
channel: false, // @todo Multichannel, false for global
}, { level: UAC.isModerator });
}, { level: isModerator });
}
} else if (payload.hash === '*') {
core.muzzledHashes = {};
@ -49,7 +51,7 @@ export async function run({
cmd: 'info',
text: `${socket.nick} unmuzzled all users`,
channel: false, // @todo Multichannel, false for global
}, { level: UAC.isModerator });
}, { level: isModerator });
}
// find target & remove mute status
@ -67,7 +69,7 @@ export async function run({
cmd: 'info',
text: `${socket.nick}#${socket.trip} unmuzzled : ${target}`,
channel: false, // @todo Multichannel, false for global
}, { level: UAC.isModerator });
}, { level: isModerator });
return true;
}

View File

@ -4,14 +4,16 @@
Description: Removes a target ip from the ratelimiter
*/
import * as UAC from '../utility/UAC/_info';
import {
isModerator,
} from '../utility/_UAC';
// module main
export async function run({
core, server, socket, payload,
}) {
// increase rate limit chance and ignore if not admin or mod
if (!UAC.isModerator(socket.level)) {
if (!isModerator(socket.level)) {
return server.police.frisk(socket.address, 10);
}
@ -56,7 +58,7 @@ export async function run({
cmd: 'info',
text: `${socket.nick}#${socket.trip} unbanned: ${target}`,
channel: false, // @todo Multichannel, false for global
}, { level: UAC.isModerator });
}, { level: isModerator });
// stats are fun
core.stats.decrement('users-banned');

View File

@ -4,12 +4,14 @@
Description: Clears all bans and ratelimits
*/
import * as UAC from '../utility/UAC/_info';
import {
isModerator,
} from '../utility/_UAC';
// module main
export async function run({ core, server, socket }) {
// increase rate limit chance and ignore if not admin or mod
if (!UAC.isModerator(socket.level)) {
if (!isModerator(socket.level)) {
return server.police.frisk(socket.address, 10);
}
@ -32,7 +34,7 @@ export async function run({ core, server, socket }) {
cmd: 'info',
text: `${socket.nick}#${socket.trip} unbanned all ip addresses`,
channel: false, // @todo Multichannel, false for global
}, { level: UAC.isModerator });
}, { level: isModerator });
return true;
}

View File

@ -1,119 +0,0 @@
// NOTE: this has been moved into /utility/ as _UAC.js
/**
* User Account Control information containing level constants
* and simple helper functions related to users
* @property {Object} levels - Defines labels for default permission ranges
* @author MinusGix ( https://github.com/MinusGix )
* @version v1.0.0
* @license WTFPL ( http://www.wtfpl.net/txt/copying/ )
*/
/**
* Object defining labels for default permission ranges
* @typedef {Object} levels
* @property {number} admin Global administrator range
* @property {number} moderator Global moderator range
* @property {number} channelOwner Local administrator range
* @property {number} channelModerator Local moderator range
* @property {number} channelTrusted Local (non-public) channel trusted
* @property {number} trustedUser Public channel trusted
* @property {number} default Default user level
*/
export const levels = {
admin: 9999999,
moderator: 999999,
channelOwner: 99999,
channelModerator: 9999,
channelTrusted: 8999,
trustedUser: 500,
default: 100,
};
/**
* Returns true if target level is equal or greater than the global admin level
* @public
* @param {number} level Level to verify
* @return {boolean}
*/
export function isAdmin(level) {
return level >= levels.admin;
}
/**
* Returns true if target level is equal or greater than the global moderator level
* @public
* @param {number} level Level to verify
* @return {boolean}
*/
export function isModerator(level) {
return level >= levels.moderator;
}
/**
* Returns true if target level is equal or greater than the channel owner level
* @public
* @param {number} level Level to verify
* @return {boolean}
*/
export function isChannelOwner(level) {
return level >= levels.channelOwner;
}
/**
* Returns true if target level is equal or greater than the channel moderator level
* @public
* @param {number} level Level to verify
* @return {boolean}
*/
export function isChannelModerator(level) {
return level >= levels.channelModerator;
}
/**
* Returns true if target level is equal or greater than the channel trust level
* @public
* @param {number} level Level to verify
* @return {boolean}
*/
export function isChannelTrusted(level) {
return level >= levels.channelTrusted;
}
/**
* Returns true if target level is equal or greater than a trusted user
* @public
* @param {number} level Level to verify
* @return {boolean}
*/
export function isTrustedUser(level) {
return level >= levels.trustedUser;
}
/**
* Return an object containing public information about the socket
* @public
* @param {WebSocket} socket Target client
* @return {Object}
*/
export function getUserDetails(socket) {
return {
uType: socket.uType,
nick: socket.nick,
trip: socket.trip || 'null',
hash: socket.hash,
level: socket.level,
userid: socket.userid,
};
}
/**
* Returns true if the nickname is valid
* @public
* @param {string} nick Nickname to verify
* @return {boolean}
*/
export function verifyNickname(nick) {
return /^[a-zA-Z0-9_]{1,24}$/.test(nick);
}

View File

@ -22,6 +22,7 @@ export function upgradeLegacyJoin(server, socket, payload) {
// these would have been applied in the `session` module, apply it now
socket.hash = server.getSocketHash(socket);
socket.isBot = false;
socket.color = false;
// pull the password from the nick
const nickArray = payload.nick.split('#', 2);

View File

@ -104,12 +104,14 @@ export function isTrustedUser(level) {
*/
export function getUserDetails(socket) {
return {
uType: socket.uType,
nick: socket.nick,
trip: socket.trip || 'null',
trip: socket.trip || '',
uType: socket.uType,
hash: socket.hash,
level: socket.level,
userid: socket.userid,
isBot: socket.isBot,
color: socket.color,
};
}
@ -154,13 +156,12 @@ export function getUserPerms(pass, config, channel) {
};
}
let level = levels.default;
// check if user is global mod
config.mods.forEach((mod) => { // eslint-disable-line consistent-return
if (trip === mod.trip) {
return {
trip,
level: levels.moderator,
};
level = levels.moderator;
}
});
@ -181,6 +182,6 @@ export function getUserPerms(pass, config, channel) {
return {
trip,
level: levels.default,
level,
};
}