feat: Introduce and separate `BOOT` audit log category from `SYSTEM`, defaulting both to disabled.

This commit is contained in:
이정수 2026-03-27 17:53:00 +09:00
parent 47dc4ab124
commit 0ccbbf9d31
11 changed files with 42 additions and 29 deletions

View File

@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "AuditChannel" ALTER COLUMN "disabledCategories" SET DEFAULT ARRAY['SYSTEM']::TEXT[];

View File

@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "AuditChannel" ALTER COLUMN "disabledCategories" SET DEFAULT ARRAY['BOOT', 'SYSTEM']::TEXT[];

View File

@ -98,7 +98,7 @@ enum DeleteCondition {
model AuditChannel { model AuditChannel {
guildId String @id guildId String @id
channelId String channelId String
disabledCategories String[] @default([]) disabledCategories String[] @default(["BOOT", "SYSTEM"])
createdAt DateTime @default(now()) createdAt DateTime @default(now())
updatedAt DateTime @updatedAt updatedAt DateTime @updatedAt
} }

View File

@ -56,7 +56,8 @@ export default {
.setDescriptionLocalizations({ ko: '설정할 카테고리' }) .setDescriptionLocalizations({ ko: '설정할 카테고리' })
.setRequired(true) .setRequired(true)
.addChoices( .addChoices(
{ name: 'SYSTEM (Boot, Generic Errors)', value: 'SYSTEM' }, { name: 'SYSTEM (System Errors)', value: 'SYSTEM' },
{ name: 'BOOT (Bot Online Notifications)', value: 'BOOT' },
{ name: 'VOICE (Voice Channels)', value: 'VOICE' }, { name: 'VOICE (Voice Channels)', value: 'VOICE' },
{ name: 'PERMISSION (Permission Issues)', value: 'PERMISSION' }, { name: 'PERMISSION (Permission Issues)', value: 'PERMISSION' },
{ name: 'INVITE (Invite Tracking)', value: 'INVITE' }, { name: 'INVITE (Invite Tracking)', value: 'INVITE' },

View File

@ -25,7 +25,7 @@ export default {
client.guilds.cache.forEach(guild => { client.guilds.cache.forEach(guild => {
auditLogService.log(guild, { auditLogService.log(guild, {
category: 'SYSTEM', category: 'BOOT',
severity: 'INFO', severity: 'INFO',
title: 'Bot Online', title: 'Bot Online',
description: `Kord has successfully started or reconnected.` description: `Kord has successfully started or reconnected.`

View File

@ -215,6 +215,7 @@ export const en: TranslationSchema = {
defaultGeneratorName: ' Create Channel', defaultGeneratorName: ' Create Channel',
auditCategories: { auditCategories: {
SYSTEM: 'System', SYSTEM: 'System',
BOOT: 'Boot',
VOICE: 'Voice', VOICE: 'Voice',
PERMISSION: 'Permission', PERMISSION: 'Permission',
INVITE: 'Invite', INVITE: 'Invite',

View File

@ -215,6 +215,7 @@ export const ko: TranslationSchema = {
defaultGeneratorName: ' 채널 생성하기', defaultGeneratorName: ' 채널 생성하기',
auditCategories: { auditCategories: {
SYSTEM: '시스템', SYSTEM: '시스템',
BOOT: '부팅',
VOICE: '음성', VOICE: '음성',
PERMISSION: '권한', PERMISSION: '권한',
INVITE: '초대', INVITE: '초대',

View File

@ -132,6 +132,7 @@ export interface TranslationSchema {
defaultGeneratorName: string; defaultGeneratorName: string;
auditCategories: { auditCategories: {
SYSTEM: string; SYSTEM: string;
BOOT: string;
VOICE: string; VOICE: string;
PERMISSION: string; PERMISSION: string;
INVITE: string; INVITE: string;

View File

@ -2,7 +2,7 @@ import { Guild, EmbedBuilder, TextChannel, Colors } from 'discord.js';
import { prisma } from '../database'; import { prisma } from '../database';
export type AuditSeverity = 'INFO' | 'WARN' | 'ERROR'; export type AuditSeverity = 'INFO' | 'WARN' | 'ERROR';
export type AuditCategory = 'SYSTEM' | 'VOICE' | 'PERMISSION' | 'INVITE' | 'MIMIC'; export type AuditCategory = 'SYSTEM' | 'BOOT' | 'VOICE' | 'PERMISSION' | 'INVITE' | 'MIMIC';
export interface AuditLogPayload { export interface AuditLogPayload {
category: AuditCategory; category: AuditCategory;
@ -70,7 +70,12 @@ export class AuditLogService {
async setChannel(guildId: string, channelId: string): Promise<void> { async setChannel(guildId: string, channelId: string): Promise<void> {
await prisma.auditChannel.upsert({ await prisma.auditChannel.upsert({
where: { guildId }, where: { guildId },
create: { guildId, channelId }, create: {
guildId,
channelId,
// 기본적으로 부팅 로그(BOOT)와 시스템 로그(SYSTEM)는 받지 않도록 설정
disabledCategories: ['BOOT', 'SYSTEM']
},
update: { channelId }, update: { channelId },
}); });
} }

View File

@ -130,7 +130,7 @@ export class SetupWizardRenderer {
embed.setTitle(t(locale, 'commands.setup.step4.title')) embed.setTitle(t(locale, 'commands.setup.step4.title'))
.setDescription(t(locale, 'commands.setup.step4.desc')); .setDescription(t(locale, 'commands.setup.step4.desc'));
const categories: ('SYSTEM' | 'VOICE' | 'PERMISSION' | 'INVITE')[] = ['SYSTEM', 'VOICE', 'PERMISSION', 'INVITE']; const categories: ('BOOT' | 'SYSTEM' | 'VOICE' | 'PERMISSION' | 'INVITE')[] = ['BOOT', 'SYSTEM', 'VOICE', 'PERMISSION', 'INVITE'];
const row1 = new ActionRowBuilder<ButtonBuilder>(); const row1 = new ActionRowBuilder<ButtonBuilder>();
categories.forEach(cat => { categories.forEach(cat => {
@ -200,7 +200,7 @@ export class SetupWizardRenderer {
// 감사 로그 카테고리 요약 // 감사 로그 카테고리 요약
let catStr = 'None'; let catStr = 'None';
if (audit?.channelId) { if (audit?.channelId) {
const allCats: ('SYSTEM' | 'VOICE' | 'PERMISSION' | 'INVITE')[] = ['SYSTEM', 'VOICE', 'PERMISSION', 'INVITE']; const allCats: ('BOOT' | 'SYSTEM' | 'VOICE' | 'PERMISSION' | 'INVITE')[] = ['BOOT', 'SYSTEM', 'VOICE', 'PERMISSION', 'INVITE'];
const enabled = allCats.filter(c => !audit.disabledCategories.includes(c)); const enabled = allCats.filter(c => !audit.disabledCategories.includes(c));
catStr = enabled.map(c => t(locale, `commands.setup.auditCategories.${c}`)).join(', '); catStr = enabled.map(c => t(locale, `commands.setup.auditCategories.${c}`)).join(', ');
} }

View File

@ -1734,28 +1734,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"Kord@workspace:.":
version: 0.0.0-use.local
resolution: "Kord@workspace:."
dependencies:
"@prisma/client": "npm:6.4.1"
"@types/jest": "npm:^30.0.0"
"@types/node": "npm:^25.5.0"
"@typescript-eslint/eslint-plugin": "npm:^8.57.2"
"@typescript-eslint/parser": "npm:^8.57.2"
discord.js: "npm:^14.25.1"
dotenv: "npm:^17.3.1"
eslint: "npm:^10.1.0"
ioredis: "npm:^5.10.1"
jest: "npm:^30.3.0"
prettier: "npm:^3.8.1"
prisma: "npm:6.4.1"
ts-jest: "npm:^29.4.6"
tsx: "npm:^4.21.0"
typescript: "npm:^6.0.2"
languageName: unknown
linkType: soft
"abbrev@npm:^4.0.0": "abbrev@npm:^4.0.0":
version: 4.0.0 version: 4.0.0
resolution: "abbrev@npm:4.0.0" resolution: "abbrev@npm:4.0.0"
@ -3627,6 +3605,28 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"kord@workspace:.":
version: 0.0.0-use.local
resolution: "kord@workspace:."
dependencies:
"@prisma/client": "npm:6.4.1"
"@types/jest": "npm:^30.0.0"
"@types/node": "npm:^25.5.0"
"@typescript-eslint/eslint-plugin": "npm:^8.57.2"
"@typescript-eslint/parser": "npm:^8.57.2"
discord.js: "npm:^14.25.1"
dotenv: "npm:^17.3.1"
eslint: "npm:^10.1.0"
ioredis: "npm:^5.10.1"
jest: "npm:^30.3.0"
prettier: "npm:^3.8.1"
prisma: "npm:6.4.1"
ts-jest: "npm:^29.4.6"
tsx: "npm:^4.21.0"
typescript: "npm:^6.0.2"
languageName: unknown
linkType: soft
"leven@npm:^3.1.0": "leven@npm:^3.1.0":
version: 3.1.0 version: 3.1.0
resolution: "leven@npm:3.1.0" resolution: "leven@npm:3.1.0"