From 79c3bb7427a5e9dc4393d31b176a4322c0388900 Mon Sep 17 00:00:00 2001 From: teesh3rt Date: Thu, 13 Mar 2025 20:36:28 +0200 Subject: [PATCH] feat: toki pona li pona mute a --- src/apis/sona.py | 101 +++++++++++++++++++++++++++++++++++++++++++ src/exts/fun/sona.py | 59 +++++++++++++++++++++++++ 2 files changed, 160 insertions(+) create mode 100644 src/apis/sona.py create mode 100644 src/exts/fun/sona.py diff --git a/src/apis/sona.py b/src/apis/sona.py new file mode 100644 index 0000000..5f55f2c --- /dev/null +++ b/src/apis/sona.py @@ -0,0 +1,101 @@ +from pydantic import BaseModel +from typing import Optional +from enum import Enum +import httpx + + +class Book(Enum): + Pu = "pu" + KuSuli = "ku suli" + KuLili = "ku lili" + NoBook = "none" + + +class CoinedEra(Enum): + PrePu = "pre-pu" + PostPu = "post-pu" + PostKu = "post-ku" + + +class UsageCategory(Enum): + Core = "core" + Common = "common" + Uncommon = "uncommon" + Obscure = "obscure" + Sandbox = "sandbox" + + +class Resources(BaseModel): + sona_pona: Optional[str] = "" + lipamanka_semantic: Optional[str] = "" + + +class Representations(BaseModel): + sitelen_emosi: Optional[str] = "" + sitelen_jelo: Optional[list[str]] = [] + ligatures: Optional[list[str]] = [] + sitelen_sitelen: Optional[str] = "" + ucsur: Optional[str] = "" + + +class Etymology(BaseModel): + word: Optional[str] = "" + alt: Optional[str] = "" + + +class Audio(BaseModel): + link: str + author: str + + +class InnerEtymologyTranslation(BaseModel): + definition: Optional[str] = "" + language: str + + +class Translation(BaseModel): + commentary: str + definition: str + etymology: list[InnerEtymologyTranslation] + sp_etymology: str + + +class Word(BaseModel): + id: str + + book: Book + + coined_era: CoinedEra + coined_year: str + + creator: list[str] + + see_also: list[str] + + resources: Optional[Resources] = Resources() + + representations: Optional[Representations] = Representations() + + source_language: str + + usage_category: UsageCategory + + word: str + + deprecated: bool + + etymology: list[Etymology] + + audio: list[Audio] + + usage: dict[str, int] + + translations: dict[str, Translation] + + +def get_word(word: str, languages=["en"]) -> Word: + response = httpx.get( + f"https://api.linku.la/v1/words/{word}", params={"lang": ",".join(languages)} + ) + response.raise_for_status() + return Word(**response.json()) diff --git a/src/exts/fun/sona.py b/src/exts/fun/sona.py new file mode 100644 index 0000000..b0c62d9 --- /dev/null +++ b/src/exts/fun/sona.py @@ -0,0 +1,59 @@ +from discord.ext import commands +import discord +import apis.sona as sonaapi +from discord import app_commands +from loguru import logger + + +class Sona(commands.Cog): + def __init__(self, bot): + self.bot = bot + + @app_commands.command(name="seme", description="Get a toki pona word's definition.") + async def seme( + self, interaction: discord.Interaction, word: str, language: str = "en" + ): + try: + sona = sonaapi.get_word(word, [language]) + logger.debug(f"Successfully got definition for: {word}") + except Exception as e: + logger.error(e) + error_embed = discord.Embed( + title="Error", + description="Word not found.", + color=discord.Color.red(), + ) + logger.error(f"Error getting definition for: {word}") + await interaction.response.send_message(embed=error_embed) + return + + sitelen_emosi = sona.representations.sitelen_emosi + + if sona.usage_category == sonaapi.UsageCategory.Core: + color = discord.Color.green() + elif sona.usage_category == sonaapi.UsageCategory.Common: + color = discord.Color.blue() + elif sona.usage_category == sonaapi.UsageCategory.Uncommon: + color = discord.Color.orange() + elif sona.usage_category == sonaapi.UsageCategory.Obscure: + color = discord.Color.purple() + else: + color = discord.Color.from_rgb(255, 255, 255) + + embed = discord.Embed( + title=sona.word + f" {sitelen_emosi}" if sitelen_emosi != "" else "", + description=sona.translations[language].definition, + color=color, + ) + + see_also = " | See also: " + ", ".join(sona.see_also) + embed.set_footer( + text=f"Category: {sona.usage_category.value} | Book: {sona.book.value}" + + (see_also if sona.see_also != [] else "") + ) + + await interaction.response.send_message(embed=embed) + + +async def setup(bot): + await bot.add_cog(Sona(bot))