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 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
|
# This example builds on the concepts of the app_commands/basic.py example
# It's suggested to look at that one to understand certain concepts first.
from typing import Literal, Union, NamedTuple
from enum import Enum
import discord
from discord import app_commands
MY_GUILD = discord.Object(id=0) # replace with your guild id
class MyClient(discord.Client):
def __init__(self):
super().__init__(intents=discord.Intents.default())
self.tree = app_commands.CommandTree(self)
async def setup_hook(self):
self.tree.copy_global_to(guild=MY_GUILD)
await self.tree.sync(guild=MY_GUILD)
client = MyClient()
@client.event
async def on_ready():
print(f'Logged in as {client.user} (ID: {client.user.id})')
print('------')
# A transformer is a class that specifies how a parameter in your code
# should behave both when used on Discord and when you receive it from Discord.
# There are a few built-in transformers, this example will show these along with
# creating your own for maximum flexibility.
# The first built-in transformer is app_commands.Range
# It works on `str`, `int`, and `float` options and tells you
# the maximum and minimum values (or length in the case of `str`) allowed
@client.tree.command()
@app_commands.describe(first='The first number to add', second='The second number to add')
async def add(
interaction: discord.Interaction,
# This makes it so the first parameter can only be between 0 to 100.
first: app_commands.Range[int, 0, 100],
# This makes it so the second parameter must be over 0, with no maximum limit.
second: app_commands.Range[int, 0, None],
):
"""Adds two numbers together"""
await interaction.response.send_message(f'{first} + {second} = {first + second}', ephemeral=True)
# Other transformers include regular type hints that are supported by Discord
# Examples of these include int, str, float, bool, User, Member, Role, and any channel type.
# Since there are a lot of these, for brevity only a channel example will be included.
# This command shows how to only show text and voice channels to a user using the Union type hint
# combined with the VoiceChannel and TextChannel types.
@client.tree.command(name='channel-info')
@app_commands.describe(channel='The channel to get info of')
async def channel_info(interaction: discord.Interaction, channel: Union[discord.VoiceChannel, discord.TextChannel]):
"""Shows basic channel info for a text or voice channel."""
embed = discord.Embed(title='Channel Info')
embed.add_field(name='Name', value=channel.name, inline=True)
embed.add_field(name='ID', value=channel.id, inline=True)
embed.add_field(
name='Type',
value='Voice' if isinstance(channel, discord.VoiceChannel) else 'Text',
inline=True,
)
embed.set_footer(text='Created').timestamp = channel.created_at
await interaction.response.send_message(embed=embed)
# In order to support choices, the library has a few ways of doing this.
# The first one is using a typing.Literal for basic choices.
# On Discord, this will show up as two choices, Buy and Sell.
# In the code, you will receive either 'Buy' or 'Sell' as a string.
@client.tree.command()
@app_commands.describe(action='The action to do in the shop', item='The target item')
async def shop(interaction: discord.Interaction, action: Literal['Buy', 'Sell'], item: str):
"""Interact with the shop"""
await interaction.response.send_message(f'Action: {action}\nItem: {item}')
# The second way to do choices is via an Enum from the standard library
# On Discord, this will show up as four choices: apple, banana, cherry, and dragonfruit
# In the code, you will receive the appropriate enum value.
class Fruits(Enum):
apple = 0
banana = 1
cherry = 2
dragonfruit = 3
@client.tree.command()
@app_commands.describe(fruit='The fruit to choose')
async def fruit(interaction: discord.Interaction, fruit: Fruits):
"""Choose a fruit!"""
await interaction.response.send_message(repr(fruit))
# You can also make your own transformer by inheriting from app_commands.Transformer
class Point(NamedTuple):
x: int
y: int
# The default transformer takes in a string option and you can transform
# it into any value you'd like.
#
# Transformers also support various other settings such as overriding
# properties like `choices`, `max_value`, `min_value`, `type`, or `channel_types`.
# However, this is outside of the scope of this example so check the documentation
# for more information.
class PointTransformer(app_commands.Transformer):
async def transform(self, interaction: discord.Interaction, value: str) -> Point:
(x, _, y) = value.partition(',')
return Point(x=int(x.strip()), y=int(y.strip()))
@client.tree.command()
async def graph(
interaction: discord.Interaction,
# In order to use the transformer, you should use Transform to tell the
# library to use it.
point: app_commands.Transform[Point, PointTransformer],
):
await interaction.response.send_message(str(point))
# For more basic transformers for your own types without too much repetition,
# a concept known as "inline transformers" is supported. This allows you to use
# a classmethod to have a string based transformer. It's only useful
# if you only care about transforming a string to a class and nothing else.
class Point3D(NamedTuple):
x: int
y: int
z: int
# This is the same as the above transformer except inline
@classmethod
async def transform(cls, interaction: discord.Interaction, value: str):
x, y, z = value.split(',')
return cls(x=int(x.strip()), y=int(y.strip()), z=int(z.strip()))
@client.tree.command()
async def graph3d(interaction: discord.Interaction, point: Point3D):
await interaction.response.send_message(str(point))
client.run('token')
|