Files
keiko/src/events/threadUpdate.ts
T
hikari 453ebd0f15
Node.js CI / CI (push) Successful in 28s
Security Scan and Upload / Security & DefectDojo Upload (push) Successful in 2m12s
feat: sanction DM links and per-event colour coding (#13)
## Summary

- Adds resource links (appeal form, sanction logs, contact page, community invite) to all sanction DMs, separated from the sanction text by a Components v2 separator
- Adds a unique accent colour for every mod log and activity log event type, giving each action a distinct visual identity at a glance

## Changes

- `src/utils/components.ts` — Added `sanctionDmMessage` helper with two-section container (sanction text + links); added full `Colours` palette covering all sanction and activity event types; added `ColourKey` export
- `src/commands/{ban,kick,mute,softban,warn}.ts` — Updated DMs to use `sanctionDmMessage` with the appropriate colour
- `src/modules/logModAction.ts` / `logActivity.ts` — Thread `colour` parameter through to message builders
- All event and command files updated with their respective colours

 This PR was created with help from Hikari~ 🌸

Reviewed-on: #13
Co-authored-by: Hikari <hikari@nhcarrigan.com>
Co-committed-by: Hikari <hikari@nhcarrigan.com>
2026-03-31 17:33:35 -07:00

69 lines
1.9 KiB
TypeScript

/**
* @copyright nhcarrigan
* @license Naomi's Public License
* @author Naomi Carrigan
*/
/* eslint-disable unicorn/no-keyword-prefix -- old/new prefixes are the established Discord.js event parameter names */
import { logActivity } from "../modules/logActivity.js";
import { logger } from "../utils/logger.js";
import type { AnyThreadChannel } from "discord.js";
/**
* Logs thread update events to the activity log channel.
* Only logs when the thread name changes to avoid noise from archive state changes.
* @param oldThread - The thread state before the update.
* @param newThread - The thread state after the update.
* @returns A promise that resolves when the event has been logged.
*/
export const onThreadUpdate = async(
oldThread: AnyThreadChannel,
newThread: AnyThreadChannel,
): Promise<void> => {
if (
oldThread.name === newThread.name
&& oldThread.archived === newThread.archived
) {
return;
}
try {
const changes: Array<string> = [];
if (oldThread.name !== newThread.name) {
changes.push(`**Name**: \`${oldThread.name}\`\`${newThread.name}\``);
}
if (oldThread.archived !== newThread.archived) {
const wasArchived = oldThread.archived === true
? "Yes"
: "No";
const isArchived = newThread.archived === true
? "Yes"
: "No";
changes.push(`**Archived**: ${wasArchived}${isArchived}`);
}
const fields = [
`**Thread**: ${newThread.name} (\`${newThread.id}\`)`,
`**Parent**: <#${newThread.parentId ?? "Unknown"}>`,
...changes,
].join("\n");
await logActivity({
client: newThread.client,
colour: "threadUpdated",
emoji: "🔄",
fields: fields,
title: "Thread Updated",
});
} catch (error) {
await logger.error(
"Failed to log thread update",
error instanceof Error
? error
: new Error(String(error)),
);
}
};