Implement basic tag system

This commit is contained in:
Hri7566 2024-08-03 01:00:20 -04:00
parent 828443cb93
commit 9b48d41bd8
9 changed files with 87 additions and 39 deletions

View File

@ -20,10 +20,12 @@ Brandon's server originally used MongoDB for storing user data, but there are to
- Chat
- Original chat filter by chacha and Brandon Lockaby
- Commands for debugging or administrative purposes
- Piano Notes
- Uses the same `NoteQuota` implementation from the client
- Usernames/colors
- Allowing color changing can be toggled in the config
- Allowing color changing can be toggled in the config, similar to MPP.com
- Default user parameters can be set
- Channels
- Channel list
- Channel settings
@ -37,20 +39,32 @@ Brandon's server originally used MongoDB for storing user data, but there are to
- Chat muting
- Rate limit bypasses
- Channel/User-targeted notifications
- Server-wide/channel-specific/user-specific notifications
- New admin messages
- Restart message
- Triggers notification on every connected socket, then shuts down after 20 seconds
- Server must be setup as a pm2/docker/systemd process
- Server must be setup as a pm2/docker/systemd process for automatic restarting
- Ability to change tags
## TODO
- Fully implement and test tags
- Tags are sent to clients now
- Check if tags are sent to everyone
- Permission groups and permissions
- Probable permission groups: owner, admin, mod, trialmod, default
- Setup tags for each permission group
- Full server-wide event bus
- Channel events
- Socket events
- User data events
- Permission-related events
- Redo all of the validations with Zod
- This probably means making Zod schemas for every single message type
- Also user and channel data
- Test every frontend
- Test fishing bot
- Remote console
## Backlog/Notes

View File

@ -7,13 +7,17 @@ defaultFlags:
# Whether or not to allow users to change their color.
# Brandon's server has this set to false, but multiple users have reported it to be on before 2016.
enableColorChanging: false
enableColorChanging: true
# Allows custom data inside note messages.
# This was in the original server, but not in MPP.net's server.
# This only exists for backwards compatibility with scripts like nagalun's drarwing script.
enableCustomNoteData: true
# Whether or not to enable tags that are sent publicly.
# This won't prevent admins from changing tags internally, but it will not be sent to clients.
enableTags: true
# This is the user data that the server will use to send admin chat messages with.
adminParticipant:
_id: "0"
@ -27,11 +31,11 @@ enableAdminEval: true
# The token validation scheme. Valid values are "none", "jwt" and "uuid".
# This server will still validate existing tokens generated with other schemes if not set to "none".
tokenAuth: none
tokenAuth: jwt
# The browser challenge scheme. Valid values are "none", "obf" and "basic".
# This is to change what is sent in the "b" message.
# "none" will disable the browser challenge,
# "obf" will sent an obfuscated function to the client,
# and "basic" will just send a simple function that expects a boolean.
browserChallenge: none
browserChallenge: basic

View File

@ -88,7 +88,7 @@ export class Channel extends EventEmitter {
(typeof set.color2 == "undefined" ||
set.color2 === this.settings.color2)
) {
this.logger.debug("color 2 darken triggered");
//this.logger.debug("color 2 darken triggered");
set.color2 = darken(set.color);
}
@ -97,7 +97,7 @@ export class Channel extends EventEmitter {
// Set the verified settings
for (const key of Object.keys(validatedSet)) {
this.logger.debug(`${key}: ${(validatedSet as any)[key]}`);
//this.logger.debug(`${key}: ${(validatedSet as any)[key]}`);
if ((validatedSet as any)[key] === false) continue;
(this.settings as any)[key] = (set as any)[key];
}
@ -480,7 +480,7 @@ export class Channel extends EventEmitter {
if (this.isTrueLobby()) {
// Get the next lobby number
const nextID = this.getNextLobbyID();
this.logger.debug("New ID:", nextID);
//this.logger.debug("New ID:", nextID);
// Move them to the next lobby
return socket.setChannel(nextID);
}
@ -691,7 +691,7 @@ export class Channel extends EventEmitter {
name: p.name,
color: p.color,
id: p.id,
tag: config.sendTags ? p.tag : undefined
tag: usersConfig.enableTags ? p.tag : undefined
});
}

View File

@ -20,31 +20,6 @@ loadForcedStartupChannels();
// This literally breaks editors and they stick all the imports here instead of at the top
import "./util/readline";
import { Socket, socketsBySocketID } from "./ws/Socket";
import { createSocketID } from "./util/id";
// Nevermind we use it twice
logger.info("Ready");
// Connect 5 sockets
const sockets = [];
for (let i = 0; i < 5; i++) {
setTimeout(() => {
const socket = new Socket(undefined, createSocketID());
socket.on("ready", () => {
logger.info(`Socket ${i} is ready`);
});
socket.setChannel("lobby");
sockets.push(socket);
if (socket.socketID == undefined) {
socket.socketID = createSocketID();
}
socketsBySocketID.set(socket.socketID, socket);
}, i * 5000);
}

