|
1
|
|
|
from random import randint |
|
2
|
|
|
from typing import Tuple |
|
3
|
|
|
|
|
4
|
|
|
from aiohttp import ClientSession |
|
5
|
|
|
|
|
6
|
|
|
from pincer import Client, command |
|
7
|
|
|
from pincer.exceptions import CommandCooldownError |
|
8
|
|
|
from pincer.objects import Embed, MessageContext, Message, InteractionFlags |
|
9
|
|
|
from pincer.utils import MISSING |
|
10
|
|
|
|
|
11
|
|
|
|
|
12
|
|
|
# Create our base bot client, if you want to you can use an init an |
|
13
|
|
|
# super call it. But that isn't required for this example. |
|
14
|
|
|
|
|
15
|
|
|
|
|
16
|
|
|
class Bot(Client): |
|
17
|
|
|
# Our url from where we'll get our juicy memes! |
|
18
|
|
|
MEME_URL = "https://some-random-api.ml/meme" |
|
19
|
|
|
|
|
20
|
|
|
@staticmethod |
|
21
|
|
|
def random_color(): |
|
22
|
|
|
""" |
|
23
|
|
|
Generate a valid random Discord color! |
|
24
|
|
|
""" |
|
25
|
|
|
return randint(0, 16581375) |
|
26
|
|
|
|
|
27
|
|
|
async def get_meme(self) -> Tuple[str, str]: |
|
28
|
|
|
""" |
|
29
|
|
|
Get a random meme from our configured MEME_URL! |
|
30
|
|
|
""" |
|
31
|
|
|
# Standard aiohttp session setup: |
|
32
|
|
|
async with ClientSession() as session: |
|
33
|
|
|
# Send our HTTP get request! |
|
34
|
|
|
async with session.get(self.MEME_URL) as response: |
|
35
|
|
|
# To extract the data we need to have the json as a dict! |
|
36
|
|
|
data = await response.json() |
|
37
|
|
|
|
|
38
|
|
|
# If the json was malformed, make sure we have backup values! |
|
39
|
|
|
caption = data.get("caption", "Oops, something went wrong!") |
|
40
|
|
|
image = data.get("image", MISSING) |
|
41
|
|
|
|
|
42
|
|
|
# Return it as a tuple so we can easily extract the two |
|
43
|
|
|
# values in our method which called this! |
|
44
|
|
|
return caption, image |
|
45
|
|
|
|
|
46
|
|
|
@Client.event |
|
47
|
|
|
async def on_ready(self): |
|
48
|
|
|
# Our client has successfully started, lets let ourself know that! |
|
49
|
|
|
print("Successfully created discord client on", self.bot) |
|
50
|
|
|
|
|
51
|
|
|
@command( |
|
52
|
|
|
# We don't want to send too many requests to our `MEME_URL` so |
|
53
|
|
|
# lets use cooldowns! |
|
54
|
|
|
# Only allow one request |
|
55
|
|
|
cooldown=1, |
|
56
|
|
|
# For every three seconds |
|
57
|
|
|
cooldown_scale=3, |
|
58
|
|
|
# And just to make things more clear for our user on what this |
|
59
|
|
|
# command does, lets define a description! |
|
60
|
|
|
description="Get a random meme!", |
|
61
|
|
|
) |
|
62
|
|
|
async def meme(self): |
|
63
|
|
|
# Fetch our caption and image from our `MEME_URL`. |
|
64
|
|
|
caption, image = await self.get_meme() |
|
65
|
|
|
|
|
66
|
|
|
# Respond with an embed which contains the meme and caption! |
|
67
|
|
|
return ( |
|
68
|
|
|
Embed(caption, color=self.random_color()) |
|
69
|
|
|
.set_image(image) |
|
70
|
|
|
.set_footer( |
|
71
|
|
|
"Provided by some-random-api.ml", |
|
72
|
|
|
"https://i.some-random-api.ml/logo.png", |
|
73
|
|
|
) |
|
74
|
|
|
) |
|
75
|
|
|
|
|
76
|
|
|
@Client.event |
|
77
|
|
|
async def on_command_error(self, ctx: MessageContext, error: Exception): |
|
78
|
|
|
# OH NO, something went wrong while executing our command. |
|
79
|
|
|
# Don't worry tho, it might be our user whom is trespassing our |
|
80
|
|
|
# set cooldown. Lets check if the error is a cooldown error, |
|
81
|
|
|
if isinstance(error, CommandCooldownError): |
|
82
|
|
|
# Yeah, the user got rate limited by our cooldown. |
|
83
|
|
|
# Lets let them know in a private embed message! |
|
84
|
|
|
return Message( |
|
85
|
|
|
embeds=[ |
|
86
|
|
|
Embed( |
|
87
|
|
|
title="Oops...", |
|
88
|
|
|
description=f"The `{ctx.command.app.name}` command can " |
|
89
|
|
|
f"only be used `{ctx.command.cooldown}` time*(s)* every" |
|
90
|
|
|
f" `{ctx.command.cooldown_scale}` second*(s)*!", |
|
91
|
|
|
color=self.random_color(), |
|
92
|
|
|
) |
|
93
|
|
|
], |
|
94
|
|
|
flags=InteractionFlags.EPHEMERAL, |
|
95
|
|
|
) |
|
96
|
|
|
|
|
97
|
|
|
# Oh no, it wasn't a cooldown error. Lets throw it! |
|
98
|
|
|
raise error |
|
99
|
|
|
|
|
100
|
|
|
|
|
101
|
|
|
if __name__ == "__main__": |
|
102
|
|
|
# Of course we have to run our client, you can replace the |
|
103
|
|
|
# XXXYOURBOTTOKENHEREXXX with your token, or dynamically get it |
|
104
|
|
|
# through a dotenv/env. |
|
105
|
|
|
Bot("XXXYOURBOTTOKENHEREXXX").run() |
|
106
|
|
|
|