Skip to content

Commit 7b2f93f

Browse files
committed
new safe utils.commons.asyncget method
1 parent bb1dcdf commit 7b2f93f

File tree

10 files changed

+110
-35
lines changed

10 files changed

+110
-35
lines changed

src/commands/games/CheapGames.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@
6161
from enum import StrEnum
6262
import datetime
6363
import asyncio
64-
import time
64+
import json
6565

6666
from utils.exceptions import ExtensionException
6767
from utils.commons import Extensions, asyncget
@@ -288,7 +288,9 @@ async def trigger_update(self, interaction : Interaction):
288288
config, enabled = await self.db.getExtensionConfig(interaction.guild, Extensions.CHEAPGAMES)
289289
assert enabled, f'The extension is not enabled'
290290

291-
self.giveaways = await asyncget("https://gamerpower.com/api/giveaways")
291+
content_type, content, code, reason = await asyncget("https://gamerpower.com/api/giveaways")
292+
assert content_type == 'application/json' and code == 200, f'Error while fetching new giveaways (code: {code}): {reason}'
293+
self.giveaways = json.loads(content)
292294

293295
configuration = await self.handle_server_updates((interaction.guild.id, Extensions.CHEAPGAMES.value, enabled, config))
294296

@@ -307,7 +309,9 @@ async def update_giveaways_and_deals(self):
307309
async with self.db:
308310
configurations = await self.db.getAllExtensionConfig(Extensions.CHEAPGAMES)
309311

310-
self.giveaways = await asyncget("https://gamerpower.com/api/giveaways")
312+
content_type, content, code, reason = await asyncget("https://gamerpower.com/api/giveaways")
313+
assert content_type == 'application/json' and code == 200, f'Error while fetching new giveaways (code: {code}): {reason}'
314+
self.giveaways = json.loads(content)
311315

312316
tasks : list[asyncio.Task] = []
313317
for guild_id, ext_id, enabled, config in configurations:

src/commands/games/FreeGames.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@
1414
View, \
1515
button
1616

17-
from enum import StrEnum
1817
from datetime import datetime, timezone
18+
from enum import StrEnum
19+
import json
1920

2021
from utils.terminal import getlogger
2122
from utils.commons import asyncget
@@ -217,7 +218,9 @@ async def next_button(self, button: Button, interaction: Interaction):
217218
@button(label="Info", style=ButtonStyle.primary)
218219
async def more_information(self, button: Button, interaction: Interaction):
219220
try:
220-
info = await asyncget(f'https://www.freetogame.com/api/game?id={self.data[self.n]['id']}')
221+
content_type, content, code, reason = await asyncget(f'https://www.freetogame.com/api/game?id={self.data[self.n]['id']}')
222+
assert content_type == 'application/json' and code == 200, f"Error while fetching game info (code: {code}): {reason}"
223+
info : dict = json.loads(content)
221224

