From 5ec06bab571fa92c4c3bc3ba772cc8ca23d27ab2 Mon Sep 17 00:00:00 2001 From: wolfy01 <45273698+wolfy01@users.noreply.github.com> Date: Tue, 7 Apr 2020 01:59:49 -0400 Subject: [PATCH 01/32] Create Ratelimit.js --- src/Ratelimit.js | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/Ratelimit.js diff --git a/src/Ratelimit.js b/src/Ratelimit.js new file mode 100644 index 0000000..f43157d --- /dev/null +++ b/src/Ratelimit.js @@ -0,0 +1,40 @@ + +var RateLimit = function(interval_ms) { + this._interval_ms = interval_ms || 0; // (0 means no limit) + this._after = 0; +}; + +RateLimit.prototype.attempt = function(time) { + var time = time || Date.now(); + if(time < this._after) return false; + this._after = time + this._interval_ms; + return true; +}; + +RateLimit.prototype.setInterval = function(interval_ms) { + this._after += interval_ms - this._interval_ms; + this._interval_ms = interval_ms; +}; + +var RateLimitChain = function(num, interval_ms) { + this.setNumAndInterval(num, interval_ms); +}; + +RateLimitChain.prototype.attempt = function(time) { + var time = time || Date.now(); + for(var i = 0; i < this._chain.length; i++) { + if(this._chain[i].attempt(time)) return true; + } + return false; +}; + +RateLimitChain.prototype.setNumAndInterval = function(num, interval_ms) { + this._chain = []; + for(var i = 0; i < num; i++) { + this._chain.push(new RateLimit(interval_ms)); + } +}; + +var exports = typeof module !== "undefined" ? module.exports : this; +exports.RateLimit = RateLimit; +exports.RateLimitChain = RateLimitChain; From 96c15473bacac8d59ea2010ddaa130eab303b027 Mon Sep 17 00:00:00 2001 From: wolfy01 <45273698+wolfy01@users.noreply.github.com> Date: Tue, 7 Apr 2020 02:01:41 -0400 Subject: [PATCH 02/32] Update Client.js --- src/Client.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Client.js b/src/Client.js index c762e68..4751df9 100644 --- a/src/Client.js +++ b/src/Client.js @@ -1,3 +1,5 @@ +const RateLimit = require('./RateLimit.js').RateLimit; +const RateLimitChain = require('./RateLimit.js').RateLimitChain; const Room = require("./Room.js"); require('node-json-color-stringify'); class Client extends EventEmitter { @@ -14,6 +16,10 @@ class Client extends EventEmitter { this.ip = (req.connection.remoteAddress).replace("::ffff:", ""); this.destroied = false; this.bindEventListeners(); + this.cursQuota = new RateLimit(16); + this.chatQuota = new RateLimitChain(4, 4000); + this.nameQuota = new RateLimitChain(30, 30 * 60000); + this.crowned_chatQuota = new RateLimitChain(10, 2000); require('./Message.js')(this); } isConnected() { @@ -102,4 +108,4 @@ class Client extends EventEmitter { }); } } -module.exports = Client; \ No newline at end of file +module.exports = Client; From 22110d0541a06e84bbdfa442bf2086c09678ade5 Mon Sep 17 00:00:00 2001 From: wolfy01 <45273698+wolfy01@users.noreply.github.com> Date: Tue, 7 Apr 2020 02:04:11 -0400 Subject: [PATCH 03/32] Update Message.js --- src/Message.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/Message.js b/src/Message.js index b8b79d9..4ed2a24 100644 --- a/src/Message.js +++ b/src/Message.js @@ -30,6 +30,7 @@ module.exports = (cl) => { } }) cl.on("m", msg => { + if (!cl.cursQuota.attempt()) return; if (!(cl.channel && cl.participantId)) return; if (!msg.hasOwnProperty("x")) msg.x = null; if (!msg.hasOwnProperty("y")) msg.y = null; @@ -60,6 +61,15 @@ module.exports = (cl) => { cl.channel.updateCh(); }) cl.on("a", msg => { + if (cl.channel.isLobby(cl.channel._id)) { + if (!cl.chatQuota.attempt()) return; + } else { + if (!(cl.user._id == cl.channel.crown.userId)) { + if (!cl.chatQuota.attempt()) return; + } else { + if (!cl.crowned_chatQuota.attempt()) return; + } + } if (!(cl.channel && cl.participantId)) return; if (!msg.hasOwnProperty('message')) return; if (cl.channel.settings.chat) { @@ -100,6 +110,7 @@ module.exports = (cl) => { cl.server.roomlisteners.delete(cl.connectionid); }) cl.on("userset", msg => { + if (!cl.usersetQuota.attempt()) return; if (!(cl.channel && cl.participantId)) return; if (!msg.hasOwnProperty("set") || !msg.set) msg.set = {}; if (msg.set.hasOwnProperty('name') && typeof msg.set.name == "string") { @@ -165,4 +176,4 @@ module.exports = (cl) => { }) -} \ No newline at end of file +} From 6129f8f1610f5389a4078e980197f39c62c74dec Mon Sep 17 00:00:00 2001 From: wolfy01 <45273698+wolfy01@users.noreply.github.com> Date: Tue, 7 Apr 2020 02:04:35 -0400 Subject: [PATCH 04/32] Update Client.js --- src/Client.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Client.js b/src/Client.js index 4751df9..4081a1c 100644 --- a/src/Client.js +++ b/src/Client.js @@ -18,7 +18,7 @@ class Client extends EventEmitter { this.bindEventListeners(); this.cursQuota = new RateLimit(16); this.chatQuota = new RateLimitChain(4, 4000); - this.nameQuota = new RateLimitChain(30, 30 * 60000); + this.usersetQuota = new RateLimitChain(30, 30 * 60000); this.crowned_chatQuota = new RateLimitChain(10, 2000); require('./Message.js')(this); } From 55e1a759585b79a975eca390d31dd4308eec9e36 Mon Sep 17 00:00:00 2001 From: wolfy01 <45273698+wolfy01@users.noreply.github.com> Date: Tue, 7 Apr 2020 02:16:21 -0400 Subject: [PATCH 05/32] Update Client.js --- src/Client.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/Client.js b/src/Client.js index 4081a1c..6527005 100644 --- a/src/Client.js +++ b/src/Client.js @@ -16,10 +16,13 @@ class Client extends EventEmitter { this.ip = (req.connection.remoteAddress).replace("::ffff:", ""); this.destroied = false; this.bindEventListeners(); - this.cursQuota = new RateLimit(16); - this.chatQuota = new RateLimitChain(4, 4000); - this.usersetQuota = new RateLimitChain(30, 30 * 60000); - this.crowned_chatQuota = new RateLimitChain(10, 2000); + this.quotas = { + chat: new RateLimitChain(4, 4000), + name: new RateLimitChain(30, 30 * 60000), + cursor: new RateLimit(16), + kickban: new RateLimitChain(2, 1000), + crowned_chat: new RateLimitChain(10, 2000) + } require('./Message.js')(this); } isConnected() { From 066f1d0df3b9d03db090286275d6d0cbd44595f8 Mon Sep 17 00:00:00 2001 From: wolfy01 <45273698+wolfy01@users.noreply.github.com> Date: Tue, 7 Apr 2020 02:17:16 -0400 Subject: [PATCH 06/32] Update Message.js --- src/Message.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/Message.js b/src/Message.js index 4ed2a24..874b233 100644 --- a/src/Message.js +++ b/src/Message.js @@ -30,7 +30,7 @@ module.exports = (cl) => { } }) cl.on("m", msg => { - if (!cl.cursQuota.attempt()) return; + if (!cl.quotas.cursor.attempt()) return; if (!(cl.channel && cl.participantId)) return; if (!msg.hasOwnProperty("x")) msg.x = null; if (!msg.hasOwnProperty("y")) msg.y = null; @@ -62,12 +62,12 @@ module.exports = (cl) => { }) cl.on("a", msg => { if (cl.channel.isLobby(cl.channel._id)) { - if (!cl.chatQuota.attempt()) return; + if (!cl.quotas.chat.attempt()) return; } else { if (!(cl.user._id == cl.channel.crown.userId)) { - if (!cl.chatQuota.attempt()) return; + if (!cl.quotas.chat.attempt()) return; } else { - if (!cl.crowned_chatQuota.attempt()) return; + if (!cl.quotas.crowned_chat.attempt()) return; } } if (!(cl.channel && cl.participantId)) return; @@ -110,7 +110,7 @@ module.exports = (cl) => { cl.server.roomlisteners.delete(cl.connectionid); }) cl.on("userset", msg => { - if (!cl.usersetQuota.attempt()) return; + if (!cl.quotas.name.attempt()) return; if (!(cl.channel && cl.participantId)) return; if (!msg.hasOwnProperty("set") || !msg.set) msg.set = {}; if (msg.set.hasOwnProperty('name') && typeof msg.set.name == "string") { @@ -132,6 +132,7 @@ module.exports = (cl) => { } }) cl.on('kickban', msg => { + if (!cl.quotas.kickban.attempt()) return; if (!(cl.channel && cl.participantId)) return; if (!(cl.user._id == cl.channel.crown.userId)) return; if (msg.hasOwnProperty('_id') && typeof msg._id == "string") { From 7040b176aa566acafd8a998559cb866ab942881d Mon Sep 17 00:00:00 2001 From: wolfy01 <45273698+wolfy01@users.noreply.github.com> Date: Tue, 7 Apr 2020 02:17:29 -0400 Subject: [PATCH 07/32] Delete .gitignore --- .gitignore | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .gitignore diff --git a/.gitignore b/.gitignore deleted file mode 100644 index a6c57f5..0000000 --- a/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*.json From f8b4cc2f5517afe27d4837dee6f48afa2665501d Mon Sep 17 00:00:00 2001 From: wolfy01 <45273698+wolfy01@users.noreply.github.com> Date: Tue, 7 Apr 2020 02:17:38 -0400 Subject: [PATCH 08/32] Delete .gitattributes --- .gitattributes | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index dfe0770..0000000 --- a/.gitattributes +++ /dev/null @@ -1,2 +0,0 @@ -# Auto detect text files and perform LF normalization -* text=auto From 3a3cf0f4e09a205c62dd8c49810ccefe68d83650 Mon Sep 17 00:00:00 2001 From: wolfy01 <45273698+wolfy01@users.noreply.github.com> Date: Tue, 7 Apr 2020 02:18:04 -0400 Subject: [PATCH 09/32] Create users.json --- src/db/users.json | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/db/users.json diff --git a/src/db/users.json b/src/db/users.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/src/db/users.json @@ -0,0 +1 @@ +{} From ba154a0b060d118a09e5706e39e3ddf9453b3e78 Mon Sep 17 00:00:00 2001 From: wolfy01 <45273698+wolfy01@users.noreply.github.com> Date: Tue, 7 Apr 2020 02:18:20 -0400 Subject: [PATCH 10/32] Delete textfile.txt --- src/db/textfile.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/db/textfile.txt diff --git a/src/db/textfile.txt b/src/db/textfile.txt deleted file mode 100644 index e69de29..0000000 From 4f8ab58266998812804405f49880582d1cc15c57 Mon Sep 17 00:00:00 2001 From: wolfy01 <45273698+wolfy01@users.noreply.github.com> Date: Tue, 7 Apr 2020 02:19:03 -0400 Subject: [PATCH 11/32] Create config.json --- src/db/config.json | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 src/db/config.json diff --git a/src/db/config.json b/src/db/config.json new file mode 100644 index 0000000..ce8db5c --- /dev/null +++ b/src/db/config.json @@ -0,0 +1,10 @@ +{ + "port": "3000", + "motd": "You agree to read this message.", + "_id_PrivateKey": "boppity", + "defaultUsername": "Anonymous", + "defaultRoomColor": "#3b5054", + "defaultLobbyColor": "#19b4b9", + "defaultLobbyColor2": "#801014", + "adminpass": "adminpass" +} From 9cb5b1b425f1ada1fa770285b4e8d001caf292c1 Mon Sep 17 00:00:00 2001 From: wolfy01 <45273698+wolfy01@users.noreply.github.com> Date: Tue, 7 Apr 2020 02:41:10 -0400 Subject: [PATCH 12/32] Update index.js --- index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 62db0b2..81dae58 100644 --- a/index.js +++ b/index.js @@ -15,8 +15,8 @@ global.isObj = function(a){ return typeof a === "object" && !Array.isArray(a) && a !== null; } -let Server = require("./src/Server.js"); -let config = require('./src/db/config.json'); +let Server = require("./src/Server"); +let config = require('./src/db/config'); global.SERVER = new Server(config); let console = process.platform == 'win32' ? new AsyncConsole("", input => { try { From 7d02ef588d5363aa5e0cae70a27c2b193061b60b Mon Sep 17 00:00:00 2001 From: wolfy01 <45273698+wolfy01@users.noreply.github.com> Date: Tue, 7 Apr 2020 02:42:12 -0400 Subject: [PATCH 13/32] quotas --- src/Client.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/Client.js b/src/Client.js index 6527005..b7f5b54 100644 --- a/src/Client.js +++ b/src/Client.js @@ -1,3 +1,5 @@ +const config = require('./db/config'); +const quotas = config.quotas; const RateLimit = require('./RateLimit.js').RateLimit; const RateLimitChain = require('./RateLimit.js').RateLimitChain; const Room = require("./Room.js"); @@ -17,11 +19,12 @@ class Client extends EventEmitter { this.destroied = false; this.bindEventListeners(); this.quotas = { - chat: new RateLimitChain(4, 4000), - name: new RateLimitChain(30, 30 * 60000), - cursor: new RateLimit(16), - kickban: new RateLimitChain(2, 1000), - crowned_chat: new RateLimitChain(10, 2000) + chat: new RateLimitChain(quotas.chat.amount, quotas.chat.time), + name: new RateLimitChain(quotas.name.amount, quotas.name.time), + room: new RateLimit(quotas.room.time), + cursor: new RateLimit(quotas.cursor.time), + kickban: new RateLimitChain(quotas.kickban.amount, quotas.kickban.time), + crowned_chat: new RateLimitChain(quotas.crowned_chat.amount, quotas.crowned_chat.time) } require('./Message.js')(this); } From d2f216a974b51f36609e9a2c789cf8873f55f0e5 Mon Sep 17 00:00:00 2001 From: wolfy01 <45273698+wolfy01@users.noreply.github.com> Date: Tue, 7 Apr 2020 02:42:49 -0400 Subject: [PATCH 14/32] room quota --- src/Message.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Message.js b/src/Message.js index 874b233..ea4ee86 100644 --- a/src/Message.js +++ b/src/Message.js @@ -23,6 +23,7 @@ module.exports = (cl) => { }]) }) cl.on("ch", msg => { + if (!cl.quotas.room.attempt()) return; if (!msg.hasOwnProperty("set") || !msg.set) msg.set = {}; if (msg.hasOwnProperty("_id") && typeof msg._id == "string") { if (msg._id.length > 512) return; From 1850aaa68a529399b97e790781bf5bd5b7f91c1d Mon Sep 17 00:00:00 2001 From: wolfy01 <45273698+wolfy01@users.noreply.github.com> Date: Tue, 7 Apr 2020 02:44:34 -0400 Subject: [PATCH 15/32] Update and rename config.json to config.js Add quotas --- src/db/config.js | 34 ++++++++++++++++++++++++++++++++++ src/db/config.json | 10 ---------- 2 files changed, 34 insertions(+), 10 deletions(-) create mode 100644 src/db/config.js delete mode 100644 src/db/config.json diff --git a/src/db/config.js b/src/db/config.js new file mode 100644 index 0000000..eeeb1e2 --- /dev/null +++ b/src/db/config.js @@ -0,0 +1,34 @@ +module.exports = Object.seal({ + "port": "8080", + "motd": "You agree to read this message.", + "_id_PrivateKey": "boppity", + "defaultUsername": "Anonymous", + "defaultRoomColor": "#3b5054", + "defaultLobbyColor": "#19b4b9", + "defaultLobbyColor2": "#801014", + "adminpass": "adminpass_h4gKJCX2", + "quotas":{ + "chat":{ + "amount": 4, + "time": 4000 + }, + "name":{ + "amount": 30, + "time": 30 * 60000 + }, + "room":{ + "time": 500 + }, + "cursor":{ + "time": 16 + }, + "kickban":{ + "amount": 2, + "time": 1000 + }, + "crowned_chat":{ + "amount": 10, + "time": 4000 + } + } +}) diff --git a/src/db/config.json b/src/db/config.json deleted file mode 100644 index ce8db5c..0000000 --- a/src/db/config.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "port": "3000", - "motd": "You agree to read this message.", - "_id_PrivateKey": "boppity", - "defaultUsername": "Anonymous", - "defaultRoomColor": "#3b5054", - "defaultLobbyColor": "#19b4b9", - "defaultLobbyColor2": "#801014", - "adminpass": "adminpass" -} From 2d25aafbf384e6e254250fc8cd95e587f7f5b399 Mon Sep 17 00:00:00 2001 From: wolfy01 <45273698+wolfy01@users.noreply.github.com> Date: Tue, 7 Apr 2020 02:45:55 -0400 Subject: [PATCH 16/32] Update config.js --- src/db/config.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/db/config.js b/src/db/config.js index eeeb1e2..58bfddc 100644 --- a/src/db/config.js +++ b/src/db/config.js @@ -1,12 +1,12 @@ module.exports = Object.seal({ - "port": "8080", + "port": "3000", "motd": "You agree to read this message.", "_id_PrivateKey": "boppity", "defaultUsername": "Anonymous", "defaultRoomColor": "#3b5054", "defaultLobbyColor": "#19b4b9", "defaultLobbyColor2": "#801014", - "adminpass": "adminpass_h4gKJCX2", + "adminpass": "adminpass", "quotas":{ "chat":{ "amount": 4, From 9aa2acfd64db05ecf65fad599b67b731b3cd852c Mon Sep 17 00:00:00 2001 From: Wolfy Date: Tue, 7 Apr 2020 03:54:17 -0400 Subject: [PATCH 17/32] Remove --- README.md | 2 - index.js | 27 --- package.json | 32 ---- src/Client.js | 117 ------------ src/ColorEncoder.js | 16 -- src/Message.js | 181 ------------------- src/Quota.js | 87 --------- src/Ratelimit.js | 40 ----- src/Room.js | 420 -------------------------------------------- src/Server.js | 41 ----- src/TODO.txt | 2 - src/User.js | 53 ------ src/db/config.js | 34 ---- src/db/users.json | 1 - 14 files changed, 1053 deletions(-) delete mode 100644 README.md delete mode 100644 index.js delete mode 100644 package.json delete mode 100644 src/Client.js delete mode 100644 src/ColorEncoder.js delete mode 100644 src/Message.js delete mode 100644 src/Quota.js delete mode 100644 src/Ratelimit.js delete mode 100644 src/Room.js delete mode 100644 src/Server.js delete mode 100644 src/TODO.txt delete mode 100644 src/User.js delete mode 100644 src/db/config.js delete mode 100644 src/db/users.json diff --git a/README.md b/README.md deleted file mode 100644 index 33b4471..0000000 --- a/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# mpp-server -Attempt at making a MPP Server. \ No newline at end of file diff --git a/index.js b/index.js deleted file mode 100644 index 81dae58..0000000 --- a/index.js +++ /dev/null @@ -1,27 +0,0 @@ -//call new Server -global.WebSocket = require('ws'); -global.EventEmitter = require('events').EventEmitter; -global.fs = require('fs'); -global.createKeccakHash = require('keccak'); -const AsyncConsole = require('asyncconsole') - -global.isString = function(a){ - return typeof a === 'string'; -} -global.isBool = function(a){ - return typeof a === 'boolean'; -} -global.isObj = function(a){ - return typeof a === "object" && !Array.isArray(a) && a !== null; -} - -let Server = require("./src/Server"); -let config = require('./src/db/config'); -global.SERVER = new Server(config); -let console = process.platform == 'win32' ? new AsyncConsole("", input => { - try { - console.log(JSON.stringify(eval(input))); - } catch(e) { - console.log(e.toString()); - } -}) : {}; diff --git a/package.json b/package.json deleted file mode 100644 index 895bc77..0000000 --- a/package.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "name": "mpp-server-master", - "version": "1.0.0", - "description": "Attempt at making a MPP Server.", - "main": "index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/BopItFreak/mpp-server.git" - }, - "keywords": [ - "mpp", - "server", - "multiplayerpiano" - ], - "author": "BopItFreak", - "license": "ISC", - "bugs": { - "url": "https://github.com/BopItFreak/mpp-server/issues" - }, - "homepage": "https://github.com/BopItFreak/mpp-server#readme", - "dependencies": { - "asyncconsole": "^1.3.9", - "events": "^3.0.0", - "keccak": "^2.0.0", - "node-json-color-stringify": "^1.1.0", - "ws": "^7.1.2" - }, - "devDependencies": {} -} diff --git a/src/Client.js b/src/Client.js deleted file mode 100644 index b7f5b54..0000000 --- a/src/Client.js +++ /dev/null @@ -1,117 +0,0 @@ -const config = require('./db/config'); -const quotas = config.quotas; -const RateLimit = require('./RateLimit.js').RateLimit; -const RateLimitChain = require('./RateLimit.js').RateLimitChain; -const Room = require("./Room.js"); -require('node-json-color-stringify'); -class Client extends EventEmitter { - constructor(ws, req, server) { - super(); - EventEmitter.call(this); - this.user; - this.connectionid = server.connectionid; - this.server = server; - this.participantId; - this.channel; - this.ws = ws; - this.req = req; - this.ip = (req.connection.remoteAddress).replace("::ffff:", ""); - this.destroied = false; - this.bindEventListeners(); - this.quotas = { - chat: new RateLimitChain(quotas.chat.amount, quotas.chat.time), - name: new RateLimitChain(quotas.name.amount, quotas.name.time), - room: new RateLimit(quotas.room.time), - cursor: new RateLimit(quotas.cursor.time), - kickban: new RateLimitChain(quotas.kickban.amount, quotas.kickban.time), - crowned_chat: new RateLimitChain(quotas.crowned_chat.amount, quotas.crowned_chat.time) - } - require('./Message.js')(this); - } - isConnected() { - return this.ws && this.ws.readyState === WebSocket.OPEN; - } - isConnecting() { - return this.ws && this.ws.readyState === WebSocket.CONNECTING; - } - setChannel(_id, settings) { - if (this.channel && this.channel._id == _id) return; - if (this.server.rooms.get(_id)) { - let room = this.server.rooms.get(_id); - let userbanned = room.bans.get(this.user._id); - if (userbanned && (Date.now() - userbanned.bannedtime >= userbanned.msbanned)) { - room.bans.delete(userbanned.user._id); - userbanned = undefined; - } - if (userbanned) { - console.log(Date.now() - userbanned.bannedtime) - room.Notification(this.user._id, - "Notice", - `Currently banned from \"${_id}\" for ${Math.ceil(Math.floor((userbanned.msbanned - (Date.now() - userbanned.bannedtime)) / 1000) / 60)} minutes.`, - 7000, - "", - "#room", - "short" - ); - return; - } - let channel = this.channel; - if (channel) this.channel.emit("bye", this); - if (channel) this.channel.updateCh(); - this.channel = this.server.rooms.get(_id); - this.channel.join(this); - } else { - let room = new Room(this.server, _id, settings); - this.server.rooms.set(_id, room); - if (this.channel) this.channel.emit("bye", this); - this.channel = this.server.rooms.get(_id); - this.channel.join(this); - } - } - sendArray(arr) { - if (this.isConnected()) { - //console.log(`SEND: `, JSON.colorStringify(arr)); - this.ws.send(JSON.stringify(arr)); - } - } - destroy() { - this.ws.close(); - if (this.channel) { - this.channel.emit("bye", this) - } - this.user; - this.participantId; - this.channel; - this.server.roomlisteners.delete(this.connectionid); - this.connectionid; - this.server.connections.delete(this.connectionid); - this.destroied = true; - console.log(`Removed Connection ${this.connectionid}.`); - } - bindEventListeners() { - this.ws.on("message", (evt, admin) => { - try { - let transmission = JSON.parse(evt); - for (let msg of transmission) { - if (!msg.hasOwnProperty("m")) return; - if (!this.server.legit_m.includes(msg.m)) return; - this.emit(msg.m, msg, !!admin); - //console.log(`RECIEVE: `, JSON.colorStringify(msg)); - } - } catch (e) { - console.log(e) - this.destroy(); - } - }); - this.ws.on("close", () => { - if (!this.destroied) - this.destroy(); - }); - this.ws.addEventListener("error", (err) => { - console.error(err); - if (!this.destroied) - this.destroy(); - }); - } -} -module.exports = Client; diff --git a/src/ColorEncoder.js b/src/ColorEncoder.js deleted file mode 100644 index d91f04b..0000000 --- a/src/ColorEncoder.js +++ /dev/null @@ -1,16 +0,0 @@ -function hashCode(str) { // java String#hashCode - var hash = 0; - for (var i = 0; i < str.length; i++) { - hash = str.charCodeAt(i) + ((hash << 5) - hash); - } - return hash; -} - -function intToRGB(i){ - var c = (i & 0x00FFFFFF) - .toString(16) - .toUpperCase(); - - return "00000".substring(0, 6 - c.length) + c; -} -module.exports = {hashCode, intToRGB}; \ No newline at end of file diff --git a/src/Message.js b/src/Message.js deleted file mode 100644 index ea4ee86..0000000 --- a/src/Message.js +++ /dev/null @@ -1,181 +0,0 @@ -const User = require("./User.js"); -const Room = require("./Room.js"); -module.exports = (cl) => { - cl.once("hi", () => { - let user = new User(cl); - user.getUserData().then((data) => { - let msg = {}; - msg.m = "hi"; - msg.motd = cl.server.welcome_motd; - msg.t = Date.now(); - msg.u = data; - msg.v = "Beta"; - cl.sendArray([msg]) - cl.user = data; - }) - }) - cl.on("t", msg => { - if (msg.hasOwnProperty("e") && !isNaN(msg.e)) - cl.sendArray([{ - m: "t", - t: Date.now(), - e: msg.e - }]) - }) - cl.on("ch", msg => { - if (!cl.quotas.room.attempt()) return; - if (!msg.hasOwnProperty("set") || !msg.set) msg.set = {}; - if (msg.hasOwnProperty("_id") && typeof msg._id == "string") { - if (msg._id.length > 512) return; - cl.setChannel(msg._id, msg.set); - } - }) - cl.on("m", msg => { - if (!cl.quotas.cursor.attempt()) return; - if (!(cl.channel && cl.participantId)) return; - if (!msg.hasOwnProperty("x")) msg.x = null; - if (!msg.hasOwnProperty("y")) msg.y = null; - if (parseInt(msg.x) == NaN) msg.x = null; - if (parseInt(msg.y) == NaN) msg.y = null; - cl.channel.emit("m", cl, msg.x, msg.y) - - }) - cl.on("chown", msg => { - if (!(cl.channel && cl.participantId)) return; - //console.log((Date.now() - cl.channel.crown.time)) - //console.log(!(cl.channel.crown.userId != cl.user._id), !((Date.now() - cl.channel.crown.time) > 15000)); - if (!(cl.channel.crown.userId == cl.user._id) && !((Date.now() - cl.channel.crown.time) > 15000)) return; - if (msg.hasOwnProperty("id")) { - // console.log(cl.channel.crown) - if (cl.user._id == cl.channel.crown.userId || cl.channel.crowndropped) - cl.channel.chown(msg.id); - } else { - if (cl.user._id == cl.channel.crown.userId || cl.channel.crowndropped) - cl.channel.chown(); - } - }) - cl.on("chset", msg => { - if (!(cl.channel && cl.participantId)) return; - if (!(cl.user._id == cl.channel.crown.userId)) return; - if (!msg.hasOwnProperty("set") || !msg.set) msg.set = cl.channel.verifySet(cl.channel._id,{}); - cl.channel.settings = msg.set; - cl.channel.updateCh(); - }) - cl.on("a", msg => { - if (cl.channel.isLobby(cl.channel._id)) { - if (!cl.quotas.chat.attempt()) return; - } else { - if (!(cl.user._id == cl.channel.crown.userId)) { - if (!cl.quotas.chat.attempt()) return; - } else { - if (!cl.quotas.crowned_chat.attempt()) return; - } - } - if (!(cl.channel && cl.participantId)) return; - if (!msg.hasOwnProperty('message')) return; - if (cl.channel.settings.chat) { - cl.channel.emit('a', cl, msg); - } - }) - cl.on('n', msg => { - if (!(cl.channel && cl.participantId)) return; - if (!msg.hasOwnProperty('t') || !msg.hasOwnProperty('n')) return; - if (typeof msg.t != 'number' || typeof msg.n != 'object') return; - if (cl.channel.settings.crownsolo) { - if ((cl.channel.crown.userId == cl.user._id) && !cl.channel.crowndropped) { - cl.channel.playNote(cl, msg); - } - } else { - cl.channel.playNote(cl, msg); - } - }) - cl.on('+ls', msg => { - if (!(cl.channel && cl.participantId)) return; - cl.server.roomlisteners.set(cl.connectionid, cl); - let rooms = []; - for (let room of Array.from(cl.server.rooms.values())) { - let data = room.fetchData().ch; - if (room.bans.get(cl.user._id)) { - data.banned = true; - } - if (room.settings.visible) rooms.push(data); - } - cl.sendArray([{ - "m": "ls", - "c": true, - "u": rooms - }]) - }) - cl.on('-ls', msg => { - if (!(cl.channel && cl.participantId)) return; - cl.server.roomlisteners.delete(cl.connectionid); - }) - cl.on("userset", msg => { - if (!cl.quotas.name.attempt()) return; - if (!(cl.channel && cl.participantId)) return; - if (!msg.hasOwnProperty("set") || !msg.set) msg.set = {}; - if (msg.set.hasOwnProperty('name') && typeof msg.set.name == "string") { - if (msg.set.name.length > 40) return; - cl.user.name = msg.set.name; - let user = new User(cl); - user.getUserData().then((usr) => { - let dbentry = user.userdb.get(cl.user._id); - if (!dbentry) return; - dbentry.name = msg.set.name; - user.updatedb(); - cl.server.rooms.forEach((room) => { - room.updateParticipant(cl.participantId, { - name: msg.set.name - }); - }) - }) - - } - }) - cl.on('kickban', msg => { - if (!cl.quotas.kickban.attempt()) return; - if (!(cl.channel && cl.participantId)) return; - if (!(cl.user._id == cl.channel.crown.userId)) return; - if (msg.hasOwnProperty('_id') && typeof msg._id == "string") { - let _id = msg._id; - let ms = msg.ms || 0; - cl.channel.kickban(_id, ms); - } - }) - cl.on("bye", msg => { - cl.destroy(); - }) - cl.on("admin message", msg => { - if (!(cl.channel && cl.participantId)) return; - if (!msg.hasOwnProperty('password') || !msg.hasOwnProperty('msg')) return; - if (typeof msg.msg != 'object') return; - if (msg.password !== cl.server.adminpass) return; - cl.ws.emit("message", JSON.stringify([msg.msg]), true); - }) - //admin only stuff - cl.on('color', (msg, admin) => { - if (!admin) return; - if (typeof cl.channel.verifyColor(msg.color) != 'string') return; - if (!msg.hasOwnProperty('id') && !msg.hasOwnProperty('_id')) return; - cl.server.connections.forEach((usr) => { - if ((usr.channel && usr.participantId && usr.user) && (usr.user._id == msg._id || (usr.participantId == msg.id))) { - let user = new User(usr); - user.cl.user.color = msg.color; - user.getUserData().then((uSr) => { - if (!uSr._id) return; - let dbentry = user.userdb.get(uSr._id); - if (!dbentry) return; - dbentry.color = msg.color; - //user.updatedb(); - cl.server.rooms.forEach((room) => { - room.updateParticipant(usr.participantId, { - color: msg.color - }); - }) - }) - } - }) - - }) - -} diff --git a/src/Quota.js b/src/Quota.js deleted file mode 100644 index 16bb717..0000000 --- a/src/Quota.js +++ /dev/null @@ -1,87 +0,0 @@ -class Quota { - constructor(cb) { - this.cb = cb; - this.setParams(); - this.resetPoints(); - }; - static NQ_PARAMS_LOBBY = { - allowance: 200, - max: 600 - }; - static NQ_PARAMS_NORMAL = { - allowance: 400, - max: 1200 - }; - static NQ_PARAMS_RIDICULOUS = { - allowance: 600, - max: 1800 - }; - static NQ_PARAMS_OFFLINE = { - allowance: 8000, - max: 24000, - maxHistLen: 3 - }; - static CH_PARAMS = { - allowance: 8000, - max: 24000, - maxHistLen: 3 - } - getParams() { - return { - m: "nq", - allowance: this.allowance, - max: this.max, - maxHistLen: this.maxHistLen - }; - }; - setParams(params) { - params = params || NoteQuota.PARAMS_OFFLINE; - var allowance = params.allowance || this.allowance || NoteQuota.PARAMS_OFFLINE.allowance; - var max = params.max || this.max || NoteQuota.PARAMS_OFFLINE.max; - var maxHistLen = params.maxHistLen || this.maxHistLen || NoteQuota.PARAMS_OFFLINE.maxHistLen; - if (allowance !== this.allowance || max !== this.max || maxHistLen !== this.maxHistLen) { - this.allowance = allowance; - this.max = max; - this.maxHistLen = maxHistLen; - this.resetPoints(); - return true; - } - return false; - }; - resetPoints() { - this.points = this.max; - this.history = []; - for (var i = 0; i < this.maxHistLen; i++) - this.history.unshift(this.points); - if (this.cb) this.cb(this.points); - }; - tick() { - // keep a brief history - this.history.unshift(this.points); - this.history.length = this.maxHistLen; - // hook a brother up with some more quota - if (this.points < this.max) { - this.points += this.allowance; - if (this.points > this.max) this.points = this.max; - // fire callback - if (this.cb) this.cb(this.points); - } - }; - spend(needed) { - // check whether aggressive limitation is needed - var sum = 0; - for (var i in this.history) { - sum += this.history[i]; - } - if (sum <= 0) needed *= this.allowance; - // can they afford it? spend - if (this.points < needed) { - return false; - } else { - this.points -= needed; - if (this.cb) this.cb(this.points); // fire callback - return true; - } - }; -} -module.exports = Quota; \ No newline at end of file diff --git a/src/Ratelimit.js b/src/Ratelimit.js deleted file mode 100644 index f43157d..0000000 --- a/src/Ratelimit.js +++ /dev/null @@ -1,40 +0,0 @@ - -var RateLimit = function(interval_ms) { - this._interval_ms = interval_ms || 0; // (0 means no limit) - this._after = 0; -}; - -RateLimit.prototype.attempt = function(time) { - var time = time || Date.now(); - if(time < this._after) return false; - this._after = time + this._interval_ms; - return true; -}; - -RateLimit.prototype.setInterval = function(interval_ms) { - this._after += interval_ms - this._interval_ms; - this._interval_ms = interval_ms; -}; - -var RateLimitChain = function(num, interval_ms) { - this.setNumAndInterval(num, interval_ms); -}; - -RateLimitChain.prototype.attempt = function(time) { - var time = time || Date.now(); - for(var i = 0; i < this._chain.length; i++) { - if(this._chain[i].attempt(time)) return true; - } - return false; -}; - -RateLimitChain.prototype.setNumAndInterval = function(num, interval_ms) { - this._chain = []; - for(var i = 0; i < num; i++) { - this._chain.push(new RateLimit(interval_ms)); - } -}; - -var exports = typeof module !== "undefined" ? module.exports : this; -exports.RateLimit = RateLimit; -exports.RateLimitChain = RateLimitChain; diff --git a/src/Room.js b/src/Room.js deleted file mode 100644 index f6f6520..0000000 --- a/src/Room.js +++ /dev/null @@ -1,420 +0,0 @@ -//array of rooms -//room class -//room deleter -//databases in Map - -class Room extends EventEmitter { - constructor(server, _id, settings) { - super(); - EventEmitter.call(this); - this._id = _id; - this.server = server; - this.crown = null; - this.crowndropped = false; - this.settings = this.verifySet(this._id,{set:settings}); - this.chatmsgs = []; - this.ppl = new Map(); - this.connections = []; - this.bindEventListeners(); - this.server.rooms.set(_id, this); - this.bans = new Map(); - } - join(cl) { //this stuff is complicated - let otheruser = this.connections.find((a) => a.user._id == cl.user._id) - if (!otheruser) { - let participantId = createKeccakHash('keccak256').update((Math.random().toString() + cl.ip)).digest('hex').substr(0, 24); - cl.user.id = participantId; - cl.participantId = participantId; - if (((this.connections.length == 0 && Array.from(this.ppl.values()).length == 0) && !this.isLobby(this._id)) || this.crown && (this.crown.userId == cl.user._id)) { //user that created the room, give them the crown. - this.crown = { - participantId: cl.participantId, - userId: cl.user._id, - time: Date.now(), - startPos: { - x: 50, - y: 50 - }, - endPos: { - x: this.getCrownX(), - y: this.getCrownY() - } - } - this.crowndropped = false; - } - this.ppl.set(participantId, cl); - this.connections.push(cl); - this.sendArray([{ - color: this.ppl.get(cl.participantId).user.color, - id: this.ppl.get(cl.participantId).participantId, - m: "p", - name: this.ppl.get(cl.participantId).user.name, - x: this.ppl.get(cl.participantId).x || 200, - y: this.ppl.get(cl.participantId).y || 100, - _id: cl.user._id - }], cl, false) - cl.sendArray([{ - m: "c", - c: this.chatmsgs.slice(-1 * 32) - }]) - this.updateCh(cl); - } else { - cl.user.id = otheruser.participantId; - cl.participantId = otheruser.participantId; - this.connections.push(cl); - cl.sendArray([{ - m: "c", - c: this.chatmsgs.slice(-1 * 32) - }]) - this.updateCh(cl); - } - - } - remove(p) { //this is complicated too - let otheruser = this.connections.filter((a) => a.user._id == p.user._id); - if (!(otheruser.length > 1)) { - this.ppl.delete(p.participantId); - this.connections.splice(this.connections.findIndex((a) => a.connectionid == p.connectionid), 1); - console.log(`Deleted client ${p.user.id}`); - this.sendArray([{ - m: "bye", - p: p.participantId - }], p, false); - if (this.crown) - if (this.crown.userId == p.user._id && !this.crowndropped) { - this.chown(); - } - this.updateCh(); - } else { - this.connections.splice(this.connections.findIndex((a) => a.connectionid == p.connectionid), 1); - } - - } - updateCh(cl) { //update channel for all people in channel - if (Array.from(this.ppl.values()).length <= 0) this.destroy(); - this.connections.forEach((usr) => { - this.server.connections.get(usr.connectionid).sendArray([this.fetchData(usr, cl)]) - }) - this.server.updateRoom(this.fetchData()); - } - updateParticipant(pid, options) { - let p = this.ppl.get(pid); - if (!p) return; - options.name ? this.ppl.get(pid).user.name = options.name : {}; - options._id ? this.ppl.get(pid).user._id = options._id : {}; - options.color ? this.ppl.get(pid).user.color = options.color : {}; - this.connections.filter((ofo) => ofo.participantId == p.participantId).forEach((usr) => { - options.name ? usr.user.name = options.name : {}; - options._id ? usr.user._id = options._id : {}; - options.color ? usr.user.color = options.color : {}; - }) - this.sendArray([{ - color: p.user.color, - id: p.participantId, - m: "p", - name: p.user.name, - x: p.x || 200, - y: p.y || 100, - _id: p.user._id - }]) - } - destroy() { //destroy room - this._id; - console.log(`Deleted room ${this._id}`); - this.settings = {}; - this.ppl; - this.connnections; - this.chatmsgs; - this.server.rooms.delete(this._id); - } - sendArray(arr, not, onlythisparticipant) { - this.connections.forEach((usr) => { - if (!not || (usr.participantId != not.participantId && !onlythisparticipant) || (usr.connectionid != not.connectionid && onlythisparticipant)) { - try { - this.server.connections.get(usr.connectionid).sendArray(arr) - } catch (e) { - console.log(e); - } - } - }) - } - fetchData(usr, cl) { - let chppl = []; - [...this.ppl.values()].forEach((a) => { - chppl.push(a.user); - }) - let data = { - m: "ch", - p: "ofo", - ch: { - count: chppl.length, - crown: this.crown, - settings: this.settings, - _id: this._id - }, - ppl: chppl - } - if (cl) { - if (usr.connectionid == cl.connectionid) { - data.p = cl.participantId; - } else { - delete data.p; - } - } else { - delete data.p; - } - if (data.ch.crown == null) { - delete data.ch.crown; - } else { - - } - return data; - } - verifyColor(strColor){ - var test2 = /^#[0-9A-F]{6}$/i.test(strColor); - if(test2 == true){ - return strColor; - } else{ - return false; - } - } - isLobby(_id) { - if (_id.startsWith("lobby")) { - let lobbynum = _id.split("lobby")[1]; - if (_id == "lobby") { - return true; - } - if (!(parseInt(lobbynum).toString() == lobbynum)) return false; - for (let i in lobbynum) { - if (parseInt(lobbynum[i]) >= 0) { - if (parseInt(i) + 1 == lobbynum.length) return true; - - } else { - return false; - } - } - } else if (_id.startsWith("test/")) { - if (_id == "test/") { - return false; - } else { - return true; - } - } else { - return false; - } - - } - getCrownY() { - return 50 - 30; - } - getCrownX() { - return 50; - } - chown(id) { - let prsn = this.ppl.get(id); - if (prsn) { - this.crown = { - participantId: prsn.participantId, - userId: prsn.user._id, - time: Date.now(), - startPos: { - x: 50, - y: 50 - }, - endPos: { - x: this.getCrownX(), - y: this.getCrownY() - }, - } - this.crowndropped = false; - } else { - this.crown = { - userId: this.crown.userId, - time: Date.now(), - startPos: { - x: 50, - y: 50 - }, - endPos: { - x: this.getCrownX(), - y: this.getCrownY() - } - } - this.crowndropped = true; - } - this.updateCh(); - } - setCords(p, x, y) { - if (p.participantId && this.ppl.get(p.participantId)) { - x ? this.ppl.get(p.participantId).x = x : {}; - y ? this.ppl.get(p.participantId).y = y : {}; - this.sendArray([{ - m: "m", - id: p.participantId, - x: this.ppl.get(p.participantId).x, - y: this.ppl.get(p.participantId).y - }], p, false); - } - } - chat(p, msg) { - if (msg.message.length > 512) return; - let filter = ["AMIGHTYWIND"]; - let regexp = new RegExp("\\b(" + filter.join("|") + ")\\b", "i"); - if (regexp.test(msg.message)) return; - let prsn = this.ppl.get(p.participantId); - if (prsn) { - let message = {}; - message.m = "a"; - message.a = msg.message; - message.p = { - color: p.user.color, - id: p.participantId, - name: p.user.name, - _id: p.user._id - }; - message.t = Date.now(); - this.sendArray([message]); - this.chatmsgs.push(message); - } - } - playNote(cl, note) { - this.sendArray([{ - m: "n", - n: note.n, - p: cl.participantId, - t: note.t - }], cl, true); - } - kickban(_id, ms) { - ms = parseInt(ms); - if (ms >= (1000 * 60 * 60 - 500)) return; - if (ms < 0) return; - ms = Math.round(ms / 1000) * 1000; - let user = this.connections.find((usr) => usr.user._id == _id); - if (!user) return; - let asd = true; - let tonc = true; - let pthatbanned = this.ppl.get(this.crown.participantId); - this.connections.filter((usr) => usr.participantId == user.participantId).forEach((u) => { - user.bantime = Math.floor(Math.floor(ms / 1000) / 60); - user.bannedtime = Date.now(); - user.msbanned = ms; - this.bans.set(user.user._id, user); - if (this.crown && (this.crown.userId)) { - u.setChannel("test/awkward", {}); - if (asd) - this.Notification(user.user._id, - "Notice", - `Banned from \"${this._id}\" for ${Math.floor(Math.floor(ms / 1000) / 60)} minutes.`, - "", - 7000, - "#room", - "short" - ) - if (asd) - this.Notification("room", - "Notice", - `${pthatbanned.user.name} banned ${user.user.name} from the channel for ${Math.floor(Math.floor(ms / 1000) / 60)} minutes.`, - "", - 7000, - "#room", - "short" - ) - if (this.crown && (this.crown.userId == _id) && tonc) { - this.Notification("room", - "Certificate of Award", - `Let it be known that ${user.user.name} kickbanned him/her self.`, - "", - 7000, - "#room" - ); - tonc = false; - } - - } - - }) - } - Notification(who, title, text, html, duration, target, klass, id) { - let obj = { - m: "notification", - title: title, - text: text, - html: html, - target: target, - duration: duration, - class: klass, - id: id - }; - if (!id) delete obj.id; - if (!title) delete obj.title; - if (!text) delete obj.text; - if (!html) delete obj.html; - if (!target) delete obj.target; - if (!duration) delete obj.duration; - if (!klass) delete obj.class; - switch (who) { - case "all": { - for (let con of Array.from(this.server.connections.values())) { - con.sendArray([obj]); - } - break; - } - case "room": { - for (let con of this.connections) { - con.sendArray([obj]); - } - break; - } - default: { - Array.from(this.server.connections.values()).filter((usr) => usr.user._id == who).forEach((p) => { - p.sendArray([obj]); - }); - } - } - } - bindEventListeners() { - this.on("bye", participant => { - this.remove(participant); - }) - - this.on("m", (participant, x, y) => { - this.setCords(participant, x, y); - }) - - this.on("a", (participant, msg) => { - this.chat(participant, msg); - }) - } - verifySet(_id,msg){ - if(!isObj(msg.set)) msg.set = {visible:true,color:this.server.defaultRoomColor,chat:true,crownsolo:false}; - if(isBool(msg.set.lobby)){ - if(!this.isLobby(_id)) delete msg.set.lobby; // keep it nice and clean - }else{ - if(this.isLobby(_id)) msg.set = {visible:true,color:this.server.defaultLobbyColor,color2:this.server.defaultLobbyColor2,chat:true,crownsolo:false,lobby:true}; - } - if(!isBool(msg.set.visible)){ - if(msg.set.visible == undefined) msg.set.visible = (!isObj(this.settings) ? true : this.settings.visible); - else msg.set.visible = true; - }; - if(!isBool(msg.set.chat)){ - if(msg.set.chat == undefined) msg.set.chat = (!isObj(this.settings) ? true : this.settings.chat); - else msg.set.chat = true; - }; - if(!isBool(msg.set.crownsolo)){ - if(msg.set.crownsolo == undefined) msg.set.crownsolo = (!isObj(this.settings) ? false : this.settings.crownsolo); - else msg.set.crownsolo = false; - }; - if(!isString(msg.set.color) || !/^#[0-9a-f]{6}$/i.test(msg.set.color)) msg.set.color = (!isObj(this.settings) ? this.server.defaultRoomColor : this.settings.color); - if(isString(msg.set.color2)){ - if(!/^#[0-9a-f]{6}$/i.test(msg.set.color2)){ - if(this.settings){ - if(this.settings.color2) msg.set.color2 = this.settings.color2; - else delete msg.set.color2; // keep it nice and clean - } - } - }; - return msg.set; - } - -} -module.exports = Room; diff --git a/src/Server.js b/src/Server.js deleted file mode 100644 index 8d29a44..0000000 --- a/src/Server.js +++ /dev/null @@ -1,41 +0,0 @@ -const Client = require("./Client.js") -class Server extends EventEmitter { - constructor(config) { - super(); - EventEmitter.call(this); - this.wss = new WebSocket.Server({ - port: config.port, - backlog: 100, - verifyClient: function (info, done) { - done(true) - } - }); - this.connectionid = 0; - this.connections = new Map(); - this.roomlisteners = new Map(); - this.rooms = new Map(); - this.wss.on('connection', (ws, req) => { - this.connections.set(++this.connectionid, new Client(ws, req, this)); - }); - this.legit_m = ["a", "bye", "hi", "ch", "+ls", "-ls", "m", "n", "devices", "t", "chset", "userset", "chown", "kickban", "admin message", "color"] - this.welcome_motd = config.motd || "You agree to read this message."; - this._id_Private_Key = config._id_PrivateKey || "boppity"; - this.defaultUsername = config.defaultUsername || "Anonymous"; - this.defaultRoomColor = config.defaultRoomColor || "#3b5054"; - this.defaultLobbyColor = config.defaultLobbyColor || "#19b4b9"; - this.defaultLobbyColor2 = config.defaultLobbyColor2 || "#801014"; - this.adminpass = config.adminpass || "Bop It"; - }; - updateRoom(data) { - if (!data.ch.settings.visible) return; - for (let cl of Array.from(this.roomlisteners.values())) { - cl.sendArray([{ - "m": "ls", - "c": false, - "u": [data.ch] - }]) - } - } -} - -module.exports = Server; \ No newline at end of file diff --git a/src/TODO.txt b/src/TODO.txt deleted file mode 100644 index f9af52b..0000000 --- a/src/TODO.txt +++ /dev/null @@ -1,2 +0,0 @@ - -Room.js make color verifier diff --git a/src/User.js b/src/User.js deleted file mode 100644 index bd10b83..0000000 --- a/src/User.js +++ /dev/null @@ -1,53 +0,0 @@ -const ColorEncoder = require("./ColorEncoder.js"); -const { promisify } = require('util'); -let userdb; -class User { - constructor(cl) { - this.cl = cl; - this.server = this.cl.server; - this.userdb = userdb; - this.default_db = {}; - } - async getUserData() { - if (!userdb || (userdb instanceof Map && [...userdb.entries()] == [])) { - await this.setUpDb(); - } - let _id = createKeccakHash('keccak256').update((this.cl.server._id_Private_Key + this.cl.ip)).digest('hex').substr(0, 24); - let usertofind = userdb.get(_id); - if (!usertofind) { - if (typeof usertofind == 'object' && (usertofind.hasOwnProperty('name') && usertofind.name != this.server.defaultUsername)) return; - userdb.set(_id, { - "color": `#${ColorEncoder.intToRGB(ColorEncoder.hashCode(_id)).toLowerCase()}`, - "name": this.server.defaultUsername, - "_id": _id, - "ip": this.cl.ip - }); - this.updatedb(); - } - let user = userdb.get(_id); - return { - "color": user.color, - "name": user.name, - "_id": user._id, - } - } - async updatedb() { - const writeFile = promisify(fs.writeFile); - await writeFile('src/db/users.json', JSON.stringify(User.strMapToObj(userdb), null, 2)); - } - async setUpDb() { - const writeFile = promisify(fs.writeFile); - const readdir = promisify(fs.readdir); - let files = await readdir("src/db/"); - if (!files.includes("users.json")) { - await writeFile('src/db/users.json', JSON.stringify(this.default_db, null, 2)) - userdb = new Map(Object.entries(require("./db/users.json"))); - } else { - userdb = new Map(Object.entries(require("./db/users.json"))); - } - } - static strMapToObj(strMap) { - return [...strMap.entries()].reduce((obj, [key, value]) => (obj[key] = value, obj), {}); - } -} -module.exports = User; \ No newline at end of file diff --git a/src/db/config.js b/src/db/config.js deleted file mode 100644 index 58bfddc..0000000 --- a/src/db/config.js +++ /dev/null @@ -1,34 +0,0 @@ -module.exports = Object.seal({ - "port": "3000", - "motd": "You agree to read this message.", - "_id_PrivateKey": "boppity", - "defaultUsername": "Anonymous", - "defaultRoomColor": "#3b5054", - "defaultLobbyColor": "#19b4b9", - "defaultLobbyColor2": "#801014", - "adminpass": "adminpass", - "quotas":{ - "chat":{ - "amount": 4, - "time": 4000 - }, - "name":{ - "amount": 30, - "time": 30 * 60000 - }, - "room":{ - "time": 500 - }, - "cursor":{ - "time": 16 - }, - "kickban":{ - "amount": 2, - "time": 1000 - }, - "crowned_chat":{ - "amount": 10, - "time": 4000 - } - } -}) diff --git a/src/db/users.json b/src/db/users.json deleted file mode 100644 index 0967ef4..0000000 --- a/src/db/users.json +++ /dev/null @@ -1 +0,0 @@ -{} From 280c0d67c58562820a2d2b3b68ea1601e3700956 Mon Sep 17 00:00:00 2001 From: Wolfy Date: Tue, 7 Apr 2020 03:55:16 -0400 Subject: [PATCH 18/32] Add Add everything --- Quotas.js | 51 ++++++ README.md | 2 + banned.json | 3 + config.js | 10 + index.js | 27 +++ package.json | 32 ++++ src/Client.js | 121 +++++++++++++ src/ColorEncoder.js | 16 ++ src/Message.js | 254 ++++++++++++++++++++++++++ src/Quota.js | 58 ++++++ src/Ratelimit.js | 40 ++++ src/Room.js | 432 ++++++++++++++++++++++++++++++++++++++++++++ src/Server.js | 45 +++++ src/TODO.txt | 2 + src/User.js | 56 ++++++ src/db/users.json | 114 ++++++++++++ 16 files changed, 1263 insertions(+) create mode 100644 Quotas.js create mode 100644 README.md create mode 100644 banned.json create mode 100644 config.js create mode 100644 index.js create mode 100644 package.json create mode 100644 src/Client.js create mode 100644 src/ColorEncoder.js create mode 100644 src/Message.js create mode 100644 src/Quota.js create mode 100644 src/Ratelimit.js create mode 100644 src/Room.js create mode 100644 src/Server.js create mode 100644 src/TODO.txt create mode 100644 src/User.js create mode 100644 src/db/users.json diff --git a/Quotas.js b/Quotas.js new file mode 100644 index 0000000..8953448 --- /dev/null +++ b/Quotas.js @@ -0,0 +1,51 @@ +module.exports = Object.seal({ + "note": { + "lobby": { + "allowance": 200, + "max": 600, + "maxHistLen": 3 + }, + "normal": { + "allowance": 400, + "max": 1200, + "maxHistLen": 3 + }, + "insane": { + "allowance": 600, + "max": 1800, + "maxHistLen": 3 + } + }, + "chat": { + "lobby": { + "amount": 4, + "time": 4000 + }, + "normal": { + "amount": 4, + "time": 4000 + }, + "insane": { + "amount": 10, + "time": 4000 + } + }, + "chown": { + "amount": 10, + "time": 5000 + }, + "name": { + "amount": 30, + "time": 30 * 60000 + }, + "room": { + "time": 500 + }, + "cursor": { + "time": 16 + }, + "kickban": { + "amount": 2, + "time": 1000 + } +}) \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..33b4471 --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# mpp-server +Attempt at making a MPP Server. \ No newline at end of file diff --git a/banned.json b/banned.json new file mode 100644 index 0000000..1610ea1 --- /dev/null +++ b/banned.json @@ -0,0 +1,3 @@ +[ + +] \ No newline at end of file diff --git a/config.js b/config.js new file mode 100644 index 0000000..e27916c --- /dev/null +++ b/config.js @@ -0,0 +1,10 @@ +module.exports = Object.seal({ + "port": "8080", + "motd": "You agree to read this message.", + "_id_PrivateKey": "boppity", + "defaultUsername": "Anonymous", + "defaultRoomColor": "#3b5054", + "defaultLobbyColor": "#19b4b9", + "defaultLobbyColor2": "#801014", + "adminpass": "27PP6YLTxg0b1P2B8eGSOki1" +}) \ No newline at end of file diff --git a/index.js b/index.js new file mode 100644 index 0000000..8442191 --- /dev/null +++ b/index.js @@ -0,0 +1,27 @@ +//call new Server +global.WebSocket = require('ws'); +global.EventEmitter = require('events').EventEmitter; +global.fs = require('fs'); +global.createKeccakHash = require('keccak'); +const AsyncConsole = require('asyncconsole') + +global.isString = function(a){ + return typeof a === 'string'; +} +global.isBool = function(a){ + return typeof a === 'boolean'; +} +global.isObj = function(a){ + return typeof a === "object" && !Array.isArray(a) && a !== null; +} + +let Server = require("./src/Server"); +let config = require('./config'); +global.SERVER = new Server(config); +let console = process.platform == 'win32' ? new AsyncConsole("", input => { + try { + console.log(JSON.stringify(eval(input))); + } catch(e) { + console.log(e.toString()); + } +}) : {}; diff --git a/package.json b/package.json new file mode 100644 index 0000000..85f2681 --- /dev/null +++ b/package.json @@ -0,0 +1,32 @@ +{ + "name": "mpp-server-master", + "version": "1.0.0", + "description": "Attempt at making a MPP Server.", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/BopItFreak/mpp-server.git" + }, + "keywords": [ + "mpp", + "server", + "multiplayerpiano" + ], + "author": "BopItFreak", + "license": "ISC", + "bugs": { + "url": "https://github.com/BopItFreak/mpp-server/issues" + }, + "homepage": "https://github.com/BopItFreak/mpp-server#readme", + "dependencies": { + "asyncconsole": "^1.3.9", + "events": "^3.1.0", + "keccak": "^2.1.0", + "node-json-color-stringify": "^1.1.0", + "ws": "^7.2.3" + }, + "devDependencies": {} +} diff --git a/src/Client.js b/src/Client.js new file mode 100644 index 0000000..d3c4f32 --- /dev/null +++ b/src/Client.js @@ -0,0 +1,121 @@ +const quotas = require('../Quotas'); +const RateLimit = require('./RateLimit.js').RateLimit; +const RateLimitChain = require('./RateLimit.js').RateLimitChain; +const Room = require("./Room.js"); +require('node-json-color-stringify'); +class Client extends EventEmitter { + constructor(ws, req, server) { + super(); + EventEmitter.call(this); + this.user; + this.connectionid = server.connectionid; + this.server = server; + this.participantId; + this.channel; + this.ws = ws; + this.req = req; + this.ip = (req.connection.remoteAddress).replace("::ffff:", ""); + this.destroied = false; + this.bindEventListeners(); + this.quotas = { + //note: new limiter(2000, { allowance:3000, max:24000, maxHistLen:3}), + chat: { + lobby: new RateLimitChain(quotas.chat.lobby.amount, quotas.chat.lobby.time), + normal: new RateLimitChain(quotas.chat.normal.amount, quotas.chat.normal.time), + insane: new RateLimitChain(quotas.chat.insane.amount, quotas.chat.insane.time) + }, + name: new RateLimitChain(quotas.name.amount, quotas.name.time), + room: new RateLimit(quotas.room.time), + chown: new RateLimitChain(quotas.chown.amount, quotas.chown.time), + cursor: new RateLimit(quotas.cursor.time), + kickban: new RateLimitChain(quotas.kickban.amount, quotas.kickban.time), + } + require('./Message.js')(this); + } + isConnected() { + return this.ws && this.ws.readyState === WebSocket.OPEN; + } + isConnecting() { + return this.ws && this.ws.readyState === WebSocket.CONNECTING; + } + setChannel(_id, settings) { + if (this.channel && this.channel._id == _id) return; + if (this.server.rooms.get(_id)) { + let room = this.server.rooms.get(_id); + let userbanned = room.bans.get(this.user._id); + if (userbanned && (Date.now() - userbanned.bannedtime >= userbanned.msbanned)) { + room.bans.delete(userbanned.user._id); + userbanned = undefined; + } + if (userbanned) { + console.log(Date.now() - userbanned.bannedtime) + room.Notification(this.user._id, + "Notice", + `Currently banned from \"${_id}\" for ${Math.ceil(Math.floor((userbanned.msbanned - (Date.now() - userbanned.bannedtime)) / 1000) / 60)} minutes.`, + 7000, + "", + "#room", + "short" + ); + return; + } + let channel = this.channel; + if (channel) this.channel.emit("bye", this); + if (channel) this.channel.updateCh(); + this.channel = this.server.rooms.get(_id); + this.channel.join(this); + } else { + let room = new Room(this.server, _id, settings); + this.server.rooms.set(_id, room); + if (this.channel) this.channel.emit("bye", this); + this.channel = this.server.rooms.get(_id); + this.channel.join(this); + } + } + sendArray(arr) { + if (this.isConnected()) { + //console.log(`SEND: `, JSON.colorStringify(arr)); + this.ws.send(JSON.stringify(arr)); + } + } + destroy() { + this.ws.close(); + if (this.channel) { + this.channel.emit("bye", this) + } + this.user; + this.participantId; + this.channel; + this.server.roomlisteners.delete(this.connectionid); + this.connectionid; + this.server.connections.delete(this.connectionid); + this.destroied = true; + console.log(`Removed Connection ${this.connectionid}.`); + } + bindEventListeners() { + this.ws.on("message", (evt, admin) => { + try { + let transmission = JSON.parse(evt); + for (let msg of transmission) { + if (!msg.hasOwnProperty("m")) return; + if (!this.server.legit_m.includes(msg.m)) return; + this.emit(msg.m, msg, !!admin); + //console.log(`RECIEVE: `, JSON.colorStringify(msg)); + } + } catch (e) { + console.log(e) + this.destroy(); + } + }); + this.ws.on("close", () => { + if (!this.destroied) + this.destroy(); + }); + this.ws.addEventListener("error", (err) => { + console.error(err); + if (!this.destroied) + this.destroy(); + }); + } +} +module.exports = Client; \ No newline at end of file diff --git a/src/ColorEncoder.js b/src/ColorEncoder.js new file mode 100644 index 0000000..d91f04b --- /dev/null +++ b/src/ColorEncoder.js @@ -0,0 +1,16 @@ +function hashCode(str) { // java String#hashCode + var hash = 0; + for (var i = 0; i < str.length; i++) { + hash = str.charCodeAt(i) + ((hash << 5) - hash); + } + return hash; +} + +function intToRGB(i){ + var c = (i & 0x00FFFFFF) + .toString(16) + .toUpperCase(); + + return "00000".substring(0, 6 - c.length) + c; +} +module.exports = {hashCode, intToRGB}; \ No newline at end of file diff --git a/src/Message.js b/src/Message.js new file mode 100644 index 0000000..c62d304 --- /dev/null +++ b/src/Message.js @@ -0,0 +1,254 @@ +const config = require('./db/config'); +const quotas = config.quotas; +const User = require("./User.js"); +module.exports = (cl) => { + cl.once("hi", () => { + let user = new User(cl); + user.getUserData().then((data) => { + let msg = {}; + msg.m = "hi"; + msg.motd = cl.server.welcome_motd; + msg.t = Date.now(); + msg.u = data; + msg.v = "Beta"; + cl.sendArray([msg]) + cl.user = data; + }) + }) + cl.on("t", msg => { + if (msg.hasOwnProperty("e") && !isNaN(msg.e)) + cl.sendArray([{ + m: "t", + t: Date.now(), + e: msg.e + }]) + }) + cl.on("ch", msg => { + if (!cl.quotas.room.attempt()) return; + if (!msg.hasOwnProperty("set") || !msg.set) msg.set = {}; + if (msg.hasOwnProperty("_id") && typeof msg._id == "string") { + if (msg._id.length > 512) return; + cl.setChannel(msg._id, msg.set); + if (cl.channel.isLobby(cl.channel._id)) { + cl.channel.sendNotequota(quotas.note.lobby.allowance, quotas.note.lobby.max, quotas.note.lobby.maxHistLen); + } else { + if (!(cl.user._id == cl.channel.crown.userId)) { + cl.channel.sendNotequota(quotas.note.normal.allowance, quotas.note.normal.max, quotas.note.normal.maxHistLen); + } else { + cl.channel.sendNotequota(quotas.note.insane.allowance, quotas.note.insane.max, quotas.note.insane.maxHistLen); + } + } + } + }) + cl.on("m", msg => { + if (!cl.quotas.cursor.attempt()) return; + if (!(cl.channel && cl.participantId)) return; + if (!msg.hasOwnProperty("x")) msg.x = null; + if (!msg.hasOwnProperty("y")) msg.y = null; + if (parseInt(msg.x) == NaN) msg.x = null; + if (parseInt(msg.y) == NaN) msg.y = null; + cl.channel.emit("m", cl, msg.x, msg.y) + + }) + cl.on("chown", msg => { + if (!cl.quotas.chown.attempt()) return; + if (!(cl.channel && cl.participantId)) return; + //console.log((Date.now() - cl.channel.crown.time)) + //console.log(!(cl.channel.crown.userId != cl.user._id), !((Date.now() - cl.channel.crown.time) > 15000)); + if (!(cl.channel.crown.userId == cl.user._id) && !((Date.now() - cl.channel.crown.time) > 15000)) return; + if (msg.hasOwnProperty("id")) { + // console.log(cl.channel.crown) + if (cl.user._id == cl.channel.crown.userId || cl.channel.crowndropped) + cl.channel.chown(msg.id); + } else { + if (cl.user._id == cl.channel.crown.userId || cl.channel.crowndropped) + cl.channel.chown(); + } + }) + cl.on("chset", msg => { + if (!(cl.channel && cl.participantId)) return; + if (!(cl.user._id == cl.channel.crown.userId)) return; + if (!msg.hasOwnProperty("set") || !msg.set) msg.set = cl.channel.verifySet(cl.channel._id,{}); + cl.channel.settings = msg.set; + cl.channel.updateCh(); + }) + cl.on("a", msg => { + if (cl.channel.isLobby(cl.channel._id)) { + if (!cl.quotas.chat.lobby.attempt()) return; + } else { + if (!(cl.user._id == cl.channel.crown.userId)) { + if (!cl.quotas.chat.normal.attempt()) return; + } else { + if (!cl.quotas.chat.insane.attempt()) return; + } + } + if (!(cl.channel && cl.participantId)) return; + if (!msg.hasOwnProperty('message')) return; + if (cl.channel.settings.chat) { + cl.channel.emit('a', cl, msg); + } + }) + cl.on('n', msg => { + if (!(cl.channel && cl.participantId)) return; + if (!msg.hasOwnProperty('t') || !msg.hasOwnProperty('n')) return; + if (typeof msg.t != 'number' || typeof msg.n != 'object') return; + if (cl.channel.settings.crownsolo) { + if ((cl.channel.crown.userId == cl.user._id) && !cl.channel.crowndropped) { + cl.channel.playNote(cl, msg); + } + } else { + cl.channel.playNote(cl, msg); + } + }) + cl.on('+ls', msg => { + if (!(cl.channel && cl.participantId)) return; + cl.server.roomlisteners.set(cl.connectionid, cl); + let rooms = []; + for (let room of Array.from(cl.server.rooms.values())) { + let data = room.fetchData().ch; + if (room.bans.get(cl.user._id)) { + data.banned = true; + } + if (room.settings.visible) rooms.push(data); + } + cl.sendArray([{ + "m": "ls", + "c": true, + "u": rooms + }]) + }) + cl.on('-ls', msg => { + if (!(cl.channel && cl.participantId)) return; + cl.server.roomlisteners.delete(cl.connectionid); + }) + cl.on("userset", msg => { + if (!cl.quotas.name.attempt()) return; + if (!(cl.channel && cl.participantId)) return; + if (!msg.hasOwnProperty("set") || !msg.set) msg.set = {}; + if (msg.set.hasOwnProperty('name') && typeof msg.set.name == "string") { + if (msg.set.name.length > 40) return; + cl.user.name = msg.set.name; + let user = new User(cl); + user.getUserData().then((usr) => { + let dbentry = user.userdb.get(cl.user._id); + if (!dbentry) return; + dbentry.name = msg.set.name; + user.updatedb(); + cl.server.rooms.forEach((room) => { + room.updateParticipant(cl.participantId, { + name: msg.set.name + }); + }) + }) + + } + }) + cl.on('kickban', msg => { + if (!cl.quotas.kickban.attempt()) return; + if (!(cl.channel && cl.participantId)) return; + if (!(cl.user._id == cl.channel.crown.userId)) return; + if (msg.hasOwnProperty('_id') && typeof msg._id == "string") { + let _id = msg._id; + let ms = msg.ms || 0; + cl.channel.kickban(_id, ms); + } + }) + cl.on("bye", msg => { + cl.destroy(); + }) + cl.on("admin message", msg => { + if (!(cl.channel && cl.participantId)) return; + if (!msg.hasOwnProperty('password') || !msg.hasOwnProperty('msg')) return; + if (typeof msg.msg != 'object') return; + if (msg.password !== cl.server.adminpass) return; + cl.ws.emit("message", JSON.stringify([msg.msg]), true); + }) + //admin only stuff + /* + + List of admin only stuff + 1. admin_color + 2. admin_noteColor + 3. admin_chown + 4. admin_kickban + 5. admin_chset + + */ + cl.on('admin_color', (msg, admin) => { + if (!admin) return; + if (typeof cl.channel.verifyColor(msg.color) != 'string') return; + if (!msg.hasOwnProperty('id') && !msg.hasOwnProperty('_id')) return; + cl.server.connections.forEach((usr) => { + if ((usr.channel && usr.participantId && usr.user) && (usr.user._id == msg._id || (usr.participantId == msg.id))) { + let user = new User(usr); + user.cl.user.color = msg.color; + user.getUserData().then((uSr) => { + if (!uSr._id) return; + let dbentry = user.userdb.get(uSr._id); + if (!dbentry) return; + dbentry.color = msg.color; + dbentry.noteColor = msg.color; + //user.updatedb(); + cl.server.rooms.forEach((room) => { + room.updateParticipant(usr.participantId, { + color: msg.color, + noteColor: msg.color + }); + }) + }) + } + }) + + }) + cl.on('admin_noteColor', (msg, admin) => { + if (!admin) return; + if (typeof cl.channel.verifyColor(msg.color) != 'string') return; + if (!msg.hasOwnProperty('id') && !msg.hasOwnProperty('_id')) return; + cl.server.connections.forEach((usr) => { + if ((usr.channel && usr.participantId && usr.user) && (usr.user._id == msg._id || (usr.participantId == msg.id))) { + let user = new User(usr); + //user.getUserData().then((uSr) => { + //if (!uSr._id) return; + //let dbentry = user.userdb.get(uSr._id); + //if (!dbentry) return; + //dbentry.color = msg.color; + //user.updatedb(); + cl.server.rooms.forEach((room) => { + room.updateParticipant(usr.participantId, { + noteColor: msg.color + }); + }) + //}) + } + }) + + }) + cl.on("admin_chown", (msg, admin) => { + if (!admin) return; + if (msg.hasOwnProperty("id")) { + cl.channel.chown(msg.id); + console.log(msg.id); + } else { + cl.channel.chown(); + } + }) + cl.on('admin_kickban', (msg, admin) => { + if (!admin) return; + if (msg.hasOwnProperty('_id') && typeof msg._id == "string") { + let _id = msg._id; + let ms = msg.ms || 0; + cl.channel.kickban(_id, ms); + } + }) + cl.on("admin_chset", (msg, admin) => { + if (!admin) return; + if (!msg.hasOwnProperty("set") || !msg.set) msg.set = cl.channel.verifySet(cl.channel._id,{}); + cl.channel.settings = msg.set; + cl.channel.updateCh(); + }) + cl.on("admin_notification", (msg, admin) => { + if (!admin) return; + cl.channel.Notification(msg.content); + console.log(msg.content); + }) +} \ No newline at end of file diff --git a/src/Quota.js b/src/Quota.js new file mode 100644 index 0000000..a3b303a --- /dev/null +++ b/src/Quota.js @@ -0,0 +1,58 @@ +function RateLimit(a,b){ + this.a = b.a || 1; + this.m = b.m || 10; + this.mh = b.mh || 3; + this.setParams(a,{a:this.a,m:this.m,mh:this.mh}); + this.resetPoints(); + if(a !== null){ + var self = this; + this.giveInt = setInterval(()=>{self.give()},a); + }; +}; +RateLimit.prototype.setParams = function(a,b){ + var a = b.a || this.a || 1; + var m = b.m || this.m || 5; + var mh = b.mh || this.mh || 3; + clearInterval(this.giveInt); + this.giveInt = undefined; + if(a !== this.a || m !== this.m || mh !== this.mh){ + this.a = a; + this.m = m; + this.mh = mh; + this.resetPoints(); + if(a !== null){ + var self = this; + this.giveInt = setInterval(()=>{self.give()},a); + }; + return true; + }; + return false; +}; +RateLimit.prototype.resetPoints = function(){ + this.points = this.m; + this.history = []; + for(var i=0; i this.m) this.points = this.m; + }; +}; +RateLimit.prototype.spend = function(needed){ + var sum = 0; + for(var i in this.history){ + sum += this.history[i]; + }; + if(sum <= 0) needed *= this.a; + if(this.points < needed){ + return false; + }else{ + this.points -= needed; + return true; + }; +}; + +module.exports = RateLimit; \ No newline at end of file diff --git a/src/Ratelimit.js b/src/Ratelimit.js new file mode 100644 index 0000000..8d27edc --- /dev/null +++ b/src/Ratelimit.js @@ -0,0 +1,40 @@ + +var RateLimit = function(interval_ms) { + this._interval_ms = interval_ms || 0; // (0 means no limit) + this._after = 0; +}; + +RateLimit.prototype.attempt = function(time) { + var time = time || Date.now(); + if(time < this._after) return false; + this._after = time + this._interval_ms; + return true; +}; + +RateLimit.prototype.setInterval = function(interval_ms) { + this._after += interval_ms - this._interval_ms; + this._interval_ms = interval_ms; +}; + +var RateLimitChain = function(num, interval_ms) { + this.setNumAndInterval(num, interval_ms); +}; + +RateLimitChain.prototype.attempt = function(time) { + var time = time || Date.now(); + for(var i = 0; i < this._chain.length; i++) { + if(this._chain[i].attempt(time)) return true; + } + return false; +}; + +RateLimitChain.prototype.setNumAndInterval = function(num, interval_ms) { + this._chain = []; + for(var i = 0; i < num; i++) { + this._chain.push(new RateLimit(interval_ms)); + } +}; + +var exports = typeof module !== "undefined" ? module.exports : this; +exports.RateLimit = RateLimit; +exports.RateLimitChain = RateLimitChain; \ No newline at end of file diff --git a/src/Room.js b/src/Room.js new file mode 100644 index 0000000..4998b9f --- /dev/null +++ b/src/Room.js @@ -0,0 +1,432 @@ +//array of rooms +//room class +//room deleter +//databases in Map + +class Room extends EventEmitter { + constructor(server, _id, settings) { + super(); + EventEmitter.call(this); + this._id = _id; + this.server = server; + this.crown = null; + this.crowndropped = false; + this.settings = this.verifySet(this._id,{set:settings}); + this.chatmsgs = []; + this.ppl = new Map(); + this.connections = []; + this.bindEventListeners(); + this.server.rooms.set(_id, this); + this.bans = new Map(); + } + join(cl) { //this stuff is complicated + let otheruser = this.connections.find((a) => a.user._id == cl.user._id) + if (!otheruser) { + let participantId = createKeccakHash('keccak256').update((Math.random().toString() + cl.ip)).digest('hex').substr(0, 24); + cl.user.id = participantId; + cl.participantId = participantId; + if (((this.connections.length == 0 && Array.from(this.ppl.values()).length == 0) && !this.isLobby(this._id)) || this.crown && (this.crown.userId == cl.user._id)) { //user that created the room, give them the crown. + this.crown = { + participantId: cl.participantId, + userId: cl.user._id, + time: Date.now(), + startPos: { + x: 50, + y: 50 + }, + endPos: { + x: this.getCrownX(), + y: this.getCrownY() + } + } + this.crowndropped = false; + } + this.ppl.set(participantId, cl); + this.connections.push(cl); + this.sendArray([{ + color: this.ppl.get(cl.participantId).user.color, + id: this.ppl.get(cl.participantId).participantId, + m: "p", + name: this.ppl.get(cl.participantId).user.name, + x: this.ppl.get(cl.participantId).x || 200, + y: this.ppl.get(cl.participantId).y || 100, + _id: cl.user._id + }], cl, false) + cl.sendArray([{ + m: "c", + c: this.chatmsgs.slice(-1 * 32) + }]) + this.updateCh(cl); + } else { + cl.user.id = otheruser.participantId; + cl.participantId = otheruser.participantId; + this.connections.push(cl); + cl.sendArray([{ + m: "c", + c: this.chatmsgs.slice(-1 * 32) + }]) + this.updateCh(cl); + } + + } + remove(p) { //this is complicated too + let otheruser = this.connections.filter((a) => a.user._id == p.user._id); + if (!(otheruser.length > 1)) { + this.ppl.delete(p.participantId); + this.connections.splice(this.connections.findIndex((a) => a.connectionid == p.connectionid), 1); + console.log(`Deleted client ${p.user.id}`); + this.sendArray([{ + m: "bye", + p: p.participantId + }], p, false); + if (this.crown) + if (this.crown.userId == p.user._id && !this.crowndropped) { + this.chown(); + } + this.updateCh(); + } else { + this.connections.splice(this.connections.findIndex((a) => a.connectionid == p.connectionid), 1); + } + + } + updateCh(cl) { //update channel for all people in channel + if (Array.from(this.ppl.values()).length <= 0) this.destroy(); + this.connections.forEach((usr) => { + this.server.connections.get(usr.connectionid).sendArray([this.fetchData(usr, cl)]) + }) + this.server.updateRoom(this.fetchData()); + } + updateParticipant(pid, options) { + let p = this.ppl.get(pid); + if (!p) return; + options.name ? this.ppl.get(pid).user.name = options.name : {}; + options._id ? this.ppl.get(pid).user._id = options._id : {}; + options.color ? this.ppl.get(pid).user.color = options.color : {}; + options.noteColor ? this.ppl.get(pid).user.noteColor = options.noteColor : {}; + this.connections.filter((ofo) => ofo.participantId == p.participantId).forEach((usr) => { + options.name ? usr.user.name = options.name : {}; + options._id ? usr.user._id = options._id : {}; + options.color ? usr.user.color = options.color : {}; + options.noteColor ? usr.user.noteColor = options.noteColor : {}; + }) + this.sendArray([{ + color: p.user.color, + noteColor: p.user.noteColor, + //noteColor: "#000", + id: p.participantId, + m: "p", + name: p.user.name, + x: p.x || 200, + y: p.y || 100, + _id: p.user._id + }]) + } + destroy() { //destroy room + this._id; + console.log(`Deleted room ${this._id}`); + this.settings = {}; + this.ppl; + this.connnections; + this.chatmsgs; + this.server.rooms.delete(this._id); + } + sendArray(arr, not, onlythisparticipant) { + this.connections.forEach((usr) => { + if (!not || (usr.participantId != not.participantId && !onlythisparticipant) || (usr.connectionid != not.connectionid && onlythisparticipant)) { + try { + this.server.connections.get(usr.connectionid).sendArray(arr) + } catch (e) { + console.log(e); + } + } + }) + } + fetchData(usr, cl) { + let chppl = []; + [...this.ppl.values()].forEach((a) => { + chppl.push(a.user); + }) + let data = { + m: "ch", + p: "ofo", + ch: { + count: chppl.length, + crown: this.crown, + settings: this.settings, + _id: this._id + }, + ppl: chppl + } + if (cl) { + if (usr.connectionid == cl.connectionid) { + data.p = cl.participantId; + } else { + delete data.p; + } + } else { + delete data.p; + } + if (data.ch.crown == null) { + delete data.ch.crown; + } else { + + } + return data; + } + verifyColor(strColor){ + var test2 = /^#[0-9A-F]{6}$/i.test(strColor); + if(test2 == true){ + return strColor; + } else{ + return false; + } + } + isLobby(_id) { + if (_id.startsWith("lobby")) { + let lobbynum = _id.split("lobby")[1]; + if (_id == "lobby") { + return true; + } + if (!(parseInt(lobbynum).toString() == lobbynum)) return false; + for (let i in lobbynum) { + if (parseInt(lobbynum[i]) >= 0) { + if (parseInt(i) + 1 == lobbynum.length) return true; + + } else { + return false; + } + } + } else if (_id.startsWith("test/")) { + if (_id == "test/") { + return false; + } else { + return true; + } + } else { + return false; + } + + } + getCrownY() { + return 50 - 30; + } + getCrownX() { + return 50; + } + chown(id) { + let prsn = this.ppl.get(id); + if (prsn) { + this.crown = { + participantId: prsn.participantId, + userId: prsn.user._id, + time: Date.now(), + startPos: { + x: 50, + y: 50 + }, + endPos: { + x: this.getCrownX(), + y: this.getCrownY() + }, + } + this.crowndropped = false; + } else { + this.crown = { + userId: this.crown.userId, + time: Date.now(), + startPos: { + x: 50, + y: 50 + }, + endPos: { + x: this.getCrownX(), + y: this.getCrownY() + } + } + this.crowndropped = true; + } + this.updateCh(); + } + setCords(p, x, y) { + if (p.participantId && this.ppl.get(p.participantId)) { + x ? this.ppl.get(p.participantId).x = x : {}; + y ? this.ppl.get(p.participantId).y = y : {}; + this.sendArray([{ + m: "m", + id: p.participantId, + x: this.ppl.get(p.participantId).x, + y: this.ppl.get(p.participantId).y + }], p, false); + } + } + chat(p, msg) { + if (msg.message.length > 512) return; + let filter = ["AMIGHTYWIND"]; + let regexp = new RegExp("\\b(" + filter.join("|") + ")\\b", "i"); + if (regexp.test(msg.message)) return; + let prsn = this.ppl.get(p.participantId); + if (prsn) { + let message = {}; + message.m = "a"; + message.a = msg.message; + message.p = { + color: p.user.color, + id: p.participantId, + name: p.user.name, + _id: p.user._id + }; + message.t = Date.now(); + this.sendArray([message]); + this.chatmsgs.push(message); + } + } + playNote(cl, note) { + this.sendArray([{ + m: "n", + n: note.n, + p: cl.participantId, + t: note.t + }], cl, true); + } + sendNotequota(allowance = 200, max = 600, maxHistLen = 3){ + this.sendArray([{ + m: 'nq', + allowance: allowance, + max: max, + maxHistLen: maxHistLen + }]) + } + kickban(_id, ms) { + ms = parseInt(ms); + if (ms >= (1000 * 60 * 60 - 500)) return; + if (ms < 0) return; + ms = Math.round(ms / 1000) * 1000; + let user = this.connections.find((usr) => usr.user._id == _id); + if (!user) return; + let asd = true; + let tonc = true; + let pthatbanned = this.ppl.get(this.crown.participantId); + this.connections.filter((usr) => usr.participantId == user.participantId).forEach((u) => { + user.bantime = Math.floor(Math.floor(ms / 1000) / 60); + user.bannedtime = Date.now(); + user.msbanned = ms; + this.bans.set(user.user._id, user); + if (this.crown && (this.crown.userId)) { + u.setChannel("test/awkward", {}); + if (asd) + this.Notification(user.user._id, + "Notice", + `Banned from \"${this._id}\" for ${Math.floor(Math.floor(ms / 1000) / 60)} minutes.`, + "", + 7000, + "#room", + "short" + ) + if (asd) + this.Notification("room", + "Notice", + `${pthatbanned.user.name} banned ${user.user.name} from the channel for ${Math.floor(Math.floor(ms / 1000) / 60)} minutes.`, + "", + 7000, + "#room", + "short" + ) + if (this.crown && (this.crown.userId == _id) && tonc) { + this.Notification("room", + "Certificate of Award", + `Let it be known that ${user.user.name} kickbanned him/her self.`, + "", + 7000, + "#room" + ); + tonc = false; + } + + } + + }) + } + Notification(who, title, text, html, duration, target, klass, id) { + let obj = { + m: "notification", + title: title, + text: text, + html: html, + target: target, + duration: duration, + class: klass, + id: id + }; + if (!id) delete obj.id; + if (!title) delete obj.title; + if (!text) delete obj.text; + if (!html) delete obj.html; + if (!target) delete obj.target; + if (!duration) delete obj.duration; + if (!klass) delete obj.class; + switch (who) { + case "all": { + for (let con of Array.from(this.server.connections.values())) { + con.sendArray([obj]); + } + break; + } + case "room": { + for (let con of this.connections) { + con.sendArray([obj]); + } + break; + } + default: { + Array.from(this.server.connections.values()).filter((usr) => usr.user._id == who).forEach((p) => { + p.sendArray([obj]); + }); + } + } + } + bindEventListeners() { + this.on("bye", participant => { + this.remove(participant); + }) + + this.on("m", (participant, x, y) => { + this.setCords(participant, x, y); + }) + + this.on("a", (participant, msg) => { + this.chat(participant, msg); + }) + } + verifySet(_id,msg){ + if(!isObj(msg.set)) msg.set = {visible:true,color:this.server.defaultRoomColor,chat:true,crownsolo:false}; + if(isBool(msg.set.lobby)){ + if(!this.isLobby(_id)) delete msg.set.lobby; // keep it nice and clean + }else{ + if(this.isLobby(_id)) msg.set = {visible:true,color:this.server.defaultLobbyColor,color2:this.server.defaultLobbyColor2,chat:true,crownsolo:false,lobby:true}; + } + if(!isBool(msg.set.visible)){ + if(msg.set.visible == undefined) msg.set.visible = (!isObj(this.settings) ? true : this.settings.visible); + else msg.set.visible = true; + }; + if(!isBool(msg.set.chat)){ + if(msg.set.chat == undefined) msg.set.chat = (!isObj(this.settings) ? true : this.settings.chat); + else msg.set.chat = true; + }; + if(!isBool(msg.set.crownsolo)){ + if(msg.set.crownsolo == undefined) msg.set.crownsolo = (!isObj(this.settings) ? false : this.settings.crownsolo); + else msg.set.crownsolo = false; + }; + if(!isString(msg.set.color) || !/^#[0-9a-f]{6}$/i.test(msg.set.color)) msg.set.color = (!isObj(this.settings) ? this.server.defaultRoomColor : this.settings.color); + if(isString(msg.set.color2)){ + if(!/^#[0-9a-f]{6}$/i.test(msg.set.color2)){ + if(this.settings){ + if(this.settings.color2) msg.set.color2 = this.settings.color2; + else delete msg.set.color2; // keep it nice and clean + } + } + }; + return msg.set; + } + +} +module.exports = Room; diff --git a/src/Server.js b/src/Server.js new file mode 100644 index 0000000..fae58ce --- /dev/null +++ b/src/Server.js @@ -0,0 +1,45 @@ +const Client = require("./Client.js"); +const banned = require('../banned.json'); + +class Server extends EventEmitter { + constructor(config) { + super(); + EventEmitter.call(this); + this.wss = new WebSocket.Server({ + port: config.port, + backlog: 100, + verifyClient: (info) => { + //if (banned.includes(info.req.headers['x-forwarded-for'].split(",")[0].replace('::ffff:', ''))) return false; + if (banned.includes((info.req.connection.remoteAddress).replace("::ffff:", ""))) return false; + return true; + } + }); + this.connectionid = 0; + this.connections = new Map(); + this.roomlisteners = new Map(); + this.rooms = new Map(); + this.wss.on('connection', (ws, req) => { + this.connections.set(++this.connectionid, new Client(ws, req, this)); + }); + this.legit_m = ["a", "bye", "hi", "ch", "+ls", "-ls", "m", "n", "devices", "t", "chset", "userset", "chown", "kickban", "admin message", "color"] + this.welcome_motd = config.motd || "You agree to read this message."; + this._id_Private_Key = config._id_PrivateKey || "boppity"; + this.defaultUsername = config.defaultUsername || "Anonymous"; + this.defaultRoomColor = config.defaultRoomColor || "#3b5054"; + this.defaultLobbyColor = config.defaultLobbyColor || "#19b4b9"; + this.defaultLobbyColor2 = config.defaultLobbyColor2 || "#801014"; + this.adminpass = config.adminpass || "Bop It"; + }; + updateRoom(data) { + if (!data.ch.settings.visible) return; + for (let cl of Array.from(this.roomlisteners.values())) { + cl.sendArray([{ + "m": "ls", + "c": false, + "u": [data.ch] + }]) + } + } +} + +module.exports = Server; \ No newline at end of file diff --git a/src/TODO.txt b/src/TODO.txt new file mode 100644 index 0000000..f9af52b --- /dev/null +++ b/src/TODO.txt @@ -0,0 +1,2 @@ + +Room.js make color verifier diff --git a/src/User.js b/src/User.js new file mode 100644 index 0000000..7c4a960 --- /dev/null +++ b/src/User.js @@ -0,0 +1,56 @@ +const ColorEncoder = require("./ColorEncoder.js"); +const { promisify } = require('util'); +let userdb; +class User { + constructor(cl) { + this.cl = cl; + this.server = this.cl.server; + this.userdb = userdb; + this.default_db = {}; + } + async getUserData() { + if (!userdb || (userdb instanceof Map && [...userdb.entries()] == [])) { + await this.setUpDb(); + } + let _id = createKeccakHash('keccak256').update((this.cl.server._id_Private_Key + this.cl.ip)).digest('hex').substr(0, 24); + //console.log("CONNECTED IP: " + this.cl.ip); + let usertofind = userdb.get(_id); + if (!usertofind) { + if (typeof usertofind == 'object' && (usertofind.hasOwnProperty('name') && usertofind.name != this.server.defaultUsername)) return; + userdb.set(_id, { + "color": `#${ColorEncoder.intToRGB(ColorEncoder.hashCode(_id)).toLowerCase()}`, + "noteColor": `#${ColorEncoder.intToRGB(ColorEncoder.hashCode(_id)).toLowerCase()}`, + "name": this.server.defaultUsername, + "_id": _id, + "ip": this.cl.ip + }); + this.updatedb(); + } + let user = userdb.get(_id); + return { + "color": user.color, + "noteColor": user.noteColor, + "name": user.name, + "_id": user._id, + } + } + async updatedb() { + const writeFile = promisify(fs.writeFile); + await writeFile('src/db/users.json', JSON.stringify(User.strMapToObj(userdb), null, 2)); + } + async setUpDb() { + const writeFile = promisify(fs.writeFile); + const readdir = promisify(fs.readdir); + let files = await readdir("src/db/"); + if (!files.includes("users.json")) { + await writeFile('src/db/users.json', JSON.stringify(this.default_db, null, 2)) + userdb = new Map(Object.entries(require("./db/users.json"))); + } else { + userdb = new Map(Object.entries(require("./db/users.json"))); + } + } + static strMapToObj(strMap) { + return [...strMap.entries()].reduce((obj, [key, value]) => (obj[key] = value, obj), {}); + } +} +module.exports = User; \ No newline at end of file diff --git a/src/db/users.json b/src/db/users.json new file mode 100644 index 0000000..50dd7fe --- /dev/null +++ b/src/db/users.json @@ -0,0 +1,114 @@ +{ + "9c9f38bad2839d9e33f29361": { + "color": "#4cff5c", + "noteColor": "#4cff5c", + "name": "Anonymous", + "_id": "9c9f38bad2839d9e33f29361", + "ip": "68.72.101.149" + }, + "77e4cce49134dcc22f9db512": { + "color": "#e4a438", + "noteColor": "#e4a438", + "name": "Anonymous", + "_id": "77e4cce49134dcc22f9db512", + "ip": "94.15.73.43" + }, + "b8d6f3f34a1f412751a3cb13": { + "color": "#de3a55", + "noteColor": "#de3a55", + "name": "Wolfy", + "_id": "b8d6f3f34a1f412751a3cb13", + "ip": "67.141.166.70" + }, + "a2e7d9f15b88609743493790": { + "color": "#0b4667", + "noteColor": "#0b4667", + "name": "☯️ エラ ー 4̴͓̍ ̴̝̿0̵̨̒ ̵̤͊4̴̒", + "_id": "a2e7d9f15b88609743493790", + "ip": "98.182.142.78" + }, + "ca111f51c16dd98dabd3773c": { + "color": "#56da2c", + "noteColor": "#56da2c", + "name": "Rudra", + "_id": "ca111f51c16dd98dabd3773c", + "ip": "75.104.54.115" + }, + "74d18d3afb8646ae5dbe45ef": { + "color": "#2a90b8", + "noteColor": "#2a90b8", + "name": "ALLAH sad :(", + "_id": "74d18d3afb8646ae5dbe45ef", + "ip": "198.16.76.28" + }, + "0f726efbbcac60b92bf8d708": { + "color": "#b54d8d", + "noteColor": "#b54d8d", + "name": "Anonymous", + "_id": "0f726efbbcac60b92bf8d708", + "ip": "191.35.208.102" + }, + "78dbd1290e535af94d3a5357": { + "color": "#20a563", + "noteColor": "#20a563", + "name": "Rudra", + "_id": "78dbd1290e535af94d3a5357", + "ip": "198.16.74.45" + }, + "d86fa3780fbae7ab5f4b01a2": { + "color": "#836e90", + "noteColor": "#836e90", + "name": "๖ۣۜ 𝑜𝓌𝓁𝓌𝒶𝓉𝒸𝒽🦉👀", + "_id": "d86fa3780fbae7ab5f4b01a2", + "ip": "198.16.66.125" + }, + "990d86b045a8a08345b75699": { + "color": "#a7b719", + "noteColor": "#a7b719", + "name": "Qhy 「 qhy!help 」", + "_id": "990d86b045a8a08345b75699", + "ip": "54.80.91.103" + }, + "73f36b73136cc3950c4ba6ff": { + "color": "#f09d22", + "noteColor": "#f09d22", + "name": "Anonymous", + "_id": "73f36b73136cc3950c4ba6ff", + "ip": "198.16.66.195" + }, + "eec94ceb5ff11a4b1b176280": { + "color": "#1f00e7", + "noteColor": "#1f00e7", + "name": "Qhy ", + "_id": "eec94ceb5ff11a4b1b176280", + "ip": "52.87.215.231" + }, + "98bc89e0ae747d9e1375a16e": { + "color": "#26d0c5", + "noteColor": "#26d0c5", + "name": "Qhy ", + "_id": "98bc89e0ae747d9e1375a16e", + "ip": "54.144.133.13" + }, + "8755e2600aa043273aac482a": { + "color": "#0c4c4d", + "noteColor": "#0c4c4d", + "name": "Qhy ", + "_id": "8755e2600aa043273aac482a", + "ip": "34.233.126.13" + }, + "a6a35eb1546b541be5f11cc8": { + "color": "#d3de03", + "noteColor": "#d3de03", + "name": "Anonymous", + "_id": "a6a35eb1546b541be5f11cc8", + "ip": "177.18.157.8" + }, + "651d3e63d8a738ac1a40ed9f": { + "color": "#ca14aa", + "noteColor": "#ca14aa", + "name": "Anonymous", + "_id": "651d3e63d8a738ac1a40ed9f", + "ip": "77.111.247.71" + } +} \ No newline at end of file From bd7f84f5778134d776f33335e29cc5ae8fa5788b Mon Sep 17 00:00:00 2001 From: Wolfy Date: Tue, 7 Apr 2020 03:56:16 -0400 Subject: [PATCH 19/32] oops --- banned.json | 4 ++-- config.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/banned.json b/banned.json index 1610ea1..75d98b2 100644 --- a/banned.json +++ b/banned.json @@ -1,3 +1,3 @@ [ - -] \ No newline at end of file + "1.2.3.4" +] diff --git a/config.js b/config.js index e27916c..84ce5f7 100644 --- a/config.js +++ b/config.js @@ -6,5 +6,5 @@ module.exports = Object.seal({ "defaultRoomColor": "#3b5054", "defaultLobbyColor": "#19b4b9", "defaultLobbyColor2": "#801014", - "adminpass": "27PP6YLTxg0b1P2B8eGSOki1" -}) \ No newline at end of file + "adminpass": "adminpass" +}) From 4f5301e451e927e08b737a8e3fb90ca214ff58cc Mon Sep 17 00:00:00 2001 From: wolfy01 <45273698+wolfy01@users.noreply.github.com> Date: Tue, 7 Apr 2020 03:59:50 -0400 Subject: [PATCH 20/32] Delete TODO.txt --- src/TODO.txt | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 src/TODO.txt diff --git a/src/TODO.txt b/src/TODO.txt deleted file mode 100644 index f9af52b..0000000 --- a/src/TODO.txt +++ /dev/null @@ -1,2 +0,0 @@ - -Room.js make color verifier From ac1fd174c067033169beb2392ed8561bce30fab0 Mon Sep 17 00:00:00 2001 From: wolfy01 <45273698+wolfy01@users.noreply.github.com> Date: Tue, 7 Apr 2020 04:01:05 -0400 Subject: [PATCH 21/32] Create TODO.txt --- TODO.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 TODO.txt diff --git a/TODO.txt b/TODO.txt new file mode 100644 index 0000000..da4291c --- /dev/null +++ b/TODO.txt @@ -0,0 +1,3 @@ +1. Send noteQuota on room owner change. +2. Add noteQuota server side. +3. Room.js make color verifier From 4ec75f29b97d610e0bc086cbc4e887336d5469d0 Mon Sep 17 00:00:00 2001 From: wolfy01 <45273698+wolfy01@users.noreply.github.com> Date: Tue, 7 Apr 2020 04:01:23 -0400 Subject: [PATCH 22/32] Rename TODO.txt to TODO.md --- TODO.txt => TODO.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename TODO.txt => TODO.md (100%) diff --git a/TODO.txt b/TODO.md similarity index 100% rename from TODO.txt rename to TODO.md From 22fbf9c8517211fd3116697a6ad8317089329059 Mon Sep 17 00:00:00 2001 From: wolfy01 <45273698+wolfy01@users.noreply.github.com> Date: Tue, 7 Apr 2020 04:03:45 -0400 Subject: [PATCH 23/32] Change path to config Oops... --- src/Message.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Message.js b/src/Message.js index c62d304..c87041e 100644 --- a/src/Message.js +++ b/src/Message.js @@ -1,4 +1,4 @@ -const config = require('./db/config'); +const config = require('../config'); const quotas = config.quotas; const User = require("./User.js"); module.exports = (cl) => { @@ -251,4 +251,4 @@ module.exports = (cl) => { cl.channel.Notification(msg.content); console.log(msg.content); }) -} \ No newline at end of file +} From f38b995be0b6a23161243a439a378df0b84e4134 Mon Sep 17 00:00:00 2001 From: wolfy01 <45273698+wolfy01@users.noreply.github.com> Date: Tue, 7 Apr 2020 04:05:13 -0400 Subject: [PATCH 24/32] Welp... forgot we didn't need that anyways --- src/Message.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Message.js b/src/Message.js index c87041e..b393f2e 100644 --- a/src/Message.js +++ b/src/Message.js @@ -1,5 +1,4 @@ -const config = require('../config'); -const quotas = config.quotas; +const quotas = require('../Quotas'); const User = require("./User.js"); module.exports = (cl) => { cl.once("hi", () => { From fec8d63c04f3909827d4386edef3bb6bc62532ed Mon Sep 17 00:00:00 2001 From: wolfy01 <45273698+wolfy01@users.noreply.github.com> Date: Tue, 7 Apr 2020 04:21:45 -0400 Subject: [PATCH 25/32] Don't send noteQuota to all clients! --- src/Room.js | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/Room.js b/src/Room.js index 4998b9f..5606217 100644 --- a/src/Room.js +++ b/src/Room.js @@ -288,14 +288,6 @@ class Room extends EventEmitter { t: note.t }], cl, true); } - sendNotequota(allowance = 200, max = 600, maxHistLen = 3){ - this.sendArray([{ - m: 'nq', - allowance: allowance, - max: max, - maxHistLen: maxHistLen - }]) - } kickban(_id, ms) { ms = parseInt(ms); if (ms >= (1000 * 60 * 60 - 500)) return; From 5f2103ea3fb4214897a6277b9863a03a38a0826d Mon Sep 17 00:00:00 2001 From: wolfy01 <45273698+wolfy01@users.noreply.github.com> Date: Tue, 7 Apr 2020 04:22:48 -0400 Subject: [PATCH 26/32] Right way to send noteQuota to client --- src/Message.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Message.js b/src/Message.js index b393f2e..7cf8870 100644 --- a/src/Message.js +++ b/src/Message.js @@ -29,12 +29,12 @@ module.exports = (cl) => { if (msg._id.length > 512) return; cl.setChannel(msg._id, msg.set); if (cl.channel.isLobby(cl.channel._id)) { - cl.channel.sendNotequota(quotas.note.lobby.allowance, quotas.note.lobby.max, quotas.note.lobby.maxHistLen); + cl.sendArray([{m: 'nq', allowance: quotas.note.lobby.allowance, max: quotas.note.lobby.max, maxHistLen: quotas.note.lobby.maxHistLen}]) } else { if (!(cl.user._id == cl.channel.crown.userId)) { - cl.channel.sendNotequota(quotas.note.normal.allowance, quotas.note.normal.max, quotas.note.normal.maxHistLen); + cl.sendArray([{m: 'nq', allowance: quotas.note.normal.allowance, max: quotas.note.normal.max, maxHistLen: quotas.note.normal.maxHistLen}]) } else { - cl.channel.sendNotequota(quotas.note.insane.allowance, quotas.note.insane.max, quotas.note.insane.maxHistLen); + cl.sendArray([{m: 'nq', allowance: quotas.note.insane.allowance, max: quotas.note.insane.max, maxHistLen: quotas.note.insane.maxHistLen}]) } } } From 7f136874851533e9d81b49d2fbbd9273e1d8ea6d Mon Sep 17 00:00:00 2001 From: Wolfy Date: Tue, 7 Apr 2020 13:03:36 -0400 Subject: [PATCH 27/32] Quotas Make quotas ip based. Clients now can not bypass quota by having more than 1 client --- src/Client.js | 16 ---------------- src/Message.js | 28 +++++++++++++++------------- src/User.js | 22 ++++++++++++++++++++++ src/db/users.json | 21 +++++++++++++++++++++ 4 files changed, 58 insertions(+), 29 deletions(-) diff --git a/src/Client.js b/src/Client.js index d3c4f32..c762e68 100644 --- a/src/Client.js +++ b/src/Client.js @@ -1,6 +1,3 @@ -const quotas = require('../Quotas'); -const RateLimit = require('./RateLimit.js').RateLimit; -const RateLimitChain = require('./RateLimit.js').RateLimitChain; const Room = require("./Room.js"); require('node-json-color-stringify'); class Client extends EventEmitter { @@ -17,19 +14,6 @@ class Client extends EventEmitter { this.ip = (req.connection.remoteAddress).replace("::ffff:", ""); this.destroied = false; this.bindEventListeners(); - this.quotas = { - //note: new limiter(2000, { allowance:3000, max:24000, maxHistLen:3}), - chat: { - lobby: new RateLimitChain(quotas.chat.lobby.amount, quotas.chat.lobby.time), - normal: new RateLimitChain(quotas.chat.normal.amount, quotas.chat.normal.time), - insane: new RateLimitChain(quotas.chat.insane.amount, quotas.chat.insane.time) - }, - name: new RateLimitChain(quotas.name.amount, quotas.name.time), - room: new RateLimit(quotas.room.time), - chown: new RateLimitChain(quotas.chown.amount, quotas.chown.time), - cursor: new RateLimit(quotas.cursor.time), - kickban: new RateLimitChain(quotas.kickban.amount, quotas.kickban.time), - } require('./Message.js')(this); } isConnected() { diff --git a/src/Message.js b/src/Message.js index 7cf8870..1d8d319 100644 --- a/src/Message.js +++ b/src/Message.js @@ -1,4 +1,5 @@ -const quotas = require('../Quotas'); +const NoteQuotas = require('../Quotas'); +let quotas; const User = require("./User.js"); module.exports = (cl) => { cl.once("hi", () => { @@ -12,6 +13,7 @@ module.exports = (cl) => { msg.v = "Beta"; cl.sendArray([msg]) cl.user = data; + quotas = cl.server.connections[cl.user._id].quotas; }) }) cl.on("t", msg => { @@ -23,24 +25,24 @@ module.exports = (cl) => { }]) }) cl.on("ch", msg => { - if (!cl.quotas.room.attempt()) return; + if (!quotas.room.attempt()) return; if (!msg.hasOwnProperty("set") || !msg.set) msg.set = {}; if (msg.hasOwnProperty("_id") && typeof msg._id == "string") { if (msg._id.length > 512) return; cl.setChannel(msg._id, msg.set); if (cl.channel.isLobby(cl.channel._id)) { - cl.sendArray([{m: 'nq', allowance: quotas.note.lobby.allowance, max: quotas.note.lobby.max, maxHistLen: quotas.note.lobby.maxHistLen}]) + cl.sendArray([{m: 'nq', allowance: NoteQuotas.note.lobby.allowance, max: NoteQuotas.note.lobby.max, maxHistLen: NoteQuotas.note.lobby.maxHistLen}]) } else { if (!(cl.user._id == cl.channel.crown.userId)) { - cl.sendArray([{m: 'nq', allowance: quotas.note.normal.allowance, max: quotas.note.normal.max, maxHistLen: quotas.note.normal.maxHistLen}]) + cl.sendArray([{m: 'nq', allowance: NoteQuotas.note.normal.allowance, max: NoteQuotas.note.normal.max, maxHistLen: NoteQuotas.note.normal.maxHistLen}]) } else { - cl.sendArray([{m: 'nq', allowance: quotas.note.insane.allowance, max: quotas.note.insane.max, maxHistLen: quotas.note.insane.maxHistLen}]) + cl.sendArray([{m: 'nq', allowance: NoteQuotas.note.insane.allowance, max: NoteQuotas.note.insane.max, maxHistLen: NoteQuotas.note.insane.maxHistLen}]) } } } }) cl.on("m", msg => { - if (!cl.quotas.cursor.attempt()) return; + if (!quotas.cursor.attempt()) return; if (!(cl.channel && cl.participantId)) return; if (!msg.hasOwnProperty("x")) msg.x = null; if (!msg.hasOwnProperty("y")) msg.y = null; @@ -50,7 +52,7 @@ module.exports = (cl) => { }) cl.on("chown", msg => { - if (!cl.quotas.chown.attempt()) return; + if (!quotas.chown.attempt()) return; if (!(cl.channel && cl.participantId)) return; //console.log((Date.now() - cl.channel.crown.time)) //console.log(!(cl.channel.crown.userId != cl.user._id), !((Date.now() - cl.channel.crown.time) > 15000)); @@ -73,12 +75,12 @@ module.exports = (cl) => { }) cl.on("a", msg => { if (cl.channel.isLobby(cl.channel._id)) { - if (!cl.quotas.chat.lobby.attempt()) return; + if (!quotas.chat.lobby.attempt()) return; } else { if (!(cl.user._id == cl.channel.crown.userId)) { - if (!cl.quotas.chat.normal.attempt()) return; + if (!quotas.chat.normal.attempt()) return; } else { - if (!cl.quotas.chat.insane.attempt()) return; + if (!quotas.chat.insane.attempt()) return; } } if (!(cl.channel && cl.participantId)) return; @@ -121,7 +123,7 @@ module.exports = (cl) => { cl.server.roomlisteners.delete(cl.connectionid); }) cl.on("userset", msg => { - if (!cl.quotas.name.attempt()) return; + if (!quotas.name.attempt()) return; if (!(cl.channel && cl.participantId)) return; if (!msg.hasOwnProperty("set") || !msg.set) msg.set = {}; if (msg.set.hasOwnProperty('name') && typeof msg.set.name == "string") { @@ -143,7 +145,7 @@ module.exports = (cl) => { } }) cl.on('kickban', msg => { - if (!cl.quotas.kickban.attempt()) return; + if (!quotas.kickban.attempt()) return; if (!(cl.channel && cl.participantId)) return; if (!(cl.user._id == cl.channel.crown.userId)) return; if (msg.hasOwnProperty('_id') && typeof msg._id == "string") { @@ -250,4 +252,4 @@ module.exports = (cl) => { cl.channel.Notification(msg.content); console.log(msg.content); }) -} +} \ No newline at end of file diff --git a/src/User.js b/src/User.js index 7c4a960..a1a43fc 100644 --- a/src/User.js +++ b/src/User.js @@ -1,3 +1,6 @@ +const quotas = require('../Quotas'); +const RateLimit = require('./RateLimit.js').RateLimit; +const RateLimitChain = require('./RateLimit.js').RateLimitChain; const ColorEncoder = require("./ColorEncoder.js"); const { promisify } = require('util'); let userdb; @@ -13,6 +16,25 @@ class User { await this.setUpDb(); } let _id = createKeccakHash('keccak256').update((this.cl.server._id_Private_Key + this.cl.ip)).digest('hex').substr(0, 24); + if(this.server.connections[_id]){ // Connection rate quota? + //if(this.connectionsObjects[_id].connections.length < 10) this.connectionsObjects[_id].connections.push({room:undefined,ws:ws,cl:new Connection(ws)}); + }else{ + this.server.connections[_id] = { + quotas:{ + //note: new limiter(2000, { allowance:3000, max:24000, maxHistLen:3}), + chat: { + lobby: new RateLimitChain(quotas.chat.lobby.amount, quotas.chat.lobby.time), + normal: new RateLimitChain(quotas.chat.normal.amount, quotas.chat.normal.time), + insane: new RateLimitChain(quotas.chat.insane.amount, quotas.chat.insane.time) + }, + name: new RateLimitChain(quotas.name.amount, quotas.name.time), + room: new RateLimit(quotas.room.time), + chown: new RateLimitChain(quotas.chown.amount, quotas.chown.time), + cursor: new RateLimit(quotas.cursor.time), + kickban: new RateLimitChain(quotas.kickban.amount, quotas.kickban.time), + } + }; + }; //console.log("CONNECTED IP: " + this.cl.ip); let usertofind = userdb.get(_id); if (!usertofind) { diff --git a/src/db/users.json b/src/db/users.json index 50dd7fe..6944412 100644 --- a/src/db/users.json +++ b/src/db/users.json @@ -110,5 +110,26 @@ "name": "Anonymous", "_id": "651d3e63d8a738ac1a40ed9f", "ip": "77.111.247.71" + }, + "310260bf24ad833846100e82": { + "color": "#5091f3", + "noteColor": "#5091f3", + "name": "Anonymous", + "_id": "310260bf24ad833846100e82", + "ip": "54.172.205.12" + }, + "c6d435dd7fa48be7cea001ba": { + "color": "#e4f154", + "noteColor": "#e4f154", + "name": "Anonymous", + "_id": "c6d435dd7fa48be7cea001ba", + "ip": "75.91.45.152" + }, + "4828437c28f608315e2a3051": { + "color": "#5c1ec9", + "noteColor": "#5c1ec9", + "name": "Samsung", + "_id": "4828437c28f608315e2a3051", + "ip": "23.237.128.50" } } \ No newline at end of file From 745787eadd089d77c22afa7fadc4f47fd93fbf9d Mon Sep 17 00:00:00 2001 From: Wolfy Date: Tue, 7 Apr 2020 13:05:36 -0400 Subject: [PATCH 28/32] Update users.json --- src/db/users.json | 136 +--------------------------------------------- 1 file changed, 1 insertion(+), 135 deletions(-) diff --git a/src/db/users.json b/src/db/users.json index 6944412..0967ef4 100644 --- a/src/db/users.json +++ b/src/db/users.json @@ -1,135 +1 @@ -{ - "9c9f38bad2839d9e33f29361": { - "color": "#4cff5c", - "noteColor": "#4cff5c", - "name": "Anonymous", - "_id": "9c9f38bad2839d9e33f29361", - "ip": "68.72.101.149" - }, - "77e4cce49134dcc22f9db512": { - "color": "#e4a438", - "noteColor": "#e4a438", - "name": "Anonymous", - "_id": "77e4cce49134dcc22f9db512", - "ip": "94.15.73.43" - }, - "b8d6f3f34a1f412751a3cb13": { - "color": "#de3a55", - "noteColor": "#de3a55", - "name": "Wolfy", - "_id": "b8d6f3f34a1f412751a3cb13", - "ip": "67.141.166.70" - }, - "a2e7d9f15b88609743493790": { - "color": "#0b4667", - "noteColor": "#0b4667", - "name": "☯️ エラ ー 4̴͓̍ ̴̝̿0̵̨̒ ̵̤͊4̴̒", - "_id": "a2e7d9f15b88609743493790", - "ip": "98.182.142.78" - }, - "ca111f51c16dd98dabd3773c": { - "color": "#56da2c", - "noteColor": "#56da2c", - "name": "Rudra", - "_id": "ca111f51c16dd98dabd3773c", - "ip": "75.104.54.115" - }, - "74d18d3afb8646ae5dbe45ef": { - "color": "#2a90b8", - "noteColor": "#2a90b8", - "name": "ALLAH sad :(", - "_id": "74d18d3afb8646ae5dbe45ef", - "ip": "198.16.76.28" - }, - "0f726efbbcac60b92bf8d708": { - "color": "#b54d8d", - "noteColor": "#b54d8d", - "name": "Anonymous", - "_id": "0f726efbbcac60b92bf8d708", - "ip": "191.35.208.102" - }, - "78dbd1290e535af94d3a5357": { - "color": "#20a563", - "noteColor": "#20a563", - "name": "Rudra", - "_id": "78dbd1290e535af94d3a5357", - "ip": "198.16.74.45" - }, - "d86fa3780fbae7ab5f4b01a2": { - "color": "#836e90", - "noteColor": "#836e90", - "name": "๖ۣۜ 𝑜𝓌𝓁𝓌𝒶𝓉𝒸𝒽🦉👀", - "_id": "d86fa3780fbae7ab5f4b01a2", - "ip": "198.16.66.125" - }, - "990d86b045a8a08345b75699": { - "color": "#a7b719", - "noteColor": "#a7b719", - "name": "Qhy 「 qhy!help 」", - "_id": "990d86b045a8a08345b75699", - "ip": "54.80.91.103" - }, - "73f36b73136cc3950c4ba6ff": { - "color": "#f09d22", - "noteColor": "#f09d22", - "name": "Anonymous", - "_id": "73f36b73136cc3950c4ba6ff", - "ip": "198.16.66.195" - }, - "eec94ceb5ff11a4b1b176280": { - "color": "#1f00e7", - "noteColor": "#1f00e7", - "name": "Qhy ", - "_id": "eec94ceb5ff11a4b1b176280", - "ip": "52.87.215.231" - }, - "98bc89e0ae747d9e1375a16e": { - "color": "#26d0c5", - "noteColor": "#26d0c5", - "name": "Qhy ", - "_id": "98bc89e0ae747d9e1375a16e", - "ip": "54.144.133.13" - }, - "8755e2600aa043273aac482a": { - "color": "#0c4c4d", - "noteColor": "#0c4c4d", - "name": "Qhy ", - "_id": "8755e2600aa043273aac482a", - "ip": "34.233.126.13" - }, - "a6a35eb1546b541be5f11cc8": { - "color": "#d3de03", - "noteColor": "#d3de03", - "name": "Anonymous", - "_id": "a6a35eb1546b541be5f11cc8", - "ip": "177.18.157.8" - }, - "651d3e63d8a738ac1a40ed9f": { - "color": "#ca14aa", - "noteColor": "#ca14aa", - "name": "Anonymous", - "_id": "651d3e63d8a738ac1a40ed9f", - "ip": "77.111.247.71" - }, - "310260bf24ad833846100e82": { - "color": "#5091f3", - "noteColor": "#5091f3", - "name": "Anonymous", - "_id": "310260bf24ad833846100e82", - "ip": "54.172.205.12" - }, - "c6d435dd7fa48be7cea001ba": { - "color": "#e4f154", - "noteColor": "#e4f154", - "name": "Anonymous", - "_id": "c6d435dd7fa48be7cea001ba", - "ip": "75.91.45.152" - }, - "4828437c28f608315e2a3051": { - "color": "#5c1ec9", - "noteColor": "#5c1ec9", - "name": "Samsung", - "_id": "4828437c28f608315e2a3051", - "ip": "23.237.128.50" - } -} \ No newline at end of file +{} From ea8957bcd5c7bb2ced8b82453b4690164e85f816 Mon Sep 17 00:00:00 2001 From: Wolfy Date: Tue, 7 Apr 2020 14:38:57 -0400 Subject: [PATCH 29/32] Fix things fix some forgotten thigs, like adding the correct messages (legit_m) to the server... and cleaning up Quotas.js and Config.js --- Quotas.js | 72 +++++++++++++++++++++++------------------------ banned.json | 4 +-- config.js | 16 +++++------ src/Message.js | 4 +-- src/Server.js | 26 +++++++++++++++-- src/db/users.json | 38 ++++++++++++++++++++++++- 6 files changed, 109 insertions(+), 51 deletions(-) diff --git a/Quotas.js b/Quotas.js index 8953448..f706b51 100644 --- a/Quotas.js +++ b/Quotas.js @@ -1,51 +1,51 @@ module.exports = Object.seal({ - "note": { - "lobby": { - "allowance": 200, - "max": 600, - "maxHistLen": 3 + note: { + lobby: { + allowance: 200, + max: 600, + maxHistLen: 3 }, - "normal": { - "allowance": 400, - "max": 1200, - "maxHistLen": 3 + normal: { + allowance: 400, + max: 1200, + maxHistLen: 3 }, - "insane": { - "allowance": 600, - "max": 1800, - "maxHistLen": 3 + insane: { + allowance: 600, + max: 1800, + maxHistLen: 3 } }, - "chat": { - "lobby": { - "amount": 4, - "time": 4000 + chat: { + lobby: { + amount: 4, + time: 4000 }, - "normal": { - "amount": 4, - "time": 4000 + normal: { + amount: 4, + time: 4000 }, - "insane": { - "amount": 10, - "time": 4000 + insane: { + amount: 10, + time: 4000 } }, - "chown": { - "amount": 10, - "time": 5000 + chown: { + amount: 10, + time: 5000 }, - "name": { - "amount": 30, - "time": 30 * 60000 + name: { + amount: 30, + time: 30 * 60000 }, - "room": { - "time": 500 + room: { + time: 500 }, - "cursor": { - "time": 16 + cursor: { + time: 16 }, - "kickban": { - "amount": 2, - "time": 1000 + kickban: { + amount: 2, + time: 1000 } }) \ No newline at end of file diff --git a/banned.json b/banned.json index 75d98b2..1610ea1 100644 --- a/banned.json +++ b/banned.json @@ -1,3 +1,3 @@ [ - "1.2.3.4" -] + +] \ No newline at end of file diff --git a/config.js b/config.js index 84ce5f7..0497b8a 100644 --- a/config.js +++ b/config.js @@ -1,10 +1,10 @@ module.exports = Object.seal({ - "port": "8080", - "motd": "You agree to read this message.", - "_id_PrivateKey": "boppity", - "defaultUsername": "Anonymous", - "defaultRoomColor": "#3b5054", - "defaultLobbyColor": "#19b4b9", - "defaultLobbyColor2": "#801014", - "adminpass": "adminpass" + port: "8080", + motd: "You agree to read this message.", + _id_PrivateKey: "boppity", + defaultUsername: "Anonymous", + defaultRoomColor: "#3b5054", + defaultLobbyColor: "#19b4b9", + defaultLobbyColor2: "#801014", + adminpass: "adminpass" }) diff --git a/src/Message.js b/src/Message.js index 1d8d319..5a26e5b 100644 --- a/src/Message.js +++ b/src/Message.js @@ -157,7 +157,7 @@ module.exports = (cl) => { cl.on("bye", msg => { cl.destroy(); }) - cl.on("admin message", msg => { + cl.on("admin message" || "adminmsg" || "admin msg", msg => { if (!(cl.channel && cl.participantId)) return; if (!msg.hasOwnProperty('password') || !msg.hasOwnProperty('msg')) return; if (typeof msg.msg != 'object') return; @@ -189,7 +189,7 @@ module.exports = (cl) => { if (!dbentry) return; dbentry.color = msg.color; dbentry.noteColor = msg.color; - //user.updatedb(); + user.updatedb(); cl.server.rooms.forEach((room) => { room.updateParticipant(usr.participantId, { color: msg.color, diff --git a/src/Server.js b/src/Server.js index fae58ce..362eca9 100644 --- a/src/Server.js +++ b/src/Server.js @@ -9,7 +9,6 @@ class Server extends EventEmitter { port: config.port, backlog: 100, verifyClient: (info) => { - //if (banned.includes(info.req.headers['x-forwarded-for'].split(",")[0].replace('::ffff:', ''))) return false; if (banned.includes((info.req.connection.remoteAddress).replace("::ffff:", ""))) return false; return true; } @@ -21,7 +20,30 @@ class Server extends EventEmitter { this.wss.on('connection', (ws, req) => { this.connections.set(++this.connectionid, new Client(ws, req, this)); }); - this.legit_m = ["a", "bye", "hi", "ch", "+ls", "-ls", "m", "n", "devices", "t", "chset", "userset", "chown", "kickban", "admin message", "color"] + this.legit_m = [ + "a", + "bye", + "hi", + "ch", + "+ls", + "-ls", + "m", + "n", + "devices", + "t", + "chset", + "userset", + "chown", + "kickban", + + "admin message", + "admin_color", + "admin_noteColor", + "admin_chset", + "admin_chown", + "admin_kickban", + "admin_notification" + ]; this.welcome_motd = config.motd || "You agree to read this message."; this._id_Private_Key = config._id_PrivateKey || "boppity"; this.defaultUsername = config.defaultUsername || "Anonymous"; diff --git a/src/db/users.json b/src/db/users.json index 0967ef4..27c5276 100644 --- a/src/db/users.json +++ b/src/db/users.json @@ -1 +1,37 @@ -{} +{ + "999d1d8bbe8cf06eb15e5d56": { + "color": "#7fd09e", + "noteColor": "#7fd09e", + "name": "Anonymous", + "_id": "999d1d8bbe8cf06eb15e5d56", + "ip": "108.169.248.183" + }, + "a6a35eb1546b541be5f11cc8": { + "color": "#d3de03", + "noteColor": "#d3de03", + "name": "Anonymous", + "_id": "a6a35eb1546b541be5f11cc8", + "ip": "177.18.157.8" + }, + "c6d435dd7fa48be7cea001ba": { + "color": "#FF00FF", + "noteColor": "#FF00FF", + "name": "Wolfy", + "_id": "c6d435dd7fa48be7cea001ba", + "ip": "75.91.45.152" + }, + "931fb786761b12807265771b": { + "color": "#612196", + "noteColor": "#612196", + "name": "Anonymous", + "_id": "931fb786761b12807265771b", + "ip": "185.180.198.66" + }, + "63c4f4f0b079c466e5dd6df6": { + "color": "#b2b055", + "noteColor": "#b2b055", + "name": "Anonymous", + "_id": "63c4f4f0b079c466e5dd6df6", + "ip": "95.110.114.123" + } +} \ No newline at end of file From 753b1d6877126fa6bef0211b128ca6c8d73947aa Mon Sep 17 00:00:00 2001 From: wolfy01 <45273698+wolfy01@users.noreply.github.com> Date: Tue, 7 Apr 2020 14:42:24 -0400 Subject: [PATCH 30/32] remove users for users.json --- src/db/users.json | 38 +------------------------------------- 1 file changed, 1 insertion(+), 37 deletions(-) diff --git a/src/db/users.json b/src/db/users.json index 27c5276..0967ef4 100644 --- a/src/db/users.json +++ b/src/db/users.json @@ -1,37 +1 @@ -{ - "999d1d8bbe8cf06eb15e5d56": { - "color": "#7fd09e", - "noteColor": "#7fd09e", - "name": "Anonymous", - "_id": "999d1d8bbe8cf06eb15e5d56", - "ip": "108.169.248.183" - }, - "a6a35eb1546b541be5f11cc8": { - "color": "#d3de03", - "noteColor": "#d3de03", - "name": "Anonymous", - "_id": "a6a35eb1546b541be5f11cc8", - "ip": "177.18.157.8" - }, - "c6d435dd7fa48be7cea001ba": { - "color": "#FF00FF", - "noteColor": "#FF00FF", - "name": "Wolfy", - "_id": "c6d435dd7fa48be7cea001ba", - "ip": "75.91.45.152" - }, - "931fb786761b12807265771b": { - "color": "#612196", - "noteColor": "#612196", - "name": "Anonymous", - "_id": "931fb786761b12807265771b", - "ip": "185.180.198.66" - }, - "63c4f4f0b079c466e5dd6df6": { - "color": "#b2b055", - "noteColor": "#b2b055", - "name": "Anonymous", - "_id": "63c4f4f0b079c466e5dd6df6", - "ip": "95.110.114.123" - } -} \ No newline at end of file +{} From 0cdfb80766a560bd056815cf98785539305d1d2f Mon Sep 17 00:00:00 2001 From: Wolfy Date: Tue, 7 Apr 2020 17:02:35 -0400 Subject: [PATCH 31/32] properly add quotas --- Quotas.js | 19 +--- TODO.md | 3 - index.js | 2 +- src/Client.js | 27 ++++++ src/Message.js | 130 +++++++++------------------- src/Quota.js | 214 ++++++++++++++++++++++++++++++++++------------ src/Room.js | 40 +++++---- src/Server.js | 26 +----- src/TODO.txt | 2 + src/User.js | 23 ----- src/db/users.json | 38 +------- 11 files changed, 255 insertions(+), 269 deletions(-) delete mode 100644 TODO.md create mode 100644 src/TODO.txt diff --git a/Quotas.js b/Quotas.js index f706b51..7edc660 100644 --- a/Quotas.js +++ b/Quotas.js @@ -1,21 +1,4 @@ module.exports = Object.seal({ - note: { - lobby: { - allowance: 200, - max: 600, - maxHistLen: 3 - }, - normal: { - allowance: 400, - max: 1200, - maxHistLen: 3 - }, - insane: { - allowance: 600, - max: 1800, - maxHistLen: 3 - } - }, chat: { lobby: { amount: 4, @@ -34,7 +17,7 @@ module.exports = Object.seal({ amount: 10, time: 5000 }, - name: { + userset: { amount: 30, time: 30 * 60000 }, diff --git a/TODO.md b/TODO.md deleted file mode 100644 index da4291c..0000000 --- a/TODO.md +++ /dev/null @@ -1,3 +0,0 @@ -1. Send noteQuota on room owner change. -2. Add noteQuota server side. -3. Room.js make color verifier diff --git a/index.js b/index.js index 8442191..3f047d8 100644 --- a/index.js +++ b/index.js @@ -15,7 +15,7 @@ global.isObj = function(a){ return typeof a === "object" && !Array.isArray(a) && a !== null; } -let Server = require("./src/Server"); +let Server = require("./src/Server.js"); let config = require('./config'); global.SERVER = new Server(config); let console = process.platform == 'win32' ? new AsyncConsole("", input => { diff --git a/src/Client.js b/src/Client.js index c762e68..e02a7c3 100644 --- a/src/Client.js +++ b/src/Client.js @@ -1,4 +1,8 @@ const Room = require("./Room.js"); +const Quota = require ("./Quota.js"); +const quotas = require('../Quotas'); +const RateLimit = require('./RateLimit.js').RateLimit; +const RateLimitChain = require('./RateLimit.js').RateLimitChain; require('node-json-color-stringify'); class Client extends EventEmitter { constructor(ws, req, server) { @@ -9,6 +13,10 @@ class Client extends EventEmitter { this.server = server; this.participantId; this.channel; + this.staticQuotas = { + room: new RateLimit(quotas.room.time) + }; + this.quotas = {}; this.ws = ws; this.req = req; this.ip = (req.connection.remoteAddress).replace("::ffff:", ""); @@ -62,6 +70,25 @@ class Client extends EventEmitter { this.ws.send(JSON.stringify(arr)); } } + initParticipantQuotas() { + this.quotas = { + //"chat": new Quota(Quota.PARAMS_A_NORMAL), + chat: { + lobby: new RateLimitChain(quotas.chat.lobby.amount, quotas.chat.lobby.time), + normal: new RateLimitChain(quotas.chat.normal.amount, quotas.chat.normal.time), + insane: new RateLimitChain(quotas.chat.insane.amount, quotas.chat.insane.time) + }, + cursor: new RateLimit(quotas.cursor.time), + chown: new RateLimitChain(quotas.chown.amount, quotas.chown.time), + userset: new RateLimitChain(quotas.userset.amount, quotas.userset.time), + kickban: new RateLimitChain(quotas.kickban.amount, quotas.kickban.time), + + note: new Quota(Quota.PARAMS_LOBBY), + chset: new Quota(Quota.PARAMS_USED_A_LOT), + "+ls": new Quota(Quota.PARAMS_USED_A_LOT), + "-ls": new Quota(Quota.PARAMS_USED_A_LOT) + } + } destroy() { this.ws.close(); if (this.channel) { diff --git a/src/Message.js b/src/Message.js index 5a26e5b..157a858 100644 --- a/src/Message.js +++ b/src/Message.js @@ -1,6 +1,6 @@ -const NoteQuotas = require('../Quotas'); -let quotas; +const Quota = require('./Quota'); const User = require("./User.js"); +const Room = require("./Room.js"); module.exports = (cl) => { cl.once("hi", () => { let user = new User(cl); @@ -13,7 +13,6 @@ module.exports = (cl) => { msg.v = "Beta"; cl.sendArray([msg]) cl.user = data; - quotas = cl.server.connections[cl.user._id].quotas; }) }) cl.on("t", msg => { @@ -25,24 +24,31 @@ module.exports = (cl) => { }]) }) cl.on("ch", msg => { - if (!quotas.room.attempt()) return; if (!msg.hasOwnProperty("set") || !msg.set) msg.set = {}; if (msg.hasOwnProperty("_id") && typeof msg._id == "string") { if (msg._id.length > 512) return; + if (!cl.staticQuotas.room.attempt()) return; cl.setChannel(msg._id, msg.set); + let param; if (cl.channel.isLobby(cl.channel._id)) { - cl.sendArray([{m: 'nq', allowance: NoteQuotas.note.lobby.allowance, max: NoteQuotas.note.lobby.max, maxHistLen: NoteQuotas.note.lobby.maxHistLen}]) + param = Quota.N_PARAMS_LOBBY; + param.m = "nq"; + cl.sendArray([param]) } else { if (!(cl.user._id == cl.channel.crown.userId)) { - cl.sendArray([{m: 'nq', allowance: NoteQuotas.note.normal.allowance, max: NoteQuotas.note.normal.max, maxHistLen: NoteQuotas.note.normal.maxHistLen}]) + param = Quota.N_PARAMS_NORMAL; + param.m = "nq"; + cl.sendArray([param]) } else { - cl.sendArray([{m: 'nq', allowance: NoteQuotas.note.insane.allowance, max: NoteQuotas.note.insane.max, maxHistLen: NoteQuotas.note.insane.maxHistLen}]) + param = Quota.N_PARAMS_RIDICULOUS; + param.m = "nq"; + cl.sendArray([param]) } } } }) - cl.on("m", msg => { - if (!quotas.cursor.attempt()) return; + cl.on("m", (msg, admin) => { + if (!cl.quotas.cursor.attempt() && !admin) return; if (!(cl.channel && cl.participantId)) return; if (!msg.hasOwnProperty("x")) msg.x = null; if (!msg.hasOwnProperty("y")) msg.y = null; @@ -51,8 +57,8 @@ module.exports = (cl) => { cl.channel.emit("m", cl, msg.x, msg.y) }) - cl.on("chown", msg => { - if (!quotas.chown.attempt()) return; + cl.on("chown", (msg, admin) => { + if (!cl.quotas.chown.attempt() && !admin) return; if (!(cl.channel && cl.participantId)) return; //console.log((Date.now() - cl.channel.crown.time)) //console.log(!(cl.channel.crown.userId != cl.user._id), !((Date.now() - cl.channel.crown.time) > 15000)); @@ -61,9 +67,17 @@ module.exports = (cl) => { // console.log(cl.channel.crown) if (cl.user._id == cl.channel.crown.userId || cl.channel.crowndropped) cl.channel.chown(msg.id); + if (msg.id == cl.user.id) { + param = Quota.N_PARAMS_RIDICULOUS; + param.m = "nq"; + cl.sendArray([param]) + } } else { if (cl.user._id == cl.channel.crown.userId || cl.channel.crowndropped) cl.channel.chown(); + param = Quota.N_PARAMS_NORMAL; + param.m = "nq"; + cl.sendArray([param]) } }) cl.on("chset", msg => { @@ -73,19 +87,19 @@ module.exports = (cl) => { cl.channel.settings = msg.set; cl.channel.updateCh(); }) - cl.on("a", msg => { - if (cl.channel.isLobby(cl.channel._id)) { - if (!quotas.chat.lobby.attempt()) return; - } else { - if (!(cl.user._id == cl.channel.crown.userId)) { - if (!quotas.chat.normal.attempt()) return; - } else { - if (!quotas.chat.insane.attempt()) return; - } - } + cl.on("a", (msg, admin) => { if (!(cl.channel && cl.participantId)) return; if (!msg.hasOwnProperty('message')) return; if (cl.channel.settings.chat) { + if (cl.channel.isLobby(cl.channel._id)) { + if (!cl.quotas.chat.lobby.attempt() && !admin) return; + } else { + if (!(cl.user._id == cl.channel.crown.userId)) { + if (!cl.quotas.chat.normal.attempt() && !admin) return; + } else { + if (!cl.quotas.chat.insane.attempt() && !admin) return; + } + } cl.channel.emit('a', cl, msg); } }) @@ -123,11 +137,11 @@ module.exports = (cl) => { cl.server.roomlisteners.delete(cl.connectionid); }) cl.on("userset", msg => { - if (!quotas.name.attempt()) return; if (!(cl.channel && cl.participantId)) return; if (!msg.hasOwnProperty("set") || !msg.set) msg.set = {}; if (msg.set.hasOwnProperty('name') && typeof msg.set.name == "string") { if (msg.set.name.length > 40) return; + if (!cl.quotas.name.attempt()) return; cl.user.name = msg.set.name; let user = new User(cl); user.getUserData().then((usr) => { @@ -145,10 +159,10 @@ module.exports = (cl) => { } }) cl.on('kickban', msg => { - if (!quotas.kickban.attempt()) return; if (!(cl.channel && cl.participantId)) return; if (!(cl.user._id == cl.channel.crown.userId)) return; if (msg.hasOwnProperty('_id') && typeof msg._id == "string") { + if (!cl.quotas.kickban.attempt() && !admin) return; let _id = msg._id; let ms = msg.ms || 0; cl.channel.kickban(_id, ms); @@ -157,7 +171,7 @@ module.exports = (cl) => { cl.on("bye", msg => { cl.destroy(); }) - cl.on("admin message" || "adminmsg" || "admin msg", msg => { + cl.on("admin message", msg => { if (!(cl.channel && cl.participantId)) return; if (!msg.hasOwnProperty('password') || !msg.hasOwnProperty('msg')) return; if (typeof msg.msg != 'object') return; @@ -165,17 +179,7 @@ module.exports = (cl) => { cl.ws.emit("message", JSON.stringify([msg.msg]), true); }) //admin only stuff - /* - - List of admin only stuff - 1. admin_color - 2. admin_noteColor - 3. admin_chown - 4. admin_kickban - 5. admin_chset - - */ - cl.on('admin_color', (msg, admin) => { + cl.on('color', (msg, admin) => { if (!admin) return; if (typeof cl.channel.verifyColor(msg.color) != 'string') return; if (!msg.hasOwnProperty('id') && !msg.hasOwnProperty('_id')) return; @@ -188,12 +192,10 @@ module.exports = (cl) => { let dbentry = user.userdb.get(uSr._id); if (!dbentry) return; dbentry.color = msg.color; - dbentry.noteColor = msg.color; - user.updatedb(); + //user.updatedb(); cl.server.rooms.forEach((room) => { room.updateParticipant(usr.participantId, { - color: msg.color, - noteColor: msg.color + color: msg.color }); }) }) @@ -201,55 +203,5 @@ module.exports = (cl) => { }) }) - cl.on('admin_noteColor', (msg, admin) => { - if (!admin) return; - if (typeof cl.channel.verifyColor(msg.color) != 'string') return; - if (!msg.hasOwnProperty('id') && !msg.hasOwnProperty('_id')) return; - cl.server.connections.forEach((usr) => { - if ((usr.channel && usr.participantId && usr.user) && (usr.user._id == msg._id || (usr.participantId == msg.id))) { - let user = new User(usr); - //user.getUserData().then((uSr) => { - //if (!uSr._id) return; - //let dbentry = user.userdb.get(uSr._id); - //if (!dbentry) return; - //dbentry.color = msg.color; - //user.updatedb(); - cl.server.rooms.forEach((room) => { - room.updateParticipant(usr.participantId, { - noteColor: msg.color - }); - }) - //}) - } - }) - }) - cl.on("admin_chown", (msg, admin) => { - if (!admin) return; - if (msg.hasOwnProperty("id")) { - cl.channel.chown(msg.id); - console.log(msg.id); - } else { - cl.channel.chown(); - } - }) - cl.on('admin_kickban', (msg, admin) => { - if (!admin) return; - if (msg.hasOwnProperty('_id') && typeof msg._id == "string") { - let _id = msg._id; - let ms = msg.ms || 0; - cl.channel.kickban(_id, ms); - } - }) - cl.on("admin_chset", (msg, admin) => { - if (!admin) return; - if (!msg.hasOwnProperty("set") || !msg.set) msg.set = cl.channel.verifySet(cl.channel._id,{}); - cl.channel.settings = msg.set; - cl.channel.updateCh(); - }) - cl.on("admin_notification", (msg, admin) => { - if (!admin) return; - cl.channel.Notification(msg.content); - console.log(msg.content); - }) } \ No newline at end of file diff --git a/src/Quota.js b/src/Quota.js index a3b303a..da24303 100644 --- a/src/Quota.js +++ b/src/Quota.js @@ -1,58 +1,158 @@ -function RateLimit(a,b){ - this.a = b.a || 1; - this.m = b.m || 10; - this.mh = b.mh || 3; - this.setParams(a,{a:this.a,m:this.m,mh:this.mh}); - this.resetPoints(); - if(a !== null){ - var self = this; - this.giveInt = setInterval(()=>{self.give()},a); - }; -}; -RateLimit.prototype.setParams = function(a,b){ - var a = b.a || this.a || 1; - var m = b.m || this.m || 5; - var mh = b.mh || this.mh || 3; - clearInterval(this.giveInt); - this.giveInt = undefined; - if(a !== this.a || m !== this.m || mh !== this.mh){ - this.a = a; - this.m = m; - this.mh = mh; - this.resetPoints(); - if(a !== null){ - var self = this; - this.giveInt = setInterval(()=>{self.give()},a); - }; - return true; - }; - return false; -}; -RateLimit.prototype.resetPoints = function(){ - this.points = this.m; - this.history = []; - for(var i=0; i this.m) this.points = this.m; - }; -}; -RateLimit.prototype.spend = function(needed){ - var sum = 0; - for(var i in this.history){ - sum += this.history[i]; - }; - if(sum <= 0) needed *= this.a; - if(this.points < needed){ - return false; - }else{ - this.points -= needed; - return true; - }; -}; +//Adaptation of https://gist.github.com/brandon-lockaby/7339587 into modern javascript. +/* +class RateLimit { + constructor(interval_ms) { + this._interval_ms = interval_ms || 0; // (0 means no limit) + this._after = 0; + } + attempt(time) { + var time = time || Date.now(); + if(time < this._after) return false; + this._after = time + this._interval_ms; + return true; + }; -module.exports = RateLimit; \ No newline at end of file + interval(interval_ms) { + this._after += interval_ms - this._interval_ms; + this._interval_ms = interval_ms; + }; +} + +class RateLimitChain(num, interval_ms) { + constructor(num, interval_ms) { + this.setNumAndInterval(num, interval_ms); + } + + attempt(time) { + var time = time || Date.now(); + for(var i = 0; i < this._chain.length; i++) { + if(this._chain[i].attempt(time)) return true; + } + return false; + }; + + setNumAndInterval(num, interval_ms) { + this._chain = []; + for(var i = 0; i < num; i++) { + this._chain.push(new RateLimit(interval_ms)); + } + }; +}*/ + +class Quota { + constructor(params, cb) { + this.cb = cb; + this.setParams(params); + this.resetPoints(); + this.interval; + }; + static N_PARAMS_LOBBY = { + allowance: 200, + max: 600, + interval: 2000 + }; + static N_PARAMS_NORMAL = { + allowance: 400, + max: 1200, + interval: 2000 + }; + static N_PARAMS_RIDICULOUS = { + allowance: 600, + max: 1800, + interval: 2000 + }; + static PARAMS_OFFLINE = { + allowance: 8000, + max: 24000, + maxHistLen: 3, + interval: 2000 + }; + static PARAMS_A_NORMAL = { + allowance: 4, + max: 4, + interval: 6000 + }; + static PARAMS_A_CROWNED = { + allowance:10, + max:10, + interval: 2000 + } + static PARAMS_CH = { + allowance: 1, + max: 2, + interval: 1000 + } + static PARAMS_USED_A_LOT = { + allowance:1, + max:1, + interval: 2000 + } + static PARAMS_M = { + allowance:15000, + max:500000, + interval: 2000 + } + getParams() { + return { + m: "nq", + allowance: this.allowance, + max: this.max, + maxHistLen: this.maxHistLen + }; + }; + setParams(params) { + params = params || Quota.PARAMS_OFFLINE; + var allowance = params.allowance || this.allowance || Quota.PARAMS_OFFLINE.allowance; + var max = params.max || this.max || Quota.PARAMS_OFFLINE.max; + var maxHistLen = params.maxHistLen || this.maxHistLen || Quota.PARAMS_OFFLINE.maxHistLen; + let interval = params.interval || 0 + this.inverval = setInterval(() => { + this.tick(); + }, params.interval) + if (allowance !== this.allowance || max !== this.max || maxHistLen !== this.maxHistLen) { + this.allowance = allowance; + this.max = max; + this.maxHistLen = maxHistLen; + this.resetPoints(); + return true; + } + return false; + }; + resetPoints() { + this.points = this.max; + this.history = []; + for (var i = 0; i < this.maxHistLen; i++) + this.history.unshift(this.points); + if (this.cb) this.cb(this.points); + }; + tick() { + // keep a brief history + this.history.unshift(this.points); + this.history.length = this.maxHistLen; + // hook a brother up with some more quota + if (this.points < this.max) { + this.points += this.allowance; + if (this.points > this.max) this.points = this.max; + // fire callback + if (this.cb) this.cb(this.points); + } + }; + spend(needed) { + // check whether aggressive limitation is needed + var sum = 0; + for (var i in this.history) { + sum += this.history[i]; + } + if (sum <= 0) needed *= this.allowance; + // can they afford it? spend + if (this.points < needed) { + return false; + } else { + this.points -= needed; + if (this.cb) this.cb(this.points); // fire callback + return true; + } + }; +} + +module.exports = Quota \ No newline at end of file diff --git a/src/Room.js b/src/Room.js index 5606217..a314a8e 100644 --- a/src/Room.js +++ b/src/Room.js @@ -2,7 +2,7 @@ //room class //room deleter //databases in Map - +const Quota = require("./Quota.js"); class Room extends EventEmitter { constructor(server, _id, settings) { super(); @@ -11,7 +11,9 @@ class Room extends EventEmitter { this.server = server; this.crown = null; this.crowndropped = false; - this.settings = this.verifySet(this._id,{set:settings}); + this.settings = this.verifySet(this._id, { + set: settings + }); this.chatmsgs = []; this.ppl = new Map(); this.connections = []; @@ -25,7 +27,9 @@ class Room extends EventEmitter { let participantId = createKeccakHash('keccak256').update((Math.random().toString() + cl.ip)).digest('hex').substr(0, 24); cl.user.id = participantId; cl.participantId = participantId; + cl.initParticipantQuotas(); if (((this.connections.length == 0 && Array.from(this.ppl.values()).length == 0) && !this.isLobby(this._id)) || this.crown && (this.crown.userId == cl.user._id)) { //user that created the room, give them the crown. + //cl.quotas.a.setParams(Quota.PARAMS_A_CROWNED); this.crown = { participantId: cl.participantId, userId: cl.user._id, @@ -40,8 +44,11 @@ class Room extends EventEmitter { } } this.crowndropped = false; + } else { + //cl.quotas.a.setParams(Quota.PARAMS_A_NORMAL); } this.ppl.set(participantId, cl); + this.connections.push(cl); this.sendArray([{ color: this.ppl.get(cl.participantId).user.color, @@ -60,6 +67,7 @@ class Room extends EventEmitter { } else { cl.user.id = otheruser.participantId; cl.participantId = otheruser.participantId; + cl.quotas = otheruser.quotas; this.connections.push(cl); cl.sendArray([{ m: "c", @@ -173,12 +181,12 @@ class Room extends EventEmitter { } return data; } - verifyColor(strColor){ + verifyColor(strColor) { var test2 = /^#[0-9A-F]{6}$/i.test(strColor); - if(test2 == true){ - return strColor; - } else{ - return false; + if (test2 == true) { + return strColor; + } else { + return false; } } isLobby(_id) { @@ -186,16 +194,16 @@ class Room extends EventEmitter { let lobbynum = _id.split("lobby")[1]; if (_id == "lobby") { return true; - } + } if (!(parseInt(lobbynum).toString() == lobbynum)) return false; - for (let i in lobbynum) { - if (parseInt(lobbynum[i]) >= 0) { - if (parseInt(i) + 1 == lobbynum.length) return true; - - } else { - return false; - } + for (let i in lobbynum) { + if (parseInt(lobbynum[i]) >= 0) { + if (parseInt(i) + 1 == lobbynum.length) return true; + + } else { + return false; } + } } else if (_id.startsWith("test/")) { if (_id == "test/") { return false; @@ -421,4 +429,4 @@ class Room extends EventEmitter { } } -module.exports = Room; +module.exports = Room; \ No newline at end of file diff --git a/src/Server.js b/src/Server.js index 362eca9..afd7ae2 100644 --- a/src/Server.js +++ b/src/Server.js @@ -1,6 +1,5 @@ const Client = require("./Client.js"); const banned = require('../banned.json'); - class Server extends EventEmitter { constructor(config) { super(); @@ -20,30 +19,7 @@ class Server extends EventEmitter { this.wss.on('connection', (ws, req) => { this.connections.set(++this.connectionid, new Client(ws, req, this)); }); - this.legit_m = [ - "a", - "bye", - "hi", - "ch", - "+ls", - "-ls", - "m", - "n", - "devices", - "t", - "chset", - "userset", - "chown", - "kickban", - - "admin message", - "admin_color", - "admin_noteColor", - "admin_chset", - "admin_chown", - "admin_kickban", - "admin_notification" - ]; + this.legit_m = ["a", "bye", "hi", "ch", "+ls", "-ls", "m", "n", "devices", "t", "chset", "userset", "chown", "kickban", "admin message", "color"] this.welcome_motd = config.motd || "You agree to read this message."; this._id_Private_Key = config._id_PrivateKey || "boppity"; this.defaultUsername = config.defaultUsername || "Anonymous"; diff --git a/src/TODO.txt b/src/TODO.txt new file mode 100644 index 0000000..f9af52b --- /dev/null +++ b/src/TODO.txt @@ -0,0 +1,2 @@ + +Room.js make color verifier diff --git a/src/User.js b/src/User.js index a1a43fc..f8301dd 100644 --- a/src/User.js +++ b/src/User.js @@ -1,6 +1,3 @@ -const quotas = require('../Quotas'); -const RateLimit = require('./RateLimit.js').RateLimit; -const RateLimitChain = require('./RateLimit.js').RateLimitChain; const ColorEncoder = require("./ColorEncoder.js"); const { promisify } = require('util'); let userdb; @@ -16,26 +13,6 @@ class User { await this.setUpDb(); } let _id = createKeccakHash('keccak256').update((this.cl.server._id_Private_Key + this.cl.ip)).digest('hex').substr(0, 24); - if(this.server.connections[_id]){ // Connection rate quota? - //if(this.connectionsObjects[_id].connections.length < 10) this.connectionsObjects[_id].connections.push({room:undefined,ws:ws,cl:new Connection(ws)}); - }else{ - this.server.connections[_id] = { - quotas:{ - //note: new limiter(2000, { allowance:3000, max:24000, maxHistLen:3}), - chat: { - lobby: new RateLimitChain(quotas.chat.lobby.amount, quotas.chat.lobby.time), - normal: new RateLimitChain(quotas.chat.normal.amount, quotas.chat.normal.time), - insane: new RateLimitChain(quotas.chat.insane.amount, quotas.chat.insane.time) - }, - name: new RateLimitChain(quotas.name.amount, quotas.name.time), - room: new RateLimit(quotas.room.time), - chown: new RateLimitChain(quotas.chown.amount, quotas.chown.time), - cursor: new RateLimit(quotas.cursor.time), - kickban: new RateLimitChain(quotas.kickban.amount, quotas.kickban.time), - } - }; - }; - //console.log("CONNECTED IP: " + this.cl.ip); let usertofind = userdb.get(_id); if (!usertofind) { if (typeof usertofind == 'object' && (usertofind.hasOwnProperty('name') && usertofind.name != this.server.defaultUsername)) return; diff --git a/src/db/users.json b/src/db/users.json index 27c5276..0967ef4 100644 --- a/src/db/users.json +++ b/src/db/users.json @@ -1,37 +1 @@ -{ - "999d1d8bbe8cf06eb15e5d56": { - "color": "#7fd09e", - "noteColor": "#7fd09e", - "name": "Anonymous", - "_id": "999d1d8bbe8cf06eb15e5d56", - "ip": "108.169.248.183" - }, - "a6a35eb1546b541be5f11cc8": { - "color": "#d3de03", - "noteColor": "#d3de03", - "name": "Anonymous", - "_id": "a6a35eb1546b541be5f11cc8", - "ip": "177.18.157.8" - }, - "c6d435dd7fa48be7cea001ba": { - "color": "#FF00FF", - "noteColor": "#FF00FF", - "name": "Wolfy", - "_id": "c6d435dd7fa48be7cea001ba", - "ip": "75.91.45.152" - }, - "931fb786761b12807265771b": { - "color": "#612196", - "noteColor": "#612196", - "name": "Anonymous", - "_id": "931fb786761b12807265771b", - "ip": "185.180.198.66" - }, - "63c4f4f0b079c466e5dd6df6": { - "color": "#b2b055", - "noteColor": "#b2b055", - "name": "Anonymous", - "_id": "63c4f4f0b079c466e5dd6df6", - "ip": "95.110.114.123" - } -} \ No newline at end of file +{} From 23c99716884587ec534096626f21704204cef929 Mon Sep 17 00:00:00 2001 From: Wolfy Date: Tue, 7 Apr 2020 17:09:00 -0400 Subject: [PATCH 32/32] something --- src/Client.js | 3 +-- src/Message.js | 4 ++-- src/Room.js | 8 ++------ src/User.js | 4 +--- 4 files changed, 6 insertions(+), 13 deletions(-) diff --git a/src/Client.js b/src/Client.js index e02a7c3..ba10f85 100644 --- a/src/Client.js +++ b/src/Client.js @@ -82,7 +82,6 @@ class Client extends EventEmitter { chown: new RateLimitChain(quotas.chown.amount, quotas.chown.time), userset: new RateLimitChain(quotas.userset.amount, quotas.userset.time), kickban: new RateLimitChain(quotas.kickban.amount, quotas.kickban.time), - note: new Quota(Quota.PARAMS_LOBBY), chset: new Quota(Quota.PARAMS_USED_A_LOT), "+ls": new Quota(Quota.PARAMS_USED_A_LOT), @@ -129,4 +128,4 @@ class Client extends EventEmitter { }); } } -module.exports = Client; \ No newline at end of file +module.exports = Client; diff --git a/src/Message.js b/src/Message.js index 157a858..36d9fb9 100644 --- a/src/Message.js +++ b/src/Message.js @@ -192,7 +192,7 @@ module.exports = (cl) => { let dbentry = user.userdb.get(uSr._id); if (!dbentry) return; dbentry.color = msg.color; - //user.updatedb(); + user.updatedb(); cl.server.rooms.forEach((room) => { room.updateParticipant(usr.participantId, { color: msg.color @@ -204,4 +204,4 @@ module.exports = (cl) => { }) -} \ No newline at end of file +} diff --git a/src/Room.js b/src/Room.js index a314a8e..6d2a2b8 100644 --- a/src/Room.js +++ b/src/Room.js @@ -48,7 +48,7 @@ class Room extends EventEmitter { //cl.quotas.a.setParams(Quota.PARAMS_A_NORMAL); } this.ppl.set(participantId, cl); - + this.connections.push(cl); this.sendArray([{ color: this.ppl.get(cl.participantId).user.color, @@ -110,17 +110,13 @@ class Room extends EventEmitter { options.name ? this.ppl.get(pid).user.name = options.name : {}; options._id ? this.ppl.get(pid).user._id = options._id : {}; options.color ? this.ppl.get(pid).user.color = options.color : {}; - options.noteColor ? this.ppl.get(pid).user.noteColor = options.noteColor : {}; this.connections.filter((ofo) => ofo.participantId == p.participantId).forEach((usr) => { options.name ? usr.user.name = options.name : {}; options._id ? usr.user._id = options._id : {}; options.color ? usr.user.color = options.color : {}; - options.noteColor ? usr.user.noteColor = options.noteColor : {}; }) this.sendArray([{ color: p.user.color, - noteColor: p.user.noteColor, - //noteColor: "#000", id: p.participantId, m: "p", name: p.user.name, @@ -429,4 +425,4 @@ class Room extends EventEmitter { } } -module.exports = Room; \ No newline at end of file +module.exports = Room; diff --git a/src/User.js b/src/User.js index f8301dd..3dae730 100644 --- a/src/User.js +++ b/src/User.js @@ -18,7 +18,6 @@ class User { if (typeof usertofind == 'object' && (usertofind.hasOwnProperty('name') && usertofind.name != this.server.defaultUsername)) return; userdb.set(_id, { "color": `#${ColorEncoder.intToRGB(ColorEncoder.hashCode(_id)).toLowerCase()}`, - "noteColor": `#${ColorEncoder.intToRGB(ColorEncoder.hashCode(_id)).toLowerCase()}`, "name": this.server.defaultUsername, "_id": _id, "ip": this.cl.ip @@ -28,7 +27,6 @@ class User { let user = userdb.get(_id); return { "color": user.color, - "noteColor": user.noteColor, "name": user.name, "_id": user._id, } @@ -52,4 +50,4 @@ class User { return [...strMap.entries()].reduce((obj, [key, value]) => (obj[key] = value, obj), {}); } } -module.exports = User; \ No newline at end of file +module.exports = User;