diff --git a/commands/settings.js b/commands/settings.js index 4e01bb0..b0f41f7 100644 --- a/commands/settings.js +++ b/commands/settings.js @@ -27,7 +27,8 @@ const execute = async (interaction) => { { name: "3. Toggle Allow Gift Purchase", value: "Enable or disable allowing users to buy gifts for others on this hub." }, { name: "4. Edit Terms of Service", value: "Change the terms of service for this hub." }, { name: "5. Regenerate Secret Key", value: "Generate a new secret key for this hub. (Old key will be invalidated)" }, - { name: "6. Parcel Auto-Import", value: "Set up automatic importing of Parcel purchases when linking." } + { name: "6. Parcel Auto-Import", value: "Set up automatic importing of Parcel purchases when linking." }, + { name: "7. Delete hub and all products", value: "***__WARNING: THIS IS DANGEROUS__***" } ] }] }); await interaction.user.send({ content: "Say an option number, or `cancel` to exit!" }); diff --git a/messageHandlers/hub_settings.js b/messageHandlers/hub_settings.js index 2e81b28..bd869ad 100644 --- a/messageHandlers/hub_settings.js +++ b/messageHandlers/hub_settings.js @@ -35,29 +35,35 @@ const cancel = (user) => { } const opts = { // Map of option number to step number - 1: {step: 21, exec: () => { + 1: {step: 21, exec: (hubId, uid) => { return 'Please provide the new short description. Say `cancel` to exit.'; }}, - 2: {step: 22, exec: () => { + 2: {step: 22, exec: (hubId, uid) => { return 'Please provide the new long description. Say `cancel` to exit.'; }}, - 3: {step: 1, exec: async (hubId) => { + 3: {step: 1, exec: async (hubId, uid) => { const [hub] = await pool.query('SELECT allowGiftPurchase FROM hubs WHERE id = ?', [hubId]); if (!hub) return 'Error fetching hub data.'; const newValue = hub.allowGiftPurchase ? 0 : 1; await pool.query('UPDATE hubs SET allowGiftPurchase = ? WHERE id = ?', [newValue, hubId]); return `Allow Gift Purchase is now set to: ${newValue ? "Yes" : "No"}.\n\nType another option number, or \`cancel\` to exit.`; }}, - 4: {step: 24, exec: () => { + 4: {step: 24, exec: (hubId, uid) => { return 'Please provide the new Terms of Service. Say `cancel` to exit.'; }}, - 5: {step: 25, exec: async (hubId) => { + 5: {step: 25, exec: async (hubId, uid) => { const newKey = crypto.randomBytes(16).toString('hex'); await pool.query('UPDATE hubs SET secretKey = ? WHERE id = ?', [newKey, hubId]); return `New secret key generated: ||${newKey}||\n\nType another option number, or \`cancel\` to exit.`; }}, - 6: {step: 1, exec: () => { + 6: {step: 1, exec: (hubId, uid) => { return 'Parcel Auto-Import setup is not yet implemented. Type another option number, or `cancel` to exit.'; + }}, + 7: {step: 27, exec: async (hubId, uid) => { + // generate a random confirmation code + const confirmationCode = crypto.randomBytes(8).toString('hex'); + global.hubSettingsHandlers[uid].confirmationCode = confirmationCode; + return `***__WARNING: THIS WILL DELETE THE HUB AND ALL PRODUCTS! THIS ACTION CANNOT BE UNDONE.__***\nTo confirm deletion, please type the following: \`confirm ${confirmationCode}\`. Type \`cancel\` to exit.`; }} } @@ -74,7 +80,7 @@ const execute = async (message) => { return; } global.hubSettingsHandlers[message.author.id].step = opts[option].step; - const response = await opts[option].exec(global.hubSettingsHandlers[message.author.id].hub); + const response = await opts[option].exec(global.hubSettingsHandlers[message.author.id].hub, message.author.id); message.channel.send(response); break; case 21: // Edit Short Description @@ -119,6 +125,41 @@ const execute = async (message) => { global.hubSettingsHandlers[message.author.id].step = 1; message.channel.send('Terms of Service updated.\n\nType an option number, or `cancel` to exit.'); break; + case 27: // Delete Hub + const confirmMatch = message.content.trim().match(/^confirm (\w{16})$/); + if (message.content.toLowerCase() === 'cancel') { + cancel(message.author); + return; + } + if (!confirmMatch || confirmMatch[1] !== global.hubSettingsHandlers[message.author.id].confirmationCode) { + message.channel.send('Invalid confirmation code. Please type the exact confirmation code sent to you, or `cancel` to exit.'); + return; + } + // Proceed with deletion + const hubId = global.hubSettingsHandlers[message.author.id].hub; + // Delete fileAuth + message.channel.send("Deleting file authorizations..."); + await pool.query('DELETE FROM fileAuth WHERE productId IN (SELECT id FROM products WHERE hubId = ?)', [hubId]); + // Delete files + message.channel.send("Deleting product files..."); + const files = await pool.query('SELECT filePath FROM products WHERE hubId = ?', [hubId]); + for (const file of files) { + if (fs.existsSync(file.filePath)) { + fs.unlinkSync(file.filePath); + } + } + // Delete purchases + message.channel.send("Deleting purchases..."); + await pool.query('DELETE FROM purchases WHERE productId IN (SELECT id FROM products WHERE hubId = ?)', [hubId]); + // Delete products + message.channel.send("Deleting products..."); + await pool.query('DELETE FROM products WHERE hubId = ?', [hubId]); + // Delete hub + message.channel.send("Deleting hub..."); + await pool.query('DELETE FROM hubs WHERE id = ?', [hubId]); + message.channel.send('Hub has been deleted. Exiting settings. Thank you!'); + cancel(message.author); + break; default: message.channel.send('Invalid step.'); log.error(`Invalid hub settings step for user ${message.author.id}: ${global.hubSettingsHandlers[message.author.id].step}`);