forked from Pycord-Development/pycord
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathconverters.py
129 lines (103 loc) · 5.07 KB
/
converters.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# This example requires the 'members' privileged intent to use the Member converter,
# and the 'message_content' privileged intent for prefixed commands.
from typing import Union
import discord
from discord.ext import commands
intents = discord.Intents.default()
intents.members = True
intents.message_content = True
bot = commands.Bot(command_prefix=commands.when_mentioned_or("!"), intents=intents)
@bot.command()
async def userinfo(ctx: commands.Context, user: discord.User):
# In the command signature above, you can see that the `user`
# parameter is type hinted to `discord.User`. This means that
# during command invocation we will attempt to convert
# the value passed as `user` to a `discord.User` instance.
# The documentation notes what can be converted and, in the case of `discord.User`,
# you pass an ID, mention or username (discriminator optional)
# E.g. 80088516616269824, @Danny or Danny#0007
# NOTE: Type hinting acts as a converter within the `commands` framework only.
# In standard Python, it is used for documentation and IDE assistance purposes.
# If the conversion is successful, we will have a `discord.User`
# instance and can do the following:
user_id = user.id
username = user.name
avatar = user.display_avatar.url
await ctx.send(f"User found: {user_id} -- {username}\n{avatar}")
@userinfo.error
async def userinfo_error(ctx: commands.Context, error: commands.CommandError):
# If the conversion above fails for any reason, it will raise
# `commands.BadArgument`, which we handle this in this error handler:
if isinstance(error, commands.BadArgument):
return await ctx.send("Couldn't find that user.")
# Custom Converter here
class ChannelOrMemberConverter(commands.Converter):
async def convert(self, ctx: commands.Context, argument: str):
# In this example we have made a custom converter.
# This checks if an input is convertible to a
# `discord.Member` or `discord.TextChannel` instance from the
# input the user has given us using the pre-existing converters
# that the library provides.
member_converter = commands.MemberConverter()
try:
# Try and convert to a Member instance.
# If this fails, then an exception is raised.
# Otherwise, we just return the converted member value.
member = await member_converter.convert(ctx, argument)
except commands.MemberNotFound:
pass
else:
return member
# Do the same for TextChannel...
textchannel_converter = commands.TextChannelConverter()
try:
channel = await textchannel_converter.convert(ctx, argument)
except commands.ChannelNotFound:
pass
else:
return channel
# If the value could not be converted we can raise an error
# so our error handlers can deal with it in one place.
# The error has to be CommandError derived, so BadArgument works fine here.
raise commands.BadArgument(
f'No Member or TextChannel could be converted from "{argument}"'
)
@bot.command()
async def notify(ctx: commands.Context, target: ChannelOrMemberConverter):
# This command signature utilises the custom converter written above.
# What will happen during command invocation is that the `target` above will be passed to
# the `argument` parameter of the `ChannelOrMemberConverter.convert` method and
# the conversion will go through the process defined there.
await target.send(f"Hello, {target.name}!")
@bot.command()
async def ignore(
ctx: commands.Context, target: Union[discord.Member, discord.TextChannel]
):
# This command signature utilises the `typing.Union` typehint.
# The `commands` framework attempts a conversion of each type in this Union *in order*.
# So, it will attempt to convert whatever is passed to `target` to a `discord.Member` instance.
# If that fails, it will attempt to convert it to a `discord.TextChannel` instance.
# See: https://docs.pycord.dev/en/master/ext/commands/commands.html#typing-union
# NOTE: If a Union typehint converter fails it will raise `commands.BadUnionArgument`
# instead of `commands.BadArgument`.
# To check the resulting type, `isinstance` is used
if isinstance(target, discord.Member):
await ctx.send(
f"Member found: {target.mention}, adding them to the ignore list."
)
elif isinstance(
target, discord.TextChannel
): # This could be an `else` but for completeness' sake.
await ctx.send(
f"Channel found: {target.mention}, adding it to the ignore list."
)
# Built-in type converters.
@bot.command()
async def multiply(ctx: commands.Context, number: int, maybe: bool):
# We want an `int` and a `bool` parameter here.
# `bool` is a slightly special case, as shown here:
# See: https://docs.pycord.dev/en/master/ext/commands/commands.html#bool
if maybe:
return await ctx.send(str(number * 2))
await ctx.send(str(number * 5))
bot.run("TOKEN")