From 2e1af3db7a5b5c5ceef647aa565a98eb646bf5b6 Mon Sep 17 00:00:00 2001 From: Hipperooni Date: Tue, 29 Oct 2024 18:39:49 +1100 Subject: [PATCH 1/3] Add xp overwrite functions --- src/discord/commands/guild/d.admin.ts | 103 +++++++++++++++++++++++++- src/global/utils/experience.ts | 17 ++++- 2 files changed, 115 insertions(+), 5 deletions(-) diff --git a/src/discord/commands/guild/d.admin.ts b/src/discord/commands/guild/d.admin.ts index 1d075ca6..7d044337 100644 --- a/src/discord/commands/guild/d.admin.ts +++ b/src/discord/commands/guild/d.admin.ts @@ -6,6 +6,10 @@ import { } from 'discord.js'; import axios from 'axios'; import { stripIndents } from 'common-tags'; +import { + experience_category, experience_type, user_experience, +} from '@prisma/client'; +import { expForNextLevel, findXPfromLevel } from '../../../global/utils/experience'; import { SlashCommand } from '../../@types/commandDef'; import commandContext from '../../utils/context'; import deployCommands from '../../utils/commandDeploy'; @@ -144,6 +148,72 @@ async function setStatus( await interaction.editReply(`Status set to ${statusType} ${status}`); } +async function overwriteUserData( + interaction: ChatInputCommandInteraction, +): Promise { + const member = interaction.options.getUser('user'); + if (!member) { + await interaction.editReply('Error: User not found.'); + return; + } + + const category = interaction.options.getString('category') as experience_category; + const type = interaction.options.getString('type') as experience_type; + const level = interaction.options.getInteger('level'); + + if (!category || !type || level === null) { + await interaction.editReply('Error: Missing category, type, or level.'); + return; + } + + const userData = await db.users.upsert({ + where: { + discord_id: member.id, + }, + create: { + discord_id: member.id, + }, + update: {}, + }); + + const experienceData = await db.user_experience.findFirst({ + where: { + user_id: userData.id, + category, + type, + }, + }); + + if (!experienceData) { + console.log('No experience data found for the user.'); + await interaction.editReply('Error: No experience data found for the user.'); + return; + } + + const levelPoints = await findXPfromLevel(level); + console.log(`Updating category ${category} for user ${member.id} to level ${level} with ${levelPoints} points.`); + + try { + const result = await db.user_experience.updateMany({ + where: { + user_id: userData.id, + category, + type, + }, + data: { + level, + level_points: levelPoints, + total_points: levelPoints, + }, + }); + console.log(`Update result: ${JSON.stringify(result)}`); // Log the result of the update + } catch (error) { + console.error(`Error updating database: ${(error as Error).message}`); // Log any errors + } + + await interaction.editReply(`User level and points updated for category ${category} to level ${level} with ${levelPoints} points.`); +} + export const dAdmin: SlashCommand = { data: new SlashCommandBuilder() .setName('admin') @@ -187,12 +257,37 @@ export const dAdmin: SlashCommand = { .addStringOption(option => option .setName('url') .setDescription('The URL of the banner') - .setRequired(true))), + .setRequired(true))) + .addSubcommand(subcommand => subcommand + .setName('overwriteuserdata') + .setDescription('Overwrite user data') + .addUserOption(option => option.setName('user').setDescription('The user to update').setRequired(true)) + .addStringOption(option => option.setName('category') + .setDescription('The category to update') + .setRequired(true) + .addChoices( + { name: 'General', value: 'GENERAL' }, + { name: 'Tripsitter', value: 'TRIPSITTER' }, + { name: 'Developer', value: 'DEVELOPER' }, + { name: 'Team', value: 'TEAM' }, + { name: 'Ignored', value: 'IGNORED' }, + // Add more categories as needed + )) + .addStringOption(option => option.setName('type') + .setDescription('The type to update') + .setRequired(true) + .addChoices( + { name: 'Text', value: 'TEXT' }, + { name: 'Voice', value: 'VOICE' }, + // Add more types as needed + )) + .addIntegerOption(option => option.setName('level').setDescription('The level to set').setRequired(true))), + async execute(interaction) { if (!interaction.channel) return false; if (!interaction.guild) return false; log.info(F, await commandContext(interaction)); - const command = interaction.options.getSubcommand() as 'restart' | 'rebuild' | 'deploy' | 'setstatus' | 'setavatar' | 'setbanner'; + const command = interaction.options.getSubcommand() as 'restart' | 'rebuild' | 'deploy' | 'setstatus' | 'setavatar' | 'setbanner' | 'overwriteuserdata'; // By default we want to make the reply private await interaction.deferReply({ ephemeral: true }); // eslint-disable-next-line sonarjs/no-small-switch @@ -221,6 +316,10 @@ export const dAdmin: SlashCommand = { await setStatus(interaction, interaction.options.getString('prefix') as string, interaction.options.getString('status') as string); break; } + case 'overwriteuserdata': { + await overwriteUserData(interaction); + break; + } default: { log.debug(F, `default ${command}`); await interaction.editReply('Command not found'); diff --git a/src/global/utils/experience.ts b/src/global/utils/experience.ts index 92a41e6f..2ebb79d8 100644 --- a/src/global/utils/experience.ts +++ b/src/global/utils/experience.ts @@ -33,13 +33,24 @@ const announcementEmojis = [ '🎇', ]; -export async function expForNextLevel( - level:number, -):Promise { +export async function expForNextLevel(level: number): Promise { // This is a simple formula, making sure it's standardized across the system return 5 * (level ** 2) + (50 * level) + 100; } +export async function findXPfromLevel(level: number): Promise { + let totalXP = 0; + + const xpPromises = []; + for (let currentLevel = 1; currentLevel < level; currentLevel += 1) { + xpPromises.push(expForNextLevel(currentLevel)); + } + const xpResults = await Promise.all(xpPromises); + totalXP = xpResults.reduce((acc, xp) => acc + xp, 0); + + return totalXP; +} + export async function getTotalLevel( totalExp:number, ):Promise<{ level: number, level_points: number }> { From 7ed04847d077a7c7bc09e6c3e00ecaf151943702 Mon Sep 17 00:00:00 2001 From: Hipperooni Date: Tue, 29 Oct 2024 18:43:18 +1100 Subject: [PATCH 2/3] Update logging for xp overwrites --- src/discord/commands/guild/d.admin.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/discord/commands/guild/d.admin.ts b/src/discord/commands/guild/d.admin.ts index 7d044337..b64cc8b7 100644 --- a/src/discord/commands/guild/d.admin.ts +++ b/src/discord/commands/guild/d.admin.ts @@ -185,13 +185,13 @@ async function overwriteUserData( }); if (!experienceData) { - console.log('No experience data found for the user.'); + log.debug(F, `No experience data found for user ${userData.id} in category ${category} type ${type}.`); await interaction.editReply('Error: No experience data found for the user.'); return; } const levelPoints = await findXPfromLevel(level); - console.log(`Updating category ${category} for user ${member.id} to level ${level} with ${levelPoints} points.`); + log.debug(F, `Overwriting user data for user ${userData.id} in category ${category} type ${type} to level ${level} with ${levelPoints} XP points.`); try { const result = await db.user_experience.updateMany({ @@ -206,9 +206,9 @@ async function overwriteUserData( total_points: levelPoints, }, }); - console.log(`Update result: ${JSON.stringify(result)}`); // Log the result of the update + console.log(`Update result: ${JSON.stringify(result)}`); } catch (error) { - console.error(`Error updating database: ${(error as Error).message}`); // Log any errors + console.error(`Error updating database: ${(error as Error).message}`); } await interaction.editReply(`User level and points updated for category ${category} to level ${level} with ${levelPoints} points.`); From 4382069e5c402e9e52ada351385190228c981c84 Mon Sep 17 00:00:00 2001 From: Hipperooni Date: Tue, 29 Oct 2024 18:48:24 +1100 Subject: [PATCH 3/3] Fix lint oops --- src/discord/commands/guild/d.admin.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/discord/commands/guild/d.admin.ts b/src/discord/commands/guild/d.admin.ts index b64cc8b7..7f93e2f6 100644 --- a/src/discord/commands/guild/d.admin.ts +++ b/src/discord/commands/guild/d.admin.ts @@ -7,9 +7,9 @@ import { import axios from 'axios'; import { stripIndents } from 'common-tags'; import { - experience_category, experience_type, user_experience, + experience_category, experience_type, } from '@prisma/client'; -import { expForNextLevel, findXPfromLevel } from '../../../global/utils/experience'; +import { findXPfromLevel } from '../../../global/utils/experience'; import { SlashCommand } from '../../@types/commandDef'; import commandContext from '../../utils/context'; import deployCommands from '../../utils/commandDeploy';