From 4267a8f50d1d69ade38cfecd36b1e97f0db57824 Mon Sep 17 00:00:00 2001 From: wlinator Date: Sun, 22 Sep 2024 17:35:13 +0200 Subject: [PATCH 1/4] Add inspirobot command --- modules/misc/inspirotbot.py | 49 +++++++++++++++++++++++++++++++++++++ wrappers/inspirobot.py | 20 +++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 modules/misc/inspirotbot.py create mode 100644 wrappers/inspirobot.py diff --git a/modules/misc/inspirotbot.py b/modules/misc/inspirotbot.py new file mode 100644 index 0000000..92c6d0c --- /dev/null +++ b/modules/misc/inspirotbot.py @@ -0,0 +1,49 @@ +from discord import app_commands +from discord.ext import commands + +import lib.format +from lib.client import Luminara +from lib.exceptions import LumiException +from ui.embeds import Builder +from wrappers.inspirobot import InspiroBot + + +class Inspirobot(commands.Cog): + def __init__(self, bot: Luminara) -> None: + self.bot: Luminara = bot + self.inspirobot.usage = lib.format.generate_usage(self.inspirobot) + + @commands.hybrid_command( + name="inspirobot", + aliases=["inspiro", "ib"], + ) + @app_commands.describe(ephemeral="Whether to send the image ephemerally.") + @commands.is_nsfw() + async def inspirobot(self, ctx: commands.Context[Luminara], *, ephemeral: bool = False) -> None: + """ + Get a random AI-generated motivational image from Inspirobot. + + Parameters + ---------- + ctx : commands.Context[Luminara] + The context of the command. + ephemeral : bool, optional + Whether to send the image ephemerally. Defaults to False. + """ + async with ctx.typing(): + try: + image_url = await InspiroBot().get_image() + except Exception as e: + msg = f"Failed to get image URL from Inspirobot: {e}" + raise LumiException(msg) from e + + embed = Builder.create_embed( + Builder.SUCCESS, + author_text="InspiroBot (AI Generated)", + image_url=image_url, + ) + await ctx.send(embed=embed, ephemeral=ephemeral) + + +async def setup(bot: Luminara) -> None: + await bot.add_cog(Inspirobot(bot)) diff --git a/wrappers/inspirobot.py b/wrappers/inspirobot.py new file mode 100644 index 0000000..4142f29 --- /dev/null +++ b/wrappers/inspirobot.py @@ -0,0 +1,20 @@ +import httpx + + +class InspiroBot: + def __init__(self): + self.base_url = "https://inspirobot.me/api?generate=true" + + async def get_image(self) -> str: + """ + Get a random motivational image from Inspirobot. + + Returns + ------- + str + The URL of the image. + """ + async with httpx.AsyncClient() as client: + response = await client.get(self.base_url) + response.raise_for_status() + return response.text From e43bbf91c59694625b55a3e0b6a4fddc14dcb460 Mon Sep 17 00:00:00 2001 From: wlinator Date: Sun, 22 Sep 2024 17:37:41 +0200 Subject: [PATCH 2/4] Properly handle is_nsfw() errors --- handlers/error.py | 1 + locales/strings.en-US.json | 1 + 2 files changed, 2 insertions(+) diff --git a/handlers/error.py b/handlers/error.py index 704d25e..97bd33c 100644 --- a/handlers/error.py +++ b/handlers/error.py @@ -17,6 +17,7 @@ error_map: dict[type[Exception], str] = { commands.NoPrivateMessage: CONST.STRINGS["error_no_private_message_description"], commands.NotOwner: CONST.STRINGS["error_not_owner_unknown"], commands.PrivateMessageOnly: CONST.STRINGS["error_private_message_only_description"], + commands.NSFWChannelRequired: CONST.STRINGS["error_nsfw_channel_required_description"], exceptions.BirthdaysDisabled: CONST.STRINGS["error_birthdays_disabled_description"], } diff --git a/locales/strings.en-US.json b/locales/strings.en-US.json index fdc0132..967233d 100644 --- a/locales/strings.en-US.json +++ b/locales/strings.en-US.json @@ -178,6 +178,7 @@ "error_not_enough_cash": "you don't have enough cash.", "error_not_owner": "{0} tried to use a bot admin command ({1})", "error_not_owner_unknown": "Unknown", + "error_nsfw_channel_required_description": "this command can only be used in Age-Restricted (NSFW) channels.", "error_out_of_time": "you ran out of time.", "error_out_of_time_economy": "you ran out of time. Your bet was forfeited.", "error_private_message_only_author": "Private Message Only", From 2ad200532dbc31fc5705896f9a27956f4d9ae5bb Mon Sep 17 00:00:00 2001 From: wlinator Date: Sun, 22 Sep 2024 17:38:27 +0200 Subject: [PATCH 3/4] up version --- settings.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.yaml b/settings.yaml index 9af9460..c53846f 100644 --- a/settings.yaml +++ b/settings.yaml @@ -88,7 +88,7 @@ info: title: Luminara author: wlinator license: GNU General Public License v3.0 - version: "3.0.1" + version: "3.2.0" repository_url: https://git.wlinator.org/Luminara/Lumi invite_url: https://discord.com/oauth2/authorize?client_id=1038050427272429588&permissions=8&scope=bot From 568b6166b06dbb37b61c54249693e0b93aa5e580 Mon Sep 17 00:00:00 2001 From: wlinator Date: Sun, 22 Sep 2024 17:45:48 +0200 Subject: [PATCH 4/4] small tweaks --- locales/strings.en-US.json | 1 + modules/misc/inspirotbot.py | 11 ++++------- wrappers/inspirobot.py | 2 +- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/locales/strings.en-US.json b/locales/strings.en-US.json index 967233d..bc667a4 100644 --- a/locales/strings.en-US.json +++ b/locales/strings.en-US.json @@ -201,6 +201,7 @@ "info_service_footer": "Info Service", "info_system": "**System:** {0} ({1})\n", "info_uptime": "**Uptime:** \n", + "inspirobot_author": "InspiroBot (AI Generated)", "intro_content": "Introduction by {0}", "intro_content_footer": "Type .intro in my DMs to start", "intro_no_channel": "the introduction channel is not set, please contact a moderator.", diff --git a/modules/misc/inspirotbot.py b/modules/misc/inspirotbot.py index 92c6d0c..d1c98a1 100644 --- a/modules/misc/inspirotbot.py +++ b/modules/misc/inspirotbot.py @@ -1,8 +1,8 @@ -from discord import app_commands from discord.ext import commands import lib.format from lib.client import Luminara +from lib.const import CONST from lib.exceptions import LumiException from ui.embeds import Builder from wrappers.inspirobot import InspiroBot @@ -17,9 +17,8 @@ class Inspirobot(commands.Cog): name="inspirobot", aliases=["inspiro", "ib"], ) - @app_commands.describe(ephemeral="Whether to send the image ephemerally.") @commands.is_nsfw() - async def inspirobot(self, ctx: commands.Context[Luminara], *, ephemeral: bool = False) -> None: + async def inspirobot(self, ctx: commands.Context[Luminara]) -> None: """ Get a random AI-generated motivational image from Inspirobot. @@ -27,8 +26,6 @@ class Inspirobot(commands.Cog): ---------- ctx : commands.Context[Luminara] The context of the command. - ephemeral : bool, optional - Whether to send the image ephemerally. Defaults to False. """ async with ctx.typing(): try: @@ -39,10 +36,10 @@ class Inspirobot(commands.Cog): embed = Builder.create_embed( Builder.SUCCESS, - author_text="InspiroBot (AI Generated)", + author_text=CONST.STRINGS["inspirobot_author"], image_url=image_url, ) - await ctx.send(embed=embed, ephemeral=ephemeral) + await ctx.send(embed=embed) async def setup(bot: Luminara) -> None: diff --git a/wrappers/inspirobot.py b/wrappers/inspirobot.py index 4142f29..fb21c31 100644 --- a/wrappers/inspirobot.py +++ b/wrappers/inspirobot.py @@ -14,7 +14,7 @@ class InspiroBot: str The URL of the image. """ - async with httpx.AsyncClient() as client: + async with httpx.AsyncClient(timeout=10.0) as client: response = await client.get(self.base_url) response.raise_for_status() return response.text