13
13
from logging import info
14
14
from inspect import signature , Parameter
15
15
from functools import partial
16
- from typing import Coroutine , Union , Dict , List , Optional
16
+ from typing import Coroutine , Union , Dict , List , Optional , Tuple
17
17
18
18
from .migrate import migrate_requiring_bot
19
19
from .static .enums import Category
@@ -48,6 +48,10 @@ async def get_prefix(bot: "BaseBot", message: discord.Message):
48
48
# in case message.guild is `None` or something went wrong getting the prefix the bot still NEEDS to react to mentions and k!
49
49
return commands .when_mentioned_or ("k!" )(bot , message )
50
50
51
+ class KilluaAPIException (Exception ):
52
+ """Raised when the Killua API returns an error"""
53
+ def __init__ (self , message : str ):
54
+ self .message = message
51
55
52
56
class BaseBot (commands .AutoShardedBot ):
53
57
def __init__ (self , * args , ** kwargs ):
@@ -342,6 +346,67 @@ async def callback(
342
346
343
347
return callback
344
348
349
+ async def _get_text_response_modal (
350
+ self ,
351
+ ctx : commands .Context ,
352
+ text : str ,
353
+ timeout : int = None ,
354
+ timeout_message : str = None ,
355
+ interaction : discord .Interaction = None ,
356
+ * args ,
357
+ ** kwargs
358
+ ) -> Union [str , None ]:
359
+ """Gets a response from a textinput UI"""
360
+ modal = Modal (title = "Answer the question and click submit" , timeout = timeout )
361
+ textinput = discord .ui .TextInput (label = text , * args , ** kwargs )
362
+ modal .add_item (textinput )
363
+
364
+ if interaction :
365
+ await interaction .response .send_modal (modal )
366
+ else :
367
+ await ctx .interaction .response .send_modal (modal )
368
+
369
+ await modal .wait ()
370
+ if modal .timed_out :
371
+ if timeout_message :
372
+ await ctx .send (timeout_message , delete_after = 5 )
373
+ return
374
+ await modal .interaction .response .defer ()
375
+ return textinput .value
376
+
377
+ async def _get_text_response_message (
378
+ self ,
379
+ ctx : commands .Context ,
380
+ text : str ,
381
+ timeout : int = None ,
382
+ timeout_message : str = None ,
383
+ * args ,
384
+ ** kwargs ,
385
+ ) -> Union [str , None ]:
386
+ """Gets a response by waiting a message sent by the user"""
387
+ def check (m : discord .Message ):
388
+ return m .author .id == ctx .author .id
389
+
390
+ msg = await ctx .send (text )
391
+ try :
392
+ confirm_msg : discord .Message = await self .wait_for (
393
+ "message" , check = check , timeout = timeout
394
+ )
395
+ except asyncio .TimeoutError :
396
+ if timeout_message :
397
+ await ctx .send (timeout_message , delete_after = 5 )
398
+ res = None
399
+ else :
400
+ res = confirm_msg .content
401
+
402
+ await msg .delete ()
403
+ try :
404
+ await confirm_msg .delete ()
405
+ except discord .Forbidden :
406
+ pass
407
+
408
+ return res
409
+
345
410
async def get_text_response (
346
411
self ,
347
412
ctx : commands .Context ,
@@ -352,53 +417,45 @@ async def get_text_response(
352
417
* args ,
353
418
** kwargs ,
354
419
) -> Union [str , None ]:
355
- """Gets a reponse from either a textinput UI or by waiting for a response"""
420
+ """Gets a response from either a textinput UI or by waiting for a response"""
356
421
357
422
if (ctx .interaction and not ctx .interaction .response .is_done ()) or interaction :
358
- modal = Modal (
359
- title = "Anser the question(s) and click submit" , timeout = timeout
423
+ return await self . _get_text_response_modal (
424
+ ctx , text , timeout , timeout_message , interaction , * args , ** kwargs
360
425
)
361
- textinput = discord .ui .TextInput (label = text , * args , ** kwargs )
362
- modal .add_item (textinput )
363
-
364
- if interaction :
365
- await interaction .response .send_modal (modal )
366
- else :
367
- await ctx .interaction .response .send_modal (modal )
368
-
369
- await modal .wait ()
370
- if modal .timed_out :
371
- if timeout_message :
372
- await ctx .send (timeout_message , delete_after = 5 )
373
- return
374
- await modal .interaction .response .defer ()
375
-
376
- return textinput .value
377
-
378
426
else :
427
+ return await self ._get_text_response_message (
428
+ ctx , text , timeout , timeout_message , * args , ** kwargs
429
+ )
379
430
380
- def check (m : discord .Message ):
381
- return m .author .id == ctx .author .id
431
+ async def make_embed_from_api (
432
+ self ,
433
+ image_url : str ,
434
+ embed : discord .Embed
435
+ ) -> Tuple [discord .Embed , Optional [discord .File ]]:
436
+ """
437
+ Makes an embed from a Killua API image url.
382
438
383
- msg = await ctx .send (text )
384
- try :
385
- confirmmsg : discord .Message = await self .wait_for (
386
- "message" , check = check , timeout = timeout
387
- )
388
- except asyncio .TimeoutError :
389
- if timeout_message :
390
- await ctx .send (timeout_message , delete_after = 5 )
391
- res = None
392
- else :
393
- res = confirmmsg .content
439
+ If the bot is running in a dev environment, the image is downloaded
440
+ and sent as a file.
394
441
395
- await msg .delete ()
396
- try :
397
- await confirmmsg .delete ()
398
- except commands .Forbidden :
399
- pass
442
+ Raises:
443
+ KilluaAPIException: If the Killua API returns an error
444
+ """
445
+ file = None
446
+ if self .is_dev :
447
+ # Upload the image as attachment instead
448
+ data = await self .session .get (image_url )
449
+ if data .status != 200 :
450
+ raise KilluaAPIException (await data .text ())
451
+
452
+ extension = image_url .split ("." )[- 1 ]
453
+ embed .set_image (url = f"attachment://image.{ extension } " )
454
+ file = discord .File (BytesIO (await data .read ()), f"image.{ extension } " )
455
+ else :
456
+ embed .set_image (url = image_url )
457
+ return embed , file
400
458
401
- return res
402
459
403
460
async def update_presence (self ):
404
461
status = await DB .const .find_one ({"_id" : "presence" })
0 commit comments