diff --git a/bot/cogs/commands/econ.py b/bot/cogs/commands/econ.py index a2b00869..ec67bdd0 100644 --- a/bot/cogs/commands/econ.py +++ b/bot/cogs/commands/econ.py @@ -2405,6 +2405,142 @@ async def daily_quest(self, ctx: Ctx): if view is not None: view.message = message + @commands.command(name="iteminfo", aliases=["ii"]) + async def item_info(self, ctx: Ctx, *, item_name: str): + FORMATTED_TAGS = { + "4july": "Fourth of July", + "halloween": "Halloween", + "mkwii": "Mario Kart Wii", + "easter": "Easter", + } + FORMATTED_TAGS_FOR_TITLE = { + "mine": f"[{self.d.emojis.netherite_pickaxe_ench}]", + "fish": f"[{self.d.emojis.fishing_rod} ]", + "4july": f"[{self.d.emojis.american_flag} Fourth of July]", + "halloween": "[Halloween]", + "mkwii": f"[{self.d.emojis.item_box} Mario Kart Wii]", + "easter": f"[{self.d.emojis.bunny_ears} Easter]", + } + FORMATTED_TAGS_KEYS = dict([ + (key, idx) for idx, key in enumerate(list(FORMATTED_TAGS_FOR_TITLE)) + ]) + + processed_item_name = item_name.lower().replace(" ", "").replace("'", "") + item_name, item_count = await self.db.fuzzy_fetch_item_and_count(item_name) + + findable_entry: Findable | None + if item_name is None: + # Couldn't find item in database, so no one has it, so try to find it in + # findable entries + findable_entry = next( + ( + fe + for fe in self.d.findables + if fe.item.lower().replace(" ", "").replace("'", "") == processed_item_name + ), + None, + ) + + if findable_entry: + item_name = findable_entry.item + else: + findable_entry = next( + (fe for fe in self.d.findables if fe.item == item_name), + None, + ) + + if item_name is None: + await ctx.reply_embed("No item with the name can be found") + return + + db_item = await self.db.fetch_item(ctx.author.id, item_name) + + item_emoji: str | None = emojify_item(self.d, item_name, default=None) + + embed = discord.Embed(color=self.bot.embed_color) + + embed.title = f"{item_name} {self.d.emojis.air}" + if item_emoji: + embed.title = item_emoji + " " + embed.title + + drop_rate_text = "Not mineable / fishable" + trait_text = "" + + if db_item is not None and db_item.sellable: + trait_text += "💸 Sellable\n" + + if findable_entry: + for findable_tag in sorted( + findable_entry.tags, key=(lambda t: FORMATTED_TAGS_KEYS.get(t, 100)) + ): + if findable_tag in ("mine", "fish") and "disabled" in findable_entry.tags: + continue + + if formatted_tag := FORMATTED_TAGS_FOR_TITLE.get(findable_tag): + embed.title += " " + formatted_tag + + if "disabled" not in findable_entry.tags: + drop_rate_text = "" + if "mine" in findable_entry.tags: + drop_rate_text += f"{self.d.emojis.netherite_pickaxe_ench} Mining: `1/{findable_entry.rarity}`\n" + + if "fish" in findable_entry.tags: + drop_rate_text += ( + f"{self.d.emojis.fishing_rod} Fishing: `1/{findable_entry.rarity}`\n" + ) + + if item_name in ctx.l.econ.item_bible.item_mapping: + embed.description = ( + "\n> \ufeff\n".join([ + f"> {dl.format(prefix=ctx.prefix)}" + for dl in ctx.l.econ.item_bible.item_mapping[item_name].description + ]) + + "\n\ufeff" + ) + + # tradeable: bool | None = None + # if findable_entry is not None: + # tradeable = not findable_entry.sticky + # elif db_item is not None: + # tradeable = not db_item.sticky + + if (findable_entry is not None and not findable_entry.sticky) or ( + db_item is not None and not db_item.sticky + ): + trait_text += "🤝 Tradeable\n" + + if item_name.lower() in self.d.shop_items: + trait_text += "🛍️ Purchaseable in `!!shop`\n" + + if trait_text: + embed.add_field(name="Traits", value=trait_text) + embed.add_field(name="\ufeff", value="\ufeff") + + embed.add_field(name="Drop Rate", value=drop_rate_text) + + embed.add_field( + name="Rarity", + value=f"`{item_count} {'person has this item' if item_count == 1 else 'people have this item'}`", + inline=False, + ) + + if ( + findable_entry + and (item_season := next((t for t in findable_entry.tags if t in FORMATTED_TAGS), None)) + and (season_dates := self.d.findable_seasons.get(item_season)) + ): + item_season_name = FORMATTED_TAGS[item_season] + + formatted_dates = f" ({season_dates[0][0]}/{season_dates[0][1]} - {season_dates[1][0]}/{season_dates[1][1]})" + + embed.add_field( + name="Event / Season", + value=f"{item_season_name}{formatted_dates}", + inline=False, + ) + + await ctx.reply(embed=embed) + # @commands.command(name="fight", aliases=["battle"]) # @commands.is_owner() # @commands.cooldown(1, 1, commands.BucketType.user) diff --git a/bot/cogs/core/database.py b/bot/cogs/core/database.py index 39a141e0..501d9005 100644 --- a/bot/cogs/core/database.py +++ b/bot/cogs/core/database.py @@ -332,6 +332,22 @@ async def remove_item(self, user_id: int, name: str, amount: int) -> None: # update badges await self.badges.update_badge_uncle_scrooge(user_id) + async def fuzzy_fetch_item_and_count(self, name: str) -> tuple[str | None, int]: + result = await self.db.fetchrow( + ( + "SELECT name, COUNT(*) AS count " + "FROM items WHERE " + " REGEXP_REPLACE(LOWER(name), '[''\\s]', '', 'gi') = REGEXP_REPLACE(LOWER($1), '[''\\s]', '', 'gi') " + "GROUP BY name;" + ), + name, + ) + + if result is None: + return None, 0 + + return result["name"], result["count"] + async def log_transaction( self, item: str, diff --git a/bot/data/text/en.json b/bot/data/text/en.json index 4f28c1a8..9885a57e 100644 --- a/bot/data/text/en.json +++ b/bot/data/text/en.json @@ -2236,6 +2236,222 @@ "Pog champ!" ] } + }, + "item_bible": { + "item_mapping": { + "Wood Pickaxe": { + "description": [ + "When mining, has a `5/26` chance of mining up emeralds. Upgrade to a **Stone Pickaxe** to receive better voting rewards." + ] + }, + "Stone Pickaxe": { + "description": [ + "When mining, has a `6/26` chance of mining up emeralds. Upgrade to an **Iron Pickaxe** to receive better voting rewards." + ] + }, + "Iron Pickaxe": { + "description": [ + "When mining, has a `7/26` chance of mining up emeralds. Upgrade to a **Gold Pickaxe** to receive better voting rewards." + ] + }, + "Gold Pickaxe": { + "description": [ + "When mining, has a `9/26` chance of mining up emeralds. Upgrade to a **Diamond Pickaxe** to receive better voting rewards." + ] + }, + "Diamond Pickaxe": { + "description": [ + "When mining, has a `11/26` chance of mining up emeralds. Upgrade to a **Netherite Pickaxe** to receive better voting rewards." + ] + }, + "Netherite Pickaxe": { + "description": [ + "When mining, has a `13/26` chance of mining up emeralds." + ] + }, + "Wood Sword": { + "description": [ + "Deals a base damage of `1-2hp` against mobs." + ] + }, + "Stone Sword": { + "description": [ + "Deals a base damage of `1-3hp` against mobs." + ] + }, + "Iron Sword": { + "description": [ + "Deals a base damage of `2-4hp` against mobs." + ] + }, + "Gold Sword": { + "description": [ + "Deals a base damage of `4-5hp` against mobs." + ] + }, + "Diamond Sword": { + "description": [ + "Deals a base damage of `6-7hp` against mobs." + ] + }, + "Netherite Sword": { + "description": [ + "Deals a base damage of `7-10hp` against mobs." + ] + }, + "Wood Hoe": { + "description": [ + "Allows you to plant up to `10 plots` of farmland using the `{prefix}farm` command." + ] + }, + "Stone Hoe": { + "description": [ + "Allows you to plant up to `20 plots` of farmland using the `{prefix}farm` command." + ] + }, + "Iron Hoe": { + "description": [ + "Allows you to plant up to `30 plots` of farmland using the `{prefix}farm` command." + ] + }, + "Gold Hoe": { + "description": [ + "Allows you to plant up to `40 plots` of farmland using the `{prefix}farm` command." + ] + }, + "Diamond Hoe": { + "description": [ + "Allows you to plant up to `50 plots` of farmland using the `{prefix}farm` command." + ] + }, + "Netherite Hoe": { + "description": [ + "Allows you to plant up to `60 plots` of farmland using the `{prefix}farm` command." + ] + }, + "Fishing Rod": { + "description": [ + "Allows you to fish for **Cod**, **Salmon**, **Tropical Fish**, **Pufferfish**, **Rainbow Trout**, **Gold Fish**, and **Emerald Fish** using the `{prefix}fish` command." + ] + }, + "Vault Potion": { + "description": [ + "Use the vault potion with the `{prefix}use Vault Potion` command to increase your available `{prefix}vault` capacity." + ] + }, + "Haste I Potion": { + "description": [ + "Reduces the `{prefix}mine` command cooldown by `1 second` for `7 minutes`." + ] + }, + "Haste II Potion": { + "description": [ + "Reduces the `{prefix}mine` command cooldown by `2 seconds` for `6 minutes`." + ] + }, + "Fortune I Book": { + "description": [ + "Increases the emerald reward from the `{prefix}mine` command by `1-2 emeralds`.", + "This enchantment book is applied automatically as long as it remains in your inventory, and also transfers to all new pickaxes. This enchantment book does not stack." + ] + }, + "Fortune II Book": { + "description": [ + "Increases the emerald reward from the `{prefix}mine` command by `1-3 emeralds`.", + "This enchantment book is applied automatically as long as it remains in your inventory, and also transfers to all new pickaxes. This enchantment book does not stack." + ] + }, + "Fortune III Book": { + "description": [ + "Increases the emerald reward from the `{prefix}mine` command by `1-4 emeralds`.", + "This enchantment book is applied automatically as long as it remains in your inventory, and also transfers to all new pickaxes. This enchantment book does not stack." + ] + }, + "Sharpness I Book": { + "description": [ + "Increases base sword damage by `25%` (for a total of `125%`) when fighting mobs.", + "This enchantment book is applied automatically as long as it remains in your inventory, and also transfers to all new swords. This enchantment book does not stack." + ] + }, + "Sharpness II Book": { + "description": [ + "Increases base sword damage by `50%` (for a total of `150%`) when fighting mobs.", + "This enchantment book is applied automatically as long as it remains in your inventory, and also transfers to all new swords. This enchantment book does not stack." + ] + }, + "Time Pearl": { + "description": [ + "Upon using the item with the `{prefix}use Time Pearl` command, it fast-forwards time by two days; growing crops, resetting cooldowns for `{prefix}honey`, `{prefix}pillage`, `{prefix}search`, clears all active effects (for example, haste) and consumes the item." + ] + }, + "Shield Pearl": { + "description": [ + "Using this item with the `{prefix}use Shield Pearl` command will allow you to prevent people from pillaging you with the `{prefix}pillage` for up to one month. Using this item will consume it.", + "If you use the `{prefix}pillage` command while a **Shield Pearl** is active, its effect will be cancelled and you will become pillageable." + ] + }, + "Rich Person Trophy": { + "description": [ + "With a **Rich Person Trophy**, you get a bonus to the `{prefix}gamble` command, `200%` emeralds from the `{prefix}trashcan empty` command, `150%` emeralds from opening **Barrel**s, and `200%` emeralds from the `{prefix}mine` command. But remember... **greed has a price**..." + ] + }, + "Jar Of Bees": { + "description": [ + "Purchasing **Jar Of Bees** from the `{prefix}shop` allows you to harvest honey from them daily using the `{prefix}honey` command." + ] + }, + "Glass Beaker": { + "description": [ + "Allows you to transform a **Slime Ball** into a **Beaker Of Slime** with the `{prefix}use Glass Beaker` command, allowing it to be traded with other players." + ] + }, + "Netherite Scrap": { + "description": [ + "This item is required when purchasing certain items from the `{prefix}shop`." + ] + }, + "Slime Trophy": { + "description": [ + "Having this item in your inventory decreases your chances of missing attacks against **Baby Slime**s." + ] + }, + "Fishing Trophy": { + "description": [ + "Having this item in your inventory decreases your chances of fishing up junk when using the `{prefix}fish` command." + ] + }, + "Wheat Seed": { + "description": [ + "You can plant a **Wheat Seed** using the `{prefix}farm plant Wheat Seed` command to grow `1-2` **Wheat**." + ] + }, + "Carrot": { + "description": [ + "You can plant a **Carrot** using the `{prefix}farm plant Carrot` command to grow `1-3` **Carrot**s." + ] + }, + "Potato": { + "description": [ + "You can plant a **Potato** using the `{prefix}farm plant Potato` command to grow `1-3` **Potato**es." + ] + }, + "Melon Seed": { + "description": [ + "You can plant a **Melon Seed** using the `{prefix}farm plant Melon Seed` command to grow `2-5` **Melon**." + ] + }, + "Chorus Seed": { + "description": [ + "You can plant a **Chorus Seed** using the `{prefix}farm plant Chorus Seed` command to grow `1-2` **Chorus Fruit**." + ] + }, + "Infernum's Scroll": { + "description": [ + "Allows you to change (re-roll) your daily quest with the `{prefix}use Infernum's Scroll` command. Using this item consumes it.", + "This item drops from all mobs with a chance of about `1/40` (affected by looting enchantments)." + ] + } + } } } } diff --git a/bot/models/translation.py b/bot/models/translation.py index a0598f94..805960aa 100644 --- a/bot/models/translation.py +++ b/bot/models/translation.py @@ -778,6 +778,14 @@ class Econ_DailyQuests(ImmutableBaseModel): encouragements: Econ_Quests_Encouragements +class Econ_ItemBible_MappingEntry(ImmutableBaseModel): + description: list[str] + + +class Econ_ItemBible(ImmutableBaseModel): + item_mapping: dict[str, Econ_ItemBible_MappingEntry] + + class Econ(ImmutableBaseModel): use_a_number_stupid: str page: str @@ -802,6 +810,7 @@ class Econ(ImmutableBaseModel): lb: Econ_Lb trash: Econ_Trash daily_quests: Econ_DailyQuests + item_bible: Econ_ItemBible class Translation(ImmutableBaseModel):