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

normalized

This commit is contained in:
marzavec 2020-09-17 00:44:32 -05:00
parent 6266b1432d
commit 72324050f5
45 changed files with 1873 additions and 241 deletions

14
.editorconfig Normal file
View File

@ -0,0 +1,14 @@
# editorconfig.org
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 2
trim_trailing_whitespace = true
[*.md]
trim_trailing_whitespace = false

15
.eslintrc.js Normal file
View File

@ -0,0 +1,15 @@
module.exports = {
env: {
browser: true,
commonjs: true,
es2021: true,
},
extends: [
'airbnb-base',
],
parserOptions: {
ecmaVersion: 12,
},
rules: {
},
};

107
.gitattributes vendored Normal file
View File

@ -0,0 +1,107 @@
# From https://github.com/Danimoth/gitattributes/blob/master/Web.gitattributes
# Handle line endings automatically for files detected as text
# and leave all files detected as binary untouched.
* text=auto
#
# The above will handle all files NOT found below
#
#
## These files are text and should be normalized (Convert crlf => lf)
#
# source code
*.php text
*.css text
*.sass text
*.scss text
*.less text
*.styl text
*.js text eol=lf
*.coffee text
*.json text
*.htm text
*.html text
*.xml text
*.svg text
*.txt text
*.ini text
*.inc text
*.pl text
*.rb text
*.py text
*.scm text
*.sql text
*.sh text
*.bat text
# templates
*.ejs text
*.hbt text
*.jade text
*.haml text
*.hbs text
*.dot text
*.tmpl text
*.phtml text
# server config
.htaccess text
.nginx.conf text
# git config
.gitattributes text
.gitignore text
.gitconfig text
# code analysis config
.jshintrc text
.jscsrc text
.jshintignore text
.csslintrc text
# misc config
*.yaml text
*.yml text
.editorconfig text
# build config
*.npmignore text
*.bowerrc text
# Heroku
Procfile text
.slugignore text
# Documentation
*.md text
LICENSE text
AUTHORS text
#
## These files are binary and should be left untouched
#
# (binary is a macro for -text -diff)
*.png binary
*.jpg binary
*.jpeg binary
*.gif binary
*.ico binary
*.mov binary
*.mp4 binary
*.mp3 binary
*.flv binary
*.fla binary
*.swf binary
*.gz binary
*.zip binary
*.7z binary
*.ttf binary
*.eot binary
*.woff binary
*.pyc binary
*.pdf binary

1407
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -18,14 +18,20 @@
"clear": "pm2 flush", "clear": "pm2 flush",
"status": "pm2 list", "status": "pm2 list",
"refresh": "pm2 flush && pm2 stop pm2.config.js && pm2 delete pm2.config.js", "refresh": "pm2 flush && pm2 stop pm2.config.js && pm2 delete pm2.config.js",
"postinstall": "cd ./server && npm install && npm run config" "postinstall": "cd ./server && npm install && npm run config",
"lint": "eslint --ignore-path .gitignore -- ./server ",
"lint:fix": "eslint --ignore-path .gitignore --fix -- ./server "
}, },
"author": "Marzavec", "author": "Marzavec",
"license": "WTFPL", "license": "WTFPL",
"dependencies": { "dependencies": {
"esm": "^3.2.25", "esm": "^3.2.25",
"http-server": "^0.12.3", "http-server": "^0.12.3",
"pm2": "^4.4.1", "pm2": "^4.4.1"
"react-icons": "^3.11.0" },
"devDependencies": {
"eslint": "^7.9.0",
"eslint-config-airbnb-base": "^14.2.0",
"eslint-plugin-import": "^2.22.0"
} }
} }

View File

@ -6,7 +6,7 @@
*/ */
// import and initialize the core application // import and initialize the core application
import { CoreApp } from './src/serverLib/CoreApp'; import CoreApp from './src/serverLib/CoreApp';
const coreApp = new CoreApp(); const coreApp = new CoreApp();
coreApp.init(); coreApp.init();

View File

