Compare commits
2 Commits
5d5c10d7a5
...
f52715abf3
Author | SHA1 | Date |
---|---|---|
Hri7566 | f52715abf3 | |
Hri7566 | 4c20bea437 |
|
@ -25,7 +25,7 @@ interface CachedKickban {
|
||||||
|
|
||||||
export class Channel extends EventEmitter {
|
export class Channel extends EventEmitter {
|
||||||
private settings: Partial<IChannelSettings>;
|
private settings: Partial<IChannelSettings>;
|
||||||
private ppl = new Array<Participant>();
|
private ppl = new Array<Participant & { uuids: string[] }>();
|
||||||
public chatHistory = new Array<ClientEvents["a"]>();
|
public chatHistory = new Array<ClientEvents["a"]>();
|
||||||
|
|
||||||
private async loadChatHistory() {
|
private async loadChatHistory() {
|
||||||
|
@ -55,9 +55,9 @@ export class Channel extends EventEmitter {
|
||||||
|
|
||||||
if (!this.isLobby()) {
|
if (!this.isLobby()) {
|
||||||
if (set) {
|
if (set) {
|
||||||
this.logger.debug("Passed settings:", set);
|
//this.logger.debug("Passed settings:", set);
|
||||||
const validatedSet = validateChannelSettings(set);
|
const validatedSet = validateChannelSettings(set);
|
||||||
this.logger.debug("Validated settings:", validatedSet);
|
//this.logger.debug("Validated settings:", validatedSet);
|
||||||
|
|
||||||
for (const key of Object.keys(set)) {
|
for (const key of Object.keys(set)) {
|
||||||
if ((validatedSet as any)[key] === false) continue;
|
if ((validatedSet as any)[key] === false) continue;
|
||||||
|
@ -94,10 +94,13 @@ export class Channel extends EventEmitter {
|
||||||
this.logger.info("Loaded Chat History.");
|
this.logger.info("Loaded Chat History.");
|
||||||
|
|
||||||
this.on("update", () => {
|
this.on("update", () => {
|
||||||
|
//this.logger.debug("-------- UPDATE START --------");
|
||||||
// Send updated info
|
// Send updated info
|
||||||
for (const socket of socketsBySocketID.values()) {
|
for (const socket of socketsBySocketID.values()) {
|
||||||
for (const p of this.ppl) {
|
for (const p of this.ppl) {
|
||||||
if (socket.getParticipantID() == p.id) {
|
//if (socket.getParticipantID() == p.id) {
|
||||||
|
if (p.uuids.includes(socket.getUUID())) {
|
||||||
|
//this.logger.debug("sending to", socket.getUUID())
|
||||||
socket.sendChannelUpdate(
|
socket.sendChannelUpdate(
|
||||||
this.getInfo(),
|
this.getInfo(),
|
||||||
this.getParticipantList()
|
this.getParticipantList()
|
||||||
|
@ -141,6 +144,10 @@ export class Channel extends EventEmitter {
|
||||||
if (msg.message.startsWith("/")) {
|
if (msg.message.startsWith("/")) {
|
||||||
this.emit("command", msg, socket);
|
this.emit("command", msg, socket);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (msg.message == "debug") {
|
||||||
|
this.logger.info(socket.getUUID(), socket.currentChannelID);
|
||||||
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.logger.error(err);
|
this.logger.error(err);
|
||||||
}
|
}
|
||||||
|
@ -191,12 +198,14 @@ export class Channel extends EventEmitter {
|
||||||
if (set.owner_id) set.owner_id = undefined;
|
if (set.owner_id) set.owner_id = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
this.logger.debug(
|
this.logger.debug(
|
||||||
"Dreaded color2 conditions:",
|
"Dreaded color2 conditions:",
|
||||||
typeof set.color == "string",
|
typeof set.color == "string",
|
||||||
"and",
|
"and",
|
||||||
typeof set.color2 == "undefined"
|
typeof set.color2 == "undefined"
|
||||||
);
|
);
|
||||||
|
*/
|
||||||
|
|
||||||
if (
|
if (
|
||||||
typeof set.color == "string" &&
|
typeof set.color == "string" &&
|
||||||
|
@ -256,6 +265,7 @@ export class Channel extends EventEmitter {
|
||||||
public join(socket: Socket): void {
|
public join(socket: Socket): void {
|
||||||
//! /!\ Players are forced to join the same channel on two different tabs!
|
//! /!\ Players are forced to join the same channel on two different tabs!
|
||||||
//? TODO Should this be a bug or a feature?
|
//? TODO Should this be a bug or a feature?
|
||||||
|
//this.logger.debug("join triggered");
|
||||||
|
|
||||||
if (this.isDestroyed()) return;
|
if (this.isDestroyed()) return;
|
||||||
const part = socket.getParticipant() as Participant;
|
const part = socket.getParticipant() as Participant;
|
||||||
|
@ -269,26 +279,48 @@ export class Channel extends EventEmitter {
|
||||||
// TODO Send notification for ban
|
// TODO Send notification for ban
|
||||||
const chs = ChannelList.getList();
|
const chs = ChannelList.getList();
|
||||||
for (const ch of chs) {
|
for (const ch of chs) {
|
||||||
if (ch.getID() == config.fullChannel) {
|
const chid = ch.getID();
|
||||||
return ch.join(socket);
|
if (chid == config.fullChannel) {
|
||||||
|
return socket.setChannel(chid)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is user in this channel?
|
// Is user in this channel?
|
||||||
if (this.hasUser(part._id)) {
|
if (this.hasUser(part._id)) {
|
||||||
// Alreay in channel, don't add to list, but tell them they're here
|
// Already in channel, don't add to list, but tell them they're here
|
||||||
hasChangedChannel = true;
|
hasChangedChannel = true;
|
||||||
this.ppl.push(part);
|
|
||||||
|
for (const p of this.ppl) {
|
||||||
|
if (p.id !== part.id) continue;
|
||||||
|
p.uuids.push(socket.getUUID())
|
||||||
|
}
|
||||||
|
|
||||||
|
socket.sendChannelUpdate(this.getInfo(), this.getParticipantList());
|
||||||
} else {
|
} else {
|
||||||
// Are we full?
|
// Are we full?
|
||||||
if (!this.isFull()) {
|
if (!this.isFull()) {
|
||||||
// Add to channel
|
// Add to channel
|
||||||
hasChangedChannel = true;
|
hasChangedChannel = true;
|
||||||
this.ppl.push(part);
|
this.ppl.push({
|
||||||
|
_id: part._id,
|
||||||
|
name: part.name,
|
||||||
|
color: part.color,
|
||||||
|
id: part.id,
|
||||||
|
tag: part.tag,
|
||||||
|
uuids: [socket.getUUID()]
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
// Put them in full channel
|
if (socket.currentChannelID !== config.fullChannel) {
|
||||||
return socket.setChannel(config.fullChannel);
|
// Put them in full channel
|
||||||
|
const chs = ChannelList.getList();
|
||||||
|
for (const ch of chs) {
|
||||||
|
const chid = ch.getID();
|
||||||
|
if (chid == config.fullChannel) {
|
||||||
|
return socket.setChannel(chid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -348,7 +380,7 @@ export class Channel extends EventEmitter {
|
||||||
// Broadcast a channel update so everyone subscribed to the channel list can see us
|
// Broadcast a channel update so everyone subscribed to the channel list can see us
|
||||||
this.emit("update", this);
|
this.emit("update", this);
|
||||||
|
|
||||||
this.logger.debug("Settings:", this.settings);
|
//this.logger.debug("Settings:", this.settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -386,6 +418,11 @@ export class Channel extends EventEmitter {
|
||||||
]);
|
]);
|
||||||
|
|
||||||
this.emit("update", this);
|
this.emit("update", this);
|
||||||
|
} else {
|
||||||
|
for (const p of this.ppl) {
|
||||||
|
if (!p.uuids.includes(socket.getUUID())) continue;
|
||||||
|
p.uuids.splice(p.uuids.indexOf(socket.getUUID()), 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -425,7 +462,13 @@ export class Channel extends EventEmitter {
|
||||||
* @returns List of people
|
* @returns List of people
|
||||||
*/
|
*/
|
||||||
public getParticipantList() {
|
public getParticipantList() {
|
||||||
return this.ppl;
|
return this.ppl.map(p => ({
|
||||||
|
id: p.id,
|
||||||
|
_id: p._id,
|
||||||
|
name: p.name,
|
||||||
|
color: p.color,
|
||||||
|
tag: p.tag
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -606,35 +649,60 @@ export class Channel extends EventEmitter {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Kickban a poor soul for t milliseconds.
|
* Kickban a participant for t milliseconds.
|
||||||
* @param _id User ID to ban
|
* @param _id User ID to ban
|
||||||
* @param t Time in millseconds to ban for
|
* @param t Time in millseconds to ban for
|
||||||
**/
|
**/
|
||||||
public kickban(_id: string, t: number = 1000 * 60 * 30) {
|
public kickban(_id: string, t: number = 1000 * 60 * 30) {
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
|
|
||||||
if (!this.hasUser(_id)) return;
|
let shouldUpdate = false;
|
||||||
|
|
||||||
const part = this.ppl.find(p => p._id == _id);
|
|
||||||
if (!part) return;
|
|
||||||
|
|
||||||
this.bans.push({
|
|
||||||
userId: _id,
|
|
||||||
startTime: now,
|
|
||||||
endTime: now + t
|
|
||||||
});
|
|
||||||
|
|
||||||
const socket = findSocketByPartID(part.id);
|
|
||||||
if (!socket) return;
|
|
||||||
|
|
||||||
const banChannel = ChannelList.getList().find(
|
const banChannel = ChannelList.getList().find(
|
||||||
ch => ch.getID() == config.fullChannel
|
ch => ch.getID() == config.fullChannel
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!banChannel) return;
|
if (!banChannel) return;
|
||||||
banChannel.join(socket);
|
|
||||||
|
|
||||||
this.emit("update", this);
|
let isBanned = this.bans.map(b => b.userId).includes(_id);
|
||||||
|
let overwrite = false;
|
||||||
|
|
||||||
|
if (isBanned) {
|
||||||
|
overwrite = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
let uuidsToKick: string[] = [];
|
||||||
|
|
||||||
|
for (const part of this.ppl) {
|
||||||
|
if (part._id !== _id) continue;
|
||||||
|
|
||||||
|
if (!overwrite) {
|
||||||
|
this.bans.push({
|
||||||
|
userId: _id,
|
||||||
|
startTime: now,
|
||||||
|
endTime: now + t
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
for (const ban of this.bans) {
|
||||||
|
if (ban.userId !== _id) continue;
|
||||||
|
ban.startTime = now;
|
||||||
|
ban.endTime = now + t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uuidsToKick = [...uuidsToKick, ...part.uuids];
|
||||||
|
|
||||||
|
shouldUpdate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const socket of socketsBySocketID.values()) {
|
||||||
|
if (uuidsToKick.includes(socket.getUUID())) {
|
||||||
|
socket.setChannel(banChannel.getID());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldUpdate)
|
||||||
|
this.emit("update", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public isBanned(_id: string) {
|
public isBanned(_id: string) {
|
||||||
|
|
|
@ -16,10 +16,14 @@ export async function saveChatHistory(_id: string, chatHistory: object) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getChatHistory(_id: string) {
|
export async function getChatHistory(_id: string) {
|
||||||
const history = await prisma.chatHistory.findFirst({ where: { id: _id } });
|
try {
|
||||||
if (!history) {
|
const history = await prisma.chatHistory.findFirst({ where: { id: _id } });
|
||||||
|
if (!history) {
|
||||||
|
return [];
|
||||||
|
} else {
|
||||||
|
return JSON.parse(history.messages);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
return [];
|
return [];
|
||||||
} else {
|
|
||||||
return JSON.parse(history.messages);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,20 +27,24 @@ export async function deleteUser(_id: string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function readUser(_id: string) {
|
export async function readUser(_id: string) {
|
||||||
const data = await prisma.user.findUnique({
|
try {
|
||||||
where: { id: _id }
|
const data = await prisma.user.findUnique({
|
||||||
});
|
where: { id: _id }
|
||||||
|
});
|
||||||
|
|
||||||
if (!data) return null;
|
if (!data) return null;
|
||||||
|
|
||||||
// return {
|
// return {
|
||||||
// _id: data.id,
|
// _id: data.id,
|
||||||
// name: data.name,
|
// name: data.name,
|
||||||
// color: data.color,
|
// color: data.color,
|
||||||
// flags: data.flags
|
// flags: data.flags
|
||||||
// };
|
// };
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
|
} catch (err) {
|
||||||
|
return createUser(_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function updateUser(
|
export async function updateUser(
|
||||||
|
|
|
@ -37,6 +37,7 @@ export class Socket extends EventEmitter {
|
||||||
private id: string;
|
private id: string;
|
||||||
private _id: string;
|
private _id: string;
|
||||||
private ip: string;
|
private ip: string;
|
||||||
|
private uuid: string;
|
||||||
private user: User | null = null;
|
private user: User | null = null;
|
||||||
|
|
||||||
public gateway = new Gateway();
|
public gateway = new Gateway();
|
||||||
|
@ -48,9 +49,9 @@ export class Socket extends EventEmitter {
|
||||||
_id: string | undefined;
|
_id: string | undefined;
|
||||||
set: Partial<IChannelSettings> | undefined;
|
set: Partial<IChannelSettings> | undefined;
|
||||||
} = {
|
} = {
|
||||||
_id: undefined,
|
_id: undefined,
|
||||||
set: {}
|
set: {}
|
||||||
};
|
};
|
||||||
|
|
||||||
public currentChannelID: string | undefined;
|
public currentChannelID: string | undefined;
|
||||||
private cursorPos: Vector2<CursorValue> = { x: 200, y: 100 };
|
private cursorPos: Vector2<CursorValue> = { x: 200, y: 100 };
|
||||||
|
@ -64,19 +65,26 @@ export class Socket extends EventEmitter {
|
||||||
|
|
||||||
// User ID
|
// User ID
|
||||||
this._id = createUserID(this.getIP());
|
this._id = createUserID(this.getIP());
|
||||||
|
this.uuid = crypto.randomUUID();
|
||||||
|
|
||||||
// Check if we're already connected
|
// Check if we're already connected
|
||||||
// We need to skip ourselves, so we loop here instead of using a helper
|
// We need to skip ourselves, so we loop here instead of using a helper
|
||||||
let foundSocket;
|
let foundSocket;
|
||||||
|
let count = 0;
|
||||||
|
|
||||||
for (const socket of socketsBySocketID.values()) {
|
for (const socket of socketsBySocketID.values()) {
|
||||||
if (socket.socketID == this.socketID) continue;
|
if (socket.socketID == this.socketID || socket.ws.readyState !== 1) continue;
|
||||||
|
|
||||||
if (socket.getUserID() == this.getUserID()) {
|
if (socket.getUserID() == this.getUserID()) {
|
||||||
foundSocket = socket;
|
foundSocket = socket;
|
||||||
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (count >= 4) {
|
||||||
|
this.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
// logger.debug("Found socket?", foundSocket);
|
// logger.debug("Found socket?", foundSocket);
|
||||||
|
|
||||||
if (!foundSocket) {
|
if (!foundSocket) {
|
||||||
|
@ -84,11 +92,11 @@ export class Socket extends EventEmitter {
|
||||||
this.id = createID();
|
this.id = createID();
|
||||||
} else {
|
} else {
|
||||||
// Use original session ID
|
// Use original session ID
|
||||||
// this.id = foundSocket.id;
|
this.id = foundSocket.id;
|
||||||
|
|
||||||
// Break us off
|
// Break us off
|
||||||
this.id = "broken";
|
//this.id = "broken";
|
||||||
this.destroy();
|
//this.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
|
@ -460,6 +468,10 @@ export class Socket extends EventEmitter {
|
||||||
channel.kickban(_id, ms);
|
channel.kickban(_id, ms);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getUUID() {
|
||||||
|
return this.uuid;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const socketsBySocketID = new Map<string, Socket>();
|
export const socketsBySocketID = new Map<string, Socket>();
|
||||||
|
|
|
@ -6,6 +6,7 @@ export const color: ServerEventListener<"color"> = {
|
||||||
id: "color",
|
id: "color",
|
||||||
callback: async (msg, socket) => {
|
callback: async (msg, socket) => {
|
||||||
// I'm not allowed to use this feature on MPP.net for a really stupid reason
|
// I'm not allowed to use this feature on MPP.net for a really stupid reason
|
||||||
|
// Nevermind, fishing bot has color again
|
||||||
const id = msg._id;
|
const id = msg._id;
|
||||||
const color = msg.color;
|
const color = msg.color;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
import { Logger } from "../../../../util/Logger";
|
||||||
|
import { ServerEventListener } from "../../../../util/types";
|
||||||
|
|
||||||
|
const logger = new Logger("chown");
|
||||||
|
|
||||||
|
export const chown: ServerEventListener<"chown"> = {
|
||||||
|
id: "chown",
|
||||||
|
callback: (msg, socket) => {
|
||||||
|
// Change channel ownership
|
||||||
|
if (typeof msg.id == "undefined") return;
|
||||||
|
|
||||||
|
|
||||||
|
const ch = socket.getCurrentChannel();
|
||||||
|
if (!ch) return;
|
||||||
|
|
||||||
|
if (!socket.isOwner()) return;
|
||||||
|
|
||||||
|
if (!ch.crown) {
|
||||||
|
// TODO Crown admin stuff
|
||||||
|
} else {
|
||||||
|
if (!ch.crown.canBeSetBy(socket)) return;
|
||||||
|
|
||||||
|
const heir = ch.getParticipantList().find(p => p.id == msg.id);
|
||||||
|
if (!heir) return;
|
||||||
|
|
||||||
|
ch.chown(heir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
|
@ -3,9 +3,9 @@ import { ServerEventListener } from "../../../../util/types";
|
||||||
export const kickban: ServerEventListener<"kickban"> = {
|
export const kickban: ServerEventListener<"kickban"> = {
|
||||||
id: "kickban",
|
id: "kickban",
|
||||||
callback: (msg, socket) => {
|
callback: (msg, socket) => {
|
||||||
// Kickban asshole from channel
|
// Kickbanning some asshole from channel
|
||||||
if (!msg._id) return;
|
if (typeof msg._id !== "string") return;
|
||||||
if (!msg.ms) return;
|
if (typeof msg.ms !== "number") return;
|
||||||
socket.kickban(msg._id, msg.ms);
|
socket.kickban(msg._id, msg.ms);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -15,6 +15,7 @@ import { admin_message } from "./handlers/admin_message";
|
||||||
import { chset } from "./handlers/chset";
|
import { chset } from "./handlers/chset";
|
||||||
import { kickban } from "./handlers/kickban";
|
import { kickban } from "./handlers/kickban";
|
||||||
import { bye } from "./handlers/bye";
|
import { bye } from "./handlers/bye";
|
||||||
|
import { chown } from "./handlers/chown";
|
||||||
|
|
||||||
// Imagine not having an "addMany" function...
|
// Imagine not having an "addMany" function...
|
||||||
|
|
||||||
|
@ -44,7 +45,8 @@ EVENTGROUP_USER.addMany(
|
||||||
admin_message,
|
admin_message,
|
||||||
chset,
|
chset,
|
||||||
kickban,
|
kickban,
|
||||||
bye
|
bye,
|
||||||
|
chown
|
||||||
);
|
);
|
||||||
|
|
||||||
eventGroups.push(EVENTGROUP_USER);
|
eventGroups.push(EVENTGROUP_USER);
|
||||||
|
|
Loading…
Reference in New Issue