Add per-staff metrics: StaffAction event log + /stats command
Event-sourced tracking of staff/ticket lifecycle actions, plus a /stats command. Foundation for a future tickets-website analytics dashboard. Data: - StaffAction model (event log) + Ticket.game / Ticket.closedAt - STATS_ADMIN_IDS config (who may view others' stats) Recording (fire-and-forget, idempotent on real state transitions): - claim, response (channel reply + /response send), escalate, de-escalate, transfer, close (4 sites), reopen — each denormalizes ticketType, tier, priority, game, requester (senderEmail / creatorId), guildId - close events carry closerType / resolverId (claimer credit) / wasClaimed; transfer carries fromId / toId; reopen stamps resolverId - conditional close transition helper (atomic open->closed + closedAt) shared by all four close paths Query + command: - pure period parser (presets + free-text) and stats shaper (per-metric keys) - command-aware autocomplete dispatch - /stats: period (autocomplete) + member (admin-gated) + source (all/email/ discord), ManageMessages + staff-role gated, ephemeral, tier-labeled embed 288+ unit tests; timing/busiest-times data is collected but displayed later.
This commit is contained in:
@@ -415,7 +415,38 @@ async function registerCommands() {
|
||||
.setDescription('Set your personal email signature (valediction, display name, tagline)')
|
||||
.setContexts([InteractionContextType.Guild])
|
||||
.setIntegrationTypes([ApplicationIntegrationType.GuildInstall])
|
||||
.setDefaultMemberPermissions(PermissionFlagsBits.ManageMessages)
|
||||
.setDefaultMemberPermissions(PermissionFlagsBits.ManageMessages),
|
||||
|
||||
new SlashCommandBuilder()
|
||||
.setName('stats')
|
||||
.setDescription('View staff metrics for a given time window')
|
||||
.setContexts([InteractionContextType.Guild])
|
||||
.setIntegrationTypes([ApplicationIntegrationType.GuildInstall])
|
||||
.setDefaultMemberPermissions(PermissionFlagsBits.ManageMessages)
|
||||
.addStringOption(opt =>
|
||||
opt
|
||||
.setName('period')
|
||||
.setDescription('Time window (e.g. "30 days", "3 months", "1 year")')
|
||||
.setRequired(false)
|
||||
.setAutocomplete(true)
|
||||
)
|
||||
.addUserOption(opt =>
|
||||
opt
|
||||
.setName('member')
|
||||
.setDescription('Staff member to view stats for (admin only)')
|
||||
.setRequired(false)
|
||||
)
|
||||
.addStringOption(opt =>
|
||||
opt
|
||||
.setName('source')
|
||||
.setDescription('Filter by ticket source')
|
||||
.setRequired(false)
|
||||
.addChoices(
|
||||
{ name: 'All', value: 'all' },
|
||||
{ name: 'Email', value: 'email' },
|
||||
{ name: 'Discord', value: 'discord' }
|
||||
)
|
||||
)
|
||||
];
|
||||
|
||||
const contextMenuCommands = [
|
||||
|
||||
Reference in New Issue
Block a user