const { SlashCommandBuilder, EmbedBuilder } = require('discord.js'); module.exports = { category: 'utility', global: true, data: new SlashCommandBuilder() .setName('budget') .setDescription('The thing') .addSubcommand(subcommand => subcommand .setName('set') .setDescription('Set weekly budget') .addIntegerOption(option => option.setName('amount') .setRequired(true) .setDescription('Amount as int')) .addBooleanOption(option => option.setName('override') .setRequired(false) .setDescription('Override budget of current period')) ) .addSubcommand(subcommand => subcommand .setName('view') .setDescription('View your grocery spendings for the current or previous week') .addBooleanOption(option => option .setName('lastweek') .setDescription('Show spendings from the previous budget cycle instead of the current one') .setRequired(false) ) ) .addSubcommand(subcommand => subcommand .setName('stats') .setDescription('View detailed spending and savings statistics') ), async execute(interaction) { console.log('budget command entrypoint'); let db = await interaction.client.localDB; let discordId = interaction.member.id; console.log(db, discordId); let allowed = ['372115788498468864', '222457277708369928'].includes(discordId); console.log(allowed); if (!allowed) { console.log('budget command denied'); await interaction.reply('This command may only be invoked by Miffy!'); return; } console.log(`Switcching on sub ${interaction.options.getSubcommand()}`); switch (interaction.options.getSubcommand()) { case 'set': console.log('budget command set'); let override = interaction.options.getBoolean('override') ?? false; let budget = interaction.options.get('amount').value; db.prepare(`INSERT OR REPLACE INTO bot_config (id, weekly_budget) VALUES (1, ?)`).run(budget); if (override) { db.prepare(` UPDATE weekly_budgets SET budget_amount = ? WHERE id = ( SELECT id FROM weekly_budgets WHERE date('now', 'localtime') BETWEEN start_date AND end_date ORDER BY id DESC LIMIT 1 )`).run(budget); } await interaction.reply(`Budget set to ${Number(budget).toFixed(2)}.`); break; case 'view': const currentBudget = db.prepare(` SELECT id, budget_amount, exchange_rate, start_date, end_date FROM weekly_budgets WHERE date('now', 'localtime') BETWEEN start_date AND end_date LIMIT 1 `).get(); const userSpendings = db.prepare(` SELECT amount, message_raw FROM grocery_spendings WHERE budget_id = ? AND discord_id = ? `).all(currentBudget.id, interaction.member.id); const totalSpentEur = userSpendings.reduce((acc, s) => { return acc + s.amount; }, 0); const remainingEur = currentBudget.budget_amount - totalSpentEur; const remainingSek = remainingEur * currentBudget.exchange_rate; const todayTimestamp = Math.floor(Date.now() / 1000); const endTimestamp = Math.floor(new Date(`${currentBudget.end_date}T23:59:59`).getTime() / 1000); const budgetEmbed = new EmbedBuilder() .setColor(remainingEur > 0 ? 0x00ff00 : 0xff0000) .setTitle(`${interaction.member.displayName} Budget as of `) .setDescription(`Period: \`${currentBudget.start_date}\` to \`${currentBudget.end_date}\`\nReset `) .addFields( { name: 'Spent', value: `${totalSpentEur.toFixed(2)} €\n${(totalSpentEur * currentBudget.exchange_rate).toFixed(2)} kr`, inline: true }, { name: 'Remaining', value: `${remainingEur.toFixed(2)} €\n${remainingSek.toFixed(2)} kr`, inline: true }, ) .setFooter({ text: `Exchange rate this week: 1 € = ${currentBudget.exchange_rate.toFixed(2)} kr` }) .setTimestamp(); await interaction.reply({ embeds: [budgetEmbed] }); break case 'stats': const allBudgets = db.prepare(` SELECT id, budget_amount, exchange_rate, start_date, end_date FROM weekly_budgets ORDER BY start_date DESC LIMIT 4 `).all(); let statsDescription = ""; let cumulativeSavingsEur = 0; for (const budgetPeriod of allBudgets) { const periodSpendings = db.prepare(` SELECT amount FROM grocery_spendings WHERE budget_id = ? AND discord_id = ? `).all(budgetPeriod.id, interaction.member.id); const totalSpentInPeriodEur = periodSpendings.reduce((acc, s) => acc + s.amount, 0); const savedInPeriodEur = budgetPeriod.budget_amount - totalSpentInPeriodEur; cumulativeSavingsEur += savedInPeriodEur; statsDescription += `**Period: ${budgetPeriod.start_date} - ${budgetPeriod.end_date}**\n`; statsDescription += `Budget: ${budgetPeriod.budget_amount.toFixed(2)}€\n`; statsDescription += `Spent: ${totalSpentInPeriodEur.toFixed(2)}€ (${(totalSpentInPeriodEur * budgetPeriod.exchange_rate).toFixed(2)} kr)\n`; statsDescription += `Saved: ${savedInPeriodEur.toFixed(2)}€ (${(savedInPeriodEur * budgetPeriod.exchange_rate).toFixed(2)} kr)\n`; statsDescription += `Cumulative: ${cumulativeSavingsEur.toFixed(2)}€\n\n`; } if (allBudgets.length === 0) { statsDescription = "No budget periods on record."; } const statsEmbed = new EmbedBuilder() .setColor(0x0099ff) .setTitle(`${interaction.member.displayName}'s Budget Statistics`) .setDescription(statsDescription) .setTimestamp(); await interaction.reply({ embeds: [statsEmbed] }); break; default: await interaction.reply(`Sub mismatch. Switching on ${interaction.options.getSubcommand()}`); break; } }, };