diff --git a/README.md b/README.md index 102a11c..0baaf46 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,8 @@ | moderation | `kick`, `ban`, `nick`, `purge`, `hackban`, `warnings`, `archive` | | sidestore | `sidestore`, `refresh`, `code`, `crash`, `pairing`, `server`, `half`, `sparse`, `afc`, `udid` | | idevice | `idevice`, `noapps`, `errorcode`, `developermode`, `mountddi` | -| miscellaneous | `keanu`, `labubu`, `piracy` | +| miscellaneous | `keanu`, `labubu`, `piracy`, `tryitandsee`, `rickroll` | +| utilities | `translate` | ## Download diff --git a/cogs/general/help.py b/cogs/general/help.py index 97dd6e9..536462f 100644 --- a/cogs/general/help.py +++ b/cogs/general/help.py @@ -13,7 +13,7 @@ class Help(commands.Cog, name="help"): interaction: discord.Interaction, current: str, ) -> list[app_commands.Choice[str]]: - categories = ["general", "fun", "moderation", "owner", "sidestore", "idevice", "miscellaneous"] + categories = ["general", "fun", "moderation", "owner", "sidestore", "idevice", "miscellaneous", "utilities"] suggestions = [] for category in categories: @@ -89,6 +89,9 @@ class Help(commands.Cog, name="help"): "invite": "owner", "logs": "owner", + # Utilities Commands + "translate": "utilities", + # Miscellaneous Commands "keanu": "miscellaneous", "labubu": "miscellaneous", @@ -104,6 +107,7 @@ class Help(commands.Cog, name="help"): "owner": "Owner commands", "sidestore": "SideStore troubleshooting commands", "idevice": "idevice troubleshooting commands", + "utilities": "Utility commands", "miscellaneous": "Miscellaneous commands" } diff --git a/cogs/miscellaneous/rr.py b/cogs/miscellaneous/rickroll.py similarity index 100% rename from cogs/miscellaneous/rr.py rename to cogs/miscellaneous/rickroll.py diff --git a/cogs/moderation/ban.py b/cogs/moderation/ban.py index 14ad9ba..fb3405f 100644 --- a/cogs/moderation/ban.py +++ b/cogs/moderation/ban.py @@ -41,7 +41,7 @@ class Ban(commands.Cog, name="ban"): title="Ban", description=f"**{user}** was banned by **{context.author}**!", color=0x7289DA, - ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") + ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/CPKHQd.png") embed.add_field(name="Reason:", value=reason) await context.send(embed=embed) return @@ -50,7 +50,7 @@ class Ban(commands.Cog, name="ban"): title="Error!", description="I don't have permission to ban this user.", color=0xE02B2B, - ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") + ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/CPKHQd.png") await context.send(embed=embed, ephemeral=True) return except Exception: @@ -58,7 +58,7 @@ class Ban(commands.Cog, name="ban"): title="Error!", description="An error occurred while trying to ban the user.", color=0xE02B2B, - ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") + ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/CPKHQd.png") await context.send(embed=embed, ephemeral=True) return @@ -67,7 +67,7 @@ class Ban(commands.Cog, name="ban"): title="Missing Permissions!", description="You don't have the `Ban Members` permission to use this command.", color=0xE02B2B, - ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") + ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/CPKHQd.png") await context.send(embed=embed, ephemeral=True) return @@ -76,7 +76,7 @@ class Ban(commands.Cog, name="ban"): title="Cannot Ban User", description="This user has a higher or equal role to me. Make sure my role is above theirs.", color=0xE02B2B, - ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") + ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/CPKHQd.png") await context.send(embed=embed, ephemeral=True) return @@ -86,7 +86,7 @@ class Ban(commands.Cog, name="ban"): title="Cannot Ban User", description="You cannot ban this user as they have a higher or equal role to you.", color=0xE02B2B, - ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") + ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/CPKHQd.png") await context.send(embed=embed, ephemeral=True) return @@ -111,7 +111,7 @@ class Ban(commands.Cog, name="ban"): title="Ban", description=f"You were banned by **{context.author}** from **{context.guild.name}**!\nReason: {reason}", color=0xE02B2B, - ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") + ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/CPKHQd.png") await member.send(embed=dm_embed) except (discord.Forbidden, discord.HTTPException): pass @@ -128,7 +128,7 @@ class Ban(commands.Cog, name="ban"): title="Ban", description=f"**{user}** was banned by **{context.author}**!", color=0x7289DA, - ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") + ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/CPKHQd.png") embed.add_field(name="Reason:", value=reason) if delete_messages != "none": @@ -145,7 +145,7 @@ class Ban(commands.Cog, name="ban"): title="Error!", description="I don't have permission to ban this user. Make sure my role is above theirs.", color=0xE02B2B, - ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") + ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/CPKHQd.png") await context.send(embed=embed, ephemeral=True) except discord.HTTPException as e: if "Cannot ban the owner of a guild" in str(e): @@ -153,20 +153,20 @@ class Ban(commands.Cog, name="ban"): title="Cannot Ban User", description="You cannot ban the server owner.", color=0xE02B2B, - ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") + ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/CPKHQd.png") else: embed = discord.Embed( title="Error!", description=f"Discord API error: {str(e)}", color=0xE02B2B, - ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") + ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/CPKHQd.png") await context.send(embed=embed, ephemeral=True) except Exception as e: embed = discord.Embed( title="Debug Error!", description=f"Error type: {type(e).__name__}\nError message: {str(e)}", color=0xE02B2B, - ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") + ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/CPKHQd.png") await context.send(embed=embed, ephemeral=True) except Exception as e: @@ -174,7 +174,7 @@ class Ban(commands.Cog, name="ban"): title="Error!", description="An unexpected error occurred.", color=0xE02B2B, - ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") + ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/CPKHQd.png") await context.send(embed=embed, ephemeral=True) async def delete_all_user_messages(self, guild: discord.Guild, user_id: int) -> None: diff --git a/cogs/moderation/hackban.py b/cogs/moderation/hackban.py index e210dda..4109db8 100644 --- a/cogs/moderation/hackban.py +++ b/cogs/moderation/hackban.py @@ -37,7 +37,7 @@ class HackBan(commands.Cog, name="hackban"): title="Ban", description=f"**{user}** (ID: {user_id}) was banned by **{context.author}**!", color=0x7289DA, - ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") + ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/CPKHQd.png") embed.add_field(name="Reason:", value=reason) await context.send(embed=embed) except Exception: @@ -45,7 +45,7 @@ class HackBan(commands.Cog, name="hackban"): title="Error!", description="An error occurred while trying to ban the user. Make sure ID is an existing ID that belongs to a user.", color=0xE02B2B, - ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") + ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/CPKHQd.png") await context.send(embed=embed) diff --git a/cogs/moderation/kick.py b/cogs/moderation/kick.py index ddd8d6e..2bdb2a5 100644 --- a/cogs/moderation/kick.py +++ b/cogs/moderation/kick.py @@ -29,7 +29,7 @@ class Kick(commands.Cog, name="kick"): title="Error!", description="This user is not in the server.", color=0xE02B2B, - ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") + ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/CPKHQd.png") await context.send(embed=embed, ephemeral=True) return @@ -38,7 +38,7 @@ class Kick(commands.Cog, name="kick"): title="Missing Permissions!", description="You don't have the `Kick Members` permission to use this command.", color=0xE02B2B, - ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") + ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/CPKHQd.png") await context.send(embed=embed, ephemeral=True) return @@ -47,7 +47,7 @@ class Kick(commands.Cog, name="kick"): title="Cannot Kick User", description="This user has a higher or equal role to me. Make sure my role is above theirs.", color=0xE02B2B, - ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") + ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/CPKHQd.png") await context.send(embed=embed, ephemeral=True) return @@ -57,7 +57,7 @@ class Kick(commands.Cog, name="kick"): title="Cannot Kick User", description="You cannot kick this user as they have a higher or equal role to you.", color=0xE02B2B, - ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") + ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/CPKHQd.png") await context.send(embed=embed, ephemeral=True) return @@ -69,7 +69,7 @@ class Kick(commands.Cog, name="kick"): title="Kick", description=f"You were kicked by **{context.author}** from **{context.guild.name}**!\nReason: {reason}", color=0xE02B2B, - ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") + ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/CPKHQd.png") ) except (discord.Forbidden, discord.HTTPException): @@ -81,7 +81,7 @@ class Kick(commands.Cog, name="kick"): title="Kick", description=f"**{user}** was kicked by **{context.author}**!", color=0x7289DA, - ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") + ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/CPKHQd.png") embed.add_field(name="Reason:", value=reason) await context.send(embed=embed) @@ -91,7 +91,7 @@ class Kick(commands.Cog, name="kick"): title="Error!", description="I don't have permission to kick this user. Make sure my role is above theirs.", color=0xE02B2B, - ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") + ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/CPKHQd.png") await context.send(embed=embed, ephemeral=True) except discord.HTTPException as e: if "Cannot kick the owner of a guild" in str(e): @@ -99,20 +99,20 @@ class Kick(commands.Cog, name="kick"): title="Cannot Kick User", description="You cannot kick the server owner.", color=0xE02B2B, - ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") + ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/CPKHQd.png") else: embed = discord.Embed( title="Error!", description=f"Discord API error: {str(e)}", color=0xE02B2B, - ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") + ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/CPKHQd.png") await context.send(embed=embed, ephemeral=True) except Exception as e: embed = discord.Embed( title="Debug Error!", description=f"Error type: {type(e).__name__}\nError message: {str(e)}", color=0xE02B2B, - ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") + ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/CPKHQd.png") await context.send(embed=embed, ephemeral=True) except Exception as e: @@ -120,7 +120,7 @@ class Kick(commands.Cog, name="kick"): title="Error!", description="An unexpected error occurred.", color=0xE02B2B, - ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") + ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/CPKHQd.png") await context.send(embed=embed, ephemeral=True) diff --git a/cogs/moderation/nick.py b/cogs/moderation/nick.py index 20db568..3eb7565 100644 --- a/cogs/moderation/nick.py +++ b/cogs/moderation/nick.py @@ -31,7 +31,7 @@ class Nick(commands.Cog, name="nick"): title="Missing Permissions!", description="You are missing the permission(s) `manage_nicknames` to execute this command!", color=0xE02B2B, - ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") + ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/CPKHQd.png") return await context.send(embed=embed, ephemeral=True) if not context.guild.me.guild_permissions.manage_nicknames: @@ -39,7 +39,7 @@ class Nick(commands.Cog, name="nick"): title="Missing Permissions!", description="I am missing the permission(s) `manage_nicknames` to execute this command!", color=0xE02B2B, - ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") + ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/CPKHQd.png") return await context.send(embed=embed, ephemeral=True) member = context.guild.get_member(user.id) or await context.guild.fetch_member( @@ -51,14 +51,14 @@ class Nick(commands.Cog, name="nick"): title="Nickname", description=f"**{member}'s** new nickname is **{nickname}**!", color=0x7289DA, - ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") + ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/CPKHQd.png") await context.send(embed=embed) except: embed = discord.Embed( title="Missing Permissions!", description="An error occurred while trying to change the nickname of the user. Make sure my role is above the role of the user you want to change the nickname.", color=0xE02B2B, - ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") + ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/CPKHQd.png") await context.send(embed=embed, ephemeral=True) diff --git a/cogs/moderation/purge.py b/cogs/moderation/purge.py index 646b761..c56e73e 100644 --- a/cogs/moderation/purge.py +++ b/cogs/moderation/purge.py @@ -29,7 +29,7 @@ class Purge(commands.Cog, name="purge"): description=f"**{context.author}** cleared **{len(purged_messages)-1}** messages!", color=0x7289DA, ) - embed.set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") + embed.set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/CPKHQd.png") await context.channel.send(embed=embed) diff --git a/cogs/moderation/warnings.py b/cogs/moderation/warnings.py index abb9787..dc8f4bf 100644 --- a/cogs/moderation/warnings.py +++ b/cogs/moderation/warnings.py @@ -33,7 +33,7 @@ class Warnings(commands.Cog, name="warnings"): title="Missing Permissions!", description="You are missing the permission(s) `manage_messages` to execute this command!", color=0xE02B2B, - ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") + ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/CPKHQd.png") return await self.send_embed(context, embed, ephemeral=True) if context.invoked_subcommand is None: @@ -42,7 +42,7 @@ class Warnings(commands.Cog, name="warnings"): description="Please specify a subcommand.\n\n**Subcommands:**\n`add` - Add a warning to a user.\n`remove` - Remove a warning from a user.\n`list` - List all warnings of a user.", color=0x7289DA, ) - embed.set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") + embed.set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/CPKHQd.png") await self.send_embed(context, embed) @warning.command( @@ -68,7 +68,7 @@ class Warnings(commands.Cog, name="warnings"): title="Missing Permissions!", description="You are missing the permission(s) `manage_messages` to execute this command!", color=0xE02B2B, - ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") + ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/CPKHQd.png") return await self.send_embed(context, embed, ephemeral=True) member = context.guild.get_member(user.id) or await context.guild.fetch_member( user.id @@ -81,7 +81,7 @@ class Warnings(commands.Cog, name="warnings"): description=f"**{member}** was warned by **{context.author}**!\nTotal warns for this user: {total}", color=0x7289DA, ) - embed.set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") + embed.set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/CPKHQd.png") embed.add_field(name="Reason:", value=reason) await self.send_embed(context, embed) try: @@ -90,7 +90,7 @@ class Warnings(commands.Cog, name="warnings"): description=f"You were warned by **{context.author}** in **{context.guild.name}**!\nReason: {reason}", color=0xE02B2B, ) - dm_embed.set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") + dm_embed.set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/CPKHQd.png") await member.send(embed=dm_embed) except: fallback = discord.Embed( @@ -123,7 +123,7 @@ class Warnings(commands.Cog, name="warnings"): title="Missing Permissions!", description="You are missing the permission(s) `manage_messages` to execute this command!", color=0xE02B2B, - ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") + ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/CPKHQd.png") return await self.send_embed(context, embed, ephemeral=True) member = context.guild.get_member(user.id) or await context.guild.fetch_member( user.id @@ -134,7 +134,7 @@ class Warnings(commands.Cog, name="warnings"): description=f"Removed the warning **#{warn_id}** from **{member}**!\nTotal warns for this user: {total}", color=0x7289DA, ) - embed.set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") + embed.set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/CPKHQd.png") await self.send_embed(context, embed) @warning.command( @@ -154,11 +154,11 @@ class Warnings(commands.Cog, name="warnings"): title="Missing Permissions!", description="You are missing the permission(s) `manage_messages` to execute this command!", color=0xE02B2B, - ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") + ).set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/CPKHQd.png") return await self.send_embed(context, embed, ephemeral=True) warnings_list = await self.bot.database.get_warnings(user.id, context.guild.id) embed = discord.Embed(title=f"Warnings of {user}", color=0x7289DA) - embed.set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") + embed.set_author(name="Moderation", icon_url="https://yes.nighty.works/raw/CPKHQd.png") description = "" if len(warnings_list) == 0: description = "This user has no warnings." diff --git a/cogs/utilities/translate.py b/cogs/utilities/translate.py new file mode 100644 index 0000000..8b0fba0 --- /dev/null +++ b/cogs/utilities/translate.py @@ -0,0 +1,357 @@ +import discord +from discord import app_commands +from discord.ext import commands +from discord.ext.commands import Context +import aiohttp +import asyncio +import re +import json +import urllib.parse + + +class Translate(commands.Cog, name="translate"): + def __init__(self, bot) -> None: + self.bot = bot + self.languages = { + "auto": "Auto-detect", + "en": "English", + "es": "Spanish", + "fr": "French", + "de": "German", + "it": "Italian", + "pt": "Portuguese", + "ru": "Russian", + "ja": "Japanese", + "ko": "Korean", + "zh-CN": "Chinese (Simplified)", + "zh-TW": "Chinese (Traditional)", + "ar": "Arabic", + "hi": "Hindi", + "th": "Thai", + "vi": "Vietnamese", + "nl": "Dutch", + "pl": "Polish", + "tr": "Turkish", + "sv": "Swedish", + "da": "Danish", + "no": "Norwegian", + "fi": "Finnish", + "cs": "Czech", + "sk": "Slovak", + "hu": "Hungarian", + "ro": "Romanian", + "bg": "Bulgarian", + "hr": "Croatian", + "sr": "Serbian", + "sl": "Slovenian", + "et": "Estonian", + "lv": "Latvian", + "lt": "Lithuanian", + "uk": "Ukrainian", + "be": "Belarusian", + "mk": "Macedonian", + "sq": "Albanian", + "mt": "Maltese", + "is": "Icelandic", + "ga": "Irish", + "cy": "Welsh", + "gd": "Scots Gaelic", + "eu": "Basque", + "ca": "Catalan", + "gl": "Galician", + "eo": "Esperanto", + "la": "Latin", + "af": "Afrikaans", + "sw": "Swahili", + "zu": "Zulu", + "xh": "Xhosa", + "yo": "Yoruba", + "ig": "Igbo", + "ha": "Hausa", + "am": "Amharic", + "om": "Oromo", + "ti": "Tigrinya", + "so": "Somali", + "rw": "Kinyarwanda", + "lg": "Ganda", + "ny": "Chichewa", + "sn": "Shona", + "st": "Sesotho", + "tn": "Tswana", + "ts": "Tsonga", + "ss": "Swati", + "nr": "Ndebele", + "nso": "Northern Sotho", + "ve": "Venda", + "bn": "Bengali", + "gu": "Gujarati", + "kn": "Kannada", + "ml": "Malayalam", + "mr": "Marathi", + "ne": "Nepali", + "or": "Odia", + "pa": "Punjabi", + "si": "Sinhala", + "ta": "Tamil", + "te": "Telugu", + "ur": "Urdu", + "as": "Assamese", + "bho": "Bhojpuri", + "doi": "Dogri", + "gom": "Konkani", + "mai": "Maithili", + "mni-Mtei": "Meiteilon", + "sa": "Sanskrit", + "id": "Indonesian", + "ms": "Malay", + "tl": "Filipino", + "jv": "Javanese", + "su": "Sundanese", + "ceb": "Cebuano", + "hil": "Hiligaynon", + "ilo": "Iloko", + "pam": "Kapampangan", + "war": "Waray", + "my": "Myanmar", + "km": "Khmer", + "lo": "Lao", + "ka": "Georgian", + "hy": "Armenian", + "az": "Azerbaijani", + "kk": "Kazakh", + "ky": "Kyrgyz", + "mn": "Mongolian", + "tk": "Turkmen", + "ug": "Uyghur", + "uz": "Uzbek", + "tg": "Tajik", + "fa": "Persian", + "ps": "Pashto", + "sd": "Sindhi", + "he": "Hebrew", + "yi": "Yiddish", + "iw": "Hebrew", + "el": "Greek", + "lt": "Lithuanian", + "lv": "Latvian", + } + + async def send_embed(self, context: Context, embed: discord.Embed, *, ephemeral: bool = False, view: discord.ui.View = None) -> None: + interaction = getattr(context, "interaction", None) + if interaction is not None: + if interaction.response.is_done(): + await interaction.followup.send(embed=embed, ephemeral=ephemeral, view=view) + else: + await interaction.response.send_message(embed=embed, ephemeral=ephemeral, view=view) + else: + await context.send(embed=embed, view=view) + + async def _translate_with_google_web(self, text: str, from_lang: str = "auto", to_lang: str = "en") -> dict: + try: + base_url = "https://translate.googleapis.com/translate_a/single" + + params = { + "client": "gtx", + "sl": from_lang, + "tl": to_lang, + "dt": ["t", "bd"], + "q": text + } + + param_string = "&".join([f"{k}={'&'.join(v) if isinstance(v, list) else v}" for k, v in params.items()]) + url = f"{base_url}?{param_string}" + + headers = { + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36" + } + + async with aiohttp.ClientSession() as session: + async with session.get(url, headers=headers) as response: + if response.status == 200: + result_text = await response.text() + + try: + result_text = result_text.strip() + if result_text.startswith('[['): + data = json.loads(result_text) + + translated_text = "" + if data and len(data) > 0 and data[0]: + for item in data[0]: + if item and len(item) > 0: + translated_text += item[0] if item[0] else "" + + detected_lang = from_lang + if len(data) > 2 and data[2]: + detected_lang = data[2] + + return { + "translatedText": translated_text.strip(), + "detectedSourceLanguage": detected_lang + } + except: + pass + + return None + except Exception: + return None + + async def language_autocomplete(self, interaction: discord.Interaction, current: str) -> list[app_commands.Choice[str]]: + current = current.lower() + choices = [] + + for code, name in self.languages.items(): + if current in code.lower() or current in name.lower(): + display_name = f"{code} - {name}" + if len(display_name) > 100: + display_name = f"{code} - {name[:90]}..." + choices.append(app_commands.Choice(name=display_name, value=code)) + + if len(choices) >= 25: + break + + if not choices: + popular = ["en", "es", "fr", "de", "it", "pt", "ru", "ja", "ko", "zh-CN"] + for code in popular: + name = self.languages.get(code, code) + choices.append(app_commands.Choice(name=f"{code} - {name}", value=code)) + + return choices + + @commands.hybrid_command( + name="translate", + description="Translate text to another language", + ) + @app_commands.describe( + text="The text to translate", + to_lang="Target language (e.g., 'en', 'es', 'fr')", + from_lang="Source language (leave empty for auto-detect)" + ) + @app_commands.autocomplete(to_lang=language_autocomplete) + @app_commands.autocomplete(from_lang=language_autocomplete) + async def translate(self, context: Context, text: str, to_lang: str = "en", from_lang: str = None): + if not text.strip(): + embed = discord.Embed( + title="Error", + description="Please provide text to translate.", + color=0xE02B2B, + ) + embed.set_author(name="Translate", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") + await self.send_embed(context, embed, ephemeral=True) + return + + if to_lang not in self.languages: + embed = discord.Embed( + title="Error", + description=f"Invalid target language code: `{to_lang}`. Use the autocomplete feature to see available languages.", + color=0xE02B2B, + ) + embed.set_author(name="Translate", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") + await self.send_embed(context, embed, ephemeral=True) + return + + if from_lang and from_lang not in self.languages: + embed = discord.Embed( + title="Error", + description=f"Invalid source language code: `{from_lang}`. Use the autocomplete feature to see available languages.", + color=0xE02B2B, + ) + embed.set_author(name="Translate", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") + await self.send_embed(context, embed, ephemeral=True) + return + + result = await self._translate_with_google_web(text, from_lang or "auto", to_lang) + + if result and result.get("translatedText"): + detected_lang = result.get("detectedSourceLanguage", from_lang or "auto") + + from_lang_name = self.languages.get(detected_lang, detected_lang) + to_lang_name = self.languages.get(to_lang, to_lang) + + embed = discord.Embed( + title="Translation", + color=0x7289DA, + ) + embed.set_author(name="Translate", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") + embed.add_field(name="Original", value=text, inline=False) + embed.add_field(name="Translated", value=result["translatedText"], inline=False) + embed.add_field(name="From", value=f"{detected_lang} ({from_lang_name})", inline=True) + embed.add_field(name="To", value=f"{to_lang} ({to_lang_name})", inline=True) + + view = TranslateView(text, result["translatedText"], detected_lang, to_lang, self) + await self.send_embed(context, embed, view=view) + else: + embed = discord.Embed( + title="Error", + description="Translation failed. Please try again later.", + color=0xE02B2B, + ) + embed.set_author(name="Translate", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") + await self.send_embed(context, embed, ephemeral=True) + + + +class TranslateView(discord.ui.View): + def __init__(self, original_text: str, translated_text: str, from_lang: str, to_lang: str, translate_cog): + super().__init__(timeout=300) + self.original_text = original_text + self.translated_text = translated_text + self.from_lang = from_lang + self.to_lang = to_lang + self.translate_cog = translate_cog + + @discord.ui.button(label="Swap Languages", style=discord.ButtonStyle.secondary) + async def swap_languages(self, interaction: discord.Interaction, button: discord.ui.Button): + if self.from_lang == "auto": + embed = discord.Embed( + title="Cannot Swap", + description="Cannot swap when source language is auto-detected. Please specify a source language first.", + color=0xE02B2B, + ) + embed.set_author(name="Translate", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") + await interaction.response.send_message(embed=embed, ephemeral=True) + return + + result = await self.translate_cog._translate_with_google_web( + self.translated_text, self.from_lang, "en" + ) + + if result and result.get("translatedText"): + from_lang_name = self.translate_cog.languages.get(self.from_lang, self.from_lang) + to_lang_name = self.translate_cog.languages.get("en", "English") + + embed = discord.Embed( + title="Translation (Swapped)", + color=0x7289DA, + ) + embed.set_author(name="Translate", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") + embed.add_field(name="Original", value=self.translated_text, inline=False) + embed.add_field(name="Translated", value=result["translatedText"], inline=False) + embed.add_field(name="From", value=f"{self.from_lang} ({from_lang_name})", inline=True) + embed.add_field(name="To", value=f"en ({to_lang_name})", inline=True) + + new_view = TranslateView( + self.translated_text, + result["translatedText"], + self.from_lang, + "en", + self.translate_cog + ) + + await interaction.response.edit_message(embed=embed, view=new_view) + else: + embed = discord.Embed( + title="Error", + description="Failed to swap translation. Please try again later.", + color=0xE02B2B, + ) + embed.set_author(name="Translate", icon_url="https://yes.nighty.works/raw/8VLDcg.webp") + await interaction.response.send_message(embed=embed, ephemeral=True) + + async def on_timeout(self): + for item in self.children: + item.disabled = True + + +async def setup(bot): + await bot.add_cog(Translate(bot)) \ No newline at end of file