aboutsummaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorAlex Nørgaard <[email protected]>2021-02-23 08:54:31 +0000
committerGitHub <[email protected]>2021-02-23 03:54:31 -0500
commit7f05f7f6c06d728fbcdb33e58656da1c2971a09d (patch)
tree386b4e152c7db4d57631b093c83d1ceb02f9c737 /examples
parent[commands] properly assign ctx.invoked_with with ctx. (diff)
downloaddiscord.py-7f05f7f6c06d728fbcdb33e58656da1c2971a09d.tar.xz
discord.py-7f05f7f6c06d728fbcdb33e58656da1c2971a09d.zip
Add converter example
Diffstat (limited to 'examples')
-rw-r--r--examples/converters.py113
1 files changed, 113 insertions, 0 deletions
diff --git a/examples/converters.py b/examples/converters.py
new file mode 100644
index 00000000..74b9c3c4
--- /dev/null
+++ b/examples/converters.py
@@ -0,0 +1,113 @@
+# This example requires the 'members' privileged intent to use the Member converter.
+
+import typing
+
+import discord
+from discord.ext import commands
+
+intents = discord.Intents.default()
+intents.members = True
+
+bot = commands.Bot('!', intents=intents)
+
+
+async def userinfo(ctx: commands.Context, user: discord.User):
+ # In the command signature above, you can see that the `user`
+ # parameter is typehinted 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, in the case of `discord.User`
+ # you pass an ID, mention or username (discrim optional)
+ # E.g. 80088516616269824, @Danny or Danny#0007
+
+ # NOTE: typehinting acts as a converter within the `commands` framework only.
+ # In standard Python, it is use 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.avatar_url
+ await ctx.send('User found: {} -- {}\n{}'.format(user_id, username, avatar))
+
+async def userinfo_error(ctx: commands.Context, error: commands.CommandError):
+ # if the conversion above fails for any reason, it will raise `commands.BadArgument`
+ # so 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('No Member or TextChannel could be converted from "{}"'.format(argument))
+
+
+
+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('Hello, {}!'.format(target.name))
+
+async def ignore(ctx: commands.Context, target: typing.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://discordpy.readthedocs.io/en/latest/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('Member found: {}, adding them to the ignore list.'.format(target.mention))
+ elif isinstance(target, discord.TextChannel): # this could be an `else` but for completeness' sake.
+ await ctx.send('Channel found: {}, adding it to the ignore list.'.format(target.mention))
+
+# Built-in type converters.
+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://discordpy.readthedocs.io/en/latest/ext/commands/commands.html#bool
+
+ if maybe is True:
+ return await ctx.send(number * 2)
+ await ctx.send(number * 5)
+
+bot.run('token')