222225
view = GameInfoView(self, info)
223226
embed = GameInfoEmbed(info, view.images[view.image_num])
@@ -266,9 +269,9 @@ async def get(self,
266269
if sort_by: params.append(f'sort_by={sort_by}')
267270

268271
url = f'{self.baseurl}{endpoint}{'?' if len(params) > 0 else ''}{'&'.join(params)}'
269-
print(url)
270-
data = await asyncget(url)
271-
272+
content_type, content, code, reason = await asyncget(url)
273+
assert content_type == 'application/json' and code == 200, f"Error while fetching games info (code: {code}): {reason}"
274+
data : list = json.loads(content)
272275
except AssertionError as e:
273276
await interaction.followup.send(e)
274277
else:

src/commands/general/RandomCats.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,13 @@
1818
from nextcord.ui import View, Button
1919
from enum import StrEnum
2020
from io import BytesIO
21+
import json
2122
import re
2223

23-
from utils.commons import safe_asyncget, asyncget
24+
from utils.commons import asyncget
25+
from utils.terminal import getlogger
26+
27+
logger = getlogger()
2428

2529
class Font(StrEnum):
2630
AndaleMono = "Andale Mono"
@@ -77,7 +81,12 @@ def __init__(self, bot : commands.Bot):
7781
@Cog.listener()
7882
async def on_ready(self):
7983
if not self.fetched_tags:
80-
self.tags : list = await asyncget(f'{self.baseurl}/api/tags')
84+
try:
85+
content_type, content, code, reason = await asyncget(f'{self.baseurl}/api/tags')
86+
assert content_type == 'application/json' and code == 200, f'Error while fetching tags (code: {code}): {reason}'
87+
self.tags : list = json.loads(content)
88+
except AssertionError as e:
89+
logger.error(e)
8190

8291
@slash_command(name="cats", description="Set of commands to get cat images")
8392
async def cats(self, interaction : Interaction): pass
@@ -105,7 +114,6 @@ async def get_tags(self, interaction : Interaction):
105114
await interaction.followup.send(embed=embed, view=view, ephemeral=True)
106115

107116
@cats.subcommand(name="randomcat",description="Get a random cat image")
108-
@commands.cooldown(1, 60, commands.BucketType.user)
109117
async def randomcat(self,
110118
interaction : Interaction,
111119
tags : str = SlashOption(description="send a random image of a cat based on tags e.g. gif,cute", default="", required=False),
@@ -165,7 +173,7 @@ async def randomcat(self,
165173

166174
print(url)
167175

168-
content_type, content, status, reason = await safe_asyncget(url)
176+
content_type, content, status, reason = await asyncget(url)
169177

170178
assert status != 404, f"Cat not found with tags {tags} "
171179
assert status == 200 and content_type.startswith("image/"), f"An unexpected error occurred: {reason}"

src/commands/minigames/ValorantQuiz.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,13 @@
66
from cachetools import LRUCache
77
from datetime import datetime
88
from uuid import UUID
9+
import json
910

1011
from utils.commons import asyncget
12+
from utils.terminal import getlogger
13+
14+
logger = getlogger()
15+
1116
from .ValorantQuizUtils import Levels, MapModes
1217
from .ValorantQuizSession import MapQuizSession, QuizSession
1318

@@ -35,7 +40,9 @@ async def maps(self,
3540
await interaction.response.defer(ephemeral=False)
3641

3742
if not 'maps' in self.cache:
38-
self.cache['maps'] = (await asyncget(f'{self.baseurl}/maps'))['data']
43+
content_type, content, code, reason = await asyncget(f'{self.baseurl}/maps')
44+
assert content_type == 'application/json' and code == 200, f"Error while fetching game info (code: {code}): {reason}"
45+
self.cache['maps'] = json.loads(content)["data"]
3946

4047
session = MapQuizSession(
4148
level=Levels(level),
@@ -52,7 +59,7 @@ async def maps(self,
5259

5360
await interaction.followup.send(embed=embed,view=view)
5461
except AssertionError as e:
55-
print(e)
62+
logger.error(e)
5663

5764
def setup(bot : commands.Bot) -> None:
5865
bot.add_cog(ValorantQuiz(bot))

src/commands/minigames/ValorantQuizSession.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import traceback
2222
import asyncio
2323
import random
24+
import json
2425

2526
from utils.commons import asyncget
2627
from .ValorantQuizUtils import \
@@ -150,8 +151,10 @@ async def _next_round(self):
150151

151152

152153
if key == ImageTypes.PRO and self.mode == MapModes.FRAGMENTS and callouts and img_url:
153-
img_data = await asyncget(img_url, mimetype='image/png')
154-
ImageBytesIO = BytesIO(img_data)
154+
content_type, content, code, reason = await asyncget(f'{self.baseurl}/maps')
155+
assert content_type == 'image/png' and code == 200, f"Error while fetching next map image (code: {code}): {reason}"
156+
157+
ImageBytesIO = BytesIO(content)
155158

156159
callout = random.choice(callouts)
157160
xCallout = callout['location']['x']

src/commands/verify/VerificationUis.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
from enum import StrEnum
2929
import hashlib
3030
import random
31+
import json
3132

3233
from utils.exceptions import ExtensionException
3334
from utils.commons import Extensions
@@ -177,12 +178,17 @@ async def answer_button(self, button : Button, interaction : Interaction):
177178
await interaction.response.send_modal(self.modal)
178179

179180
async def async_init(self):
180-
response = await asyncget("https://api.textcaptcha.com/ggsbot.json")
181+
try:
182+
content_type, content, code, reason = await asyncget("https://api.textcaptcha.com/ggsbot.json")
183+
assert content_type == 'application/json' and code == 200, f"Error while fetching captcha data (code: {code}): {reason}"
184+
response = json.loads(content)
181185

182-
self.question = response['q']
183-
self.answers = response['a']
186+
self.question = response['q']
187+
self.answers = response['a']
184188

185-
self.set_field_at(0, name="Question", value=self.question)
189+
self.set_field_at(0, name="Question", value=self.question)
190+
except AssertionError as e:
191+
logger.error(f"Error while fetching captcha data: {e}")
186192

187193
async def on_answer(self, interaction : Interaction, answer : str):
188194
encoded_answer = hashlib.md5(answer.strip().lower().encode()).hexdigest()

src/main.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ def load_commands():
4343
except commands.NoEntryPointError as e:
4444
continue # if no entry point found maybe is a file used by the main command file.
4545
except commands.ExtensionFailed as e:
46-
logger.warning(e)
46+
logger.warning(f"Extension {e.name} failed to load: \n{traceback.format_exc()}")
4747
else:
4848
logger.info(f'Imported extension {F.LIGHTMAGENTA_EX}{category}.{filename[:-3]}{F.RESET}')
4949

src/utils/abc.py

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from nextcord import Embed, Interaction, Guild, Colour, ButtonStyle
33
from nextcord.ui import View, Item, Button
44
from typing import Callable
5-
5+
import inspect
66

77

88
class SetupUI(Embed, View):
@@ -53,4 +53,45 @@ async def __setup(self, interaction : Interaction):
5353
try:
5454
await self._submit_callback(interaction)
5555
except Exception as e:
56-
raise e
56+
raise e
57+
58+
class GGsBotPage:#(Embed, View):
59+
def __init__(self, ui : 'GGsBotUI'):
60+
#Embed.__init__(self)
61+
#View.__init__(self)
62+
self.ui = ui
63+
64+
65+
66+
class GGsBotUI:
67+
def __init__(self):
68+
self.pages = [cls(self) for _, cls in inspect.getmembers(MyUI, lambda x: inspect.isclass(x) and issubclass(x, GGsBotPage))]
69+
print(self.pages)
70+
71+
@property
72+
def bot(self): return self._bot
73+
74+
@property
75+
def guild(self): return self._guild
76+
77+
@property
78+
def config(self): return self._config
79+
80+
@config.setter
81+
def config(self, config : dict): self._config = config
82+
83+
84+
85+
class MyUI(GGsBotUI):
86+
def __init__(self):
87+
GGsBotUI.__init__(self)
88+
89+
class MyFirstPage(GGsBotPage):
90+
def __init__(self, ui : GGsBotUI):
91+
GGsBotPage.__init__(self, ui)
92+
93+
class MySecondPage(GGsBotPage):
94+
def __init__(self, ui : GGsBotUI):
95+
GGsBotPage.__init__(self, ui)
96+
97+
MyUI()

src/utils/commons.py

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,22 @@ class Extensions(StrEnum):
1010
TEMPVC = 'tempvc'
1111
VERIFY = 'verify'
1212

13-
async def asyncget(url : str, mimetype = 'application/json') -> dict | bytes:
14-
async with aiohttp.ClientSession() as session:
15-
async with session.get(url) as response:
16-
assert response.status == 200, f"Error while fetching {url}: {response.reason}"
13+
async def asyncget(url : str, timeout : int = 60, max_redirects : int = 5) -> tuple[str, bytes, int, str | None]:
14+
"""
15+
Fetches the content from the given URL asynchronously.
1716
18-
if mimetype == 'application/json':
19-
return await response.json()
20-
else:
21-
return await response.read()
17+
Args:
18+
url (:class:`str`): The URL to fetch the content from.
19+
timeout (:class:`int`, optional): The maximum time to wait for the response in seconds. Defaults to 60.
20+
max_redirects (:class:`int`, optional): The maximum number of redirects to follow. Defaults to 5.
2221
23-
async def safe_asyncget(url : str) -> tuple[str, bytes, int, str | None]:
22+
Returns:
23+
:class:`tuple`: A tuple containing:\n
24+
\t- str: The content type of the response.
25+
\t- bytes: The raw content of the response.
26+
\t- int: The HTTP status code of the response.
27+
\t- str | None: The reason phrase returned by the server, or None if not provided.
28+
"""
2429
async with aiohttp.ClientSession() as session:
25-
async with session.get(url) as response:
30+
async with session.get(url, timeout=timeout, max_redirects=max_redirects) as response:
2631
return response.content_type, await response.content.read(), response.status, response.reason

src/utils/exceptions.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,6 @@ def asEmbed(self) -> Embed:
3232

3333
return embed
3434

35-
36-
3735
class CloudFlareAIException(GGsBotException):
3836
def __init__(self, code : int | str = None, *args) -> None:
3937
"""Set of errors that are raised by the cloudflare AI."""

0 commit comments

Comments
 (0)