mpp-server-dev2/oldsrc/Client.js

354 lines
10 KiB
JavaScript
Raw Normal View History

2022-03-29 06:41:30 +02:00
const Channel = require("./Channel.js");
2023-03-31 16:43:24 +02:00
const Quota = require("./Quota.js");
const quotas = require("../Quotas");
const { RateLimit, RateLimitChain } = require("./Ratelimit.js");
2021-04-12 23:29:02 +02:00
const User = require("./User.js");
const Database = require("./Database.js");
2023-03-31 16:43:24 +02:00
const { EventEmitter } = require("events");
2021-04-12 23:29:02 +02:00
2020-04-07 09:55:16 +02:00
class Client extends EventEmitter {
2022-09-07 09:10:07 +02:00
/**
* Server-side client representation
* @param {*} ws WebSocket object
* @param {*} req WebSocket request
* @param {*} server Server
*/
2020-04-07 09:55:16 +02:00
constructor(ws, req, server) {
super();
EventEmitter.call(this);
this.connectionid = server.connectionid;
this.server = server;
this.participantId;
this.channel;
2022-05-24 20:22:19 +02:00
this.isSubscribedToAdminStream = false;
this.adminStreamInterval;
2021-04-12 23:29:02 +02:00
2020-04-07 23:02:35 +02:00
this.staticQuotas = {
room: new RateLimit(quotas.room.time)
};
2021-04-12 23:29:02 +02:00
2020-04-07 23:02:35 +02:00
this.quotas = {};
2020-04-07 09:55:16 +02:00
this.ws = ws;
this.req = req;
2023-03-31 16:43:24 +02:00
this.ip = req.connection.remoteAddress.replace("::ffff:", "");
2021-04-13 04:08:29 +02:00
this.hidden = false;
2021-04-12 23:29:02 +02:00
Database.getUserData(this, server).then(data => {
this.user = new User(this, data);
this.destroied = false;
this.bindEventListeners();
2023-03-31 16:43:24 +02:00
require("./Message.js")(this);
2021-04-12 23:29:02 +02:00
});
2020-04-07 09:55:16 +02:00
}
2021-04-12 23:29:02 +02:00
2022-09-07 09:10:07 +02:00
/**
* Check if user is connected
* @returns boolean
*/
2020-04-07 09:55:16 +02:00
isConnected() {
return this.ws && this.ws.readyState === WebSocket.OPEN;
}
2021-04-12 23:29:02 +02:00
2022-09-07 09:10:07 +02:00
/**
* Check if user is connecting
* @returns boolean
*/
2020-04-07 09:55:16 +02:00
isConnecting() {
return this.ws && this.ws.readyState === WebSocket.CONNECTING;
}
2021-04-12 23:29:02 +02:00
2022-09-07 09:10:07 +02:00
/**
* Move user to channel
* @param {string} _id User ID
* @param {*} settings Settings object
* @returns undefined
*/
2020-04-07 09:55:16 +02:00
setChannel(_id, settings) {
if (this.channel && this.channel._id == _id) return;
2023-03-31 16:43:24 +02:00
if (this.server.channels.get(_id)) {
let ch = this.server.channels.get(_id, settings);
let userbanned = ch.bans.get(this.user._id);
2021-04-12 23:29:02 +02:00
2023-03-31 16:43:24 +02:00
if (
userbanned &&
Date.now() - userbanned.bannedtime >= userbanned.msbanned
) {
ch.bans.delete(userbanned.user._id);
2020-04-07 09:55:16 +02:00
userbanned = undefined;
}
2021-04-12 23:29:02 +02:00
2020-04-07 09:55:16 +02:00
if (userbanned) {
2023-04-01 07:05:12 +02:00
new Notification(this.server, {
targetUser: this.participantId,
targetChannel: all,
title: "Notice",
text: `Currently banned from "${_id}" for ${Math.ceil(
2023-03-31 16:43:24 +02:00
Math.floor(
(userbanned.msbanned -
(Date.now() - userbanned.bannedtime)) /
1000
) / 60
)} minutes.`,
2023-04-01 07:05:12 +02:00
duration: 7000,
id: "",
target: "#room",
class: "short",
cl: this
}).send();
2023-01-15 01:48:04 +01:00
this.setChannel(Channel.banChannel, settings);
2020-04-07 09:55:16 +02:00
return;
}
2021-04-12 23:29:02 +02:00
2020-04-07 09:55:16 +02:00
let channel = this.channel;
if (channel) this.channel.emit("bye", this);
2021-04-12 23:29:02 +02:00
if (channel) this.channel.updateCh(this);
2023-03-31 16:43:24 +02:00
this.channel = this.server.channels.get(_id);
2022-06-17 08:36:49 +02:00
this.channel.join(this);
2020-04-07 09:55:16 +02:00
} else {
2022-09-07 09:10:07 +02:00
let room = new Channel(this.server, _id, settings, this);
2023-03-31 16:43:24 +02:00
this.server.channels.set(_id, room);
2020-04-07 09:55:16 +02:00
if (this.channel) this.channel.emit("bye", this);
2023-03-31 16:43:24 +02:00
this.channel = this.server.channels.get(_id);
2021-04-12 23:29:02 +02:00
this.channel.join(this, settings);
2020-04-07 09:55:16 +02:00
}
}
2022-03-29 06:41:30 +02:00
2022-09-07 09:10:07 +02:00
/**
* Send data to client
* @param {any[]} arr Array of messages
*/
2020-04-07 09:55:16 +02:00
sendArray(arr) {
if (this.isConnected()) {
//console.log(`SEND: `, JSON.colorStringify(arr));
this.ws.send(JSON.stringify(arr));
}
}
2021-04-12 23:29:02 +02:00
2022-09-07 09:10:07 +02:00
/**
* Set username in database
* @param {string} name Username
* @param {boolean} admin Is admin?
* @returns undefined
*/
2022-07-04 00:38:42 +02:00
userset(name, admin) {
if (name.length > 40 && !admin) return;
2023-03-31 16:43:24 +02:00
2022-09-24 05:46:06 +02:00
if (this.quotas.userset) {
if (!this.quotas.userset.attempt()) return;
}
2023-03-31 16:43:24 +02:00
if (!this.user.hasFlag("freeze_name", true) || admin) {
2022-09-11 07:57:50 +02:00
this.user.name = name;
2023-03-31 16:43:24 +02:00
if (!this.user.hasFlag("freeze_name", true)) {
Database.getUserData(this, this.server).then(usr => {
2022-09-24 05:46:06 +02:00
Database.updateUser(this.user._id, this.user);
2023-03-31 16:43:24 +02:00
this.server.channels.forEach(channel => {
channel.updateParticipant(this.user._id, {
2022-09-24 05:46:06 +02:00
name: name
});
2022-08-16 12:23:21 +02:00
});
2022-07-04 00:38:42 +02:00
});
2022-09-24 05:46:06 +02:00
}
2022-09-11 07:51:53 +02:00
}
2022-07-04 00:38:42 +02:00
}
2022-09-07 09:10:07 +02:00
/**
* Set rate limits
*/
2020-04-07 23:02:35 +02:00
initParticipantQuotas() {
this.quotas = {
//"chat": new Quota(Quota.PARAMS_A_NORMAL),
chat: {
2023-03-31 16:43:24 +02:00
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
)
2020-04-07 23:02:35 +02:00
},
2023-03-31 16:43:24 +02:00
cursor: new RateLimitChain(
quotas.cursor.amount,
quotas.cursor.time
),
2020-04-07 23:02:35 +02:00
chown: new RateLimitChain(quotas.chown.amount, quotas.chown.time),
2023-03-31 16:43:24 +02:00
userset: new RateLimitChain(
quotas.userset.amount,
quotas.userset.time
),
kickban: new RateLimitChain(
quotas.kickban.amount,
quotas.kickban.time
),
2023-01-15 01:48:04 +01:00
// note: new Quota(Quota.PARAMS_LOBBY),
note: new RateLimitChain(5, 5000),
2020-04-07 23:02:35 +02:00
chset: new Quota(Quota.PARAMS_USED_A_LOT),
"+ls": new Quota(Quota.PARAMS_USED_A_LOT),
"-ls": new Quota(Quota.PARAMS_USED_A_LOT)
2023-03-31 16:43:24 +02:00
};
2020-04-07 23:02:35 +02:00
}
2021-04-12 23:29:02 +02:00
2022-09-07 09:10:07 +02:00
/**
* Stop the client
*/
2020-04-07 09:55:16 +02:00
destroy() {
2023-03-31 16:43:24 +02:00
if (this.user) {
2023-04-01 07:05:12 +02:00
let lastClient = true;
for (const cl of this.server.connections.values()) {
if (cl.user) {
if (cl.user._id == this.user._id) {
lastClient = false;
break;
}
}
}
if (lastClient) this.user.stopFlagEvents();
2023-03-31 16:43:24 +02:00
}
2023-04-01 07:05:12 +02:00
2020-04-07 09:55:16 +02:00
this.ws.close();
2023-04-01 07:05:12 +02:00
2020-04-07 09:55:16 +02:00
if (this.channel) {
2021-05-09 10:52:41 +02:00
this.channel.emit("bye", this);
2020-04-07 09:55:16 +02:00
}
this.user;
this.participantId;
this.channel;
this.server.roomlisteners.delete(this.connectionid);
this.connectionid;
this.server.connections.delete(this.connectionid);
this.destroied = true;
}
2021-04-12 23:29:02 +02:00
2022-09-07 09:10:07 +02:00
/**
* Internal
*/
2020-04-07 09:55:16 +02:00
bindEventListeners() {
this.ws.on("message", (evt, admin) => {
try {
2023-03-31 16:43:24 +02:00
if (typeof evt !== "string") evt = evt.toJSON();
2020-04-07 09:55:16 +02:00
let transmission = JSON.parse(evt);
for (let msg of transmission) {
2023-03-31 16:43:24 +02:00
if (typeof msg !== "object" || msg == null || msg == NaN)
return;
2020-04-07 09:55:16 +02:00
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) {
2023-03-31 16:43:24 +02:00
console.log(e);
2021-04-02 20:02:04 +02:00
// this.destroy();
2020-04-07 09:55:16 +02:00
}
});
2023-04-01 07:05:12 +02:00
2020-04-07 09:55:16 +02:00
this.ws.on("close", () => {
2021-04-12 23:29:02 +02:00
if (!this.destroied) {
2020-04-07 09:55:16 +02:00
this.destroy();
2021-04-12 23:29:02 +02:00
}
2020-04-07 09:55:16 +02:00
});
2023-04-01 07:05:12 +02:00
2023-03-31 16:43:24 +02:00
this.ws.addEventListener("error", err => {
2020-04-07 09:55:16 +02:00
console.error(err);
2021-04-12 23:29:02 +02:00
if (!this.destroied) {
2020-04-07 09:55:16 +02:00
this.destroy();
2021-04-12 23:29:02 +02:00
}
2020-04-07 09:55:16 +02:00
});
}
2022-05-24 20:22:19 +02:00
2022-09-07 09:10:07 +02:00
/**
* Send admin data bus message
*/
2022-05-24 20:22:19 +02:00
sendAdminData() {
let data = {};
data.m = "data";
let channels = [];
2023-03-31 16:43:24 +02:00
this.server.channels.forEach(ch => {
2022-09-11 07:51:53 +02:00
let ppl = [];
2023-04-01 07:05:12 +02:00
const chdata = ch.fetchChannelData();
for (let p of chdata.ppl) {
2022-09-11 07:51:53 +02:00
ppl.push({
user: p
});
}
2023-04-01 07:05:12 +02:00
2022-09-11 07:51:53 +02:00
channels.push({
2023-04-01 07:05:12 +02:00
chat: ch.chatmsgs.slice(-1 * 32),
2022-09-11 07:51:53 +02:00
participants: ppl
});
2022-05-24 20:22:19 +02:00
});
2022-08-16 12:23:21 +02:00
let users = [];
2023-04-01 07:05:12 +02:00
let clients = [];
2022-08-16 12:23:21 +02:00
this.server.connections.forEach(cl => {
2023-04-01 07:35:55 +02:00
if (!cl.user) return;
2023-04-01 07:05:12 +02:00
let c = {
ip: cl.ip,
2023-04-01 07:35:55 +02:00
participantId: cl.participantId,
userId: cl.user._id
2023-04-01 07:05:12 +02:00
};
clients.push(c);
2022-08-16 12:23:21 +02:00
let u = {
p: {
_id: cl.user._id,
name: cl.user.name,
color: cl.user.color,
2023-04-01 07:05:12 +02:00
flags: cl.user.flags
// inventory: cl.user.inventory
2022-08-16 12:23:21 +02:00
},
2023-03-31 16:43:24 +02:00
id: cl.participantId
};
2022-08-16 12:23:21 +02:00
users.push(u);
});
2023-03-31 16:43:24 +02:00
2022-05-24 20:22:19 +02:00
data.channelManager = {
2023-03-31 16:43:24 +02:00
loggingChannel: Channel.loggingChannel,
loggerParticipant: Channel.loggerParticipant,
2022-05-24 20:22:19 +02:00
channels
};
2022-08-16 12:23:21 +02:00
data.clientManager = {
2023-04-01 07:05:12 +02:00
users,
clients
2023-03-31 16:43:24 +02:00
};
2022-08-16 12:23:21 +02:00
2023-03-31 16:43:24 +02:00
data.uptime = Date.now() - this.server.startTime;
2023-04-01 07:05:12 +02:00
data.config = this.server.config;
if (this.user) {
data.p = {
_id: this.user._id,
name: this.user.name,
color: this.user.color,
flags: this.user.flags
// inventory: this.user.inventory
};
}
2023-01-15 01:48:04 +01:00
2022-05-24 20:22:19 +02:00
this.sendArray([data]);
}
2022-07-09 11:06:51 +02:00
/**
2023-03-31 16:43:24 +02:00
*
* @param {Channel} ch
2022-07-09 11:06:51 +02:00
* @param {Client} cl If this is present, only this client's user data will be sent(?)
*/
sendChannelUpdate(ch, cl) {
let msg = ch.fetchChannelData(this, cl);
this.sendArray([msg]);
}
2020-04-07 09:55:16 +02:00
}
2021-04-12 23:29:02 +02:00
2020-04-07 23:09:00 +02:00
module.exports = Client;