mirror of
https://github.com/aydenjahola/discord-multipurpose-bot.git
synced 2024-11-22 08:45:55 +00:00
Compare commits
No commits in common. "45fdb3537f7dc9ce4137a4aab7f8e141c5da1d5f" and "e12591e5613c8dcae261390fcd23bed69f27f62d" have entirely different histories.
45fdb3537f
...
e12591e561
10 changed files with 126 additions and 451 deletions
|
@ -4,7 +4,7 @@ const UserEconomy = require("../../models/UserEconomy");
|
||||||
module.exports = {
|
module.exports = {
|
||||||
data: new SlashCommandBuilder()
|
data: new SlashCommandBuilder()
|
||||||
.setName("balance")
|
.setName("balance")
|
||||||
.setDescription("Check your balance."),
|
.setDescription("Check your balance"),
|
||||||
|
|
||||||
async execute(interaction) {
|
async execute(interaction) {
|
||||||
const { user, guild } = interaction;
|
const { user, guild } = interaction;
|
||||||
|
@ -18,20 +18,18 @@ module.exports = {
|
||||||
userEconomy = await UserEconomy.create({
|
userEconomy = await UserEconomy.create({
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
guildId: guild.id,
|
guildId: guild.id,
|
||||||
balance: 0,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const embed = new EmbedBuilder()
|
const embed = new EmbedBuilder()
|
||||||
.setColor("#0099ff")
|
.setColor("#0099ff")
|
||||||
.setTitle(`${user.username}'s Balance`)
|
.setTitle(`${user.username}'s Balance`)
|
||||||
.setDescription(`Your balance: **${userEconomy.balance}** coins.`)
|
.setDescription(`You have **${userEconomy.balance}** coins.`)
|
||||||
|
.setTimestamp()
|
||||||
.setFooter({
|
.setFooter({
|
||||||
text: `Requested by ${user.username}`,
|
text: `Requested by ${user.username}`,
|
||||||
iconURL: user.displayAvatarURL(),
|
iconURL: user.displayAvatarURL(),
|
||||||
})
|
});
|
||||||
.setTimestamp();
|
|
||||||
|
|
||||||
await interaction.reply({ embeds: [embed] });
|
await interaction.reply({ embeds: [embed] });
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,13 +4,11 @@ const UserEconomy = require("../../models/UserEconomy");
|
||||||
module.exports = {
|
module.exports = {
|
||||||
data: new SlashCommandBuilder()
|
data: new SlashCommandBuilder()
|
||||||
.setName("daily")
|
.setName("daily")
|
||||||
.setDescription("Claim your daily reward and start a streak!"),
|
.setDescription("Claim your daily reward"),
|
||||||
|
|
||||||
async execute(interaction) {
|
async execute(interaction) {
|
||||||
const { user, guild } = interaction;
|
const { user, guild } = interaction;
|
||||||
const dailyBaseReward = 100;
|
const dailyReward = 100;
|
||||||
const streakBonus = 10;
|
|
||||||
const rareItemChance = 0.1;
|
|
||||||
const oneDay = 24 * 60 * 60 * 1000;
|
const oneDay = 24 * 60 * 60 * 1000;
|
||||||
|
|
||||||
let userEconomy = await UserEconomy.findOne({
|
let userEconomy = await UserEconomy.findOne({
|
||||||
|
@ -22,13 +20,10 @@ module.exports = {
|
||||||
userEconomy = await UserEconomy.create({
|
userEconomy = await UserEconomy.create({
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
guildId: guild.id,
|
guildId: guild.id,
|
||||||
streak: 0,
|
|
||||||
balance: 0,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
|
|
||||||
if (userEconomy.lastDaily && now - userEconomy.lastDaily < oneDay) {
|
if (userEconomy.lastDaily && now - userEconomy.lastDaily < oneDay) {
|
||||||
const remainingTime =
|
const remainingTime =
|
||||||
new Date(userEconomy.lastDaily.getTime() + oneDay) - now;
|
new Date(userEconomy.lastDaily.getTime() + oneDay) - now;
|
||||||
|
@ -40,50 +35,37 @@ module.exports = {
|
||||||
.setColor("#ff0000")
|
.setColor("#ff0000")
|
||||||
.setTitle("Daily Reward Claim")
|
.setTitle("Daily Reward Claim")
|
||||||
.setDescription(
|
.setDescription(
|
||||||
`Come back in **${hours}h ${minutes}m ${seconds}s** for your next reward!`
|
`You have already claimed your daily reward today. Come back in **${hours}h ${minutes}m ${seconds}s**!`
|
||||||
)
|
)
|
||||||
.setTimestamp()
|
|
||||||
.setFooter({
|
.setFooter({
|
||||||
text: `Requested by ${user.username}`,
|
text: `Requested in ${guild.name}`,
|
||||||
iconURL: user.displayAvatarURL(),
|
iconURL: guild.iconURL() || null,
|
||||||
});
|
});
|
||||||
|
|
||||||
await interaction.reply({ embeds: [errorEmbed] });
|
await interaction.reply({ embeds: [errorEmbed] });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (userEconomy.lastDaily && now - userEconomy.lastDaily >= oneDay) {
|
userEconomy.balance += dailyReward;
|
||||||
userEconomy.streak = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
userEconomy.streak += 1;
|
|
||||||
const reward = dailyBaseReward + userEconomy.streak * streakBonus;
|
|
||||||
userEconomy.lastDaily = now;
|
userEconomy.lastDaily = now;
|
||||||
userEconomy.balance += reward;
|
|
||||||
|
|
||||||
const rareItemEarned = Math.random() < rareItemChance;
|
|
||||||
const rareItemMessage = rareItemEarned
|
|
||||||
? "\nYou also found a **rare item** in your reward!"
|
|
||||||
: "";
|
|
||||||
|
|
||||||
await userEconomy.save();
|
await userEconomy.save();
|
||||||
|
|
||||||
const successEmbed = new EmbedBuilder()
|
const successEmbed = new EmbedBuilder()
|
||||||
.setColor("#00ff00")
|
.setColor("#00ff00")
|
||||||
.setTitle("Daily Reward Claimed!")
|
.setTitle("Daily Reward Claimed!")
|
||||||
.setDescription(
|
.setDescription(
|
||||||
`You've claimed **${reward}** coins and extended your streak!${rareItemMessage}`
|
`You claimed your daily reward of **${dailyReward}** coins!`
|
||||||
)
|
)
|
||||||
.addFields({
|
.addFields({
|
||||||
name: "Streak Bonus",
|
name: "Total Balance",
|
||||||
value: `Current streak: **${userEconomy.streak}** days`,
|
value: `You now have **${userEconomy.balance}** coins.`,
|
||||||
inline: true,
|
inline: true,
|
||||||
})
|
})
|
||||||
|
.setTimestamp()
|
||||||
.setFooter({
|
.setFooter({
|
||||||
text: `Requested by ${user.username}`,
|
text: `Requested by ${user.username}`,
|
||||||
iconURL: user.displayAvatarURL(),
|
iconURL: user.displayAvatarURL(),
|
||||||
})
|
});
|
||||||
.setTimestamp();
|
|
||||||
|
|
||||||
await interaction.reply({ embeds: [successEmbed] });
|
await interaction.reply({ embeds: [successEmbed] });
|
||||||
},
|
},
|
||||||
|
|
|
@ -5,10 +5,11 @@ const ShopItem = require("../../models/ShopItem");
|
||||||
module.exports = {
|
module.exports = {
|
||||||
data: new SlashCommandBuilder()
|
data: new SlashCommandBuilder()
|
||||||
.setName("inventory")
|
.setName("inventory")
|
||||||
.setDescription("View your inventory with item rarity"),
|
.setDescription("View your inventory"),
|
||||||
|
|
||||||
async execute(interaction) {
|
async execute(interaction) {
|
||||||
const { user, guild } = interaction;
|
const { user, guild } = interaction;
|
||||||
|
|
||||||
const inventory = await UserInventory.find({
|
const inventory = await UserInventory.find({
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
guildId: guild.id,
|
guildId: guild.id,
|
||||||
|
@ -19,10 +20,9 @@ module.exports = {
|
||||||
.setColor("#ff0000")
|
.setColor("#ff0000")
|
||||||
.setTitle("Inventory")
|
.setTitle("Inventory")
|
||||||
.setDescription("Your inventory is empty.")
|
.setDescription("Your inventory is empty.")
|
||||||
.setTimestamp()
|
|
||||||
.setFooter({
|
.setFooter({
|
||||||
text: `Requested by ${user.username}`,
|
text: `Requested in ${guild.name}`,
|
||||||
iconURL: user.displayAvatarURL(),
|
iconURL: guild.iconURL() || null,
|
||||||
});
|
});
|
||||||
|
|
||||||
await interaction.reply({ embeds: [emptyEmbed] });
|
await interaction.reply({ embeds: [emptyEmbed] });
|
||||||
|
@ -32,17 +32,8 @@ module.exports = {
|
||||||
const itemDetails = await Promise.all(
|
const itemDetails = await Promise.all(
|
||||||
inventory.map(async (item) => {
|
inventory.map(async (item) => {
|
||||||
const shopItem = await ShopItem.findOne({ itemId: item.itemId });
|
const shopItem = await ShopItem.findOne({ itemId: item.itemId });
|
||||||
|
|
||||||
if (!shopItem) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item.quantity > 0) {
|
if (item.quantity > 0) {
|
||||||
return `${shopItem.name} (x${item.quantity}) - **Rarity**: ${
|
return `${shopItem.name} (x${item.quantity})`;
|
||||||
shopItem.rarity
|
|
||||||
} - **Type**: ${shopItem.type} - **Category**: ${
|
|
||||||
shopItem.category || "N/A"
|
|
||||||
}`;
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
})
|
})
|
||||||
|
@ -50,12 +41,24 @@ module.exports = {
|
||||||
|
|
||||||
const filteredItemDetails = itemDetails.filter((detail) => detail !== null);
|
const filteredItemDetails = itemDetails.filter((detail) => detail !== null);
|
||||||
|
|
||||||
|
if (filteredItemDetails.length === 0) {
|
||||||
|
const noItemsEmbed = new EmbedBuilder()
|
||||||
|
.setColor("#ff0000")
|
||||||
|
.setTitle("Inventory")
|
||||||
|
.setDescription("Your inventory is empty.")
|
||||||
|
.setFooter({
|
||||||
|
text: `Requested in ${guild.name}`,
|
||||||
|
iconURL: guild.iconURL() || null,
|
||||||
|
});
|
||||||
|
|
||||||
|
await interaction.reply({ embeds: [noItemsEmbed] });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const inventoryEmbed = new EmbedBuilder()
|
const inventoryEmbed = new EmbedBuilder()
|
||||||
.setColor("#00ff00")
|
.setColor("#00ff00")
|
||||||
.setTitle(`${user.username}'s Inventory`)
|
.setTitle(`${user.username}'s Inventory`)
|
||||||
.setDescription(
|
.setDescription(filteredItemDetails.join("\n"))
|
||||||
filteredItemDetails.join("\n") || "No items in inventory."
|
|
||||||
)
|
|
||||||
.setTimestamp()
|
.setTimestamp()
|
||||||
.setFooter({
|
.setFooter({
|
||||||
text: `Requested by ${user.username}`,
|
text: `Requested by ${user.username}`,
|
||||||
|
|
|
@ -1,208 +0,0 @@
|
||||||
const {
|
|
||||||
SlashCommandBuilder,
|
|
||||||
EmbedBuilder,
|
|
||||||
ActionRowBuilder,
|
|
||||||
StringSelectMenuBuilder,
|
|
||||||
} = require("discord.js");
|
|
||||||
const UserInventory = require("../../models/UserInventory");
|
|
||||||
const ShopItem = require("../../models/ShopItem");
|
|
||||||
const UserEconomy = require("../../models/UserEconomy");
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
data: new SlashCommandBuilder()
|
|
||||||
.setName("sell")
|
|
||||||
.setDescription("Sell an item from your inventory."),
|
|
||||||
|
|
||||||
async execute(interaction) {
|
|
||||||
const { user, guild } = interaction;
|
|
||||||
|
|
||||||
const userInventory = await UserInventory.find({
|
|
||||||
userId: user.id,
|
|
||||||
guildId: guild.id,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (userInventory.length === 0) {
|
|
||||||
const errorEmbed = new EmbedBuilder()
|
|
||||||
.setColor("#ff0000")
|
|
||||||
.setTitle("🛑 Inventory Empty")
|
|
||||||
.setDescription("You have no items in your inventory to sell.")
|
|
||||||
.setTimestamp()
|
|
||||||
.setFooter({
|
|
||||||
text: `Requested by ${user.username}`,
|
|
||||||
iconURL: user.displayAvatarURL(),
|
|
||||||
});
|
|
||||||
|
|
||||||
await interaction.reply({ embeds: [errorEmbed], ephemeral: false });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const selectMenu = new StringSelectMenuBuilder()
|
|
||||||
.setCustomId("sell_item")
|
|
||||||
.setPlaceholder("Select an item to sell")
|
|
||||||
.addOptions(
|
|
||||||
userInventory.map((item) => ({
|
|
||||||
label: item.itemId,
|
|
||||||
value: item.itemId,
|
|
||||||
}))
|
|
||||||
);
|
|
||||||
|
|
||||||
const row = new ActionRowBuilder().addComponents(selectMenu);
|
|
||||||
|
|
||||||
const promptEmbed = new EmbedBuilder()
|
|
||||||
.setColor("#00ffff")
|
|
||||||
.setTitle("📦 Select Item to Sell")
|
|
||||||
.setDescription(
|
|
||||||
"Choose an item from your inventory to sell. The selling price is 50% less than the original item price."
|
|
||||||
)
|
|
||||||
.setTimestamp()
|
|
||||||
.setFooter({
|
|
||||||
text: `Requested by ${user.username}`,
|
|
||||||
iconURL: user.displayAvatarURL(),
|
|
||||||
});
|
|
||||||
|
|
||||||
await interaction.reply({ embeds: [promptEmbed], components: [row] });
|
|
||||||
|
|
||||||
const filter = (i) => {
|
|
||||||
return i.user.id === user.id;
|
|
||||||
};
|
|
||||||
|
|
||||||
const collector = interaction.channel.createMessageComponentCollector({
|
|
||||||
filter,
|
|
||||||
time: 15000,
|
|
||||||
});
|
|
||||||
|
|
||||||
collector.on("collect", async (i) => {
|
|
||||||
if (i.customId === "sell_item") {
|
|
||||||
const selectedItemId = i.values[0];
|
|
||||||
const selectedItem = userInventory.find(
|
|
||||||
(item) => item.itemId === selectedItemId
|
|
||||||
);
|
|
||||||
|
|
||||||
const shopItem = await ShopItem.findOne({
|
|
||||||
itemId: selectedItemId,
|
|
||||||
guildId: guild.id,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!shopItem) {
|
|
||||||
await i.reply({
|
|
||||||
content: "Item not found in the shop.",
|
|
||||||
ephemeral: false,
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const sellingPrice = Math.floor(shopItem.price / 2);
|
|
||||||
|
|
||||||
const quantityPrompt = new EmbedBuilder()
|
|
||||||
.setColor("#ffff00")
|
|
||||||
.setTitle(`💰 Selling ${shopItem.name}`)
|
|
||||||
.setDescription(
|
|
||||||
`How many of **${shopItem.name}** would you like to sell?`
|
|
||||||
)
|
|
||||||
.addFields({
|
|
||||||
name: "Sell Price",
|
|
||||||
value: `Each item sells for **${sellingPrice}** coins.`,
|
|
||||||
inline: true,
|
|
||||||
})
|
|
||||||
.setTimestamp()
|
|
||||||
.setFooter({
|
|
||||||
text: `Requested by ${user.username}`,
|
|
||||||
iconURL: user.displayAvatarURL(),
|
|
||||||
});
|
|
||||||
|
|
||||||
await i.reply({ embeds: [quantityPrompt], ephemeral: false });
|
|
||||||
|
|
||||||
const quantityFilter = (response) => {
|
|
||||||
return (
|
|
||||||
response.author.id === user.id &&
|
|
||||||
!isNaN(response.content) &&
|
|
||||||
response.content > 0
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const quantityCollector = interaction.channel.createMessageCollector({
|
|
||||||
filter: quantityFilter,
|
|
||||||
time: 15000,
|
|
||||||
});
|
|
||||||
|
|
||||||
quantityCollector.on("collect", async (response) => {
|
|
||||||
const quantityToSell = parseInt(response.content);
|
|
||||||
|
|
||||||
if (quantityToSell > selectedItem.quantity) {
|
|
||||||
await response.reply({
|
|
||||||
content: `You do not have enough **${shopItem.name}** to sell!`,
|
|
||||||
ephemeral: false,
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let userEconomy = await UserEconomy.findOne({
|
|
||||||
userId: user.id,
|
|
||||||
guildId: guild.id,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!userEconomy) {
|
|
||||||
userEconomy = await UserEconomy.create({
|
|
||||||
userId: user.id,
|
|
||||||
guildId: guild.id,
|
|
||||||
balance: 0,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
userEconomy.balance += sellingPrice * quantityToSell;
|
|
||||||
await userEconomy.save();
|
|
||||||
|
|
||||||
selectedItem.quantity -= quantityToSell;
|
|
||||||
if (selectedItem.quantity === 0) {
|
|
||||||
await UserInventory.deleteOne({
|
|
||||||
userId: user.id,
|
|
||||||
itemId: selectedItemId,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
await selectedItem.save();
|
|
||||||
}
|
|
||||||
|
|
||||||
const successEmbed = new EmbedBuilder()
|
|
||||||
.setColor("#00ff00")
|
|
||||||
.setTitle("🎉 Item Sold!")
|
|
||||||
.setDescription(
|
|
||||||
`You sold **${quantityToSell}** of **${shopItem.name}** for **${
|
|
||||||
sellingPrice * quantityToSell
|
|
||||||
}** coins!`
|
|
||||||
)
|
|
||||||
.addFields({
|
|
||||||
name: "New Balance",
|
|
||||||
value: `${userEconomy.balance} coins`,
|
|
||||||
inline: true,
|
|
||||||
})
|
|
||||||
.setFooter({
|
|
||||||
text: `Requested by ${user.username}`,
|
|
||||||
iconURL: user.displayAvatarURL(),
|
|
||||||
})
|
|
||||||
.setTimestamp();
|
|
||||||
|
|
||||||
await response.reply({ embeds: [successEmbed], ephemeral: false });
|
|
||||||
quantityCollector.stop();
|
|
||||||
});
|
|
||||||
|
|
||||||
quantityCollector.on("end", async (collected) => {
|
|
||||||
if (collected.size === 0) {
|
|
||||||
await i.followUp({
|
|
||||||
content: "You did not respond in time to sell the item.",
|
|
||||||
ephemeral: false,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
collector.on("end", async (collected) => {
|
|
||||||
if (collected.size === 0) {
|
|
||||||
await interaction.followUp({
|
|
||||||
content: "You did not select an item in time.",
|
|
||||||
ephemeral: false,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
};
|
|
|
@ -6,119 +6,96 @@ const UserInventory = require("../../models/UserInventory");
|
||||||
module.exports = {
|
module.exports = {
|
||||||
data: new SlashCommandBuilder()
|
data: new SlashCommandBuilder()
|
||||||
.setName("shop")
|
.setName("shop")
|
||||||
.setDescription("Browse the shop for items with rarity and discounts!")
|
.setDescription("View the shop and buy items")
|
||||||
.addStringOption((option) =>
|
.addStringOption((option) =>
|
||||||
option
|
option.setName("item").setDescription("The ID of the item to buy")
|
||||||
.setName("item")
|
|
||||||
.setDescription("The item you want to buy (use item name)")
|
|
||||||
.setRequired(false)
|
|
||||||
),
|
),
|
||||||
|
|
||||||
async execute(interaction) {
|
async execute(interaction) {
|
||||||
const { user, guild } = interaction;
|
const { user, guild } = interaction;
|
||||||
const discountChance = 0.3;
|
const itemId = interaction.options.getString("item");
|
||||||
const itemName = interaction.options.getString("item");
|
|
||||||
|
|
||||||
const items = await ShopItem.find({ guildId: guild.id });
|
if (!itemId) {
|
||||||
|
const items = await ShopItem.find();
|
||||||
if (items.length === 0) {
|
const itemDescriptions = items.map(
|
||||||
const emptyEmbed = new EmbedBuilder()
|
(item) => `**${item.itemId}**: ${item.name} - **${item.price}** coins`
|
||||||
.setColor("#ff0000")
|
|
||||||
.setTitle("🛒 Shop Items")
|
|
||||||
.setDescription("No items in the shop currently.")
|
|
||||||
.setTimestamp()
|
|
||||||
.setFooter({
|
|
||||||
text: `Requested by ${user.username}`,
|
|
||||||
iconURL: user.displayAvatarURL(),
|
|
||||||
});
|
|
||||||
|
|
||||||
await interaction.reply({ embeds: [emptyEmbed] });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (itemName) {
|
|
||||||
const item = items.find(
|
|
||||||
(item) => item.name.toLowerCase() === itemName.toLowerCase()
|
|
||||||
);
|
);
|
||||||
if (!item) {
|
|
||||||
await interaction.reply({
|
const shopEmbed = new EmbedBuilder()
|
||||||
content: "Item not found in the shop!",
|
.setColor("#00bfff")
|
||||||
ephemeral: false,
|
.setTitle("🛒 Shop Items")
|
||||||
|
.setDescription(
|
||||||
|
itemDescriptions.length > 0
|
||||||
|
? itemDescriptions.join("\n")
|
||||||
|
: "No items available at the moment."
|
||||||
|
)
|
||||||
|
.setFooter({
|
||||||
|
text: `Requested in ${guild.name}`,
|
||||||
|
iconURL: guild.iconURL() || null,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await interaction.reply({ embeds: [shopEmbed] });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let userEconomy = await UserEconomy.findOne({
|
const shopItem = await ShopItem.findOne({ itemId });
|
||||||
userId: user.id,
|
if (!shopItem) {
|
||||||
guildId: guild.id,
|
const notFoundEmbed = new EmbedBuilder()
|
||||||
});
|
.setColor("#ff0000")
|
||||||
if (!userEconomy) {
|
.setTitle("❌ Item Not Found")
|
||||||
userEconomy = await UserEconomy.create({
|
.setDescription("The specified item could not be found in the shop.")
|
||||||
userId: user.id,
|
.setFooter({
|
||||||
guildId: guild.id,
|
text: `Requested in ${guild.name}`,
|
||||||
|
iconURL: guild.iconURL() || null,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await interaction.reply({ embeds: [notFoundEmbed] });
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const discount = Math.random() < discountChance ? 0.8 : 1;
|
const userEconomy = await UserEconomy.findOne({
|
||||||
const discountedPrice = Math.floor(item.price * discount);
|
userId: user.id,
|
||||||
|
guildId: guild.id,
|
||||||
if (userEconomy.balance < discountedPrice) {
|
});
|
||||||
|
if (!userEconomy || userEconomy.balance < shopItem.price) {
|
||||||
const insufficientFundsEmbed = new EmbedBuilder()
|
const insufficientFundsEmbed = new EmbedBuilder()
|
||||||
.setColor("#ff0000")
|
.setColor("#ff0000")
|
||||||
.setTitle("💸 Insufficient Funds")
|
.setTitle("💸 Insufficient Funds")
|
||||||
.setDescription(
|
.setDescription("You don't have enough coins to purchase this item.")
|
||||||
`You don't have enough coins to buy **${item.name}**!`
|
|
||||||
)
|
|
||||||
.addFields(
|
|
||||||
{
|
|
||||||
name: "Your Balance",
|
|
||||||
value: `${userEconomy.balance} coins`,
|
|
||||||
inline: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Item Price",
|
|
||||||
value: `${discountedPrice} coins`,
|
|
||||||
inline: true,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.setTimestamp()
|
|
||||||
.setFooter({
|
.setFooter({
|
||||||
text: `Requested by ${user.username}`,
|
text: `Requested in ${guild.name}`,
|
||||||
iconURL: user.displayAvatarURL(),
|
iconURL: guild.iconURL() || null,
|
||||||
});
|
});
|
||||||
|
|
||||||
await interaction.reply({
|
await interaction.reply({ embeds: [insufficientFundsEmbed] });
|
||||||
embeds: [insufficientFundsEmbed],
|
|
||||||
ephemeral: false,
|
|
||||||
});
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
userEconomy.balance -= discountedPrice;
|
userEconomy.balance -= shopItem.price;
|
||||||
await userEconomy.save();
|
await userEconomy.save();
|
||||||
|
|
||||||
const userInventory = await UserInventory.findOne({
|
let userInventory = await UserInventory.findOne({
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
guildId: guild.id,
|
guildId: guild.id,
|
||||||
itemId: item.itemId,
|
itemId,
|
||||||
});
|
});
|
||||||
if (userInventory) {
|
if (userInventory) {
|
||||||
userInventory.quantity += 1;
|
userInventory.quantity += 1;
|
||||||
await userInventory.save();
|
|
||||||
} else {
|
} else {
|
||||||
await UserInventory.create({
|
userInventory = new UserInventory({
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
guildId: guild.id,
|
guildId: guild.id,
|
||||||
itemId: item.itemId,
|
itemId,
|
||||||
quantity: 1,
|
quantity: 1,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
await userInventory.save();
|
||||||
|
|
||||||
const successEmbed = new EmbedBuilder()
|
const successEmbed = new EmbedBuilder()
|
||||||
.setColor("#00ff00")
|
.setColor("#00ff00")
|
||||||
.setTitle("🎉 Purchase Successful")
|
.setTitle("🎉 Purchase Successful")
|
||||||
.setDescription(
|
.setDescription(
|
||||||
`You bought **${item.name}** for **${discountedPrice}** coins!`
|
`You've successfully purchased **${shopItem.name}** for **${shopItem.price}** coins!`
|
||||||
)
|
)
|
||||||
.setTimestamp()
|
.setTimestamp()
|
||||||
.setFooter({
|
.setFooter({
|
||||||
|
@ -126,30 +103,6 @@ module.exports = {
|
||||||
iconURL: user.displayAvatarURL(),
|
iconURL: user.displayAvatarURL(),
|
||||||
});
|
});
|
||||||
|
|
||||||
await interaction.reply({ embeds: [successEmbed], ephemeral: false });
|
await interaction.reply({ embeds: [successEmbed] });
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const shopItemsDetails = items.map((item) => {
|
|
||||||
const discount = Math.random() < discountChance ? 0.8 : 1;
|
|
||||||
const price = Math.floor(item.price * discount);
|
|
||||||
const discountText = discount < 1 ? " (Discounted!)" : "";
|
|
||||||
|
|
||||||
return `${item.name} - **${price}** coins${discountText} - Rarity: ${
|
|
||||||
item.rarity
|
|
||||||
} - Type: ${item.type} - Category: ${item.category || "N/A"}`;
|
|
||||||
});
|
|
||||||
|
|
||||||
const shopEmbed = new EmbedBuilder()
|
|
||||||
.setColor("#00ff00")
|
|
||||||
.setTitle("🛒 Shop Items")
|
|
||||||
.setDescription(shopItemsDetails.join("\n"))
|
|
||||||
.setTimestamp()
|
|
||||||
.setFooter({
|
|
||||||
text: `Requested by ${user.username}`,
|
|
||||||
iconURL: user.displayAvatarURL(),
|
|
||||||
});
|
|
||||||
|
|
||||||
await interaction.reply({ embeds: [shopEmbed] });
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,35 +4,29 @@ const UserEconomy = require("../../models/UserEconomy");
|
||||||
module.exports = {
|
module.exports = {
|
||||||
data: new SlashCommandBuilder()
|
data: new SlashCommandBuilder()
|
||||||
.setName("work")
|
.setName("work")
|
||||||
.setDescription("Work to earn coins and experience random events!"),
|
.setDescription("Work to earn coins!"),
|
||||||
|
|
||||||
async execute(interaction) {
|
async execute(interaction) {
|
||||||
const { user, guild } = interaction;
|
const { user, guild } = interaction;
|
||||||
const jobs = [
|
const workReward = 100;
|
||||||
{ name: "Farmer", reward: 100 },
|
const cooldownTime = 60 * 60 * 1000;
|
||||||
{ name: "Miner", reward: 150 },
|
|
||||||
{ name: "Chef", reward: 120 },
|
|
||||||
{ name: "Artist", reward: 130 },
|
|
||||||
];
|
|
||||||
const randomJob = jobs[Math.floor(Math.random() * jobs.length)];
|
|
||||||
const randomBonus =
|
|
||||||
Math.random() < 0.1 ? Math.floor(Math.random() * 200) : 0;
|
|
||||||
const workReward = randomJob.reward + randomBonus;
|
|
||||||
|
|
||||||
let userEconomy = await UserEconomy.findOne({
|
let userEconomy = await UserEconomy.findOne({
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
guildId: guild.id,
|
guildId: guild.id,
|
||||||
});
|
});
|
||||||
const cooldownTime = 60 * 60 * 1000;
|
|
||||||
|
|
||||||
if (!userEconomy) {
|
if (!userEconomy) {
|
||||||
userEconomy = await UserEconomy.create({
|
userEconomy = await UserEconomy.create({
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
guildId: guild.id,
|
guildId: guild.id,
|
||||||
|
lastWork: null,
|
||||||
|
balance: 0,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
|
|
||||||
if (userEconomy.lastWork && now - userEconomy.lastWork < cooldownTime) {
|
if (userEconomy.lastWork && now - userEconomy.lastWork < cooldownTime) {
|
||||||
const remainingTime = cooldownTime - (now - userEconomy.lastWork);
|
const remainingTime = cooldownTime - (now - userEconomy.lastWork);
|
||||||
const remainingMinutes = Math.ceil(remainingTime / (60 * 1000));
|
const remainingMinutes = Math.ceil(remainingTime / (60 * 1000));
|
||||||
|
@ -60,9 +54,12 @@ module.exports = {
|
||||||
const successEmbed = new EmbedBuilder()
|
const successEmbed = new EmbedBuilder()
|
||||||
.setColor("#00ff00")
|
.setColor("#00ff00")
|
||||||
.setTitle("Work Success")
|
.setTitle("Work Success")
|
||||||
.setDescription(
|
.setDescription(`You worked hard and earned **${workReward}** coins!`)
|
||||||
`You worked as a **${randomJob.name}** and earned **${workReward}** coins!`
|
.addFields({
|
||||||
)
|
name: "Total Balance",
|
||||||
|
value: `${userEconomy.balance} coins`,
|
||||||
|
inline: true,
|
||||||
|
})
|
||||||
.setTimestamp()
|
.setTimestamp()
|
||||||
.setFooter({
|
.setFooter({
|
||||||
text: `Requested by ${user.username}`,
|
text: `Requested by ${user.username}`,
|
||||||
|
|
12
index.js
12
index.js
|
@ -62,14 +62,11 @@ client.once("ready", async () => {
|
||||||
console.log(`🤖 Logged in as ${client.user.tag}`);
|
console.log(`🤖 Logged in as ${client.user.tag}`);
|
||||||
console.log(`==============================`);
|
console.log(`==============================`);
|
||||||
|
|
||||||
|
// Seed the shop items
|
||||||
|
await seedShopItems();
|
||||||
|
|
||||||
// Register commands for all existing guilds
|
// Register commands for all existing guilds
|
||||||
const guilds = client.guilds.cache.map((guild) => guild.id);
|
const guilds = client.guilds.cache.map((guild) => guild.id);
|
||||||
|
|
||||||
// Seed the shop items
|
|
||||||
for (const guildId of guilds) {
|
|
||||||
await seedShopItems(guildId); // Pass guildId to seedShopItems
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const guildId of guilds) {
|
for (const guildId of guilds) {
|
||||||
await registerCommands(guildId);
|
await registerCommands(guildId);
|
||||||
}
|
}
|
||||||
|
@ -90,9 +87,6 @@ client.on("guildCreate", async (guild) => {
|
||||||
await ServerSettings.create({ guildId: guild.id });
|
await ServerSettings.create({ guildId: guild.id });
|
||||||
console.log(`✅ Registered new server: ${guild.name} (ID: ${guild.id})`);
|
console.log(`✅ Registered new server: ${guild.name} (ID: ${guild.id})`);
|
||||||
|
|
||||||
// seed items for new guild with guildId
|
|
||||||
await seedShopItems(guild.id);
|
|
||||||
|
|
||||||
// Register slash commands for the new guild
|
// Register slash commands for the new guild
|
||||||
await registerCommands(guild.id);
|
await registerCommands(guild.id);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
|
@ -1,18 +1,10 @@
|
||||||
const mongoose = require("mongoose");
|
const mongoose = require("mongoose");
|
||||||
|
|
||||||
const shopItemSchema = new mongoose.Schema({
|
const shopItemSchema = new mongoose.Schema({
|
||||||
itemId: { type: String, required: true },
|
itemId: { type: String, required: true, unique: true },
|
||||||
guildId: { type: String, required: true },
|
|
||||||
name: { type: String, required: true },
|
name: { type: String, required: true },
|
||||||
price: { type: Number, required: true },
|
price: { type: Number, required: true },
|
||||||
description: { type: String, required: true },
|
description: { type: String, required: true },
|
||||||
rarity: {
|
|
||||||
type: String,
|
|
||||||
enum: ["Common", "Rare", "Epic", "Legendary"],
|
|
||||||
default: "Common",
|
|
||||||
},
|
|
||||||
type: { type: String, required: true },
|
|
||||||
category: { type: String },
|
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = mongoose.model("ShopItem", shopItemSchema);
|
module.exports = mongoose.model("ShopItem", shopItemSchema);
|
||||||
|
|
|
@ -6,7 +6,6 @@ const userEconomySchema = new mongoose.Schema({
|
||||||
balance: { type: Number, default: 200 },
|
balance: { type: Number, default: 200 },
|
||||||
lastDaily: { type: Date, default: null },
|
lastDaily: { type: Date, default: null },
|
||||||
lastWork: { type: Date, default: null },
|
lastWork: { type: Date, default: null },
|
||||||
streak: { type: Number, default: 0 },
|
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = mongoose.model("UserEconomy", userEconomySchema);
|
module.exports = mongoose.model("UserEconomy", userEconomySchema);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
const ShopItem = require("../models/ShopItem");
|
const ShopItem = require("../models/ShopItem");
|
||||||
|
|
||||||
async function seedShopItems(guildId) {
|
async function seedShopItems() {
|
||||||
const items = [
|
const items = [
|
||||||
// Valorant Skins
|
// Valorant Skins
|
||||||
{
|
{
|
||||||
|
@ -9,9 +9,6 @@ async function seedShopItems(guildId) {
|
||||||
price: 1200,
|
price: 1200,
|
||||||
description:
|
description:
|
||||||
"A futuristic skin for the Vandal with a sleek design and special effects.",
|
"A futuristic skin for the Vandal with a sleek design and special effects.",
|
||||||
rarity: "Rare",
|
|
||||||
type: "Skin",
|
|
||||||
category: "Valorant",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
itemId: "reaver_vandal",
|
itemId: "reaver_vandal",
|
||||||
|
@ -19,9 +16,6 @@ async function seedShopItems(guildId) {
|
||||||
price: 1500,
|
price: 1500,
|
||||||
description:
|
description:
|
||||||
"One of the most popular Vandal skins with a haunting aesthetic and special animations.",
|
"One of the most popular Vandal skins with a haunting aesthetic and special animations.",
|
||||||
rarity: "Epic",
|
|
||||||
type: "Skin",
|
|
||||||
category: "Valorant",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
itemId: "sovereign_ghost",
|
itemId: "sovereign_ghost",
|
||||||
|
@ -29,9 +23,6 @@ async function seedShopItems(guildId) {
|
||||||
price: 800,
|
price: 800,
|
||||||
description:
|
description:
|
||||||
"Golden elegance for the Ghost pistol with unique sound effects.",
|
"Golden elegance for the Ghost pistol with unique sound effects.",
|
||||||
rarity: "Common",
|
|
||||||
type: "Skin",
|
|
||||||
category: "Valorant",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
itemId: "araxys_operator",
|
itemId: "araxys_operator",
|
||||||
|
@ -39,9 +30,6 @@ async function seedShopItems(guildId) {
|
||||||
price: 2000,
|
price: 2000,
|
||||||
description:
|
description:
|
||||||
"A top-tier sniper skin with alien-like animations and sound effects.",
|
"A top-tier sniper skin with alien-like animations and sound effects.",
|
||||||
rarity: "Legendary",
|
|
||||||
type: "Skin",
|
|
||||||
category: "Valorant",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
itemId: "glitchpop_bulldog",
|
itemId: "glitchpop_bulldog",
|
||||||
|
@ -49,9 +37,6 @@ async function seedShopItems(guildId) {
|
||||||
price: 900,
|
price: 900,
|
||||||
description:
|
description:
|
||||||
"A flashy skin for the Bulldog with vibrant colors and cyberpunk vibe.",
|
"A flashy skin for the Bulldog with vibrant colors and cyberpunk vibe.",
|
||||||
rarity: "Rare",
|
|
||||||
type: "Skin",
|
|
||||||
category: "Valorant",
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// CS2 Skins
|
// CS2 Skins
|
||||||
|
@ -61,9 +46,6 @@ async function seedShopItems(guildId) {
|
||||||
price: 2500,
|
price: 2500,
|
||||||
description:
|
description:
|
||||||
"A legendary skin for the AWP with dragon designs, a rare and coveted item.",
|
"A legendary skin for the AWP with dragon designs, a rare and coveted item.",
|
||||||
rarity: "Legendary",
|
|
||||||
type: "Skin",
|
|
||||||
category: "CS2",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
itemId: "ak47_redline",
|
itemId: "ak47_redline",
|
||||||
|
@ -71,9 +53,6 @@ async function seedShopItems(guildId) {
|
||||||
price: 1000,
|
price: 1000,
|
||||||
description:
|
description:
|
||||||
"A simple yet iconic AK-47 skin with red and black color scheme.",
|
"A simple yet iconic AK-47 skin with red and black color scheme.",
|
||||||
rarity: "Common",
|
|
||||||
type: "Skin",
|
|
||||||
category: "CS2",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
itemId: "m4a4_howl",
|
itemId: "m4a4_howl",
|
||||||
|
@ -81,9 +60,6 @@ async function seedShopItems(guildId) {
|
||||||
price: 2200,
|
price: 2200,
|
||||||
description:
|
description:
|
||||||
"A rare and valuable skin for the M4A4 with a striking wolf design.",
|
"A rare and valuable skin for the M4A4 with a striking wolf design.",
|
||||||
rarity: "Epic",
|
|
||||||
type: "Skin",
|
|
||||||
category: "CS2",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
itemId: "desert_eagle_kumicho_dragon",
|
itemId: "desert_eagle_kumicho_dragon",
|
||||||
|
@ -91,9 +67,6 @@ async function seedShopItems(guildId) {
|
||||||
price: 800,
|
price: 800,
|
||||||
description:
|
description:
|
||||||
"A Desert Eagle skin with an intricate dragon design and a metallic finish.",
|
"A Desert Eagle skin with an intricate dragon design and a metallic finish.",
|
||||||
rarity: "Rare",
|
|
||||||
type: "Skin",
|
|
||||||
category: "CS2",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
itemId: "usp_kill_confirmed",
|
itemId: "usp_kill_confirmed",
|
||||||
|
@ -101,22 +74,14 @@ async function seedShopItems(guildId) {
|
||||||
price: 1100,
|
price: 1100,
|
||||||
description:
|
description:
|
||||||
"A detailed skin for the USP-S with a unique comic-style design.",
|
"A detailed skin for the USP-S with a unique comic-style design.",
|
||||||
rarity: "Epic",
|
|
||||||
type: "Skin",
|
|
||||||
category: "CS2",
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
// Upsert each item with guildId included, so changes to price, rarity, etc., get updated
|
|
||||||
for (const item of items) {
|
for (const item of items) {
|
||||||
await ShopItem.updateOne(
|
await ShopItem.updateOne({ itemId: item.itemId }, item, { upsert: true });
|
||||||
{ itemId: item.itemId, guildId },
|
|
||||||
{ ...item, guildId },
|
|
||||||
{ upsert: true }
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`✅ Shop items seeded with rarity for guild: ${guildId}`);
|
console.log("✅ Shop items seeded!");
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = seedShopItems;
|
module.exports = seedShopItems;
|
||||||
|
|
Loading…
Reference in a new issue