From 3bc6027627c932ebe2f3bf1cd4358f20f0fe74d3 Mon Sep 17 00:00:00 2001 From: dhzdhd Date: Wed, 10 Mar 2021 15:07:24 +0530 Subject: [PATCH 1/8] Adding wolfram group of commands to gurkbot --- bot/constants.py | 6 ++++ bot/exts/fun/wolfram.py | 75 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 bot/exts/fun/wolfram.py diff --git a/bot/constants.py b/bot/constants.py index 0f3feea6..32a39c46 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -23,6 +23,8 @@ class Emojis(NamedTuple): cucumber_emoji = "\U0001f952" invalid_emoji = "\u274c" + wolfram_emoji = "<:wolfram:818541752351719477>" + class Colours: green = 0x1F8B4C @@ -40,6 +42,10 @@ class Channels(NamedTuple): dev_branding = int(os.getenv("CHANNEL_DEV_BRANDING", 789193817051234306)) +class Tokens(NamedTuple): + wolfram_id = os.getenv("WOLFRAM_TOKEN") or None + + # Bot replies with pathlib.Path("bot/resources/bot_replies.yml").open(encoding="utf8") as file: bot_replies = yaml.safe_load(file) diff --git a/bot/exts/fun/wolfram.py b/bot/exts/fun/wolfram.py new file mode 100644 index 00000000..185be552 --- /dev/null +++ b/bot/exts/fun/wolfram.py @@ -0,0 +1,75 @@ +from random import choice +from typing import Union + +from aiohttp import ClientSession +from bot.constants import ERROR_REPLIES, Emojis, Tokens +from discord import Embed +from discord.ext import commands +from yarl import URL + + +class WolframCommands(commands.Cog): + """ + Wolfram Category cog, containing commands related to the WolframAlpha API. + + Commands + ├ image Fetch the response to a query in the form of an image. + ├ text Fetch the response to a query in a short phrase. + └ chat Fetch the response of the Wolfram AI based on the given question/statement. + """ + + def __init__(self, bot: commands.Bot) -> None: + self.bot = bot + self.image_url = "http://api.wolframalpha.com/v1/simple" + self.params = { + "appid": Tokens.wolfram_id, + "background": "2F3136", + "foreground": "white", + "layout": "labelbar", + "fontsize": "23", + "width": "700", + } + + @staticmethod + async def web_request(url: str, params: dict) -> Union[URL, str]: + """Web request handler for wolfram group of commands.""" + async with ClientSession() as session: + async with session.get(url=url, params=params) as resp: + if resp.status == 200: + return resp.url + elif resp.status == 501: + return "Sorry, the API could not understand your input" + elif resp.status == 400: + return "Sorry, the API did not find any input to interpret" + + @commands.group(name="wolfram", aliases=("wa",), invoke_without_command=True) + async def wolfram_group(self, ctx: commands.Context) -> None: + """Commands for wolfram.""" + await ctx.send_help(ctx.command) + + @wolfram_group.command(name="image") + async def wolfram_image(self, ctx: commands.Context, *, query: str) -> None: + """Sends wolfram image corresponding to the given query.""" + self.params["i"] = query + + async with ctx.typing(): + response = await WolframCommands.web_request( + url=self.image_url, params=self.params + ) + + if isinstance(response, str): + embed = Embed(title=choice(ERROR_REPLIES), description=response) + else: + embed = Embed(title=f"{Emojis.wolfram_emoji} Wolfram Alpha").set_image( + url=response + ) + embed.add_field( + name="Cannot see image?", + value=f"[Click here](https://www.wolframalpha.com/input/?i={query.replace(' ', '+')})", + ) + await ctx.send(ctx.author.mention, embed=embed) + + +def setup(bot: commands.Bot) -> None: + """Load the Wolfram cog.""" + bot.add_cog(WolframCommands(bot)) From 5255214a7c6ac16ba1ead539e527c3e6e549d98e Mon Sep 17 00:00:00 2001 From: dhzdhd Date: Thu, 6 Jan 2022 19:50:33 +0530 Subject: [PATCH 2/8] Migrate to slash commands and apply suggested changes --- .env-example | 2 ++ bot/constants.py | 5 ++-- bot/exts/fun/wolfram.py | 65 +++++++++++++++++++++++------------------ docker-compose.yaml | 1 + 4 files changed, 42 insertions(+), 31 deletions(-) diff --git a/.env-example b/.env-example index d0ad10b3..e61c9518 100644 --- a/.env-example +++ b/.env-example @@ -13,3 +13,5 @@ EMOJI_TRASHCAN="" ROLE_STEERING_COUNCIL="" ROLE_MODERATORS="" + +WOLFRAM_TOKEN="" diff --git a/bot/constants.py b/bot/constants.py index 8d373598..c7f1d6fc 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -43,7 +43,7 @@ class Emojis(NamedTuple): CROSS_MARK_EMOJI = "\U0000274C" MAG_RIGHT_EMOJI = "\U0001f50e" - wolfram_emoji = "<:wolfram:818541752351719477>" + wolfram_emoji = "<:wolfram:818541879314350131>" class Colours: @@ -84,7 +84,7 @@ class Roles(NamedTuple): class Tokens(NamedTuple): - wolfram_id = os.getenv("WOLFRAM_TOKEN") or None + wolfram_token = os.getenv("WOLFRAM_TOKEN") # Bot replies @@ -94,6 +94,7 @@ class Tokens(NamedTuple): POSITIVE_REPLIES = bot_replies["POSITIVE_REPLIES"] NEGATIVE_REPLIES = bot_replies["NEGATIVE_REPLIES"] + # Minecraft Server class Minecraft(NamedTuple): server_address = "mc.gurkult.com" diff --git a/bot/exts/fun/wolfram.py b/bot/exts/fun/wolfram.py index 185be552..afd79563 100644 --- a/bot/exts/fun/wolfram.py +++ b/bot/exts/fun/wolfram.py @@ -1,10 +1,11 @@ -from random import choice +import random from typing import Union +from urllib import parse -from aiohttp import ClientSession +import disnake from bot.constants import ERROR_REPLIES, Emojis, Tokens -from discord import Embed -from discord.ext import commands +from disnake import Embed +from disnake.ext import commands from yarl import URL @@ -20,9 +21,9 @@ class WolframCommands(commands.Cog): def __init__(self, bot: commands.Bot) -> None: self.bot = bot - self.image_url = "http://api.wolframalpha.com/v1/simple" + self.image_url = "https://api.wolframalpha.com/v1/simple" self.params = { - "appid": Tokens.wolfram_id, + "appid": Tokens.wolfram_token, "background": "2F3136", "foreground": "white", "layout": "labelbar", @@ -30,10 +31,9 @@ def __init__(self, bot: commands.Bot) -> None: "width": "700", } - @staticmethod - async def web_request(url: str, params: dict) -> Union[URL, str]: + async def web_request(self, url: str, params: dict) -> Union[URL, str]: """Web request handler for wolfram group of commands.""" - async with ClientSession() as session: + async with self.bot.http_session as session: async with session.get(url=url, params=params) as resp: if resp.status == 200: return resp.url @@ -42,32 +42,39 @@ async def web_request(url: str, params: dict) -> Union[URL, str]: elif resp.status == 400: return "Sorry, the API did not find any input to interpret" - @commands.group(name="wolfram", aliases=("wa",), invoke_without_command=True) - async def wolfram_group(self, ctx: commands.Context) -> None: + @commands.slash_command(guild_ids=[793864455527202847]) + async def wolfram(self, inter: disnake.ApplicationCommandInteraction) -> None: """Commands for wolfram.""" - await ctx.send_help(ctx.command) - @wolfram_group.command(name="image") - async def wolfram_image(self, ctx: commands.Context, *, query: str) -> None: - """Sends wolfram image corresponding to the given query.""" + @wolfram.sub_command() + async def image( + self, inter: disnake.ApplicationCommandInteraction, query: str + ) -> None: + """ + Send wolfram image corresponding to the given query. + + Parameters + ---------- + query: The user query. + """ + await inter.response.defer() + self.params["i"] = query - async with ctx.typing(): - response = await WolframCommands.web_request( - url=self.image_url, params=self.params + response = await self.web_request(url=self.image_url, params=self.params) + + if isinstance(response, str): + embed = Embed(title=random.choice(ERROR_REPLIES), description=response) + else: + original_url = parse.quote_plus(query) + embed = Embed(title=f"{Emojis.wolfram_emoji} Wolfram Alpha") + embed.set_image(url=str(response)) + embed.add_field( + name="Cannot see image?", + value=f"[Click here](https://www.wolframalpha.com/input/?i={original_url})", ) - if isinstance(response, str): - embed = Embed(title=choice(ERROR_REPLIES), description=response) - else: - embed = Embed(title=f"{Emojis.wolfram_emoji} Wolfram Alpha").set_image( - url=response - ) - embed.add_field( - name="Cannot see image?", - value=f"[Click here](https://www.wolframalpha.com/input/?i={query.replace(' ', '+')})", - ) - await ctx.send(ctx.author.mention, embed=embed) + await inter.edit_original_message(embed=embed) def setup(bot: commands.Bot) -> None: diff --git a/docker-compose.yaml b/docker-compose.yaml index 0abc2b42..e6d5ab32 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -35,6 +35,7 @@ services: - CHANNEL_LOGS - ROLE_STEERING_COUNCIL - ROLE_MODERATORS + - WOLFRAM_TOKEN volumes: - .:/bot From 8217db88e7bb8e4bff53f7cfbe0179168de8f766 Mon Sep 17 00:00:00 2001 From: dhzdhd Date: Thu, 6 Jan 2022 20:03:03 +0530 Subject: [PATCH 3/8] Fix closing of bot http_session on command re-execution --- bot/exts/fun/wolfram.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/bot/exts/fun/wolfram.py b/bot/exts/fun/wolfram.py index afd79563..cfa98121 100644 --- a/bot/exts/fun/wolfram.py +++ b/bot/exts/fun/wolfram.py @@ -33,14 +33,13 @@ def __init__(self, bot: commands.Bot) -> None: async def web_request(self, url: str, params: dict) -> Union[URL, str]: """Web request handler for wolfram group of commands.""" - async with self.bot.http_session as session: - async with session.get(url=url, params=params) as resp: - if resp.status == 200: - return resp.url - elif resp.status == 501: - return "Sorry, the API could not understand your input" - elif resp.status == 400: - return "Sorry, the API did not find any input to interpret" + async with self.bot.http_session.get(url=url, params=params) as resp: + if resp.status == 200: + return resp.url + elif resp.status == 501: + return "Sorry, the API could not understand your input" + elif resp.status == 400: + return "Sorry, the API did not find any input to interpret" @commands.slash_command(guild_ids=[793864455527202847]) async def wolfram(self, inter: disnake.ApplicationCommandInteraction) -> None: From 3eabda1c3fb0e889ac95c4f2c86fecd03e1e7ef9 Mon Sep 17 00:00:00 2001 From: dhzdhd Date: Thu, 6 Jan 2022 20:30:53 +0530 Subject: [PATCH 4/8] Remove wolfram emoji, change embed color and resolve param suggestion --- bot/constants.py | 2 -- bot/exts/fun/wolfram.py | 10 +++++----- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/bot/constants.py b/bot/constants.py index c7f1d6fc..fa152e87 100644 --- a/bot/constants.py +++ b/bot/constants.py @@ -43,8 +43,6 @@ class Emojis(NamedTuple): CROSS_MARK_EMOJI = "\U0000274C" MAG_RIGHT_EMOJI = "\U0001f50e" - wolfram_emoji = "<:wolfram:818541879314350131>" - class Colours: green = 0x1F8B4C diff --git a/bot/exts/fun/wolfram.py b/bot/exts/fun/wolfram.py index cfa98121..c7d92381 100644 --- a/bot/exts/fun/wolfram.py +++ b/bot/exts/fun/wolfram.py @@ -3,7 +3,7 @@ from urllib import parse import disnake -from bot.constants import ERROR_REPLIES, Emojis, Tokens +from bot.constants import Colours, ERROR_REPLIES, Tokens from disnake import Embed from disnake.ext import commands from yarl import URL @@ -58,15 +58,15 @@ async def image( """ await inter.response.defer() - self.params["i"] = query - - response = await self.web_request(url=self.image_url, params=self.params) + response = await self.web_request( + url=self.image_url, params=self.params | {"i": query} + ) if isinstance(response, str): embed = Embed(title=random.choice(ERROR_REPLIES), description=response) else: original_url = parse.quote_plus(query) - embed = Embed(title=f"{Emojis.wolfram_emoji} Wolfram Alpha") + embed = Embed(title="Wolfram Alpha", colour=Colours.green) embed.set_image(url=str(response)) embed.add_field( name="Cannot see image?", From ff37499339cd95af718f505b4351175a805c475b Mon Sep 17 00:00:00 2001 From: dhzdhd Date: Thu, 6 Jan 2022 21:45:04 +0530 Subject: [PATCH 5/8] Remove unnecessary guild ID --- bot/exts/fun/wolfram.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot/exts/fun/wolfram.py b/bot/exts/fun/wolfram.py index c7d92381..2a7c09f8 100644 --- a/bot/exts/fun/wolfram.py +++ b/bot/exts/fun/wolfram.py @@ -41,7 +41,7 @@ async def web_request(self, url: str, params: dict) -> Union[URL, str]: elif resp.status == 400: return "Sorry, the API did not find any input to interpret" - @commands.slash_command(guild_ids=[793864455527202847]) + @commands.slash_command() async def wolfram(self, inter: disnake.ApplicationCommandInteraction) -> None: """Commands for wolfram.""" From 369e392831153344c24232c82668d79f823861eb Mon Sep 17 00:00:00 2001 From: dhzdhd Date: Sat, 29 Jan 2022 21:51:43 +0530 Subject: [PATCH 6/8] Fix exposed server location and exposed token --- bot/exts/fun/wolfram.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/bot/exts/fun/wolfram.py b/bot/exts/fun/wolfram.py index 2a7c09f8..9e6db549 100644 --- a/bot/exts/fun/wolfram.py +++ b/bot/exts/fun/wolfram.py @@ -1,4 +1,5 @@ import random +from io import BytesIO from typing import Union from urllib import parse @@ -6,7 +7,6 @@ from bot.constants import Colours, ERROR_REPLIES, Tokens from disnake import Embed from disnake.ext import commands -from yarl import URL class WolframCommands(commands.Cog): @@ -29,13 +29,16 @@ def __init__(self, bot: commands.Bot) -> None: "layout": "labelbar", "fontsize": "23", "width": "700", + "location": "the moon", + "latlong": "0.0,0.0", + "ip": "1.1.1.1", } - async def web_request(self, url: str, params: dict) -> Union[URL, str]: + async def web_request(self, url: str, params: dict) -> Union[bytes, str]: """Web request handler for wolfram group of commands.""" async with self.bot.http_session.get(url=url, params=params) as resp: if resp.status == 200: - return resp.url + return await resp.read() elif resp.status == 501: return "Sorry, the API could not understand your input" elif resp.status == 400: @@ -66,8 +69,10 @@ async def image( embed = Embed(title=random.choice(ERROR_REPLIES), description=response) else: original_url = parse.quote_plus(query) + file = disnake.File(BytesIO(response), filename="image.png") + embed = Embed(title="Wolfram Alpha", colour=Colours.green) - embed.set_image(url=str(response)) + embed.set_image(file=file) embed.add_field( name="Cannot see image?", value=f"[Click here](https://www.wolframalpha.com/input/?i={original_url})", From 2d573ef6196f99f120edef640a0878a8f1c30b76 Mon Sep 17 00:00:00 2001 From: dhzdhd Date: Sat, 12 Feb 2022 21:57:46 +0530 Subject: [PATCH 7/8] Add optional themes for generated image --- bot/exts/fun/wolfram.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/bot/exts/fun/wolfram.py b/bot/exts/fun/wolfram.py index 9e6db549..7d60785c 100644 --- a/bot/exts/fun/wolfram.py +++ b/bot/exts/fun/wolfram.py @@ -1,6 +1,6 @@ import random from io import BytesIO -from typing import Union +from typing import Literal, Union from urllib import parse import disnake @@ -50,7 +50,10 @@ async def wolfram(self, inter: disnake.ApplicationCommandInteraction) -> None: @wolfram.sub_command() async def image( - self, inter: disnake.ApplicationCommandInteraction, query: str + self, + inter: disnake.ApplicationCommandInteraction, + query: str, + theme: Literal["light", "dark"] = "dark", ) -> None: """ Send wolfram image corresponding to the given query. @@ -58,11 +61,17 @@ async def image( Parameters ---------- query: The user query. + theme: The theme of the image generated. dark by default. """ await inter.response.defer() + params = self.params + + if theme == "light": + params |= {"background": "white", "foreground": "2F3136"} + response = await self.web_request( - url=self.image_url, params=self.params | {"i": query} + url=self.image_url, params=params | {"i": query} ) if isinstance(response, str): From 0052bcb6c51f44787049a4ecb9a94c4e7ff39a06 Mon Sep 17 00:00:00 2001 From: dhzdhd Date: Wed, 17 Aug 2022 11:31:59 +0530 Subject: [PATCH 8/8] Remove docstring for non implemented commands and sort imports --- bot/exts/fun/wolfram.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/bot/exts/fun/wolfram.py b/bot/exts/fun/wolfram.py index 7d60785c..6513a2b8 100644 --- a/bot/exts/fun/wolfram.py +++ b/bot/exts/fun/wolfram.py @@ -4,19 +4,18 @@ from urllib import parse import disnake -from bot.constants import Colours, ERROR_REPLIES, Tokens from disnake import Embed from disnake.ext import commands +from bot.constants import ERROR_REPLIES, Colours, Tokens + class WolframCommands(commands.Cog): """ Wolfram Category cog, containing commands related to the WolframAlpha API. Commands - ├ image Fetch the response to a query in the form of an image. - ├ text Fetch the response to a query in a short phrase. - └ chat Fetch the response of the Wolfram AI based on the given question/statement. + └ image Fetch the response to a query in the form of an image. """ def __init__(self, bot: commands.Bot) -> None: