From 3a9cfe6127c55d70ee239a9e47907494d749e3cd Mon Sep 17 00:00:00 2001 From: starkatt85 Date: Mon, 12 Jan 2026 15:04:54 +0530 Subject: [PATCH 1/5] add report command [version 1] --- build/scripts/commands/general.js | 66 ++++++++++++++++++++++++++++++- build/scripts/config.js | 1 + src/commands/general.ts | 65 +++++++++++++++++++++++++++++- src/config.ts | 1 + 4 files changed, 131 insertions(+), 2 deletions(-) diff --git a/build/scripts/commands/general.js b/build/scripts/commands/general.js index 20b9d50a..0163e303 100644 --- a/build/scripts/commands/general.js +++ b/build/scripts/commands/general.js @@ -1293,5 +1293,69 @@ exports.commands = (0, commands_1.commandList)(__assign(__assign({ about: { }); }); } + }, report: { + args: [], + description: 'Report a player to staff with a selected reason.', + perm: commands_1.Perm.play, + requirements: [commands_1.Req.cooldown(4000)], + handler: function (_a) { + return __awaiter(this, arguments, void 0, function (_b) { + var onlinePlayers, target, baseReasons, reasons, reason, issuerName, targetName, serverName, message; + var _c, _d, _e; + var sender = _b.sender, outputSuccess = _b.outputSuccess, outputFail = _b.outputFail, f = _b.f; + return __generator(this, function (_f) { + switch (_f.label) { + case 0: + onlinePlayers = (0, funcs_1.setToArray)(Groups.player); + if (onlinePlayers.length === 0) { + outputFail('No players online to report.'); + return [2 /*return*/]; + } + return [4 /*yield*/, menus_1.Menu.menu('Report Player', 'Select a player to report.', onlinePlayers, sender, { + includeCancel: true, + optionStringifier: function (player) { return player.name; } + }).catch(function () { + outputFail('Report cancelled.'); + return; + })]; + case 1: + target = _f.sent(); + if (!target) + return [2 /*return*/]; + baseReasons = [ + 'Griefing', + 'Harassment', + 'Cheating / Exploiting', + 'Spam', + 'Trolling', + 'Other', + ]; + reasons = target.admin ? __spreadArray(__spreadArray([], __read(baseReasons), false), ['Admin Abuse'], false) : baseReasons; + return [4 /*yield*/, menus_1.Menu.menu('Report Reason', "Select a reason for reporting [accent]".concat(target.name, "[]"), reasons, sender, { includeCancel: true }).catch(function () { + outputFail('Report cancelled.'); + return; + })]; + case 2: + reason = _f.sent(); + if (!reason) + return [2 /*return*/]; + issuerName = (_e = (_d = (_c = sender.player) === null || _c === void 0 ? void 0 : _c.name) !== null && _d !== void 0 ? _d : sender.name) !== null && _e !== void 0 ? _e : 'Unknown'; + targetName = target.name; + serverName = config_1.Gamemode.name(); + message = "[Report] Server: ".concat(serverName, "\n") + + "Issuer: ".concat(Strings.stripColors(issuerName), "\n") + + "Target: ".concat(Strings.stripColors(targetName)).concat(target.admin ? ' (Admin)' : '', "\n") + + "Reason: ".concat(reason); + api.sendStaffMessage(message, issuerName, function (sent) { + if (sent) + outputSuccess(f(templateObject_25 || (templateObject_25 = __makeTemplateObject(["Report sent to staff: ", " for \"", "\"."], ["Report sent to staff: ", " for \"", "\"."])), targetName, reason)); + else + outputFail('Failed to send report to staff. Please try again later.'); + }); + return [2 /*return*/]; + } + }); + }); + }, } })); -var templateObject_1, templateObject_2, templateObject_3, templateObject_4, templateObject_5, templateObject_6, templateObject_7, templateObject_8, templateObject_9, templateObject_10, templateObject_11, templateObject_12, templateObject_13, templateObject_14, templateObject_15, templateObject_16, templateObject_17, templateObject_18, templateObject_19, templateObject_20, templateObject_21, templateObject_22, templateObject_23, templateObject_24; +var templateObject_1, templateObject_2, templateObject_3, templateObject_4, templateObject_5, templateObject_6, templateObject_7, templateObject_8, templateObject_9, templateObject_10, templateObject_11, templateObject_12, templateObject_13, templateObject_14, templateObject_15, templateObject_16, templateObject_17, templateObject_18, templateObject_19, templateObject_20, templateObject_21, templateObject_22, templateObject_23, templateObject_24, templateObject_25; diff --git a/build/scripts/config.js b/build/scripts/config.js index 1beb6e89..a79e99a6 100644 --- a/build/scripts/config.js +++ b/build/scripts/config.js @@ -56,6 +56,7 @@ exports.bannedWords = { "fanum tax", "gyatt", "rizz", "skibidi", //With love, DarthScion //>:( -dart "uwu", //lol + // why?? why the uwu??? -starkatt "nig" + "ger", "nig" + "ga", "niger", "ni8" + "8er", "nig" + "gre", //our apologies to citizens of the Republic of Niger "негр", "ниггер", "re" + "tard", diff --git a/src/commands/general.ts b/src/commands/general.ts index 12d4c039..2742fec4 100644 --- a/src/commands/general.ts +++ b/src/commands/general.ts @@ -9,7 +9,7 @@ import { FColor, FishServer, Gamemode, rules, text } from "/config"; import { command, commandList, fail, formatArg, Perm, Req } from "/frameworks/commands"; import type { FishCommandData } from "/frameworks/commands/types"; import { Menu } from "/frameworks/menus"; -import { capitalizeText, Duration, escapeTextDiscord, StringBuilder, StringIO, to2DArray } from "/funcs"; +import { capitalizeText, Duration, escapeTextDiscord, StringBuilder, StringIO, to2DArray, setToArray } from "/funcs"; import { FishEvents, fishPlugin, fishState, ipPortPattern, recentWhispers, tileHistory, uuidPattern } from "/globals"; import { FMap } from "/maps"; import { FishPlayer } from "/players"; @@ -1237,5 +1237,68 @@ ${a.hidden ? "This achievement is secret." : ""}\ } } }, + + report: { + args: [], + description: 'Report a player to staff with a selected reason.', + perm: Perm.play, + requirements: [Req.cooldown(4000)], + async handler({sender, outputSuccess, outputFail, f}) { + const onlinePlayers = setToArray(Groups.player); + if(onlinePlayers.length === 0){ + outputFail('No players online to report.'); + return; + } + const target = await Menu.menu( + 'Report Player', + 'Select a player to report.', + onlinePlayers, + sender, + { + includeCancel: true, + optionStringifier: player => player.name + } + ).catch(() => { + outputFail('Report cancelled.'); + return; + }); + if(!target) return; + + const baseReasons = [ + 'Griefing', + 'Harassment', + 'Cheating / Exploiting', + 'Spam', + 'Trolling', + 'Other', + ]; + const reasons = target.admin ? [...baseReasons, 'Admin Abuse'] : baseReasons; + const reason = await Menu.menu( + 'Report Reason', + `Select a reason for reporting [accent]${target.name}[]`, + reasons, + sender, + { includeCancel: true } + ).catch(() => { + outputFail('Report cancelled.'); + return; + }); + if(!reason) return; + + const issuerName = sender.player?.name ?? sender.name ?? 'Unknown'; + const targetName = target.name; + const serverName = Gamemode.name(); + const message = + `[Report] Server: ${serverName}\n` + + `Issuer: ${Strings.stripColors(issuerName)}\n` + + `Target: ${Strings.stripColors(targetName)}${target.admin ? ' (Admin)' : ''}\n` + + `Reason: ${reason}`; + + api.sendStaffMessage(message, issuerName, (sent) => { + if(sent) outputSuccess(f`Report sent to staff: ${targetName} for "${reason}".`); + else outputFail('Failed to send report to staff. Please try again later.'); + }); + }, + } }); diff --git a/src/config.ts b/src/config.ts index e0fb1653..cc3e09be 100644 --- a/src/config.ts +++ b/src/config.ts @@ -38,6 +38,7 @@ export const bannedWords: { "fanum tax", "gyatt", "rizz", "skibidi", //With love, DarthScion //>:( -dart "uwu", //lol + // why?? why the uwu??? -starkatt "nig"+"ger", "nig"+"ga", "niger", "ni8"+"8er", "nig"+"gre", //our apologies to citizens of the Republic of Niger "негр", "ниггер", From 3248291352f3c993aac67e9e17e781dab9dbca68 Mon Sep 17 00:00:00 2001 From: StarKatt85 <88882746+starkatt85@users.noreply.github.com> Date: Mon, 12 Jan 2026 15:20:17 +0530 Subject: [PATCH 2/5] simplify issuerName fallback chain Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/commands/general.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/general.ts b/src/commands/general.ts index 2742fec4..122332b9 100644 --- a/src/commands/general.ts +++ b/src/commands/general.ts @@ -1285,7 +1285,7 @@ ${a.hidden ? "This achievement is secret." : ""}\ }); if(!reason) return; - const issuerName = sender.player?.name ?? sender.name ?? 'Unknown'; + const issuerName = sender.player?.name ?? 'Unknown'; const targetName = target.name; const serverName = Gamemode.name(); const message = From c4bfa6ab4e7af32c5b6bcaae2f48df2b2a59ee43 Mon Sep 17 00:00:00 2001 From: StarKatt85 <88882746+starkatt85@users.noreply.github.com> Date: Mon, 12 Jan 2026 15:22:20 +0530 Subject: [PATCH 3/5] prevent self-report Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/commands/general.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/commands/general.ts b/src/commands/general.ts index 122332b9..ee011ca5 100644 --- a/src/commands/general.ts +++ b/src/commands/general.ts @@ -1263,6 +1263,10 @@ ${a.hidden ? "This achievement is secret." : ""}\ return; }); if(!target) return; + if(target === sender.player){ + outputFail('You cannot report yourself.'); + return; + } const baseReasons = [ 'Griefing', From fb1f0496ae8fa1a788b7326c71f77ae8e87f50ca Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 12 Jan 2026 10:27:25 +0000 Subject: [PATCH 4/5] Automated TypeScript compile / lint --- build/scripts/commands/general.js | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/build/scripts/commands/general.js b/build/scripts/commands/general.js index 0163e303..7f0b6fe5 100644 --- a/build/scripts/commands/general.js +++ b/build/scripts/commands/general.js @@ -1301,10 +1301,10 @@ exports.commands = (0, commands_1.commandList)(__assign(__assign({ about: { handler: function (_a) { return __awaiter(this, arguments, void 0, function (_b) { var onlinePlayers, target, baseReasons, reasons, reason, issuerName, targetName, serverName, message; - var _c, _d, _e; + var _c, _d; var sender = _b.sender, outputSuccess = _b.outputSuccess, outputFail = _b.outputFail, f = _b.f; - return __generator(this, function (_f) { - switch (_f.label) { + return __generator(this, function (_e) { + switch (_e.label) { case 0: onlinePlayers = (0, funcs_1.setToArray)(Groups.player); if (onlinePlayers.length === 0) { @@ -1319,9 +1319,13 @@ exports.commands = (0, commands_1.commandList)(__assign(__assign({ about: { return; })]; case 1: - target = _f.sent(); + target = _e.sent(); if (!target) return [2 /*return*/]; + if (target === sender.player) { + outputFail('You cannot report yourself.'); + return [2 /*return*/]; + } baseReasons = [ 'Griefing', 'Harassment', @@ -1336,10 +1340,10 @@ exports.commands = (0, commands_1.commandList)(__assign(__assign({ about: { return; })]; case 2: - reason = _f.sent(); + reason = _e.sent(); if (!reason) return [2 /*return*/]; - issuerName = (_e = (_d = (_c = sender.player) === null || _c === void 0 ? void 0 : _c.name) !== null && _d !== void 0 ? _d : sender.name) !== null && _e !== void 0 ? _e : 'Unknown'; + issuerName = (_d = (_c = sender.player) === null || _c === void 0 ? void 0 : _c.name) !== null && _d !== void 0 ? _d : 'Unknown'; targetName = target.name; serverName = config_1.Gamemode.name(); message = "[Report] Server: ".concat(serverName, "\n") + From 2a8678d65a8a2f2434a6f5a37853b7f46881dcb7 Mon Sep 17 00:00:00 2001 From: BalaM314 <71201189+BalaM314@users.noreply.github.com> Date: Sat, 28 Feb 2026 13:16:56 -0500 Subject: [PATCH 5/5] PR fixes * remove unnecessary code, use existing systems * ping reports * increase cooldown to 2 minutes * no reporting managers * change reasons * call escapeTextDiscord * don't allow muted players to report --- build/scripts/commands/general.js | 79 ++++++++++++------------------- src/commands/general.ts | 78 +++++++++++------------------- 2 files changed, 57 insertions(+), 100 deletions(-) diff --git a/build/scripts/commands/general.js b/build/scripts/commands/general.js index 7f0b6fe5..cbf9b15f 100644 --- a/build/scripts/commands/general.js +++ b/build/scripts/commands/general.js @@ -1294,65 +1294,46 @@ exports.commands = (0, commands_1.commandList)(__assign(__assign({ about: { }); } }, report: { - args: [], + args: ["target:player"], description: 'Report a player to staff with a selected reason.', - perm: commands_1.Perm.play, - requirements: [commands_1.Req.cooldown(4000)], + perm: commands_1.Perm.chat, + requirements: function (_a) { + var sender = _a.sender; + return sender.hasPerm("trusted") ? [commands_1.Req.cooldown(5000)] : [commands_1.Req.cooldown(funcs_1.Duration.minutes(2))]; + }, handler: function (_a) { return __awaiter(this, arguments, void 0, function (_b) { - var onlinePlayers, target, baseReasons, reasons, reason, issuerName, targetName, serverName, message; - var _c, _d; - var sender = _b.sender, outputSuccess = _b.outputSuccess, outputFail = _b.outputFail, f = _b.f; - return __generator(this, function (_e) { - switch (_e.label) { + var reasons, reason, message; + var target = _b.args.target, sender = _b.sender, outputSuccess = _b.outputSuccess, outputFail = _b.outputFail, f = _b.f; + return __generator(this, function (_c) { + switch (_c.label) { case 0: - onlinePlayers = (0, funcs_1.setToArray)(Groups.player); - if (onlinePlayers.length === 0) { - outputFail('No players online to report.'); - return [2 /*return*/]; - } - return [4 /*yield*/, menus_1.Menu.menu('Report Player', 'Select a player to report.', onlinePlayers, sender, { - includeCancel: true, - optionStringifier: function (player) { return player.name; } - }).catch(function () { - outputFail('Report cancelled.'); - return; - })]; - case 1: - target = _e.sent(); - if (!target) - return [2 /*return*/]; - if (target === sender.player) { - outputFail('You cannot report yourself.'); - return [2 /*return*/]; - } - baseReasons = [ + if (target === sender) + (0, commands_1.fail)('You cannot report yourself.'); + if (target.ranksAtLeast("manager")) + (0, commands_1.fail)("This user cannot be reported in-game."); + reasons = [ 'Griefing', + 'False votekick', 'Harassment', - 'Cheating / Exploiting', + 'Inappropriate content', 'Spam', - 'Trolling', - 'Other', + 'Other', //TODO: use the text input menu ]; - reasons = target.admin ? __spreadArray(__spreadArray([], __read(baseReasons), false), ['Admin Abuse'], false) : baseReasons; - return [4 /*yield*/, menus_1.Menu.menu('Report Reason', "Select a reason for reporting [accent]".concat(target.name, "[]"), reasons, sender, { includeCancel: true }).catch(function () { - outputFail('Report cancelled.'); - return; - })]; + if (target.hasPerm("mod")) + reasons.push('Admin Abuse'); + if (config_1.Gamemode.sandbox()) + reasons.push("Lag machine"); + return [4 /*yield*/, menus_1.Menu.menu('Report Reason', "Select a reason for reporting ".concat(target.name), reasons, sender, { includeCancel: true })]; + case 1: + reason = _c.sent(); + return [4 /*yield*/, menus_1.Menu.confirm(sender, "Are you sure you want to report player ".concat(target.cleanedName, "? This action will notify staff members."))]; case 2: - reason = _e.sent(); - if (!reason) - return [2 /*return*/]; - issuerName = (_d = (_c = sender.player) === null || _c === void 0 ? void 0 : _c.name) !== null && _d !== void 0 ? _d : 'Unknown'; - targetName = target.name; - serverName = config_1.Gamemode.name(); - message = "[Report] Server: ".concat(serverName, "\n") + - "Issuer: ".concat(Strings.stripColors(issuerName), "\n") + - "Target: ".concat(Strings.stripColors(targetName)).concat(target.admin ? ' (Admin)' : '', "\n") + - "Reason: ".concat(reason); - api.sendStaffMessage(message, issuerName, function (sent) { + _c.sent(); + message = (0, funcs_1.escapeTextDiscord)("[In-game report] Server: ".concat(config_1.Gamemode.name(), "\nIssuer: ").concat(sender.cleanedName, "\nTarget: ").concat(target.cleanedName).concat(target.hasPerm("mod") ? ' (Admin)' : '', "\nReason: ").concat(reason, "\n").concat(config_1.text.reportsPing)); + api.sendStaffMessage(message, sender.name, function (sent) { if (sent) - outputSuccess(f(templateObject_25 || (templateObject_25 = __makeTemplateObject(["Report sent to staff: ", " for \"", "\"."], ["Report sent to staff: ", " for \"", "\"."])), targetName, reason)); + outputSuccess(f(templateObject_25 || (templateObject_25 = __makeTemplateObject(["Report sent to staff: ", " for \"", "\"."], ["Report sent to staff: ", " for \"", "\"."])), target.name, reason)); else outputFail('Failed to send report to staff. Please try again later.'); }); diff --git a/src/commands/general.ts b/src/commands/general.ts index ee011ca5..d700e773 100644 --- a/src/commands/general.ts +++ b/src/commands/general.ts @@ -1239,67 +1239,43 @@ ${a.hidden ? "This achievement is secret." : ""}\ }, report: { - args: [], + args: ["target:player"], description: 'Report a player to staff with a selected reason.', - perm: Perm.play, - requirements: [Req.cooldown(4000)], - async handler({sender, outputSuccess, outputFail, f}) { - const onlinePlayers = setToArray(Groups.player); - if(onlinePlayers.length === 0){ - outputFail('No players online to report.'); - return; - } - const target = await Menu.menu( - 'Report Player', - 'Select a player to report.', - onlinePlayers, - sender, - { - includeCancel: true, - optionStringifier: player => player.name - } - ).catch(() => { - outputFail('Report cancelled.'); - return; - }); - if(!target) return; - if(target === sender.player){ - outputFail('You cannot report yourself.'); - return; - } + perm: Perm.chat, + requirements: ({sender}) => sender.hasPerm("trusted") ? [Req.cooldown(5_000)] : [Req.cooldown(Duration.minutes(2))], + async handler({args: {target}, sender, outputSuccess, outputFail, f}) { + if(target === sender) fail('You cannot report yourself.'); + if(target.ranksAtLeast("manager")) fail(`This user cannot be reported in-game.`); - const baseReasons = [ + const reasons = [ 'Griefing', + 'False votekick', 'Harassment', - 'Cheating / Exploiting', + 'Inappropriate content', 'Spam', - 'Trolling', - 'Other', + 'Other', //TODO: use the text input menu ]; - const reasons = target.admin ? [...baseReasons, 'Admin Abuse'] : baseReasons; - const reason = await Menu.menu( + if(target.hasPerm("mod")) reasons.push('Admin Abuse'); + if(Gamemode.sandbox()) reasons.push("Lag machine"); + const reason = await Menu.menu( 'Report Reason', - `Select a reason for reporting [accent]${target.name}[]`, + `Select a reason for reporting ${target.name}`, reasons, sender, { includeCancel: true } - ).catch(() => { - outputFail('Report cancelled.'); - return; - }); - if(!reason) return; - - const issuerName = sender.player?.name ?? 'Unknown'; - const targetName = target.name; - const serverName = Gamemode.name(); - const message = - `[Report] Server: ${serverName}\n` + - `Issuer: ${Strings.stripColors(issuerName)}\n` + - `Target: ${Strings.stripColors(targetName)}${target.admin ? ' (Admin)' : ''}\n` + - `Reason: ${reason}`; - - api.sendStaffMessage(message, issuerName, (sent) => { - if(sent) outputSuccess(f`Report sent to staff: ${targetName} for "${reason}".`); + ); + + await Menu.confirm(sender, `Are you sure you want to report player ${target.cleanedName}? This action will notify staff members.`); + + const message = escapeTextDiscord( +`[In-game report] Server: ${Gamemode.name()} +Issuer: ${sender.cleanedName} +Target: ${target.cleanedName}${target.hasPerm("mod") ? ' (Admin)' : ''} +Reason: ${reason} +${text.reportsPing}`); + + api.sendStaffMessage(message, sender.name, (sent) => { + if(sent) outputSuccess(f`Report sent to staff: ${target.name} for "${reason}".`); else outputFail('Failed to send report to staff. Please try again later.'); }); },