@ -5,17 +5,19 @@
import * as UAC from '../utility/UAC/_info'; import * as UAC from '../utility/UAC/_info';
// module main // module main
export async function run(core, server, socket, data) { export async function run({
core, server, socket, payload,
}) {
// increase rate limit chance and ignore if not admin // increase rate limit chance and ignore if not admin
if (!UAC.isAdmin(socket.level)) { if (!UAC.isAdmin(socket.level)) {
return server.police.frisk(socket.address, 20); return server.police.frisk(socket.address, 20);
} }
// add new trip to config // add new trip to config
core.config.mods.push({ trip: data.trip }); core.config.mods.push({ trip: payload.trip });
// find targets current connections // find targets current connections
const newMod = server.findSockets({ trip: data.trip }); const newMod = server.findSockets({ trip: payload.trip });
if (newMod.length !== 0) { if (newMod.length !== 0) {
for (let i = 0, l = newMod.length; i < l; i += 1) { for (let i = 0, l = newMod.length; i < l; i += 1) {
// upgrade privilages // upgrade privilages
@ -33,13 +35,13 @@ export async function run(core, server, socket, data) {
// return success message // return success message
server.reply({ server.reply({
cmd: 'info', cmd: 'info',
text: `Added mod trip: ${data.trip}, remember to run 'saveconfig' to make it permanent`, text: `Added mod trip: ${payload.trip}, remember to run 'saveconfig' to make it permanent`,
}, socket); }, socket);
// notify all mods // notify all mods
server.broadcast({ server.broadcast({
cmd: 'info', cmd: 'info',
text: `Added mod: ${data.trip}`, text: `Added mod: ${payload.trip}`,
}, { level: UAC.isModerator }); }, { level: UAC.isModerator });
return true; return true;

View File

@ -1,3 +1,7 @@
/* eslint no-unused-vars: 0 */
/* eslint no-restricted-syntax: 0 */
/* eslint guard-for-in: 0 */
/* /*
Description: Outputs all current channels and their user nicks Description: Outputs all current channels and their user nicks
*/ */
@ -5,7 +9,7 @@
import * as UAC from '../utility/UAC/_info'; import * as UAC from '../utility/UAC/_info';
// module main // module main
export async function run(core, server, socket) { export async function run({ server, socket }) {
// increase rate limit chance and ignore if not admin // increase rate limit chance and ignore if not admin
if (!UAC.isAdmin(socket.level)) { if (!UAC.isAdmin(socket.level)) {
return server.police.frisk(socket.address, 20); return server.police.frisk(socket.address, 20);

View File

@ -5,7 +5,9 @@
import * as UAC from '../utility/UAC/_info'; import * as UAC from '../utility/UAC/_info';
// module main // module main
export async function run(core, server, socket, data) { export async function run({
core, server, socket, payload,
}) {
// increase rate limit chance and ignore if not admin // increase rate limit chance and ignore if not admin
if (!UAC.isAdmin(socket.level)) { if (!UAC.isAdmin(socket.level)) {
return server.police.frisk(socket.address, 20); return server.police.frisk(socket.address, 20);
@ -26,8 +28,8 @@ export async function run(core, server, socket, data) {
${loadResult}`; ${loadResult}`;
} }
if (typeof data.reason !== 'undefined') { if (typeof payload.reason !== 'undefined') {
loadResult += `\nReason: ${data.reason}`; loadResult += `\nReason: ${payload.reason}`;
} }
// send results to moderators (which the user using this command is higher than) // send results to moderators (which the user using this command is higher than)

View File

@ -5,17 +5,20 @@
import * as UAC from '../utility/UAC/_info'; import * as UAC from '../utility/UAC/_info';
// module main // module main
export async function run(core, server, socket, data) { export async function run({
core, server, socket, payload,
}) {
// increase rate limit chance and ignore if not admin // increase rate limit chance and ignore if not admin
if (!UAC.isAdmin(socket.level)) { if (!UAC.isAdmin(socket.level)) {
return server.police.frisk(socket.address, 20); return server.police.frisk(socket.address, 20);
} }
// remove trip from config // remove trip from config
core.config.mods = core.config.mods.filter((mod) => mod.trip !== data.trip); // eslint-disable-next-line no-param-reassign
core.config.mods = core.config.mods.filter((mod) => mod.trip !== payload.trip);
// find targets current connections // find targets current connections
const targetMod = server.findSockets({ trip: data.trip }); const targetMod = server.findSockets({ trip: payload.trip });
if (targetMod.length !== 0) { if (targetMod.length !== 0) {
for (let i = 0, l = targetMod.length; i < l; i += 1) { for (let i = 0, l = targetMod.length; i < l; i += 1) {
// downgrade privilages // downgrade privilages
@ -34,14 +37,14 @@ export async function run(core, server, socket, data) {
server.reply({ server.reply({
cmd: 'info', cmd: 'info',
text: `Removed mod trip: ${ text: `Removed mod trip: ${
data.trip payload.trip
}, remember to run 'saveconfig' to make it permanent`, }, remember to run 'saveconfig' to make it permanent`,
}, socket); }, socket);
// notify all mods // notify all mods
server.broadcast({ server.broadcast({
cmd: 'info', cmd: 'info',
text: `Removed mod: ${data.trip}`, text: `Removed mod: ${payload.trip}`,
}, { level: UAC.isModerator }); }, { level: UAC.isModerator });
return true; return true;

View File

@ -5,7 +5,7 @@
import * as UAC from '../utility/UAC/_info'; import * as UAC from '../utility/UAC/_info';
// module main // module main
export async function run(core, server, socket) { export async function run({ core, server, socket }) {
// increase rate limit chance and ignore if not admin // increase rate limit chance and ignore if not admin
if (!UAC.isAdmin(socket.level)) { if (!UAC.isAdmin(socket.level)) {
return server.police.frisk(socket.address, 20); return server.police.frisk(socket.address, 20);

View File

@ -5,7 +5,7 @@
import * as UAC from '../utility/UAC/_info'; import * as UAC from '../utility/UAC/_info';
// module main // module main
export async function run(core, server, socket, data) { export async function run({ server, socket, payload }) {
// increase rate limit chance and ignore if not admin // increase rate limit chance and ignore if not admin
if (!UAC.isAdmin(socket.level)) { if (!UAC.isAdmin(socket.level)) {
return server.police.frisk(socket.address, 20); return server.police.frisk(socket.address, 20);
@ -14,7 +14,7 @@ export async function run(core, server, socket, data) {
// send text to all channels // send text to all channels
server.broadcast({ server.broadcast({
cmd: 'info', cmd: 'info',
text: `Server Notice: ${data.text}`, text: `Server Notice: ${payload.text}`,
}, {}); }, {});
return true; return true;

View File

@ -1,3 +1,5 @@
/* eslint eqeqeq: 0 */
/* /*
Description: Allows calling client to change their current nickname Description: Allows calling client to change their current nickname
*/ */
@ -5,7 +7,9 @@
import * as UAC from '../utility/UAC/_info'; import * as UAC from '../utility/UAC/_info';
// module main // module main
export async function run(core, server, socket, data) { export async function run({
core, server, socket, payload,
}) {
if (server.police.frisk(socket.address, 6)) { if (server.police.frisk(socket.address, 6)) {
return server.reply({ return server.reply({
cmd: 'warn', // @todo Remove english and change to numeric id cmd: 'warn', // @todo Remove english and change to numeric id
@ -14,14 +18,14 @@ export async function run(core, server, socket, data) {
} }
// verify user data is string // verify user data is string
if (typeof data.nick !== 'string') { if (typeof payload.nick !== 'string') {
return true; return true;
} }
const previousNick = socket.nick; const previousNick = socket.nick;
// make sure requested nickname meets standards // make sure requested nickname meets standards
const newNick = data.nick.trim(); const newNick = payload.nick.trim();
if (!UAC.verifyNickname(newNick)) { if (!UAC.verifyNickname(newNick)) {
return server.reply({ return server.reply({
cmd: 'warn', // @todo Remove english and change to numeric id cmd: 'warn', // @todo Remove english and change to numeric id
@ -30,7 +34,7 @@ export async function run(core, server, socket, data) {
} }
// prevent admin impersonation // prevent admin impersonation
// TODO: prevent mod impersonation // @todo prevent mod impersonation
if (newNick.toLowerCase() === core.config.adminName.toLowerCase()) { if (newNick.toLowerCase() === core.config.adminName.toLowerCase()) {
server.police.frisk(socket.address, 4); server.police.frisk(socket.address, 4);
@ -50,9 +54,9 @@ export async function run(core, server, socket, data) {
// find any sockets that have the same nickname // find any sockets that have the same nickname
const userExists = server.findSockets({ const userExists = server.findSockets({
channel: socket.channel, channel: socket.channel,
nick: (targetNick) => targetNick.toLowerCase() === newNick.toLowerCase() && nick: (targetNick) => targetNick.toLowerCase() === newNick.toLowerCase()
// Allow them to rename themselves to a different case // Allow them to rename themselves to a different case
targetNick != previousNick, && targetNick != previousNick,
}); });
// return error if found // return error if found
@ -65,7 +69,7 @@ export async function run(core, server, socket, data) {
} }
// build join and leave notices // build join and leave notices
// TODO: this is a legacy client holdover, name changes in the future will // @todo this is a legacy client holdover, name changes in the future will
// have thieir own event // have thieir own event
const leaveNotice = { const leaveNotice = {
cmd: 'onlineRemove', cmd: 'onlineRemove',
@ -90,7 +94,7 @@ export async function run(core, server, socket, data) {
}, { channel: socket.channel }); }, { channel: socket.channel });
// commit change to nickname // commit change to nickname
socket.nick = newNick; socket.nick = newNick; // eslint-disable-line no-param-reassign
return true; return true;
} }
@ -101,7 +105,9 @@ export function initHooks(server) {
} }
// hooks chat commands checking for /nick // hooks chat commands checking for /nick
export function nickCheck(core, server, socket, payload) { export function nickCheck({
core, server, socket, payload,
}) {
if (typeof payload.text !== 'string') { if (typeof payload.text !== 'string') {
return false; return false;
} }
@ -121,9 +127,14 @@ export function nickCheck(core, server, socket, payload) {
const newNick = input[1].replace(/@/g, ''); const newNick = input[1].replace(/@/g, '');
this.run(core, server, socket, { this.run({
cmd: 'changenick', core,
nick: newNick, server,
socket,
payload: {
cmd: 'changenick',
nick: newNick,
},
}); });
return false; return false;

View File

@ -22,9 +22,11 @@ const parseText = (text) => {
}; };
// module main // module main
export async function run(core, server, socket, data) { export async function run({
core, server, socket, payload,
}) {
// check user input // check user input
const text = parseText(data.text); const text = parseText(payload.text);
if (!text) { if (!text) {
// lets not send objects or empty text, yea? // lets not send objects or empty text, yea?
@ -41,7 +43,7 @@ export async function run(core, server, socket, data) {
} }
// build chat payload // build chat payload
const payload = { const outgoingPayload = {
cmd: 'chat', cmd: 'chat',
nick: socket.nick, /* @legacy */ nick: socket.nick, /* @legacy */
userid: socket.userid, userid: socket.userid,
@ -51,17 +53,17 @@ export async function run(core, server, socket, data) {
}; };
if (UAC.isAdmin(socket.level)) { if (UAC.isAdmin(socket.level)) {
payload.admin = true; outgoingPayload.admin = true;
} else if (UAC.isModerator(socket.level)) { } else if (UAC.isModerator(socket.level)) {
payload.mod = true; outgoingPayload.mod = true;
} }
if (socket.trip) { if (socket.trip) {
payload.trip = socket.trip; /* @legacy */ outgoingPayload.trip = socket.trip; /* @legacy */
} }
// broadcast to channel peers // broadcast to channel peers
server.broadcast(payload, { channel: socket.channel }); server.broadcast(outgoingPayload, { channel: socket.channel });
// stats are fun // stats are fun
core.stats.increment('messages-sent'); core.stats.increment('messages-sent');
@ -76,7 +78,7 @@ export function initHooks(server) {
} }
// checks for miscellaneous '/' based commands // checks for miscellaneous '/' based commands
export function commandCheckIn(core, server, socket, payload) { export function commandCheckIn({ server, socket, payload }) {
if (typeof payload.text !== 'string') { if (typeof payload.text !== 'string') {
return false; return false;
} }
@ -93,7 +95,7 @@ export function commandCheckIn(core, server, socket, payload) {
return payload; return payload;
} }
export function finalCmdCheck(core, server, socket, payload) { export function finalCmdCheck({ server, socket, payload }) {
if (typeof payload.text !== 'string') { if (typeof payload.text !== 'string') {
return false; return false;
} }
@ -103,7 +105,7 @@ export function finalCmdCheck(core, server, socket, payload) {
} }
if (payload.text.startsWith('//')) { if (payload.text.startsWith('//')) {
payload.text = payload.text.substr(1); payload.text = payload.text.substr(1); // eslint-disable-line no-param-reassign
return payload; return payload;
} }

View File

@ -20,7 +20,7 @@ const parseText = (text) => {
}; };
// module main // module main
export async function run(core, server, socket, payload) { export async function run({ server, socket, payload }) {
// check user input // check user input
let text = parseText(payload.text); let text = parseText(payload.text);
@ -65,7 +65,9 @@ export function initHooks(server) {
} }
// hooks chat commands checking for /me // hooks chat commands checking for /me
export function emoteCheck(core, server, socket, payload) { export function emoteCheck({
core, server, socket, payload,
}) {
if (typeof payload.text !== 'string') { if (typeof payload.text !== 'string') {
return false; return false;
} }
@ -86,9 +88,14 @@ export function emoteCheck(core, server, socket, payload) {
input.splice(0, 1); input.splice(0, 1);
const actionText = input.join(' '); const actionText = input.join(' ');
this.run(core, server, socket, { this.run({
cmd: 'emote', core,
text: actionText, server,
socket,
payload: {
cmd: 'emote',
text: actionText,
},
}); });
return false; return false;

View File

@ -3,7 +3,9 @@
*/ */
// module main // module main
export async function run(core, server, socket, payload) { export async function run({
core, server, socket, payload,
}) {
// check for spam // check for spam
if (server.police.frisk(socket.address, 2)) { if (server.police.frisk(socket.address, 2)) {
return server.reply({ return server.reply({
@ -24,7 +26,9 @@ export async function run(core, server, socket, payload) {
const categories = core.commands.categoriesList.sort(); const categories = core.commands.categoriesList.sort();
for (let i = 0, j = categories.length; i < j; i += 1) { for (let i = 0, j = categories.length; i < j; i += 1) {
reply += `|${categories[i].replace('../src/commands/', '').replace(/^\w/, (c) => c.toUpperCase())}:|`; reply += `|${categories[i].replace('../src/commands/', '').replace(/^\w/, (c) => c.toUpperCase())}:|`;
const catCommands = core.commands.all(categories[i]).sort((a, b) => a.info.name.localeCompare(b.info.name)); const catCommands = core.commands.all(categories[i]).sort(
(a, b) => a.info.name.localeCompare(b.info.name),
);
reply += `${catCommands.map((c) => `${c.info.name}`).join(', ')}|\n`; reply += `${catCommands.map((c) => `${c.info.name}`).join(', ')}|\n`;
} }
@ -40,6 +44,7 @@ export async function run(core, server, socket, payload) {
reply += `|**Aliases:**|${typeof command.info.aliases !== 'undefined' ? command.info.aliases.join(', ') : 'None'}|\n`; reply += `|**Aliases:**|${typeof command.info.aliases !== 'undefined' ? command.info.aliases.join(', ') : 'None'}|\n`;
reply += `|**Category:**|${command.info.category.replace('../src/commands/', '').replace(/^\w/, (c) => c.toUpperCase())}|\n`; reply += `|**Category:**|${command.info.category.replace('../src/commands/', '').replace(/^\w/, (c) => c.toUpperCase())}|\n`;
reply += `|**Required Parameters:**|${command.requiredData || 'None'}|\n`; reply += `|**Required Parameters:**|${command.requiredData || 'None'}|\n`;
// eslint-disable-next-line no-useless-escape
reply += `|**Description:**|${command.info.description || '¯\_(ツ)_/¯'}|\n\n`; reply += `|**Description:**|${command.info.description || '¯\_(ツ)_/¯'}|\n\n`;
reply += `**Usage:** ${command.info.usage || command.info.name}`; reply += `**Usage:** ${command.info.usage || command.info.name}`;
} }
@ -60,7 +65,9 @@ export function initHooks(server) {
} }
// hooks chat commands checking for /whisper // hooks chat commands checking for /whisper
export function helpCheck(core, server, socket, payload) { export function helpCheck({
core, server, socket, payload,
}) {
if (typeof payload.text !== 'string') { if (typeof payload.text !== 'string') {
return false; return false;
} }
@ -68,9 +75,14 @@ export function helpCheck(core, server, socket, payload) {
if (payload.text.startsWith('/help')) { if (payload.text.startsWith('/help')) {
const input = payload.text.substr(1).split(' ', 2); const input = payload.text.substr(1).split(' ', 2);
this.run(core, server, socket, { this.run({
cmd: input[0], core,
command: input[1], server,
socket,
payload: {
cmd: input[0],
command: input[1],
},
}); });
return false; return false;

View File

@ -8,16 +8,17 @@
* @param {any} channel * @param {any} channel
* @return {string} * @return {string}
*/ */
export function getChannel (channel=undefined) { export function getChannel(channel = undefined) {
if (typeof channel === 'string') { if (typeof channel === 'string') {
return channel; return channel;
} else {
return Math.random().toString(36).substr(2, 8);
} }
return Math.random().toString(36).substr(2, 8);
} }
// module main // module main
export async function run(core, server, socket, data) { export async function run({
core, server, socket, payload,
}) {
// check for spam // check for spam
if (server.police.frisk(socket.address, 2)) { if (server.police.frisk(socket.address, 2)) {
return server.reply({ return server.reply({
@ -27,18 +28,18 @@ export async function run(core, server, socket, data) {
} }
// verify user input // verify user input
if (typeof data.userid !== 'number' || typeof data.channel !== 'string') { if (typeof payload.userid !== 'number' || typeof payload.channel !== 'string') {
return true; return true;
} }
// why would you invite yourself? // why would you invite yourself?
if (data.userid === socket.userid) { if (payload.userid === socket.userid) {
return true; return true;
} }
// @todo Verify this socket is part of data.channel - multichannel patch // @todo Verify this socket is part of payload.channel - multichannel patch
// find target user // find target user
let targetClient = server.findSockets({ channel: data.channel, userid: data.userid }); let targetClient = server.findSockets({ channel: payload.channel, userid: payload.userid });
if (targetClient.length === 0) { if (targetClient.length === 0) {
return server.reply({ return server.reply({
@ -50,22 +51,22 @@ export async function run(core, server, socket, data) {
[targetClient] = targetClient; [targetClient] = targetClient;
// generate common channel // generate common channel
const channel = getChannel(data.to); const channel = getChannel(payload.to);
// build invite // build invite
const payload = { const outgoingPayload = {
cmd: 'invite', cmd: 'invite',
channel: socket.channel, channel: socket.channel,
from: socket.userid, from: socket.userid,
to: data.userid, to: payload.userid,
inviteChannel: channel, inviteChannel: channel,
}; };
// send invite notice to target client // send invite notice to target client
server.reply(payload, targetClient); server.reply(outgoingPayload, targetClient);
// send invite notice to this client // send invite notice to this client
server.reply(payload, socket); server.reply(outgoingPayload, socket);
// stats are fun // stats are fun
core.stats.increment('invites-sent'); core.stats.increment('invites-sent');
@ -73,7 +74,7 @@ export async function run(core, server, socket, data) {
return true; return true;
} }
export const requiredData = [];//['nick']; export const requiredData = []; // ['nick'];
export const info = { export const info = {
name: 'invite', name: 'invite',
description: 'Sends an invite to the target client with the provided channel, or a random channel.', description: 'Sends an invite to the target client with the provided channel, or a random channel.',

View File

@ -1,3 +1,5 @@
/* eslint no-param-reassign: 0 */
/* /*
Description: Initial entry point, applies `channel` and `nick` to the calling socket Description: Initial entry point, applies `channel` and `nick` to the calling socket
*/ */
@ -29,7 +31,7 @@ export function parseNickname(core, data) {
return 'Nickname must consist of up to 24 letters, numbers, and underscores'; return 'Nickname must consist of up to 24 letters, numbers, and underscores';
} }
let password = data.pass || false; const password = data.pass || false;
if (hash(password + core.config.tripSalt) === core.config.adminTrip) { if (hash(password + core.config.tripSalt) === core.config.adminTrip) {
userInfo.uType = 'admin'; /* @legacy */ userInfo.uType = 'admin'; /* @legacy */
@ -43,7 +45,7 @@ export function parseNickname(core, data) {
userInfo.trip = hash(password + core.config.tripSalt); userInfo.trip = hash(password + core.config.tripSalt);
} }
// TODO: disallow moderator impersonation // @todo disallow moderator impersonation
// for (const mod of core.config.mods) { // for (const mod of core.config.mods) {
core.config.mods.forEach((mod) => { core.config.mods.forEach((mod) => {
if (userInfo.trip === mod.trip) { if (userInfo.trip === mod.trip) {
@ -56,7 +58,9 @@ export function parseNickname(core, data) {
} }
// module main // module main
export async function run(core, server, socket, data) { export async function run({
core, server, socket, payload,
}) {
// check for spam // check for spam
if (server.police.frisk(socket.address, 3)) { if (server.police.frisk(socket.address, 3)) {
return server.reply({ return server.reply({
@ -75,17 +79,17 @@ export async function run(core, server, socket, data) {
} }
// check user input // check user input
if (typeof data.channel !== 'string' || typeof data.nick !== 'string') { if (typeof payload.channel !== 'string' || typeof payload.nick !== 'string') {
return true; return true;
} }
const channel = data.channel.trim(); const channel = payload.channel.trim();
if (!channel) { if (!channel) {
// must join a non-blank channel // must join a non-blank channel
return true; return true;
} }
const userInfo = this.parseNickname(core, data); const userInfo = this.parseNickname(core, payload);
if (typeof userInfo === 'string') { if (typeof userInfo === 'string') {
return server.reply({ return server.reply({
cmd: 'warn', // @todo Remove english and change to numeric id cmd: 'warn', // @todo Remove english and change to numeric id
@ -95,7 +99,7 @@ export async function run(core, server, socket, data) {
// check if the nickname already exists in the channel // check if the nickname already exists in the channel
const userExists = server.findSockets({ const userExists = server.findSockets({
channel: data.channel, channel: payload.channel,
nick: (targetNick) => targetNick.toLowerCase() === userInfo.nick.toLowerCase(), nick: (targetNick) => targetNick.toLowerCase() === userInfo.nick.toLowerCase(),
}); });
@ -108,13 +112,13 @@ export async function run(core, server, socket, data) {
} }
// populate final userinfo fields // populate final userinfo fields
// @TODO: this could be move into parseNickname, changing the function name to match // @todo this could be move into parseNickname, changing the function name to match
userInfo.hash = server.getSocketHash(socket); userInfo.hash = server.getSocketHash(socket);
userInfo.userid = socket.userid; userInfo.userid = socket.userid;
// @TODO: place this within it's own function allowing import // @todo place this within it's own function allowing import
// prepare to notify channel peers // prepare to notify channel peers
const newPeerList = server.findSockets({ channel: data.channel }); const newPeerList = server.findSockets({ channel: payload.channel });
const nicks = []; /* @legacy */ const nicks = []; /* @legacy */
const users = []; const users = [];
@ -126,7 +130,7 @@ export async function run(core, server, socket, data) {
hash: userInfo.hash, hash: userInfo.hash,
level: userInfo.level, level: userInfo.level,
userid: userInfo.userid, userid: userInfo.userid,
channel: data.channel, channel: payload.channel,
}; };
// send join announcement and prep online set // send join announcement and prep online set
@ -141,7 +145,7 @@ export async function run(core, server, socket, data) {
hash: newPeerList[i].hash, hash: newPeerList[i].hash,
level: newPeerList[i].level, level: newPeerList[i].level,
userid: newPeerList[i].userid, userid: newPeerList[i].userid,
channel: data.channel, channel: payload.channel,
isme: false, isme: false,
}); });
} }
@ -150,7 +154,7 @@ export async function run(core, server, socket, data) {
socket.uType = userInfo.uType; /* @legacy */ socket.uType = userInfo.uType; /* @legacy */
socket.nick = userInfo.nick; socket.nick = userInfo.nick;
socket.trip = userInfo.trip; socket.trip = userInfo.trip;
socket.channel = data.channel; /* @legacy */ socket.channel = payload.channel; /* @legacy */
socket.hash = userInfo.hash; socket.hash = userInfo.hash;
socket.level = userInfo.level; socket.level = userInfo.level;
@ -162,7 +166,7 @@ export async function run(core, server, socket, data) {
hash: socket.hash, hash: socket.hash,
level: socket.level, level: socket.level,
userid: socket.userid, userid: socket.userid,
channel: data.channel, channel: payload.channel,
isme: true, isme: true,
}); });
@ -179,7 +183,7 @@ export async function run(core, server, socket, data) {
return true; return true;
} }
export const requiredData = ['channel', 'nick']; export const requiredData = []; // ['channel', 'nick'];
export const info = { export const info = {
name: 'join', name: 'join',
description: 'Place calling socket into target channel with target nick & broadcast event to channel', description: 'Place calling socket into target channel with target nick & broadcast event to channel',

View File

@ -21,7 +21,7 @@ const formatTime = (time) => {
}; };
// module main // module main
export async function run(core, server, socket) { export async function run({ core, server, socket }) {
// gather connection and channel count // gather connection and channel count
let ips = {}; let ips = {};
let channels = {}; let channels = {};
@ -63,14 +63,21 @@ export function initHooks(server) {
} }
// hooks chat commands checking for /stats // hooks chat commands checking for /stats
export function statsCheck(core, server, socket, payload) { export function statsCheck({
core, server, socket, payload,
}) {
if (typeof payload.text !== 'string') { if (typeof payload.text !== 'string') {
return false; return false;
} }
if (payload.text.startsWith('/stats')) { if (payload.text.startsWith('/stats')) {
this.run(core, server, socket, { this.run({
cmd: 'morestats', core,
server,
socket,
payload: {
cmd: 'morestats',
},
}); });
return false; return false;

View File

@ -1,9 +1,10 @@
/* /*
Description: Changes the current channel of the calling socket Description: Changes the current channel of the calling socket
@deprecated This module will be removed or replaced
*/ */
// module main // module main
export async function run(core, server, socket, data) { export async function run({ server, socket, payload }) {
// check for spam // check for spam
if (server.police.frisk(socket.address, 6)) { if (server.police.frisk(socket.address, 6)) {
return server.reply({ return server.reply({
@ -13,18 +14,18 @@ export async function run(core, server, socket, data) {
} }
// check user input // check user input
if (typeof data.channel !== 'string') { if (typeof payload.channel !== 'string') {
return true; return true;
} }
if (data.channel === '') { if (payload.channel === '') {
return server.reply({ return server.reply({
cmd: 'warn', // @todo Remove english and change to numeric id cmd: 'warn', // @todo Remove english and change to numeric id
text: 'Cannot move to an empty channel.', text: 'Cannot move to an empty channel.',
}, socket); }, socket);
} }
if (data.channel === socket.channel) { if (payload.channel === socket.channel) {
// they are trying to rejoin the channel // they are trying to rejoin the channel
return true; return true;
} }
@ -32,7 +33,7 @@ export async function run(core, server, socket, data) {
// check that the nickname isn't already in target channel // check that the nickname isn't already in target channel
const currentNick = socket.nick.toLowerCase(); const currentNick = socket.nick.toLowerCase();
const userExists = server.findSockets({ const userExists = server.findSockets({
channel: data.channel, channel: payload.channel,
nick: (targetNick) => targetNick.toLowerCase() === currentNick, nick: (targetNick) => targetNick.toLowerCase() === currentNick,
}); });
@ -60,9 +61,9 @@ export async function run(core, server, socket, data) {
} }
} }
// TODO: import function from join module // @todo import function from join module
// broadcast join notice to new peers // broadcast join notice to new peers
const newPeerList = server.findSockets({ channel: data.channel }); const newPeerList = server.findSockets({ channel: payload.channel });
const moveAnnouncement = { const moveAnnouncement = {
cmd: 'onlineAdd', cmd: 'onlineAdd',
nick: socket.nick, nick: socket.nick,
@ -85,7 +86,7 @@ export async function run(core, server, socket, data) {
}, socket); }, socket);
// commit change // commit change
socket.channel = data.channel; socket.channel = payload.channel; // eslint-disable-line no-param-reassign
return true; return true;
} }
@ -95,7 +96,9 @@ export function initHooks(server) {
server.registerHook('in', 'chat', this.moveCheck.bind(this), 29); server.registerHook('in', 'chat', this.moveCheck.bind(this), 29);
} }
export function moveCheck(core, server, socket, payload) { export function moveCheck({
core, server, socket, payload,
}) {
if (typeof payload.text !== 'string') { if (typeof payload.text !== 'string') {
return false; return false;
} }
@ -113,9 +116,14 @@ export function moveCheck(core, server, socket, payload) {
return false; return false;
} }
this.run(core, server, socket, { this.run({
cmd: 'move', core,
channel: input[1], server,
socket,
payload: {
cmd: 'move',
channel: input[1],
},
}); });
return false; return false;

View File

@ -1,3 +1,4 @@
/* eslint no-empty-function: 0 */
/* /*
Description: This module is only in place to supress error notices legacy sources may get Description: This module is only in place to supress error notices legacy sources may get
*/ */

View File

@ -1,3 +1,5 @@
/* eslint no-param-reassign: 0 */
/* /*
Description: Create a new socket session or restore previous session Description: Create a new socket session or restore previous session
*/ */
@ -5,19 +7,19 @@
// module support functions // module support functions
const createSessionID = () => { const createSessionID = () => {
let sessionID = ''; let sessionID = '';
for( let i = 0, j = 32; i < j; i++) { for (let i = 0, j = 32; i < j; i += 1) {
sessionID += Math.random().toString(36).substr(2, 9); sessionID += Math.random().toString(36).substr(2, 9);
} }
return sessionID; return sessionID;
} };
// module main // module main
export async function run(core, server, socket) { export async function run({ server, socket }) {
// gather connection and channel count // gather connection and channel count
let ips = {}; let ips = {};
let channels = {}; let channels = {};
// todo: use public channel flag // @todo use public channel flag
let publicChanCounts = { const publicChanCounts = {
lounge: 0, lounge: 0,
meta: 0, meta: 0,
math: 0, math: 0,
@ -30,13 +32,13 @@ export async function run(core, server, socket) {
chinese: 0, chinese: 0,
}; };
// todo: code resuage between here and `morestats`, export function // todo code resuage between here and `morestats`, export function
server.clients.forEach((client) => { server.clients.forEach((client) => {
if (client.channel) { if (client.channel) {
channels[client.channel] = true; channels[client.channel] = true;
ips[client.address] = true; ips[client.address] = true;
if (typeof publicChanCounts[client.channel] !== 'undefined') { if (typeof publicChanCounts[client.channel] !== 'undefined') {
publicChanCounts[client.channel]++; publicChanCounts[client.channel] += 1;
} }
} }
}); });
@ -47,7 +49,7 @@ export async function run(core, server, socket) {
ips = null; ips = null;
channels = null; channels = null;
// @todo: restore session // @todo restore session
socket.sessionID = createSessionID(); socket.sessionID = createSessionID();
socket.hcProtocol = 2; socket.hcProtocol = 2;
socket.userid = Math.floor(Math.random() * 9999999999999); socket.userid = Math.floor(Math.random() * 9999999999999);
@ -67,5 +69,5 @@ export const info = {
name: 'session', name: 'session',
description: 'Restore previous state by session id or return new session id (currently unavailable)', description: 'Restore previous state by session id or return new session id (currently unavailable)',
usage: ` usage: `
API: { cmd: 'session', id: '<previous session>' }` API: { cmd: 'session', id: '<previous session>' }`,
}; };

View File

@ -3,7 +3,7 @@
*/ */
// module main // module main
export async function run(core, server, socket) { export async function run({ core, server, socket }) {
// gather connection and channel count // gather connection and channel count
let ips = {}; let ips = {};
let channels = {}; let channels = {};

View File

@ -25,7 +25,7 @@ const parseText = (text) => {
}; };
// module main // module main
export async function run(core, server, socket, payload) { export async function run({ server, socket, payload }) {
// check user input // check user input
const text = parseText(payload.text); const text = parseText(payload.text);
@ -85,7 +85,9 @@ export function initHooks(server) {
} }
// hooks chat commands checking for /whisper // hooks chat commands checking for /whisper
export function whisperCheck(core, server, socket, payload) { export function whisperCheck({
core, server, socket, payload,
}) {
if (typeof payload.text !== 'string') { if (typeof payload.text !== 'string') {
return false; return false;
} }
@ -107,10 +109,15 @@ export function whisperCheck(core, server, socket, payload) {
input.splice(0, 2); input.splice(0, 2);
const whisperText = input.join(' '); const whisperText = input.join(' ');
this.run(core, server, socket, { this.run({
cmd: 'whisper', core,
nick: target, server,
text: whisperText, socket,
payload: {
cmd: 'whisper',
nick: target,
text: whisperText,
},
}); });
return false; return false;
@ -130,10 +137,15 @@ export function whisperCheck(core, server, socket, payload) {
input.splice(0, 1); input.splice(0, 1);
const whisperText = input.join(' '); const whisperText = input.join(' ');
this.run(core, server, socket, { this.run({
cmd: 'whisper', core,
nick: socket.whisperReply, server,
text: whisperText, socket,
payload: {
cmd: 'whisper',
nick: socket.whisperReply,
text: whisperText,
},
}); });
return false; return false;

View File

@ -4,8 +4,8 @@
*/ */
// module main // module main
export async function run(core, server, socket, data) { export async function run({ server, socket, payload }) {
if (data.cmdKey !== server.cmdKey) { if (payload.cmdKey !== server.cmdKey) {
// internal command attempt by client, increase rate limit chance and ignore // internal command attempt by client, increase rate limit chance and ignore
return server.police.frisk(socket.address, 20); return server.police.frisk(socket.address, 20);
} }

View File

@ -1,3 +1,5 @@
/* eslint no-param-reassign: 0 */
/* /*
Description: This module adjusts outgoing data, making it compatible with legacy clients Description: This module adjusts outgoing data, making it compatible with legacy clients
Dear god this module is horrifying Dear god this module is horrifying
@ -6,7 +8,7 @@
// import * as UAC from '../utility/UAC/_info'; // import * as UAC from '../utility/UAC/_info';
// module main // module main
export async function run(core, server, socket, data) { export async function run({ server, socket }) {
return server.police.frisk(socket.address, 20); return server.police.frisk(socket.address, 20);
} }
@ -21,14 +23,14 @@ export function initHooks(server) {
} }
// hook incoming join events, if session was not invoked, default proto to 1 // hook incoming join events, if session was not invoked, default proto to 1
export function joinCheck(core, server, socket, payload) { export function joinCheck({ socket, payload }) {
if (typeof socket.hcProtocol === 'undefined') { if (typeof socket.hcProtocol === 'undefined') {
socket.hcProtocol = 1; socket.hcProtocol = 1;
const nickArray = payload.nick.split('#', 2); const nickArray = payload.nick.split('#', 2);
payload.nick = nickArray[0].trim(); payload.nick = nickArray[0].trim();
if (nickArray[1] && typeof payload.pass === 'undefined') { if (nickArray[1] && typeof payload.pass === 'undefined') {
payload.pass = nickArray[1]; payload.pass = nickArray[1]; // eslint-disable-line prefer-destructuring
} }
// dunno how this happened on the legacy version // dunno how this happened on the legacy version
@ -45,9 +47,9 @@ export function joinCheck(core, server, socket, payload) {
} }
// if legacy client sent an invite, downgrade request // if legacy client sent an invite, downgrade request
export function inviteInCheck(core, server, socket, payload) { export function inviteInCheck({ server, socket, payload }) {
if (socket.hcProtocol === 1) { if (socket.hcProtocol === 1) {
let targetClient = server.findSockets({ channel: socket.channel, nick: data.nick }); let targetClient = server.findSockets({ channel: socket.channel, nick: payload.nick });
if (targetClient.length === 0) { if (targetClient.length === 0) {
server.reply({ server.reply({
@ -68,7 +70,7 @@ export function inviteInCheck(core, server, socket, payload) {
} }
// //
export function inviteOutCheck(core, server, socket, payload) { export function inviteOutCheck({ server, socket, payload }) {
if (socket.hcProtocol === 1) { if (socket.hcProtocol === 1) {
payload.cmd = 'info'; payload.cmd = 'info';
if (socket.userid === payload.from) { if (socket.userid === payload.from) {
@ -89,9 +91,9 @@ export function inviteOutCheck(core, server, socket, payload) {
return payload; return payload;
} }
export function banCheck(core, server, socket, payload) { export function banCheck({ server, socket, payload }) {
if (socket.hcProtocol === 1) { if (socket.hcProtocol === 1) {
let targetClient = server.findSockets({ channel: socket.channel, nick: data.nick }); let targetClient = server.findSockets({ channel: socket.channel, nick: payload.nick });
if (targetClient.length === 0) { if (targetClient.length === 0) {
server.reply({ server.reply({
@ -111,9 +113,9 @@ export function banCheck(core, server, socket, payload) {
return payload; return payload;
} }
export function dumbCheck(core, server, socket, payload) { export function dumbCheck({ server, socket, payload }) {
if (socket.hcProtocol === 1) { if (socket.hcProtocol === 1) {
let targetClient = server.findSockets({ channel: socket.channel, nick: data.nick }); let targetClient = server.findSockets({ channel: socket.channel, nick: payload.nick });
if (targetClient.length === 0) { if (targetClient.length === 0) {
server.reply({ server.reply({
@ -133,15 +135,15 @@ export function dumbCheck(core, server, socket, payload) {
return payload; return payload;
} }
export function kickCheck(core, server, socket, payload) { export function kickCheck({ server, socket, payload }) {
if (socket.hcProtocol === 1) { if (socket.hcProtocol === 1) {
if (typeof payload.nick !== 'number') { if (typeof payload.nick !== 'number') {
if (typeof payload.nick !== 'object' && !Array.isArray(data.nick)) { if (typeof payload.nick !== 'object' && !Array.isArray(payload.nick)) {
return true; return true;
} }
} }
let targetClient = server.findSockets({ channel: socket.channel, nick: data.nick }); const targetClient = server.findSockets({ channel: socket.channel, nick: payload.nick });
if (targetClient.length === 0) { if (targetClient.length === 0) {
return false; return false;

View File

@ -3,8 +3,8 @@
*/ */
// module main // module main
export async function run(core, server, socket, data) { export async function run({ server, socket, payload }) {
if (data.cmdKey !== server.cmdKey) { if (payload.cmdKey !== server.cmdKey) {
// internal command attempt by client, increase rate limit chance and ignore // internal command attempt by client, increase rate limit chance and ignore
return server.police.frisk(socket.address, 20); return server.police.frisk(socket.address, 20);
} }
@ -12,7 +12,7 @@ export async function run(core, server, socket, data) {
// send warning to target socket // send warning to target socket
server.reply({ server.reply({
cmd: 'warn', // @todo Remove english and change to numeric id cmd: 'warn', // @todo Remove english and change to numeric id
text: data.text text: payload.text,
}, socket); }, socket);
return true; return true;

View File

@ -1,3 +1,4 @@
/* eslint no-console: 0 */
/* /*
Description: Adds the target socket's ip to the ratelimiter Description: Adds the target socket's ip to the ratelimiter
*/ */
@ -5,19 +6,21 @@
import * as UAC from '../utility/UAC/_info'; import * as UAC from '../utility/UAC/_info';
// module main // module main
export async function run(core, server, socket, data) { export async function run({
core, server, socket, payload,
}) {
// increase rate limit chance and ignore if not admin or mod // increase rate limit chance and ignore if not admin or mod
if (!UAC.isModerator(socket.level)) { if (!UAC.isModerator(socket.level)) {
return server.police.frisk(socket.address, 10); return server.police.frisk(socket.address, 10);
} }
// check user input // check user input
if (typeof data.userid !== 'number') { if (typeof payload.userid !== 'number') {
return true; return true;
} }
// find target user // find target user
let badClient = server.findSockets({ channel: socket.channel, userid: data.userid }); let badClient = server.findSockets({ channel: socket.channel, userid: payload.userid });
if (badClient.length === 0) { if (badClient.length === 0) {
return server.reply({ return server.reply({
@ -52,8 +55,8 @@ export async function run(core, server, socket, data) {
// notify mods // notify mods
server.broadcast({ server.broadcast({
cmd: 'info', cmd: 'info',
text: `${socket.nick}#${socket.trip} banned ${targetNick} in ${data.channel}, userhash: ${badClient.hash}`, text: `${socket.nick}#${socket.trip} banned ${targetNick} in ${payload.channel}, userhash: ${badClient.hash}`,
channel: data.channel, channel: payload.channel,
user: UAC.getUserDetails(badClient), user: UAC.getUserDetails(badClient),
banner: UAC.getUserDetails(socket), banner: UAC.getUserDetails(socket),
}, { level: UAC.isModerator }); }, { level: UAC.isModerator });
@ -67,7 +70,7 @@ export async function run(core, server, socket, data) {
return true; return true;
} }
//export const requiredData = ['nick']; // export const requiredData = ['nick'];
export const info = { export const info = {
name: 'ban', name: 'ban',
description: 'Disconnects the target nickname in the same channel as calling socket & adds to ratelimiter', description: 'Disconnects the target nickname in the same channel as calling socket & adds to ratelimiter',

View File

@ -1,3 +1,6 @@
/* eslint no-param-reassign: 0 */
/* eslint no-multi-assign: 0 */
/* /*
* Description: Make a user (spammer) dumb (mute) * Description: Make a user (spammer) dumb (mute)
* Author: simple * Author: simple
@ -13,19 +16,21 @@ export function init(core) {
} }
// module main // module main
export async function run(core, server, socket, data) { export async function run({
core, server, socket, payload,
}) {
// increase rate limit chance and ignore if not admin or mod // increase rate limit chance and ignore if not admin or mod
if (!UAC.isModerator(socket.level)) { if (!UAC.isModerator(socket.level)) {
return server.police.frisk(socket.address, 10); return server.police.frisk(socket.address, 10);
} }
// check user input // check user input
if (typeof data.userid !== 'number') { if (typeof payload.userid !== 'number') {
return true; return true;
} }
// find target user // find target user
let badClient = server.findSockets({ channel: data.channel, userid: data.userid }); let badClient = server.findSockets({ channel: payload.channel, userid: payload.userid });
if (badClient.length === 0) { if (badClient.length === 0) {
return server.reply({ return server.reply({
@ -50,14 +55,14 @@ export async function run(core, server, socket, data) {
}; };
// store allies if needed // store allies if needed
if (data.allies && Array.isArray(data.allies)) { if (payload.allies && Array.isArray(payload.allies)) {
record.allies = data.allies; record.allies = payload.allies;
} }
// notify mods // notify mods
server.broadcast({ server.broadcast({
cmd: 'info', cmd: 'info',
text: `${socket.nick}#${socket.trip} muzzled ${badClient.nick} in ${data.channel}, userhash: ${badClient.hash}`, text: `${socket.nick}#${socket.trip} muzzled ${badClient.nick} in ${payload.channel}, userhash: ${badClient.hash}`,
}, { level: UAC.isModerator }); }, { level: UAC.isModerator });
return true; return true;
@ -71,7 +76,9 @@ export function initHooks(server) {
} }
// hook incoming chat commands, shadow-prevent chat if they are muzzled // hook incoming chat commands, shadow-prevent chat if they are muzzled
export function chatCheck(core, server, socket, payload) { export function chatCheck({
core, server, socket, payload,
}) {
if (typeof payload.text !== 'string') { if (typeof payload.text !== 'string') {
return false; return false;
} }
@ -116,10 +123,10 @@ export function chatCheck(core, server, socket, payload) {
} }
// shadow-prevent all invites from muzzled users // shadow-prevent all invites from muzzled users
export function inviteCheck(core, server, socket, payload) { export function inviteCheck({ core, socket, payload }) {
if (core.muzzledHashes[socket.hash]) { if (core.muzzledHashes[socket.hash]) {
// @todo convert to protocol 2 // @todo convert to protocol 2
/*const nickValid = Invite.checkNickname(payload.nick); /* const nickValid = Invite.checkNickname(payload.nick);
if (nickValid !== null) { if (nickValid !== null) {
server.reply({ server.reply({
cmd: 'warn', // @todo Remove english and change to numeric id cmd: 'warn', // @todo Remove english and change to numeric id
@ -132,7 +139,7 @@ export function inviteCheck(core, server, socket, payload) {
const channel = Invite.getChannel(); const channel = Invite.getChannel();
// send fake reply // send fake reply
server.reply(Invite.createSuccessPayload(payload.nick, channel), socket);*/ server.reply(Invite.createSuccessPayload(payload.nick, channel), socket); */
return false; return false;
} }
@ -141,7 +148,9 @@ export function inviteCheck(core, server, socket, payload) {
} }
// shadow-prevent all whispers from muzzled users // shadow-prevent all whispers from muzzled users
export function whisperCheck(core, server, socket, payload) { export function whisperCheck({
core, server, socket, payload,
}) {
if (typeof payload.nick !== 'string') { if (typeof payload.nick !== 'string') {
return false; return false;
} }
@ -159,7 +168,8 @@ export function whisperCheck(core, server, socket, payload) {
text: `You whispered to @${targetNick}: ${payload.text}`, text: `You whispered to @${targetNick}: ${payload.text}`,
}, socket); }, socket);
// blanket "spam" protection, may expose the ratelimiting lines from `chat` and use that, TODO: one day #lazydev // blanket "spam" protection, may expose the ratelimiting lines from
// `chat` and use that, @todo one day #lazydev
server.police.frisk(socket.address, 9); server.police.frisk(socket.address, 9);
return false; return false;

View File

@ -1,3 +1,5 @@
/* eslint no-console: 0 */
/* /*
Description: Forces a change on the target(s) socket's channel, then broadcasts event Description: Forces a change on the target(s) socket's channel, then broadcasts event
*/ */
@ -5,29 +7,31 @@
import * as UAC from '../utility/UAC/_info'; import * as UAC from '../utility/UAC/_info';
// module main // module main
export async function run(core, server, socket, data) { export async function run({
core, server, socket, payload,
}) {
// increase rate limit chance and ignore if not admin or mod // increase rate limit chance and ignore if not admin or mod
if (!UAC.isModerator(socket.level)) { if (!UAC.isModerator(socket.level)) {
return server.police.frisk(socket.address, 10); return server.police.frisk(socket.address, 10);
} }
// check user input // check user input
if (typeof data.userid !== 'number') { if (typeof payload.userid !== 'number') {
// @todo create multi-ban ui // @todo create multi-ban ui
if (typeof data.userid !== 'object' && !Array.isArray(data.userid)) { if (typeof payload.userid !== 'object' && !Array.isArray(payload.userid)) {
return true; return true;
} }
} }
let destChannel; let destChannel;
if (typeof data.to === 'string' && !!data.to.trim()) { if (typeof payload.to === 'string' && !!payload.to.trim()) {
destChannel = data.to; destChannel = payload.to;
} else { } else {
destChannel = Math.random().toString(36).substr(2, 8); destChannel = Math.random().toString(36).substr(2, 8);
} }
// find target user(s) // find target user(s)
const badClients = server.findSockets({ channel: data.channel, userid: data.userid }); const badClients = server.findSockets({ channel: payload.channel, userid: payload.userid });
if (badClients.length === 0) { if (badClients.length === 0) {
return server.reply({ return server.reply({
@ -76,7 +80,6 @@ export async function run(core, server, socket, data) {
console.log(`${socket.nick} [${socket.trip}] kicked ${kicked[i].nick} in ${socket.channel} to ${destChannel} `); console.log(`${socket.nick} [${socket.trip}] kicked ${kicked[i].nick} in ${socket.channel} to ${destChannel} `);
} }
// broadcast client leave event // broadcast client leave event
for (let i = 0, j = kicked.length; i < j; i += 1) { for (let i = 0, j = kicked.length; i < j; i += 1) {
server.broadcast({ server.broadcast({

View File

@ -5,23 +5,23 @@
import * as UAC from '../utility/UAC/_info'; import * as UAC from '../utility/UAC/_info';
// module main // module main
export async function run(core, server, socket, data) { export async function run({ server, socket, payload }) {
// increase rate limit chance and ignore if not admin or mod // increase rate limit chance and ignore if not admin or mod
if (!UAC.isModerator(socket.level)) { if (!UAC.isModerator(socket.level)) {
return server.police.frisk(socket.address, 10); return server.police.frisk(socket.address, 10);
} }
// check user input // check user input
if (typeof data.nick !== 'string' || typeof data.channel !== 'string') { if (typeof payload.nick !== 'string' || typeof payload.channel !== 'string') {
return true; return true;
} }
if (data.channel === socket.channel) { if (payload.channel === socket.channel) {
// moving them into the same channel? y u do this? // moving them into the same channel? y u do this?
return true; return true;
} }
const badClients = server.findSockets({ channel: socket.channel, nick: data.nick }); const badClients = server.findSockets({ channel: socket.channel, nick: payload.nick });
if (badClients.length === 0) { if (badClients.length === 0) {
return server.reply({ return server.reply({
@ -41,7 +41,7 @@ export async function run(core, server, socket, data) {
const currentNick = badClient.nick.toLowerCase(); const currentNick = badClient.nick.toLowerCase();
const userExists = server.findSockets({ const userExists = server.findSockets({
channel: data.channel, channel: payload.channel,
nick: (targetNick) => targetNick.toLowerCase() === currentNick, nick: (targetNick) => targetNick.toLowerCase() === currentNick,
}); });
@ -68,8 +68,8 @@ export async function run(core, server, socket, data) {
} }
} }
// TODO: import from join module // @todo import from join module
const newPeerList = server.findSockets({ channel: data.channel }); const newPeerList = server.findSockets({ channel: payload.channel });
const moveAnnouncement = { const moveAnnouncement = {
cmd: 'onlineAdd', cmd: 'onlineAdd',
nick: badClient.nick, nick: badClient.nick,
@ -90,12 +90,12 @@ export async function run(core, server, socket, data) {
nicks, nicks,
}, badClient); }, badClient);
badClient.channel = data.channel; badClient.channel = payload.channel;
server.broadcast({ server.broadcast({
cmd: 'info', cmd: 'info',
text: `${badClient.nick} was moved into ?${data.channel}`, text: `${badClient.nick} was moved into ?${payload.channel}`,
}, { channel: data.channel }); }, { channel: payload.channel });
return true; return true;
} }

View File

@ -1,3 +1,5 @@
/* eslint no-param-reassign: 0 */
/* /*
* Description: Pardon a dumb user to be able to speak again * Description: Pardon a dumb user to be able to speak again
* Author: simple * Author: simple
@ -13,22 +15,24 @@ export function init(core) {
} }
// module main // module main
export async function run(core, server, socket, data) { export async function run({
core, server, socket, payload,
}) {
// increase rate limit chance and ignore if not admin or mod // increase rate limit chance and ignore if not admin or mod
if (!UAC.isModerator(socket.level)) { if (!UAC.isModerator(socket.level)) {
return server.police.frisk(socket.address, 10); return server.police.frisk(socket.address, 10);
} }
// check user input // check user input
if (typeof data.ip !== 'string' && typeof data.hash !== 'string') { if (typeof payload.ip !== 'string' && typeof payload.hash !== 'string') {
return server.reply({ return server.reply({
cmd: 'warn', // @todo Remove english and change to numeric id cmd: 'warn', // @todo Remove english and change to numeric id
text: "hash:'targethash' or ip:'1.2.3.4' is required", text: "hash:'targethash' or ip:'1.2.3.4' is required",
}, socket); }, socket);
} }
if (typeof data.ip === 'string') { if (typeof payload.ip === 'string') {
if (data.ip === '*') { if (payload.ip === '*') {
core.muzzledHashes = {}; core.muzzledHashes = {};
return server.broadcast({ return server.broadcast({
@ -36,7 +40,7 @@ export async function run(core, server, socket, data) {
text: `${socket.nick} unmuzzled all users`, text: `${socket.nick} unmuzzled all users`,
}, { level: UAC.isModerator }); }, { level: UAC.isModerator });
} }
} else if (data.hash === '*') { } else if (payload.hash === '*') {
core.muzzledHashes = {}; core.muzzledHashes = {};
return server.broadcast({ return server.broadcast({
@ -47,10 +51,10 @@ export async function run(core, server, socket, data) {
// find target & remove mute status // find target & remove mute status
let target; let target;
if (typeof data.ip === 'string') { if (typeof payload.ip === 'string') {
target = server.getSocketHash(data.ip); target = server.getSocketHash(payload.ip);
} else { } else {
target = data.hash; target = payload.hash;
} }
delete core.muzzledHashes[target]; delete core.muzzledHashes[target];

View File

@ -1,3 +1,5 @@
/* eslint no-console: 0 */
/* /*
Description: Removes a target ip from the ratelimiter Description: Removes a target ip from the ratelimiter
*/ */
@ -5,14 +7,16 @@
import * as UAC from '../utility/UAC/_info'; import * as UAC from '../utility/UAC/_info';
// module main // module main
export async function run(core, server, socket, data) { export async function run({
core, server, socket, payload,
}) {
// increase rate limit chance and ignore if not admin or mod // increase rate limit chance and ignore if not admin or mod
if (!UAC.isModerator(socket.level)) { if (!UAC.isModerator(socket.level)) {
return server.police.frisk(socket.address, 10); return server.police.frisk(socket.address, 10);
} }
// check user input // check user input
if (typeof data.ip !== 'string' && typeof data.hash !== 'string') { if (typeof payload.ip !== 'string' && typeof payload.hash !== 'string') {
return server.reply({ return server.reply({
cmd: 'warn', // @todo Remove english and change to numeric id cmd: 'warn', // @todo Remove english and change to numeric id
text: "hash:'targethash' or ip:'1.2.3.4' is required", text: "hash:'targethash' or ip:'1.2.3.4' is required",
@ -22,12 +26,12 @@ export async function run(core, server, socket, data) {
// find target // find target
let mode; let mode;
let target; let target;
if (typeof data.ip === 'string') { if (typeof payload.ip === 'string') {
mode = 'ip'; mode = 'ip';
target = data.ip; target = payload.ip;
} else { } else {
mode = 'hash'; mode = 'hash';
target = data.hash; target = payload.hash;
} }
// remove arrest record // remove arrest record

View File

@ -1,3 +1,5 @@
/* eslint no-console: 0 */
/* /*
Description: Clears all bans and ratelimits Description: Clears all bans and ratelimits
*/ */
@ -5,7 +7,7 @@
import * as UAC from '../utility/UAC/_info'; import * as UAC from '../utility/UAC/_info';
// module main // module main
export async function run(core, server, socket) { export async function run({ core, server, socket }) {
// increase rate limit chance and ignore if not admin or mod // increase rate limit chance and ignore if not admin or mod
if (!UAC.isModerator(socket.level)) { if (!UAC.isModerator(socket.level)) {
return server.police.frisk(socket.address, 10); return server.police.frisk(socket.address, 10);

View File

@ -1,3 +1,9 @@
/* eslint no-bitwise: 0 */
/* eslint global-require: 0 */
/* eslint class-methods-use-this: 0 */
/* eslint no-param-reassign: 0 */
/* eslint no-console: 0 */
import { import {
start as _start, start as _start,
get, get,
@ -8,6 +14,7 @@ import {
* @author Marzavec ( https://github.com/marzavec ) * @author Marzavec ( https://github.com/marzavec )
* @version v2.0.0 * @version v2.0.0
* @license WTFPL ( http://www.wtfpl.net/txt/copying/ ) * @license WTFPL ( http://www.wtfpl.net/txt/copying/ )
* @todo Convert to use the `enquirer` package instead
*/ */
class SetupWizard { class SetupWizard {
/** /**

View File

@ -1,3 +1,5 @@
/* eslint no-console: 0 */
/** /**
* This script will be run before the package starts asking for the config data, * This script will be run before the package starts asking for the config data,
* used to output a simple guide for the coming questions, or to spam some sexy * used to output a simple guide for the coming questions, or to spam some sexy

View File

@ -1,3 +1,5 @@
/* eslint no-console: 0 */
/** /**
* This script will be run once all questions have finished and no errors have * This script will be run once all questions have finished and no errors have
* occured. You can congratulate the user on their fine choice in software usage * occured. You can congratulate the user on their fine choice in software usage

View File

@ -1,3 +1,6 @@
/* eslint no-undef: 0 */
/* eslint global-require: 0 */
/** /**
* This object contains Prompt ( https://www.npmjs.com/package/prompt ) style * This object contains Prompt ( https://www.npmjs.com/package/prompt ) style
* questions that the SetupWizard will require an answer to. Questions are asked * questions that the SetupWizard will require an answer to. Questions are asked

View File

@ -1,3 +1,5 @@
/* eslint no-console: 0 */
import { import {
basename, basename,
join, join,
@ -98,6 +100,7 @@ class CommandManager {
.replace(new RegExp(sep.replace('\\', '\\\\'), 'g'), '/'); .replace(new RegExp(sep.replace('\\', '\\\\'), 'g'), '/');
} }
// eslint-disable-next-line no-param-reassign
command.info.category = category; command.info.category = category;
if (this.categories.indexOf(category) === -1) { if (this.categories.indexOf(category) === -1) {
@ -126,6 +129,7 @@ class CommandManager {
* @private * @private
* @return {String} Module errors or null if none * @return {String} Module errors or null if none
*/ */
// eslint-disable-next-line class-methods-use-this
validateCommand(object) { validateCommand(object) {
if (typeof object !== 'object') { return 'command setup is invalid'; } if (typeof object !== 'object') { return 'command setup is invalid'; }
if (typeof object.run !== 'function') { return 'run function is missing'; } if (typeof object.run !== 'function') { return 'run function is missing'; }
@ -253,11 +257,11 @@ class CommandManager {
* @private * @private
* @return {*} Arbitrary module return data * @return {*} Arbitrary module return data
*/ */
async execute(command, server, socket, data) { async execute(command, server, socket, payload) {
if (typeof command.requiredData !== 'undefined') { if (typeof command.requiredData !== 'undefined') {
const missing = []; const missing = [];
for (let i = 0, len = command.requiredData.length; i < len; i += 1) { for (let i = 0, len = command.requiredData.length; i < len; i += 1) {
if (typeof data[command.requiredData[i]] === 'undefined') { missing.push(command.requiredData[i]); } if (typeof payload[command.requiredData[i]] === 'undefined') { missing.push(command.requiredData[i]); }
} }
if (missing.length > 0) { if (missing.length > 0) {
@ -278,7 +282,12 @@ class CommandManager {
} }
try { try {
return await command.run(this.core, server, socket, data); return await command.run({
core: this.core,
server,
socket,
payload,
});
} catch (err) { } catch (err) {
const errText = `Failed to execute '${command.info.name}': `; const errText = `Failed to execute '${command.info.name}': `;

View File

@ -1,3 +1,5 @@
/* eslint no-console: 0 */
import dateFormat from 'dateformat'; import dateFormat from 'dateformat';
import { import {
existsSync, existsSync,

View File

@ -1,3 +1,5 @@
/* eslint no-console: 0 */
import { join } from 'path'; import { join } from 'path';
import { import {
CommandManager, CommandManager,
@ -90,4 +92,4 @@ class CoreApp {
} }
} }
export { CoreApp }; export { CoreApp as default };

View File

@ -1,3 +1,6 @@
/* eslint global-require: 0 */
/* eslint no-console: 0 */
import { import {
resolve, resolve,
basename as _basename, basename as _basename,
@ -57,7 +60,7 @@ class ImportsManager {
let imported; let imported;
try { try {
imported = require(file); imported = require(file); // eslint-disable-line import/no-dynamic-require
if (!this.imports[dirName]) { if (!this.imports[dirName]) {
this.imports[dirName] = {}; this.imports[dirName] = {};

View File

@ -1,3 +1,6 @@
/* eslint no-bitwise: 0 */
/* eslint no-console: 0 */
import { import {
Server as WsServer, Server as WsServer,
OPEN as SocketReady, OPEN as SocketReady,
@ -189,10 +192,6 @@ class MainServer extends WsServer {
* Issue #1: hard coded `cmd` check * Issue #1: hard coded `cmd` check
* Issue #2: hard coded `cmd` value checks * Issue #2: hard coded `cmd` value checks
*/ */
if (typeof payload.cmd === 'undefined') {
return;
}
if (typeof payload.cmd !== 'string') { if (typeof payload.cmd !== 'string') {
return; return;
} }
@ -509,7 +508,12 @@ class MainServer extends WsServer {
for (let i = 0, j = hooks.length; i < j; i += 1) { for (let i = 0, j = hooks.length; i < j; i += 1) {
try { try {
newPayload = hooks[i].run(this.core, this, socket, newPayload); newPayload = hooks[i].run({
core: this.core,
server: this,
socket,
payload: newPayload,
});
} catch (err) { } catch (err) {
const errText = `Hook failure, '${type}', '${command}': `; const errText = `Hook failure, '${type}', '${command}': `;
if (this.core.config.logErrDetailed === true) { if (this.core.config.logErrDetailed === true) {

View File

@ -77,6 +77,7 @@ class RateLimiter {
return true; return true;
} }
// eslint-disable-next-line no-restricted-properties
record.score *= Math.pow(2, -(Date.now() - record.time) / this.halflife); record.score *= Math.pow(2, -(Date.now() - record.time) / this.halflife);
record.score += deltaScore; record.score += deltaScore;
record.time = Date.now(); record.time = Date.now();

View File

@ -1,3 +1,5 @@
/* eslint global-require: 0 */
export const CommandManager = require('./CommandManager').default; export const CommandManager = require('./CommandManager').default;
export const ConfigManager = require('./ConfigManager').default; export const ConfigManager = require('./ConfigManager').default;
export const ImportsManager = require('./ImportsManager').default; export const ImportsManager = require('./ImportsManager').default;