generated from nhcarrigan/template
1c31a49bc4
## Summary - Replaces the old AI companion bot with a full Discord moderation system - Adds 8 slash commands: `warn`, `mute`, `unmute`, `kick`, `softban`, `ban`, `unban`, `prune` - Adds logging for member join/leave, activity (messages, threads, voice), and moderation actions - Audit log integration captures manual bans, kicks, timeouts, and unbans - All applicable actions post sanctions to the Hikari sanction API - All commands are ephemeral, use Components v2, and enforce permission + role hierarchy checks ## Test plan - [ ] Run `pnpm register` to register all 8 commands to the guild - [ ] Verify each command appears in Discord and is only visible to members with the appropriate permissions - [ ] Test each command against a valid target and confirm mod log entry, DM notification, and sanction record - [ ] Test each command against an invalid target (equal/higher role, self, bot) and confirm correct error response - [ ] Perform a manual ban, kick, and timeout in the Discord UI and confirm audit log handler picks them up - [ ] Perform a manual unban and confirm it logs correctly without creating a sanction - [ ] Verify join/leave messages appear in the welcome log channel - [ ] Verify message edits, deletes, thread events, and voice state changes appear in the activity log channel ✨ This issue was created with help from Hikari~ 🌸 Reviewed-on: #11 Co-authored-by: Hikari <hikari@nhcarrigan.com> Co-committed-by: Hikari <hikari@nhcarrigan.com>
58 lines
1.7 KiB
TypeScript
58 lines
1.7 KiB
TypeScript
/**
|
|
* @copyright nhcarrigan
|
|
* @license Naomi's Public License
|
|
* @author Naomi Carrigan
|
|
*/
|
|
/* eslint-disable no-console -- Standalone registration script; no logger available */
|
|
|
|
import { REST, Routes } from "discord.js";
|
|
import { banCommand } from "./commands/ban.js";
|
|
import { kickCommand } from "./commands/kick.js";
|
|
import { muteCommand } from "./commands/mute.js";
|
|
import { pruneCommand } from "./commands/prune.js";
|
|
import { softbanCommand } from "./commands/softban.js";
|
|
import { unbanCommand } from "./commands/unban.js";
|
|
import { unmuteCommand } from "./commands/unmute.js";
|
|
import { warnCommand } from "./commands/warn.js";
|
|
import { guildConfig } from "./config/guild.js";
|
|
|
|
const commandData = [
|
|
banCommand.data.toJSON(),
|
|
unbanCommand.data.toJSON(),
|
|
kickCommand.data.toJSON(),
|
|
muteCommand.data.toJSON(),
|
|
pruneCommand.data.toJSON(),
|
|
softbanCommand.data.toJSON(),
|
|
unmuteCommand.data.toJSON(),
|
|
warnCommand.data.toJSON(),
|
|
];
|
|
|
|
const rest = new REST().setToken(process.env.DISCORD_TOKEN ?? "");
|
|
|
|
/* eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- REST returns unknown; shape is documented by Discord API */
|
|
const me = await rest.get(Routes.user()) as { id: string; username: string };
|
|
console.log(`Authenticated as: ${me.username} (${me.id})`);
|
|
|
|
try {
|
|
console.log(
|
|
`Registering ${commandData.length.toString()} commands for guild ${guildConfig.guildId}...`,
|
|
);
|
|
|
|
await rest.put(
|
|
Routes.applicationGuildCommands(
|
|
guildConfig.clientId,
|
|
guildConfig.guildId,
|
|
),
|
|
{ body: commandData },
|
|
);
|
|
|
|
console.log("Commands registered successfully.");
|
|
} catch (error) {
|
|
console.error(
|
|
"Failed to register commands:",
|
|
error instanceof Error
|
|
? error.message
|
|
: String(error),
|
|
);
|
|
}
|