View File

@ -1,10 +1,19 @@
import EventEmitter from "events";
import { padNum, unimportant } from "./helpers";
export const logEvents = new EventEmitter();
/**
* A logger that doesn't fuck with the readline prompt
* timestamps are likely wrong because of js timezones
**/
export class Logger {
/**
* Log a message
* This does weird prompt things
* @param method The method from `console` to use
* @param args The data to print
**/
private static log(method: string, ...args: any[]) {
// Un-fuck the readline prompt
process.stdout.write("\x1b[2K\r");
@ -21,8 +30,15 @@ export class Logger {
// Re-print the readline prompt (spooky cringe global variable)
if ((globalThis as unknown as any).rl)
(globalThis as unknown as any).rl.prompt();
// Emit the log event for remote consoles
logEvents.emit("log", method, unimportant(this.getDate()), unimportant(this.getHHMMSSMS()), args);
}
/**
* Get the current time in HH:MM:SS.MS format
* @returns The current time in HH:MM:SS.MS format
**/
public static getHHMMSSMS() {
const ms = Date.now();
@ -38,24 +54,44 @@ export class Logger {
return `${hh}:${mm}:${ss}.${ll}`;
}
/**
* Get the current date in ISO format
* @returns The current date in ISO format
**/
public static getDate() {
return new Date().toISOString().split("T")[0];
}
constructor(public id: string) { }
/**
* Print an info message
* @param args The data to print
**/
public info(...args: any[]) {
Logger.log("log", `[${this.id}]`, `\x1b[34m[info]\x1b[0m`, ...args);
}
/**
* Print an error message
* @param args The data to print
**/
public error(...args: any[]) {
Logger.log("error", `[${this.id}]`, `\x1b[31m[error]\x1b[0m`, ...args);
}
/**
* Print a warning message
* @param args The data to print
**/
public warn(...args: any[]) {
Logger.log("warn", `[${this.id}]`, `\x1b[33m[warn]\x1b[0m`, ...args);
}
/**
* Print a debug message
* @param args The data to print
**/
public debug(...args: any[]) {
Logger.log("debug", `[${this.id}]`, `\x1b[32m[debug]\x1b[0m`, ...args);
}

View File

@ -14,7 +14,8 @@ import {
ServerEvents,
UserFlags,
Vector2,
Notification
Notification,
Tag
} from "../util/types";
import type { User } from "@prisma/client";
import { createUser, readUser, updateUser } from "../data/user";
@ -355,11 +356,20 @@ export class Socket extends EventEmitter {
}
}
let tag: Tag | undefined;
try {
tag = JSON.parse(this.user.tag) as Tag;
} catch (err) {
logger.warn("Unable to parse tag:", err);
}
return {
_id: facadeID,
name: this.user.name,
color: this.user.color,
id: this.getParticipantID()
id: this.getParticipantID(),
tag: config.enableTags ? tag : undefined
};
} else {
return null;
@ -744,6 +754,7 @@ export class Socket extends EventEmitter {
* @param color Color of the tag
**/
public setTag(text: string, color: string) {
//logger.debug("Setting tag:", text, color);
const user = this.getUser();
if (!user) return;
user.tag = JSON.stringify({ text, color });

View File

@ -11,6 +11,7 @@ import { name } from "./handlers/name";
import { notification } from "./handlers/notification";
import { rename_channel } from "./handlers/rename_channel";
import { restart } from "./handlers/restart";
import { tag } from "./handlers/tag";
import { user_flag } from "./handlers/user_flag";
// EVENT_GROUP_ADMIN.add(color);
@ -27,7 +28,8 @@ EVENT_GROUP_ADMIN.addMany(
move,
rename_channel,
admin_chat,
eval_msg
eval_msg,
tag
);
eventGroups.push(EVENT_GROUP_ADMIN);

View File

@ -65,10 +65,13 @@ export const hi: ServerEventListener<"hi"> = {
_id: socket.getUserID(),
name: "Anonymous",
color: "#777",
id: ""
id: "",
tag: undefined
};
}
logger.debug("Tag:", part.tag);
socket.sendArray([{
m: "hi",
accountInfo: undefined,
@ -77,7 +80,8 @@ export const hi: ServerEventListener<"hi"> = {
u: {
_id: part._id,
color: part.color,
name: part.name
name: part.name,
tag: part.tag
},
motd: getMOTD(),
token

View File

@ -6,6 +6,7 @@ export interface UsersConfig {
defaultFlags: UserFlags;
enableColorChanging: boolean;
enableCustomNoteData: boolean;
enableTags: boolean;
adminParticipant: Participant;
enableAdminEval: boolean;
tokenAuth: "jwt" | "uuid" | "none";
@ -21,6 +22,7 @@ export const defaultUsersConfig: UsersConfig = {
},
enableColorChanging: false,
enableCustomNoteData: true,
enableTags: false,
adminParticipant: {
_id: "0",
name: "mpp",