diff --git a/src/discord/commands/guild/d.tripsitstats.ts b/src/discord/commands/guild/d.tripsitstats.ts new file mode 100644 index 00000000..68e93bce --- /dev/null +++ b/src/discord/commands/guild/d.tripsitstats.ts @@ -0,0 +1,49 @@ +/* eslint-disable sonarjs/no-duplicate-string */ +import { + SlashCommandBuilder, +} from 'discord.js'; +import { SlashCommand } from '../../@types/commandDef'; +import commandContext from '../../utils/context'; +import { embedTemplate } from '../../utils/embedTemplate'; +import getTripSitStatistics from '../../../global/commands/g.tripsitstats'; + +const F = f(__filename); + +export const dTripsitStats: SlashCommand = { + data: new SlashCommandBuilder() + .setName('tripsit_stats') + .setDescription('Get stats on a feature of TripSit') + .addSubcommand(subcommand => subcommand + .setName('session') + .setDescription('Get stats for TripSit sessions') + .addBooleanOption(option => option + .setName('ephemeral') + .setDescription('Set to "True" to show the response only to you'))), + // .addSubcommand(subcommand => subcommand + // .setName('command') + // .setDescription('Get stats for a command (Not Implemented)') + // .addBooleanOption(option => option + // .setName('ephemeral') + // .setDescription('Set to "True" to show the response only to you'))) + // .addSubcommand(subcommand => subcommand + // .setName('helpers') + // .setDescription('Get stats for Helpers (Not Implemented)') + // .addBooleanOption(option => option + // .setName('ephemeral') + // .setDescription('Set to "True" to show the response only to you'))), + async execute(interaction) { + log.info(F, await commandContext(interaction)); + await interaction.deferReply({ ephemeral: (interaction.options.getBoolean('ephemeral') === true) }); + + const subcommand = interaction.options.getSubcommand(); + + const stats = await getTripSitStatistics(subcommand); + const embed = embedTemplate() + .setTitle(`TripSit ${subcommand.charAt(0).toUpperCase() + subcommand.slice(1)} Stats`) + .setDescription(stats); + await interaction.editReply({ embeds: [embed] }); + return true; + }, +}; + +export default dTripsitStats; diff --git a/src/global/commands/g.tripsitstats.ts b/src/global/commands/g.tripsitstats.ts new file mode 100644 index 00000000..1baf8f75 --- /dev/null +++ b/src/global/commands/g.tripsitstats.ts @@ -0,0 +1,112 @@ +import { stripIndents } from 'common-tags'; + +const F = f(__filename); + +async function getSessionStats(): Promise { + const now = new Date(); + + // Calculate date ranges + const startOfThisMonth = new Date(now.getFullYear(), now.getMonth(), 1); + const startOfLastMonth = new Date(now.getFullYear(), now.getMonth() - 1, 1); + const startOfYear = new Date(now.getFullYear(), 0, 1); + const startOfLastYear = new Date(now.getFullYear() - 1, 0, 1); + const endOfLastYear = new Date(now.getFullYear() - 1, 11, 31, 23, 59, 59); + + // Fetch data for this month and last month + const thisMonthsTickets = await db.user_tickets.findMany({ + where: { + created_at: { + gte: startOfThisMonth, + }, + }, + }); + + const lastMonthsTickets = await db.user_tickets.findMany({ + where: { + created_at: { + gte: startOfLastMonth, + lt: startOfThisMonth, + }, + }, + }); + + // Fetch data for this year and last year + const thisYearsTickets = await db.user_tickets.findMany({ + where: { + created_at: { + gte: startOfYear, + }, + }, + }); + + const lastYearsTickets = await db.user_tickets.findMany({ + where: { + created_at: { + gte: startOfLastYear, + lt: endOfLastYear, + }, + }, + }); + + // Calculate differences + const monthDifference = thisMonthsTickets.length - lastMonthsTickets.length; + const yearDifference = thisYearsTickets.length - lastYearsTickets.length; + + // Format the results + return stripIndents` + 📊 Ticket Statistics: + - Tickets this month: ${thisMonthsTickets.length} + - Tickets last month: ${lastMonthsTickets.length} (${monthDifference >= 0 ? '+' : ''}${monthDifference}) + + - Tickets this year: ${thisYearsTickets.length} + - Tickets last year: ${lastYearsTickets.length} (${yearDifference >= 0 ? '+' : ''}${yearDifference}) + `; +} + +async function getCommandStats(): Promise { + /* Skeleton + This command should pull how many times a command has been used in total or within X time frame. + + Requires: new column or table somewhere + */ + log.info(F, 'getCommandStats'); + return 'Not implemented'; +} + +async function getHelperStats(): Promise { + /* Skeleton + This command should pull how many tickets a helper has interacted in and owned in total or within X time frame + + Requires: add a column to user_tickets and assign the user who "owns" tickets ID. + */ + log.info(F, 'getHelperStats'); + return 'Not implemented'; +} + +/** + * Fetch statistics data for a given feature from the database. + * @param feature - The feature for which statistics are requested. + * @returns The data related to the specified feature. + */ +async function getTripSitStatistics(feature: string): Promise { + try { + switch (feature) { + case 'session': + return await getSessionStats(); + + case 'commands': + return await getCommandStats(); + + case 'helpers': + return await getHelperStats(); + + default: + throw new Error(`Feature not recognized: ${feature}`); + } + } catch (error) { + log.error(F, `Error fetching statistics for feature: ${feature}. \n\nError: ${error}`); + } + return 'No stats found.'; +} + +export default getTripSitStatistics;