Refactor moderation actions to include channel and source metadata

- Updated moderation action functions to include `channelId` and `source` in the metadata for better tracking of actions.
- Introduced an `auditFrom` function to streamline the addition of audit information across various commands.
- Removed `prisma/migrations` from .gitignore to ensure migration files are tracked.
- Enhanced the `CreateCaseInput` type to accommodate new metadata structure.
This commit is contained in:
smueller
2026-07-22 11:28:43 +02:00
parent 878478e4fc
commit 405b70bdfc
7 changed files with 140 additions and 8 deletions

View File

@@ -0,0 +1,24 @@
import { describe, expect, it } from 'vitest';
import { buildCaseMetadata } from './audit.js';
describe('buildCaseMetadata', () => {
it('builds standardized purge metadata', () => {
const metadata = buildCaseMetadata({
source: 'button_confirmation',
channelId: '123',
extras: {
confirmed: true,
purge: {
requestedAmount: 10,
deletedCount: 8,
filters: { botsOnly: true }
}
}
});
expect(metadata.source).toBe('button_confirmation');
expect(metadata.channelId).toBe('123');
expect(metadata.purge?.deletedCount).toBe(8);
expect(metadata.recordedAt).toBeTypeOf('string');
});
});

View File

@@ -0,0 +1,56 @@
import { z } from 'zod';
export const CaseAuditSourceSchema = z.enum([
'slash_command',
'button_confirmation',
'escalation',
'job'
]);
export type CaseAuditSource = z.infer<typeof CaseAuditSourceSchema>;
export const PurgeAuditFiltersSchema = z.object({
targetUserId: z.string().nullable().optional(),
botsOnly: z.boolean().optional(),
linksOnly: z.boolean().optional(),
attachmentsOnly: z.boolean().optional(),
regex: z.string().nullable().optional()
});
export const CaseAuditMetadataSchema = z
.object({
source: CaseAuditSourceSchema,
recordedAt: z.string().datetime(),
channelId: z.string().optional(),
confirmed: z.boolean().optional(),
escalation: z.boolean().optional(),
warningCount: z.number().int().positive().optional(),
durationMs: z.number().int().positive().optional(),
deletedCaseId: z.string().optional(),
deletedCaseNumber: z.number().int().positive().optional(),
purge: z
.object({
requestedAmount: z.number().int().positive(),
deletedCount: z.number().int().nonnegative(),
filters: PurgeAuditFiltersSchema.optional()
})
.optional()
})
.passthrough();
export type CaseAuditMetadata = z.infer<typeof CaseAuditMetadataSchema>;
type BuildCaseMetadataInput = {
source: CaseAuditSource;
channelId?: string;
extras?: Record<string, unknown>;
};
export function buildCaseMetadata(input: BuildCaseMetadataInput): CaseAuditMetadata {
return CaseAuditMetadataSchema.parse({
source: input.source,
recordedAt: new Date().toISOString(),
channelId: input.channelId,
...input.extras
});
}

View File

@@ -1,5 +1,7 @@
import { z } from 'zod';
export * from './audit.js';
export const LocaleSchema = z.enum(['de', 'en']);
export type Locale = z.infer<typeof LocaleSchema>;