From dd049840b2d68b6c7b976252df695f61d93519c6 Mon Sep 17 00:00:00 2001 From: jateute Date: Tue, 17 Feb 2026 23:29:33 +0100 Subject: [PATCH 1/2] feat(economy): implements "Artikel bearbeiten" Implements https://featureboard.net/suggestions/95f5a741-6d35-4b86-9c67-abd900dca76e --- locales/en.json | 3 + modules/economy-system/commands/shop.js | 47 +++++++++-- modules/economy-system/configs/strings.json | 28 +++++++ modules/economy-system/economy-system.js | 89 ++++++++++++++++++++- 4 files changed, 161 insertions(+), 6 deletions(-) diff --git a/locales/en.json b/locales/en.json index ffdbde0..00ba293 100644 --- a/locales/en.json +++ b/locales/en.json @@ -776,16 +776,19 @@ "item-duplicate": "The item already exist", "role-to-high": "The specified role is higher than the highest role of the bot. Therefore the bot can't give the role to users. The item was **not** created.", "delete-item": "The user %u has deleted the shop item %i", + "edit-item": "The user %u has edited the item %i. Possible changes are:\nNew name: %n\nNew prize: %p\nNew role: %r", "user-purchase": "The user %u has purchased the shop item %i for %p.", "shop-command-description": "Use the shop-system", "shop-command-description-add": "Create a new item in the shop (admins only)", "shop-option-description-itemName": "Name of the item", + "shop-option-description-newItemName": "New name of the Item", "shop-option-description-itemID": "ID of the Item", "shop-option-description-price": "Price of the item", "shop-option-description-role": "Role to give to users who buy the item", "shop-command-description-buy": "Buy an item", "shop-command-description-list": "List all items in the shop", "shop-command-description-delete": "Remove an item from the shop", + "shop-command-description-edit": "Edit an item", "channel-not-found": "Can't find the leaderboard channel with the ID %c", "command-description-deposit": "Deposit xyz to your bank", "option-description-amount-deposit": "Amount to deposit", diff --git a/modules/economy-system/commands/shop.js b/modules/economy-system/commands/shop.js index a65eacc..7dd5e64 100644 --- a/modules/economy-system/commands/shop.js +++ b/modules/economy-system/commands/shop.js @@ -1,11 +1,11 @@ -const {createShopItem, createShopMsg, deleteShopItem, shopMsg, buyShopItem} = require('../economy-system'); +const {createShopItem, createShopMsg, deleteShopItem, shopMsg, buyShopItem, updateShopItem} = require('../economy-system'); const {localize} = require('../../../src/functions/localize'); /** * @param {*} interaction Interaction * @returns {Promise} Result */ -async function checkPerms(interaction) { +async function checkPermsAndSendReplyOnFail(interaction) { const result = interaction.client.configurations['economy-system']['config']['shopManagers'].includes(interaction.user.id) || interaction.client.config['botOperators'].includes(interaction.user.id); if (!result) await interaction.reply({ content: interaction.client.strings['not_enough_permissions'], @@ -16,7 +16,7 @@ async function checkPerms(interaction) { module.exports.subcommands = { 'add': async function (interaction) { - if (!await checkPerms(interaction)) return; + if (!await checkPermsAndSendReplyOnFail(interaction)) return; await interaction.deferReply({ephemeral: !interaction.client.configurations['economy-system']['config']['publicCommandReplies']}); await createShopItem(interaction); await shopMsg(interaction.client); @@ -32,10 +32,16 @@ module.exports.subcommands = { interaction.reply(msg); }, 'delete': async function (interaction) { - if (!await checkPerms(interaction)) return; + if (!await checkPermsAndSendReplyOnFail(interaction)) return; await interaction.deferReply({ephemeral: !interaction.client.configurations['economy-system']['config']['publicCommandReplies']}); await deleteShopItem(interaction); await shopMsg(interaction.client); + }, + 'edit': async function (interaction) { + if (!await checkPermsAndSendReplyOnFail(interaction)) return; + await interaction.deferReply({ephemeral: !interaction.client.configurations['economy-system']['config']['publicCommandReplies']}); + await updateShopItem(interaction); + await shopMsg(interaction.client); } }; @@ -117,6 +123,37 @@ module.exports.config = { required: false } ] - } + }, + { + type: 'SUB_COMMAND', + name: 'edit', + description: localize('economy-system', 'shop-command-description-edit'), + options: [ + { + type: 'STRING', + required: true, + name: 'item-id', + description: localize('economy-system', 'shop-option-description-itemID') + }, + { + type: 'STRING', + required: false, + name: 'item-new-name', + description: localize('economy-system', 'shop-option-description-newItemName') + }, + { + type: 'INTEGER', + required: false, + name: 'new-price', + description: localize('economy-system', 'shop-option-description-price') + }, + { + type: 'ROLE', + required: false, + name: 'new-role', + description: localize('economy-system', 'shop-option-description-role') + } + ] + }, ] }; \ No newline at end of file diff --git a/modules/economy-system/configs/strings.json b/modules/economy-system/configs/strings.json index 23be38b..2a0dc48 100644 --- a/modules/economy-system/configs/strings.json +++ b/modules/economy-system/configs/strings.json @@ -451,6 +451,34 @@ } ] }, + { + "name": "itemEdit", + "humanName": {}, + "default": { + "en": "Successfully edited the item %name%. Check it out using `/shop list`" + }, + "description": { + "en": "Message that gets send when a shop item gets edited" + }, + "type": "string", + "allowEmbed": true, + "params": [ + { + "name": "name", + "description": { + "en": "Name of the edited item", + "de": "Name des bearbeiteten Items" + } + }, + { + "name": "id", + "description": { + "en": "Id of the edited item", + "de": "ID des bearbeiteten Items" + } + } + ] + }, { "name": "depositMsg", "humanName": { diff --git a/modules/economy-system/economy-system.js b/modules/economy-system/economy-system.js index 7871e9a..f1d3db0 100644 --- a/modules/economy-system/economy-system.js +++ b/modules/economy-system/economy-system.js @@ -382,12 +382,98 @@ async function deleteShopItem(interaction) { }); } +/** +* Function to update a shop-item +* @param {*} interaction Interaction +* @returns {Promise} +*/ +async function updateShopItem(interaction) { + return new Promise(async (resolve) => { + const id = interaction.options.get('item-id')['value']; + + if (!id) { + await interaction.editReply('Please use the id!'); //IDK how this should happen + return resolve(); + } + + const item = await interaction.client.models['economy-system']['Shop'].findOne({ + where: { + id: id + } + }); + + if (!item) { + await interaction.editReply(embedType(interaction.client.configurations['economy-system']['strings']['noMatches'], { + '%id%': id, + '%name%': '-' + })); + return resolve(); + } + + const newNameOption = interaction.options.get('item-new-name'); + const newPrice = interaction.options.getInteger('new-price'); + const newRole = interaction.options.getRole('new-role'); + if (newRole && interaction.guild.me.roles.highest.comparePositionTo(newRole) <= 0) { + return await interaction.editReply(localize('economy-system', 'role-to-high')); + } + + if (newNameOption) { + const collidingItem = await interaction.client.models['economy-system']['Shop'].findOne({ + where: { + name: newNameOption['value'] + } + }); + if (collidingItem && collidingItem['id'] !== id) { + await interaction.editReply(embedType(interaction.client.configurations['economy-system']['strings']['itemDuplicate'], { + '%id%': id, + '%name%': "-" + })); + return resolve(localize('economy-system', 'item-duplicate')); + } + } + + if (newNameOption) { + item.name = newNameOption['value']; + } + if (newPrice) { + item.price = newPrice; + } + if (newRole) { + item.role = newRole['id']; + } + + console.log(item); + + await item.save(); + + await interaction.editReply(embedType(interaction.client.configurations['economy-system']['strings']['itemEdit'], { + '%name%': item.name, + '%id%': item.id + })); + interaction.client.logger.info(`[economy-system] ` + localize('economy-system', 'edit-item', { + u: interaction.user.tag, + i: id, + n: newNameOption ? newNameOption['value'] : "-", + p: newPrice ? newPrice : "-", + r: newRole ? newRole['name'] : "-", + })); + if (interaction.client.logChannel) await interaction.client.logChannel.send(`[economy-system] ` + localize('economy-system', 'edit-item', { + u: interaction.user.tag, + i: id, + n: newNameOption ? newNameOption['value'] : "-", + p: newPrice ? newPrice : "-", + r: newRole ? newRole['name'] : "-", + })); + resolve(`Edited the item ${item.name} successfully`); + }); +} + /** * Create the shop message * @param {Client} client Client * @param {object} guild Object of the guild * @param {boolean} ephemeral Should the message be ephemeral? - * @returns {string} + * @returns {Promise} */ async function createShopMsg(client, guild, ephemeral) { const items = await client.models['economy-system']['Shop'].findAll(); @@ -515,6 +601,7 @@ module.exports.createShopItemAPI = createShopItemAPI; module.exports.createShopItem = createShopItem; module.exports.deleteShopItemAPI = deleteShopItemAPI; module.exports.deleteShopItem = deleteShopItem; +module.exports.updateShopItem = updateShopItem; module.exports.createShopMsg = createShopMsg; module.exports.shopMsg = shopMsg; module.exports.createLeaderboard = leaderboard; \ No newline at end of file From e64c889635f131a89350b7d5525644ba8898635b Mon Sep 17 00:00:00 2001 From: jateute Date: Sun, 22 Feb 2026 22:35:32 +0100 Subject: [PATCH 2/2] fix(economy): Adressed the issues copilot pointed out and also fixed them in createShopItem --- locales/en.json | 5 +++-- modules/economy-system/configs/strings.json | 2 +- modules/economy-system/economy-system.js | 25 ++++++++++++++++----- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/locales/en.json b/locales/en.json index 00ba293..a7f9eae 100644 --- a/locales/en.json +++ b/locales/en.json @@ -776,7 +776,7 @@ "item-duplicate": "The item already exist", "role-to-high": "The specified role is higher than the highest role of the bot. Therefore the bot can't give the role to users. The item was **not** created.", "delete-item": "The user %u has deleted the shop item %i", - "edit-item": "The user %u has edited the item %i. Possible changes are:\nNew name: %n\nNew prize: %p\nNew role: %r", + "edit-item": "The user %u has edited the item %i. Possible changes are:\nNew name: %n\nNew price: %p\nNew role: %r", "user-purchase": "The user %u has purchased the shop item %i for %p.", "shop-command-description": "Use the shop-system", "shop-command-description-add": "Create a new item in the shop (admins only)", @@ -805,7 +805,8 @@ "migration-happening": "Database not up-to-date. Migrating database...", "migration-done": "Migrated database successfully.", "nothing-selected": "Select an item to buy it", - "select-menu-price": "Price: %p" + "select-menu-price": "Price: %p", + "price-less-than-zero": "The price can't be less or equal to zero" }, "status-role": { "fulfilled": "Status-role condition is fulfilled", diff --git a/modules/economy-system/configs/strings.json b/modules/economy-system/configs/strings.json index 2a0dc48..f4ff452 100644 --- a/modules/economy-system/configs/strings.json +++ b/modules/economy-system/configs/strings.json @@ -458,7 +458,7 @@ "en": "Successfully edited the item %name%. Check it out using `/shop list`" }, "description": { - "en": "Message that gets send when a shop item gets edited" + "en": "Message that gets sent when a shop item gets edited" }, "type": "string", "allowEmbed": true, diff --git a/modules/economy-system/economy-system.js b/modules/economy-system/economy-system.js index f1d3db0..0167b68 100644 --- a/modules/economy-system/economy-system.js +++ b/modules/economy-system/economy-system.js @@ -183,7 +183,16 @@ async function createShopItem(interaction) { const role = await interaction.options.getRole('role', true); const price = await interaction.options.getInteger('price'); const model = interaction.client.models['economy-system']['Shop']; - if (interaction.guild.me.roles.highest.comparePositionTo(role) <= 0) return await interaction.editReply(localize('economy-system', 'role-to-high')); + if (interaction.guild.members.me.roles.highest.comparePositionTo(role) <= 0) { + await interaction.editReply(localize('economy-system', 'role-to-high')); + return resolve(localize('economy-system', 'role-to-high')); + } + + if(price<=0) { + await interaction.editReply(localize('economy-system', 'price-less-than-zero')); + return resolve(localize('economy-system', 'price-less-than-zero')); + } + const itemModel = await model.findOne({ where: { [Op.or]: [ @@ -413,8 +422,14 @@ async function updateShopItem(interaction) { const newNameOption = interaction.options.get('item-new-name'); const newPrice = interaction.options.getInteger('new-price'); const newRole = interaction.options.getRole('new-role'); - if (newRole && interaction.guild.me.roles.highest.comparePositionTo(newRole) <= 0) { - return await interaction.editReply(localize('economy-system', 'role-to-high')); + if (newRole && interaction.guild.members.me.roles.highest.comparePositionTo(newRole) <= 0) { + await interaction.editReply(localize('economy-system', 'role-to-high')); + return resolve(localize('economy-system', 'role-to-high')); + } + + if(newPrice !== null && newPrice<=0) { + await interaction.editReply(localize('economy-system', 'price-less-than-zero')); + return resolve(localize('economy-system', 'price-less-than-zero')); } if (newNameOption) { @@ -435,15 +450,13 @@ async function updateShopItem(interaction) { if (newNameOption) { item.name = newNameOption['value']; } - if (newPrice) { + if (newPrice !== null) { item.price = newPrice; } if (newRole) { item.role = newRole['id']; } - console.log(item); - await item.save(); await interaction.editReply(embedType(interaction.client.configurations['economy-system']['strings']['itemEdit'], {