From b0a82ed07e285227404aea470ba4559b0f6fb80a Mon Sep 17 00:00:00 2001 From: neoarz Date: Thu, 2 Oct 2025 21:07:45 -0400 Subject: [PATCH] feat(dictonary):new command --- cogs/utilities/__init__.py | 22 +++++- cogs/utilities/dictionary.py | 147 +++++++++++++++++++++++++++++++++++ 2 files changed, 168 insertions(+), 1 deletion(-) create mode 100644 cogs/utilities/dictionary.py diff --git a/cogs/utilities/__init__.py b/cogs/utilities/__init__.py index fe2fca6..94f66b0 100644 --- a/cogs/utilities/__init__.py +++ b/cogs/utilities/__init__.py @@ -5,6 +5,7 @@ from discord.ext.commands import Context from .translate import translate_command, language_autocomplete from .codepreview import codepreview_command +from .dictionary import dictionary_command class Utilities(commands.GroupCog, name="utils"): def __init__(self, bot) -> None: @@ -19,7 +20,7 @@ class Utilities(commands.GroupCog, name="utils"): color=0x7289DA ) embed.set_author(name="Utilities", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") - embed.add_field(name="Available", value="translate, codepreview", inline=False) + embed.add_field(name="Available", value="translate, codepreview, dictionary", inline=False) await context.send(embed=embed) async def _invoke_hybrid(self, context: Context, name: str, **kwargs): @@ -54,6 +55,13 @@ class Utilities(commands.GroupCog, name="utils"): async def utilities_group_codepreview(self, context: Context, url: str = None): await self._invoke_hybrid(context, "codepreview", url=url) + @utilities_group.command(name="dictionary") + @app_commands.describe( + word="The word to look up" + ) + async def utilities_group_dictionary(self, context: Context, word: str = None): + await self._invoke_hybrid(context, "dictionary", word=word) + @commands.check(_require_group_prefix) @commands.hybrid_command( name="translate", @@ -77,9 +85,21 @@ class Utilities(commands.GroupCog, name="utils"): async def codepreview(self, context, url: str = None): return await codepreview_command()(self, context, url=url) + @commands.check(_require_group_prefix) + @commands.hybrid_command( + name="dictionary", + description="Get the definition of a word" + ) + @app_commands.describe( + word="The word to look up" + ) + async def dictionary(self, context, word: str = None): + return await dictionary_command()(self, context, word=word) + async def setup(bot) -> None: cog = Utilities(bot) await bot.add_cog(cog) bot.logger.info("Loaded extension 'utilities.translate'") bot.logger.info("Loaded extension 'utilities.codepreview'") + bot.logger.info("Loaded extension 'utilities.dictionary'") diff --git a/cogs/utilities/dictionary.py b/cogs/utilities/dictionary.py new file mode 100644 index 0000000..d99bd0a --- /dev/null +++ b/cogs/utilities/dictionary.py @@ -0,0 +1,147 @@ +import discord +from discord import app_commands +from discord.ext import commands +from discord.ext.commands import Context +import aiohttp + + +def dictionary_command(): + + async def send_embed(context, embed: discord.Embed, *, ephemeral: bool = False) -> None: + interaction = getattr(context, "interaction", None) + if interaction is not None: + if interaction.response.is_done(): + await interaction.followup.send(embed=embed, ephemeral=ephemeral) + else: + await interaction.response.send_message(embed=embed, ephemeral=ephemeral) + else: + await context.send(embed=embed) + + async def fetch_definition(word: str) -> dict: + try: + url = f"https://api.dictionaryapi.dev/api/v2/entries/en/{word.lower()}" + + async with aiohttp.ClientSession() as session: + async with session.get(url) as response: + if response.status == 200: + data = await response.json() + return {"success": True, "data": data} + elif response.status == 404: + return {"success": False, "error": "Word not found"} + else: + return {"success": False, "error": f"API returned status code {response.status}"} + except aiohttp.ClientError: + return {"success": False, "error": "Network error occurred"} + except Exception as e: + return {"success": False, "error": "An unexpected error occurred"} + + @commands.hybrid_command( + name="dictionary", + description="Get the definition of a word", + ) + @app_commands.describe( + word="The word to look up" + ) + async def dictionary(self, context, word: str = None): + if not word or not word.strip(): + if context.message and context.message.reference and context.message.reference.resolved: + replied_message = context.message.reference.resolved + if hasattr(replied_message, 'content') and replied_message.content: + word = replied_message.content.strip().split()[0] + else: + embed = discord.Embed( + title="Error", + description="The replied message has no text content to look up.", + color=0xE02B2B, + ).set_author(name="Utility", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") + await send_embed(context, embed, ephemeral=True) + return + else: + embed = discord.Embed( + title="Error", + description="Please provide a word to look up or reply to a message with a word.", + color=0xE02B2B, + ).set_author(name="Utility", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") + await send_embed(context, embed, ephemeral=True) + return + + word = word.strip().split()[0] + + interaction = getattr(context, "interaction", None) + if interaction is not None and not interaction.response.is_done(): + await interaction.response.defer() + + result = await fetch_definition(word) + + if not result["success"]: + error_message = result.get("error", "Unknown error") + + if error_message == "Word not found": + description = f"Could not find a definition for **{word}**.\nPlease check the spelling and try again." + else: + description = f"Failed to fetch definition: {error_message}" + + embed = discord.Embed( + title="Error", + description=description, + color=0xE02B2B, + ).set_author(name="Utility", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") + await send_embed(context, embed, ephemeral=True) + return + + data = result["data"] + + if not data or len(data) == 0: + embed = discord.Embed( + title="Error", + description=f"No definition found for **{word}**.", + color=0xE02B2B, + ).set_author(name="Utility", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") + await send_embed(context, embed, ephemeral=True) + return + + entry = data[0] + word_title = entry.get("word", word) + phonetic = entry.get("phonetic", "") + origin = entry.get("origin", "") + meanings = entry.get("meanings", []) + + embed = discord.Embed( + title=f"Dictionary", + description=f"**```{word_title}```**", + color=0x7289DA, + ) + embed.set_author(name="Utilities", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") + + if phonetic: + embed.add_field(name="Pronunciation", value=f"`{phonetic}`", inline=False) + + max_meanings = 3 + for idx, meaning in enumerate(meanings[:max_meanings]): + part_of_speech = meaning.get("partOfSpeech", "").capitalize() + definitions = meaning.get("definitions", []) + + if definitions: + + def_text = "" + for def_idx, definition in enumerate(definitions[:2], 1): + def_line = definition.get("definition", "") + example = definition.get("example", "") + + if def_line: + def_text += f"{def_idx}. {def_line}\n" + if example: + def_text += f" *Example: {example}*\n" + + if def_text: + field_name = f"{part_of_speech}" if part_of_speech else f"Definition {idx + 1}" + embed.add_field(name=field_name, value=def_text.strip(), inline=False) + + if origin and len(origin) < 1000: + embed.add_field(name="Origin", value=origin, inline=False) + + + + await send_embed(context, embed) + + return dictionary