127 lines
5.2 KiB
Python
127 lines
5.2 KiB
Python
import io
|
|
from typing import Any, Literal
|
|
|
|
import aiohttp
|
|
import discord
|
|
from colorthief import ColorThief
|
|
from red_commons.logging import RedTraceLogger, getLogger
|
|
from redbot.core import app_commands, commands
|
|
from redbot.core.bot import Red
|
|
from redbot.core.utils.chat_formatting import bold, humanize_list
|
|
|
|
from .model import PartialEmoji
|
|
|
|
|
|
class EmojiInfo(commands.Cog):
|
|
"""Retrieve information about emojis."""
|
|
|
|
__author__: list[str] = ["SeaswimmerTheFsh"]
|
|
__version__: str = "1.0.0"
|
|
__documentation__: str = "https://seacogs.coastalcommits.com/emojiinfo/"
|
|
|
|
def __init__(self, bot: Red) -> None:
|
|
super().__init__()
|
|
self.bot: Red = bot
|
|
self.logger: RedTraceLogger = getLogger(name="red.SeaCogs.Emoji")
|
|
|
|
def format_help_for_context(self, ctx: commands.Context) -> str:
|
|
pre_processed: Any | Literal[''] = super().format_help_for_context(ctx) or ""
|
|
n: Literal['\n'] | Literal[''] = "\n" if "\n\n" not in pre_processed else ""
|
|
text: list[str] = [
|
|
f"{pre_processed}{n}",
|
|
f"Cog Version: **{self.__version__}**",
|
|
f"Author: {humanize_list(items=self.__author__)}",
|
|
f"Documentation: {self.__documentation__}",
|
|
]
|
|
return "\n".join(text)
|
|
|
|
async def fetch_twemoji(self, unicode_emoji) -> str:
|
|
base_url = "https://cdn.jsdelivr.net/gh/jdecked/twemoji@latest/assets/72x72/"
|
|
emoji_codepoint = "-".join([hex(ord(char))[2:] for char in unicode_emoji])
|
|
segments = emoji_codepoint.split("-")
|
|
valid_segments = [seg for seg in segments if len(seg) >= 4]
|
|
emoji_url = f"{base_url}{valid_segments[0]}.png"
|
|
return emoji_url
|
|
|
|
async def fetch_primary_color(self, emoji_url: str) -> discord.Color | None:
|
|
async with aiohttp.ClientSession() as session:
|
|
async with session.get(emoji_url) as response:
|
|
if response.status != 200:
|
|
return None
|
|
image = await response.read()
|
|
dominant_color = ColorThief(io.BytesIO(image)).get_color(quality=1)
|
|
color = discord.Color.from_rgb(*dominant_color)
|
|
return color
|
|
|
|
async def get_emoji_info(self, emoji: PartialEmoji) -> tuple[str, str]:
|
|
if emoji.is_unicode_emoji():
|
|
try:
|
|
emoji_url = await self.fetch_twemoji(unicode_emoji=emoji.name)
|
|
except IndexError as e:
|
|
raise e
|
|
else:
|
|
emoji_url = emoji.url
|
|
|
|
if emoji.id:
|
|
emoji_id = f"{bold('ID:')} `{emoji.id}`\n"
|
|
markdown = f"`<{'a' if emoji.animated else ''}:{emoji.name}:{emoji.id}>`"
|
|
name = f"{bold('Name:')} {emoji.name}\n"
|
|
aliases = ""
|
|
group = ""
|
|
else:
|
|
emoji_id = ""
|
|
markdown = f"`{emoji}`"
|
|
name = f"{bold('Name:')} {emoji.aliases.pop(0)}\n"
|
|
aliases = f"{bold('Aliases:')} {', '.join(emoji.aliases)}\n" if emoji.aliases else ""
|
|
group = f"{bold('Group:')} {emoji.group}\n"
|
|
|
|
return (
|
|
f"{name}"
|
|
f"{emoji_id}"
|
|
f"{bold('Native:')} {emoji.is_unicode_emoji()}\n"
|
|
f"{group}"
|
|
f"{aliases}"
|
|
f"{bold('Animated:')} {emoji.animated}\n"
|
|
f"{bold('Markdown:')} {markdown}\n"
|
|
f"{bold('URL:')} [Click Here]({emoji_url})"
|
|
), emoji_url
|
|
|
|
@app_commands.command(name="emoji")
|
|
@app_commands.describe(
|
|
emoji="What emoji would you like to get information on?",
|
|
ephemeral="Would you like the response to be hidden?"
|
|
)
|
|
async def emoji_slash(self, interaction: discord.Interaction, emoji: str, ephemeral: bool = True) -> None:
|
|
"""Retrieve information about an emoji."""
|
|
await interaction.response.defer(ephemeral=ephemeral)
|
|
|
|
try:
|
|
emoji: PartialEmoji = PartialEmoji.from_str(self, value=emoji)
|
|
string, emoji_url, = await self.get_emoji_info(emoji)
|
|
except (IndexError, UnboundLocalError):
|
|
return await interaction.followup.send("Please provide a valid emoji!")
|
|
|
|
if await self.bot.embed_requested(channel=interaction.channel):
|
|
embed = embed = discord.Embed(title="Emoji Information", description=string, color = await self.fetch_primary_color(emoji_url) or await self.bot.get_embed_color(interaction.channel))
|
|
embed.set_thumbnail(url=emoji_url)
|
|
|
|
await interaction.followup.send(embed=embed)
|
|
else:
|
|
await interaction.followup.send(content=string)
|
|
|
|
@commands.command(name="emoji")
|
|
async def emoji(self, ctx: commands.Context, *, emoji: str) -> None:
|
|
"""Retrieve information about an emoji."""
|
|
try:
|
|
emoji: PartialEmoji = PartialEmoji.from_str(self, value=emoji)
|
|
string, emoji_url, = await self.get_emoji_info(emoji)
|
|
except (IndexError, UnboundLocalError):
|
|
return await ctx.send("Please provide a valid emoji!")
|
|
|
|
if await ctx.embed_requested():
|
|
embed = embed = discord.Embed(title="Emoji Information", description=string, color = await self.fetch_primary_color(emoji_url) or await ctx.embed_color)
|
|
embed.set_thumbnail(url=emoji_url)
|
|
|
|
await ctx.send(embed=embed)
|
|
else:
|
|
await ctx.send(content=string)
|