diff --git a/lib/const.py b/lib/const.py index 2255c79..318a974 100644 --- a/lib/const.py +++ b/lib/const.py @@ -2,14 +2,14 @@ import os import json import yaml from functools import lru_cache -from typing import Optional, Callable, Set +from typing import Optional, Callable, Set, List, Dict class _parser: """Internal parses class. Not intended to be used outside of this module.""" @lru_cache(maxsize=1024) - def read_settings(self) -> dict: + def read_s(self) -> dict: return self._read_file("settings.yaml", yaml.safe_load) def read_json(self, path: str) -> dict: @@ -22,10 +22,20 @@ class _parser: class _constants: _p = _parser() - _s = _parser().read_settings() + _s = _parser().read_s() # bot credentials - TOKEN: Optional[str] = os.getenv("TOKEN") + TOKEN: Optional[str] = os.environ.get("TOKEN") + INSTANCE: Optional[str] = os.environ.get("INSTANCE") + XP_GAIN_PER_MESSAGE: int = int(os.environ.get("XP_GAIN_PER_MESSAGE", 1)) + XP_GAIN_COOLDOWN: int = int(os.environ.get("XP_GAIN_COOLDOWN", 8)) + DBX_TOKEN: Optional[str] = os.environ.get("DBX_OAUTH2_REFRESH_TOKEN") + DBX_APP_KEY: Optional[str] = os.environ.get("DBX_APP_KEY") + DBX_APP_SECRET: Optional[str] = os.environ.get("DBX_APP_SECRET") + MARIADB_USER: Optional[str] = os.environ.get("MARIADB_USER") + MARIADB_PASSWORD: Optional[str] = os.environ.get("MARIADB_PASSWORD") + MARIADB_ROOT_PASSWORD: Optional[str] = os.environ.get("MARIADB_ROOT_PASSWORD") + MARIADB_DATABASE: Optional[str] = os.environ.get("MARIADB_DATABASE") OWNER_IDS: Optional[Set[int]] = ( {int(id.strip()) for id in os.environ.get("OWNER_IDS", "").split(",") if id} @@ -33,13 +43,76 @@ class _constants: else None ) - # settings + # metadata + TITLE: str = _s["info"]["title"] + AUTHOR: str = _s["info"]["author"] + LICENSE: str = _s["info"]["license"] + VERSION: str = _s["info"]["version"] + REPO_URL: str = _s["info"]["repository_url"] + INVITE_URL: str = _s["info"]["invite_url"] + + # loguru LOG_LEVEL: str = _s["logs"]["level"] or "DEBUG" LOG_FORMAT: str = _s["logs"]["format"] + + # cogs COG_IGNORE_LIST: Set[str] = ( set(_s["cogs"]["ignore"]) if _s["cogs"]["ignore"] else set() ) + # images + ALLOWED_IMAGE_EXTENSIONS: List[str] = _s["images"]["allowed_image_extensions"] + BIRTHDAY_GIF_URL: str = _s["images"]["birthday_gif_url"] + + # colors + COLOR_DEFAULT: int = _s["colors"]["color_default"] + COLOR_WARNING: int = _s["colors"]["color_warning"] + COLOR_ERROR: int = _s["colors"]["color_error"] + + # economy + DAILY_REWARD: int = _s["economy"]["daily_reward"] + BLACKJACK_MULTIPLIER: float = _s["economy"]["blackjack_multiplier"] + BLACKJACK_HIT_EMOJI: str = _s["economy"]["blackjack_hit_emoji"] + BLACKJACK_STAND_EMOJI: str = _s["economy"]["blackjack_stand_emoji"] + SLOTS_MULTIPLIERS: Dict[str, float] = _s["economy"]["slots_multipliers"] + + # art from git repository + _fetch_url: str = _s["art"]["fetch_url"] + + LUMI_LOGO_OPAQUE: str = _fetch_url + _s["art"]["logo"]["opaque"] + LUMI_LOGO_TRANSPARENT: str = _fetch_url + _s["art"]["logo"]["transparent"] + BOOST_ICON: str = _fetch_url + _s["art"]["icons"]["boost"] + CHECK_ICON: str = _fetch_url + _s["art"]["icons"]["check"] + CROSS_ICON: str = _fetch_url + _s["art"]["icons"]["cross"] + EXCLAIM_ICON: str = _fetch_url + _s["art"]["icons"]["exclaim"] + HAMMER_ICON: str = _fetch_url + _s["art"]["icons"]["hammer"] + MONEY_BAG_ICON: str = _fetch_url + _s["art"]["icons"]["money_bag"] + MONEY_COINS_ICON: str = _fetch_url + _s["art"]["icons"]["money_coins"] + QUESTION_ICON: str = _fetch_url + _s["art"]["icons"]["question"] + STREAK_ICON: str = _fetch_url + _s["art"]["icons"]["streak"] + STREAK_BRONZE_ICON: str = _fetch_url + _s["art"]["icons"]["streak_bronze"] + STREAK_GOLD_ICON: str = _fetch_url + _s["art"]["icons"]["streak_gold"] + STREAK_SILVER_ICON: str = _fetch_url + _s["art"]["icons"]["streak_silver"] + WARNING_ICON: str = _fetch_url + _s["art"]["icons"]["warning"] + + # art from imgur + FLOWERS_ART: str = _s["art"]["juicybblue"]["flowers"] + TEAPOT_ART: str = _s["art"]["juicybblue"]["teapot"] + MUFFIN_ART: str = _s["art"]["juicybblue"]["muffin"] + CLOUD_ART: str = _s["art"]["other"]["cloud"] + TROPHY_ART: str = _s["art"]["other"]["trophy"] + + # emotes + EMOTES_SERVER_ID: int = _s["emotes"]["guild_id"] + EMOTE_IDS: Dict[str, int] = _s["emotes"]["emote_ids"] + + # introductions (currently only usable in ONE guild) + INTRODUCTIONS_GUILD_ID: int = _s["introductions"]["intro_guild_id"] + INTRODUCTIONS_CHANNEL_ID: int = _s["introductions"]["intro_channel_id"] + INTRODUCTIONS_QUESTION_MAPPING: Dict[str, str] = _s["introductions"][ + "intro_question_mapping" + ] + # Reponse strings # TODO: Implement switching between languages STRINGS = _p.read_json("strings.en-US") diff --git a/modules/misc/ping.py b/modules/misc/ping.py index 7cfe18e..8ba78e0 100644 --- a/modules/misc/ping.py +++ b/modules/misc/ping.py @@ -1,4 +1,6 @@ from discord.ext import commands +from lib.const import CONST +from ui.embeds import builder class Ping(commands.Cog): @@ -10,7 +12,16 @@ class Ping(commands.Cog): usage="ping", ) async def ping(self, ctx: commands.Context[commands.Bot]) -> None: - await ctx.send(f"Pong! Latency: {self.bot.latency * 1000:.2f}ms") + embed = builder.create_success_embed( + ctx, + author_text=CONST.STRINGS["ping_author"], + description=CONST.STRINGS["ping_pong"], + footer_text=CONST.STRINGS["ping_footer"].format( + round(1000 * self.bot.latency), + ), + ) + + await ctx.send(embed=embed) async def setup(bot: commands.Bot) -> None: diff --git a/settings.yaml b/settings.yaml index 93a1781..11e567d 100644 --- a/settings.yaml +++ b/settings.yaml @@ -1,6 +1,110 @@ +info: + title: Luminara + author: wlinator + license: GNU General Public License v3.0 + version: "2.9.0" # "Settings & Customizability" update + repository_url: https://git.wlinator.org/Luminara/Lumi + invite_url: https://discord.com/oauth2/authorize?client_id=1038050427272429588&permissions=8&scope=bot + logs: level: DEBUG format: "{time:YYYY-MM-DD HH:mm:ss} | {level: <8} | {name}:{function}:{line} - {message}" cogs: ignore: # add cogs to ignore here + +images: + allowed_image_extensions: + - .jpg + - .png + birthday_gif_url: https://media1.tenor.com/m/NXvU9jbBUGMAAAAC/fireworks.gif + +colors: + color_default: 0xFF8C00 + color_warning: 0xFF7600 + color_error: 0xFF4500 + +economy: + daily_reward: 500 + blackjack_multiplier: 1.4 + blackjack_hit_emoji: <:hit:1119262723285467156> + blackjack_stand_emoji: <:stand:1118923298298929154> + slots_multipliers: + pair: 1.5 + three_of_a_kind: 4 + three_diamonds: 6 + jackpot: 15 + +art: + fetch_url: https://git.wlinator.org/Luminara/Art/raw/branch/main/ + logo: + opaque: lumi_logo.png + transparent: lumi_logo_transparent.png + icons: + boost: lumi_boost.png + check: lumi_check.png + cross: lumi_cross.png + exclaim: lumi_exclaim.png + hammer: lumi_hammer.png + money_bag: lumi_money_bag.png + money_coins: lumi_money_coins.png + question: lumi_question.png + streak: lumi_streak.png + streak_bronze: lumi_streak_bronze.png + streak_gold: lumi_streak_gold.png + streak_silver: lumi_streak_silver.png + warning: lumi_warning.png + juicybblue: + flowers: https://i.imgur.com/79XfsbS.png + teapot: https://i.imgur.com/wFsgSnr.png + muffin: https://i.imgur.com/hSauh7K.png + other: + cloud: https://i.imgur.com/rc68c43.png + trophy: https://i.imgur.com/dvIIr2G.png + +emotes: + guild_id: 1038051105642401812 + emote_ids: + slots_animated_id: 1119262805309259776 + slots_0_id: 1119262803816095825 + slots_1_id: 1119262801261760592 + slots_2_id: 1119262800049614939 + slots_3_id: 1119262796497039510 + slots_4_id: 1119262794676715681 + slots_5_id: 1119262792386621555 + slots_6_id: 1119262791061229669 + S_Wide: 1119286730302955651 + L_Wide: 1119286763802857533 + O_Wide: 1119286787169329203 + T_Wide: 1119286804634406942 + CBorderBLeft: 1119286973572595712 + CBorderBRight: 1119286918459445408 + CBorderTLeft: 1119287006464331806 + CBorderTRight: 1119286865284051035 + HBorderB: 1119286936155213835 + HBorderT: 1119287027662344322 + VBorder: 1119286889854279680 + WSmall: 1119288536282173490 + ISmall: 1119288552673517608 + NSmall: 1119288579382857830 + LCentered: 1119287296127156325 + OCentered: 1119287563245584394 + SCentered: 1119287327588634647 + ECentered: 1119287343833165945 + Blank: 1119287267001905283 + lost: 1119288454212243607 + +introductions: + intro_guild_id: 719227135151046700 + intro_channel_id: 973619250507972600 + intro_question_mapping: + Nickname: how would you like to be identified in the server? (nickname) + Age: how old are you? + Region: where do you live? + Languages: which languages do you speak? + Pronouns: what are your preferred pronouns? + Sexuality: what's your sexuality? + Relationship status: what's your current relationship status? + Likes & interests: likes & interests + Dislikes: dislikes + EXTRAS: "EXTRAS: job status, zodiac sign, hobbies, etc. Tell us about yourself!" diff --git a/ui/embeds.py b/ui/embeds.py new file mode 100644 index 0000000..da8cb9b --- /dev/null +++ b/ui/embeds.py @@ -0,0 +1,206 @@ +import datetime + +import discord + +from lib.const import CONST + + +class builder: + @staticmethod + def create_embed( + ctx, + title=None, + author_text=None, + author_icon_url=None, + author_url=None, + description=None, + color=None, + footer_text=None, + footer_icon_url=None, + show_name=True, + image_url=None, + thumbnail_url=None, + timestamp=None, + hide_author=False, + hide_author_icon=False, + hide_timestamp=False, + ) -> discord.Embed: + if not hide_author: + if not author_text: + author_text = ctx.author.name + elif show_name: + description = f"**{ctx.author.name}** {description}" + + if not hide_author_icon and not author_icon_url: + author_icon_url = ctx.author.display_avatar.url + + if not footer_text: + footer_text = "Luminara" + if not footer_icon_url: + footer_icon_url = CONST.LUMI_LOGO_TRANSPARENT + + embed = discord.Embed( + title=title, + description=description, + color=color or CONST.COLOR_DEFAULT, + ) + if not hide_author: + embed.set_author( + name=author_text, + icon_url=None if hide_author_icon else author_icon_url, + url=author_url, + ) + embed.set_footer(text=footer_text, icon_url=footer_icon_url) + if not hide_timestamp: + embed.timestamp = timestamp or datetime.datetime.now() + + if image_url: + embed.set_image(url=image_url) + if thumbnail_url: + embed.set_thumbnail(url=thumbnail_url) + + return embed + + @staticmethod + def create_error_embed( + ctx, + title=None, + author_text=None, + author_icon_url=None, + author_url=None, + description=None, + footer_text=None, + show_name=True, + image_url=None, + thumbnail_url=None, + timestamp=None, + hide_author=False, + hide_author_icon=False, + hide_timestamp=False, + ) -> discord.Embed: + return builder.create_embed( + ctx, + title=title, + author_text=author_text, + author_icon_url=author_icon_url or CONST.CROSS_ICON, + author_url=author_url, + description=description, + color=CONST.COLOR_ERROR, + footer_text=footer_text, + footer_icon_url=CONST.LUMI_LOGO_TRANSPARENT, + show_name=show_name, + image_url=image_url, + thumbnail_url=thumbnail_url, + timestamp=timestamp, + hide_author=hide_author, + hide_author_icon=hide_author_icon, + hide_timestamp=hide_timestamp, + ) + + @staticmethod + def create_success_embed( + ctx, + title=None, + author_text=None, + author_icon_url=None, + author_url=None, + description=None, + footer_text=None, + show_name=True, + image_url=None, + thumbnail_url=None, + timestamp=None, + hide_author=False, + hide_author_icon=False, + hide_timestamp=False, + ) -> discord.Embed: + return builder.create_embed( + ctx, + title=title, + author_text=author_text, + author_icon_url=author_icon_url or CONST.CHECK_ICON, + author_url=author_url, + description=description, + color=CONST.COLOR_DEFAULT, + footer_text=footer_text, + footer_icon_url=CONST.LUMI_LOGO_TRANSPARENT, + show_name=show_name, + image_url=image_url, + thumbnail_url=thumbnail_url, + timestamp=timestamp, + hide_author=hide_author, + hide_author_icon=hide_author_icon, + hide_timestamp=hide_timestamp, + ) + + @staticmethod + def create_info_embed( + ctx, + title=None, + author_text=None, + author_icon_url=None, + author_url=None, + description=None, + footer_text=None, + show_name=True, + image_url=None, + thumbnail_url=None, + timestamp=None, + hide_author=False, + hide_author_icon=False, + hide_timestamp=False, + ) -> discord.Embed: + return builder.create_embed( + ctx, + title=title, + author_text=author_text, + author_icon_url=author_icon_url or CONST.EXCLAIM_ICON, + author_url=author_url, + description=description, + color=CONST.COLOR_DEFAULT, + footer_text=footer_text, + footer_icon_url=CONST.LUMI_LOGO_TRANSPARENT, + show_name=show_name, + image_url=image_url, + thumbnail_url=thumbnail_url, + timestamp=timestamp, + hide_author=hide_author, + hide_author_icon=hide_author_icon, + hide_timestamp=hide_timestamp, + ) + + @staticmethod + def create_warning_embed( + ctx, + title=None, + author_text=None, + author_icon_url=None, + author_url=None, + description=None, + footer_text=None, + show_name=True, + image_url=None, + thumbnail_url=None, + timestamp=None, + hide_author=False, + hide_author_icon=False, + hide_timestamp=False, + ) -> discord.Embed: + return builder.create_embed( + ctx, + title=title, + author_text=author_text, + author_icon_url=author_icon_url or CONST.WARNING_ICON, + author_url=author_url, + description=description, + color=CONST.COLOR_WARNING, + footer_text=footer_text, + footer_icon_url=CONST.LUMI_LOGO_TRANSPARENT, + show_name=show_name, + image_url=image_url, + thumbnail_url=thumbnail_url, + timestamp=timestamp, + hide_author=hide_author, + hide_author_icon=hide_author_icon, + hide_timestamp=hide_timestamp, + )