From a0eaddbdab4ea4d786d95d38f514e5c77c5d926b Mon Sep 17 00:00:00 2001 From: xVye Date: Sun, 31 Aug 2025 11:28:31 +0200 Subject: [PATCH 1/2] feat: log chats from muted players --- .../migration.sql | 12 ++++++ prisma/multiworld/schema.prisma | 2 + .../migration.sql | 38 +++++++++++++++++++ prisma/singleworld/schema.prisma | 2 + src/db/types.ts | 2 + .../client/handler/MessagePrivateHandler.ts | 17 +++++---- .../client/handler/MessagePublicHandler.ts | 11 +++--- src/server/friend/FriendServer.ts | 12 ++++-- 8 files changed, 81 insertions(+), 15 deletions(-) create mode 100644 prisma/multiworld/migrations/20250831072837_log_chat_muted/migration.sql create mode 100644 prisma/singleworld/migrations/20250831072931_log_chat_muted/migration.sql diff --git a/prisma/multiworld/migrations/20250831072837_log_chat_muted/migration.sql b/prisma/multiworld/migrations/20250831072837_log_chat_muted/migration.sql new file mode 100644 index 000000000..c1b8b5266 --- /dev/null +++ b/prisma/multiworld/migrations/20250831072837_log_chat_muted/migration.sql @@ -0,0 +1,12 @@ +/* + Warnings: + + - Added the required column `muted` to the `private_chat` table without a default value. This is not possible if the table is not empty. + - Added the required column `muted` to the `public_chat` table without a default value. This is not possible if the table is not empty. + +*/ +-- AlterTable +ALTER TABLE `private_chat` ADD COLUMN `muted` BOOLEAN NOT NULL; + +-- AlterTable +ALTER TABLE `public_chat` ADD COLUMN `muted` BOOLEAN NOT NULL; diff --git a/prisma/multiworld/schema.prisma b/prisma/multiworld/schema.prisma index da67c5f1f..f947cf6df 100644 --- a/prisma/multiworld/schema.prisma +++ b/prisma/multiworld/schema.prisma @@ -207,6 +207,7 @@ model public_chat { timestamp DateTime coord Int message String + muted Boolean } model private_chat { @@ -219,6 +220,7 @@ model private_chat { coord Int to_account_id Int message String + muted Boolean } model report { diff --git a/prisma/singleworld/migrations/20250831072931_log_chat_muted/migration.sql b/prisma/singleworld/migrations/20250831072931_log_chat_muted/migration.sql new file mode 100644 index 000000000..9c1af70f0 --- /dev/null +++ b/prisma/singleworld/migrations/20250831072931_log_chat_muted/migration.sql @@ -0,0 +1,38 @@ +/* + Warnings: + + - Added the required column `muted` to the `private_chat` table without a default value. This is not possible if the table is not empty. + - Added the required column `muted` to the `public_chat` table without a default value. This is not possible if the table is not empty. + +*/ +-- RedefineTables +PRAGMA defer_foreign_keys=ON; +PRAGMA foreign_keys=OFF; +CREATE TABLE "new_private_chat" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "account_id" INTEGER NOT NULL, + "profile" TEXT NOT NULL, + "timestamp" DATETIME NOT NULL, + "coord" INTEGER NOT NULL, + "to_account_id" INTEGER NOT NULL, + "message" TEXT NOT NULL, + "muted" BOOLEAN NOT NULL +); +INSERT INTO "new_private_chat" ("account_id", "coord", "id", "message", "profile", "timestamp", "to_account_id") SELECT "account_id", "coord", "id", "message", "profile", "timestamp", "to_account_id" FROM "private_chat"; +DROP TABLE "private_chat"; +ALTER TABLE "new_private_chat" RENAME TO "private_chat"; +CREATE TABLE "new_public_chat" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "account_id" INTEGER NOT NULL, + "profile" TEXT NOT NULL, + "world" INTEGER NOT NULL, + "timestamp" DATETIME NOT NULL, + "coord" INTEGER NOT NULL, + "message" TEXT NOT NULL, + "muted" BOOLEAN NOT NULL +); +INSERT INTO "new_public_chat" ("account_id", "coord", "id", "message", "profile", "timestamp", "world") SELECT "account_id", "coord", "id", "message", "profile", "timestamp", "world" FROM "public_chat"; +DROP TABLE "public_chat"; +ALTER TABLE "new_public_chat" RENAME TO "public_chat"; +PRAGMA foreign_keys=ON; +PRAGMA defer_foreign_keys=OFF; diff --git a/prisma/singleworld/schema.prisma b/prisma/singleworld/schema.prisma index eb793c0a2..9035b95ac 100644 --- a/prisma/singleworld/schema.prisma +++ b/prisma/singleworld/schema.prisma @@ -208,6 +208,7 @@ model public_chat { timestamp DateTime coord Int message String + muted Boolean } model private_chat { @@ -220,6 +221,7 @@ model private_chat { coord Int to_account_id Int message String + muted Boolean } model report { diff --git a/src/db/types.ts b/src/db/types.ts index c4f150594..d2a2c688c 100644 --- a/src/db/types.ts +++ b/src/db/types.ts @@ -161,6 +161,7 @@ export type private_chat = { coord: number; to_account_id: number; message: string; + muted: number; }; export type public_chat = { id: Generated; @@ -170,6 +171,7 @@ export type public_chat = { timestamp: string; coord: number; message: string; + muted: number; }; export type report = { id: Generated; diff --git a/src/network/game/client/handler/MessagePrivateHandler.ts b/src/network/game/client/handler/MessagePrivateHandler.ts index 548e3ba77..ed7073a68 100644 --- a/src/network/game/client/handler/MessagePrivateHandler.ts +++ b/src/network/game/client/handler/MessagePrivateHandler.ts @@ -15,8 +15,15 @@ export default class MessagePrivateHandler extends MessageHandler new Date()) { - // todo: do we still log their attempt to chat? + World.sendPrivateMessage(player, username, unpacked); return false; } @@ -24,12 +31,8 @@ export default class MessagePrivateHandler extends MessageHandler { @@ -16,17 +17,17 @@ export default class MessagePublicHandler extends MessageHandler return false; } - if (player.muted_until !== null && player.muted_until > new Date()) { - // todo: do we still log their attempt to chat? - return false; - } - const buf: Packet = Packet.alloc(0); buf.pdata(input, 0, input.length); buf.pos = 0; const unpack: string = WordPack.unpack(buf, input.length); buf.release(); + if (player.muted_until !== null && player.muted_until > new Date()) { + World.logPublicChat(player, unpack); + return false; + } + player.messageColor = color; player.messageEffect = effect; player.messageType = Math.min(player.staffModLevel, 2); diff --git a/src/server/friend/FriendServer.ts b/src/server/friend/FriendServer.ts index 3fbde67e5..27a68d735 100644 --- a/src/server/friend/FriendServer.ts +++ b/src/server/friend/FriendServer.ts @@ -274,6 +274,7 @@ export class FriendServer { const from = await db.selectFrom('account').selectAll().where('username', '=', fromBase37(username37)).executeTakeFirstOrThrow(); const to = await db.selectFrom('account').selectAll().where('username', '=', fromBase37(targetUsername37)).executeTakeFirstOrThrow(); + const muted = from.muted_until !== null && new Date(from.muted_until) > new Date() ? 1 : 0; await db .insertInto('private_chat') @@ -283,15 +284,19 @@ export class FriendServer { to_account_id: to.id, timestamp: toDbDate(Date.now()), coord: message.coord, - message: chat + message: chat, + muted }) .execute(); - await this.sendPrivateMessage(profile, username37, staffLvl, pmId, targetUsername37, chat); + if (!muted) { + await this.sendPrivateMessage(profile, username37, staffLvl, pmId, targetUsername37, chat); + } } else if (type === FriendsClientOpcodes.PUBLIC_CHAT_LOG) { const { nodeId, nodeTime, profile, username, coord, chat } = message; const from = await db.selectFrom('account').selectAll().where('username', '=', username).executeTakeFirstOrThrow(); + const muted = from.muted_until !== null && new Date(from.muted_until) > new Date() ? 1 : 0; await db .insertInto('public_chat') @@ -302,7 +307,8 @@ export class FriendServer { timestamp: toDbDate(nodeTime), coord, - message: chat + message: chat, + muted }) .execute(); } else if (type === FriendsClientOpcodes.RELAY_MUTE) { From 04cc6b634c1a32903fbd89a1a2b4f04581527707 Mon Sep 17 00:00:00 2001 From: xVye Date: Sun, 31 Aug 2025 12:01:02 +0200 Subject: [PATCH 2/2] fix: invalid_name should be checked before attempting to send a message --- src/engine/World.ts | 2 +- .../client/handler/MessagePrivateHandler.ts | 20 ++++++++----------- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/src/engine/World.ts b/src/engine/World.ts index 5ac8a815e..43f08dff6 100644 --- a/src/engine/World.ts +++ b/src/engine/World.ts @@ -1663,7 +1663,7 @@ class World { } } - sendPrivateMessage(player: Player, targetUsername37: bigint, message: string): void { + attemptPrivateMessage(player: Player, targetUsername37: bigint, message: string): void { //printDebug(`[World] sendPrivateMessage => player: ${player.username}, target: ${targetUsername37} (${fromBase37(targetUsername37)}), message: '${message}'`); this.friendThread.postMessage({ diff --git a/src/network/game/client/handler/MessagePrivateHandler.ts b/src/network/game/client/handler/MessagePrivateHandler.ts index ed7073a68..0f22d50d1 100644 --- a/src/network/game/client/handler/MessagePrivateHandler.ts +++ b/src/network/game/client/handler/MessagePrivateHandler.ts @@ -15,26 +15,22 @@ export default class MessagePrivateHandler extends MessageHandler new Date()) { - World.sendPrivateMessage(player, username, unpacked); - return false; - } + player.socialProtect = true; - if (fromBase37(username) === 'invalid_name') { - World.notifyPlayerBan('automated', player.username, Date.now() + 172800000); + if (player.muted_until !== null && player.muted_until > new Date()) { return false; } - - World.sendPrivateMessage(player, username, unpacked); - - player.socialProtect = true; return true; } }