Skip to content

Commit bcdc942

Browse files
author
Krypton
committed
Template v4.0
* Now using [`disnake`](https://docs.disnake.dev) * Added a command that uses buttons *(coinflip)* * Added a command that uses selection dropdown *(rps)* * **Every** command is now in slash command **and** normal command (old way with prefix) * Make sure to **enable the message intents** for normal commands as it's now a privileged intent. * The **slash command** is **above**, the **normal command** is **below**
1 parent f5039a3 commit bcdc942

13 files changed

+980
-284
lines changed

README.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,9 @@ Here is an explanation of what everything is:
8383

8484
| Variable | What it is |
8585
| ------------------------- | ----------------------------------------------------------------------|
86+
| YOUR_BOT_PREFIX_HERE | The prefix you want to use for normal commands |
8687
| YOUR_BOT_TOKEN_HERE | The token of your bot |
88+
| YOUR_BOT_PERMISSIONS_HERE | The permissions integer your bot needs when it gets invited |
8789
| YOUR_APPLICATION_ID_HERE | The application ID of your bot |
8890
| OWNERS | The user ID of all the bot owners |
8991

@@ -137,7 +139,7 @@ the [tags on this repository](https://github.com/kkrypt0nn/Python-Discord-Bot-Te
137139

138140
## Built With
139141

140-
* [Python 3.9](https://www.python.org/)
142+
* [Python 3.9.9](https://www.python.org/)
141143

142144
## License
143145

UPDATES.md

+11-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,15 @@
22

33
Here is the list of all the updates that I made on this template.
44

5+
### Version 4.0
6+
7+
* Now using [`disnake`](https://docs.disnake.dev)
8+
* Added a command that uses buttons *(coinflip)*
9+
* Added a command that uses selection dropdown *(rps)*
10+
* **Every** command is now in slash command **and** normal command (old way with prefix)
11+
* Make sure to **enable the message intents** for normal commands as it's now a privileged intent.
12+
* The **slash command** is **above**, the **normal command** is **below**
13+
514
### Version 3.1.1
615

716
* Fixed `TypeError: 'NoneType' object is not iterable` for prefix -> Python 3.10
@@ -65,7 +74,7 @@ Here is the list of all the updates that I made on this template.
6574
### Version 2.4
6675

6776
* Added some fun commands
68-
* Colors are saved in the [config file](config.py) for easier usage
77+
* Colors are saved in the [config file](config.json) for easier usage
6978
* Cogs are now being loaded automatically
7079
* Fixed some typos
7180

@@ -89,7 +98,7 @@ Here is the list of all the updates that I made on this template.
8998

9099
* Added cogs
91100
* Added f-strings and removed `.format()`
92-
* Created [config file](config.py) for easier setup
101+
* Created [config file](config.json) for easier setup
93102

94103
### Version 1.2
95104

bot.py

+81-29
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
Description:
44
This is a template to create your own discord bot in python.
55
6-
Version: 3.1.1
6+
Version: 4.0
77
"""
88

99
import json
@@ -12,10 +12,10 @@
1212
import random
1313
import sys
1414

15-
import discord
16-
from discord.ext import tasks
17-
from discord.ext.commands import Bot
18-
from discord_slash import SlashCommand, SlashContext
15+
import disnake
16+
from disnake import ApplicationCommandInteraction
17+
from disnake.ext import tasks, commands
18+
from disnake.ext.commands import Bot
1919

2020
import exceptions
2121

@@ -28,44 +28,43 @@
2828
"""
2929
Setup bot intents (events restrictions)
3030
For more information about intents, please go to the following websites:
31-
https://discordpy.readthedocs.io/en/latest/intents.html
32-
https://discordpy.readthedocs.io/en/latest/intents.html#privileged-intents
31+
https://docs.disnake.dev/en/latest/intents.html
32+
https://docs.disnake.dev/en/latest/intents.html#privileged-intents
3333
3434
3535
Default Intents:
36-
intents.messages = True
37-
intents.reactions = True
38-
intents.guilds = True
39-
intents.emojis = True
4036
intents.bans = True
41-
intents.guild_typing = False
42-
intents.typing = False
4337
intents.dm_messages = False
4438
intents.dm_reactions = False
4539
intents.dm_typing = False
40+
intents.emojis = True
4641
intents.guild_messages = True
4742
intents.guild_reactions = True
43+
intents.guild_typing = False
44+
intents.guilds = True
4845
intents.integrations = True
4946
intents.invites = True
47+
intents.reactions = True
48+
intents.typing = False
5049
intents.voice_states = False
5150
intents.webhooks = False
5251
5352
Privileged Intents (Needs to be enabled on dev page), please use them only if you need them:
54-
intents.presences = True
5553
intents.members = True
54+
intents.messages = True
55+
intents.presences = True
5656
"""
5757

58-
intents = discord.Intents.default()
58+
intents = disnake.Intents.default()
5959

60-
bot = Bot(command_prefix="", intents=intents) # The command prefix is a required argument, but will never be used
61-
slash = SlashCommand(bot, sync_commands=True)
60+
bot = Bot(command_prefix=config["prefix"], intents=intents)
6261

6362

6463
# The code in this even is executed when the bot is ready
6564
@bot.event
6665
async def on_ready():
6766
print(f"Logged in as {bot.user.name}")
68-
print(f"Discord.py API version: {discord.__version__}")
67+
print(f"disnake API version: {disnake.__version__}")
6968
print(f"Python version: {platform.python_version()}")
7069
print(f"Running on: {platform.system()} {platform.release()} ({os.name})")
7170
print("-------------------")
@@ -76,7 +75,7 @@ async def on_ready():
7675
@tasks.loop(minutes=1.0)
7776
async def status_task():
7877
statuses = ["with you!", "with Krypton!", "with humans!"]
79-
await bot.change_presence(activity=discord.Game(random.choice(statuses)))
78+
await bot.change_presence(activity=disnake.Game(random.choice(statuses)))
8079

8180

8281
# Removes the default help command of discord.py to be able to create our custom help command.
@@ -96,35 +95,88 @@ async def status_task():
9695

9796
# The code in this event is executed every time someone sends a message, with or without the prefix
9897
@bot.event
99-
async def on_message(message: discord.Message):
98+
async def on_message(message: disnake.Message):
10099
# Ignores if a command is being executed by a bot or by the bot itself
101100
if message.author == bot.user or message.author.bot:
102101
return
103102
await bot.process_commands(message)
104103

105104

106-
# The code in this event is executed every time a command has been *successfully* executed
105+
# The code in this event is executed every time a slash command has been *successfully* executed
107106
@bot.event
108-
async def on_slash_command(ctx: SlashContext):
109-
full_command_name = ctx.name
110-
split = full_command_name.split(" ")
111-
executed_command = str(split[0])
107+
async def on_slash_command(interaction: ApplicationCommandInteraction):
112108
print(
113-
f"Executed {executed_command} command in {ctx.guild.name} (ID: {ctx.guild.id}) by {ctx.author} (ID: {ctx.author.id})")
109+
f"Executed {interaction.data.name} command in {interaction.guild.name} (ID: {interaction.guild.id}) by {interaction.author} (ID: {interaction.author.id})")
114110

115111

116-
# The code in this event is executed every time a valid commands catches an error
112+
# The code in this event is executed every time a valid slash command catches an error
117113
@bot.event
118-
async def on_slash_command_error(context: SlashContext, error: Exception):
114+
async def on_slash_command_error(interaction: ApplicationCommandInteraction, error: Exception):
119115
if isinstance(error, exceptions.UserBlacklisted):
120116
"""
121117
The code here will only execute if the error is an instance of 'UserBlacklisted', which can occur when using
122118
the @checks.is_owner() check in your command, or you can raise the error by yourself.
123119
124120
'hidden=True' will make so that only the user who execute the command can see the message
125121
"""
122+
embed = disnake.Embed(
123+
title="Error!",
124+
description="You are blacklisted from using the bot.",
125+
color=0xE02B2B
126+
)
127+
print("A blacklisted user tried to execute a command.")
128+
return await interaction.send(embed=embed, ephemeral=True)
129+
elif isinstance(error, commands.errors.MissingPermissions):
130+
embed = disnake.Embed(
131+
title="Error!",
132+
description="You are missing the permission(s) `" + ", ".join(
133+
error.missing_permissions) + "` to execute this command!",
134+
color=0xE02B2B
135+
)
126136
print("A blacklisted user tried to execute a command.")
127-
return await context.send("You are blacklisted from using the bot.", hidden=True)
137+
return await interaction.send(embed=embed, ephemeral=True)
138+
raise error
139+
140+
141+
# The code in this event is executed every time a normal command has been *successfully* executed
142+
@bot.event
143+
async def on_command_completion(ctx):
144+
fullCommandName = ctx.command.qualified_name
145+
split = fullCommandName.split(" ")
146+
executedCommand = str(split[0])
147+
print(
148+
f"Executed {executedCommand} command in {ctx.guild.name} (ID: {ctx.message.guild.id}) by {ctx.message.author} (ID: {ctx.message.author.id})")
149+
150+
151+
# The code in this event is executed every time a normal valid command catches an error
152+
@bot.event
153+
async def on_command_error(context, error):
154+
if isinstance(error, commands.CommandOnCooldown):
155+
minutes, seconds = divmod(error.retry_after, 60)
156+
hours, minutes = divmod(minutes, 60)
157+
hours = hours % 24
158+
embed = disnake.Embed(
159+
title="Hey, please slow down!",
160+
description=f"You can use this command again in {f'{round(hours)} hours' if round(hours) > 0 else ''} {f'{round(minutes)} minutes' if round(minutes) > 0 else ''} {f'{round(seconds)} seconds' if round(seconds) > 0 else ''}.",
161+
color=0xE02B2B
162+
)
163+
await context.send(embed=embed)
164+
elif isinstance(error, commands.MissingPermissions):
165+
embed = disnake.Embed(
166+
title="Error!",
167+
description="You are missing the permission(s) `" + ", ".join(
168+
error.missing_permissions) + "` to execute this command!",
169+
color=0xE02B2B
170+
)
171+
await context.send(embed=embed)
172+
elif isinstance(error, commands.MissingRequiredArgument):
173+
embed = disnake.Embed(
174+
title="Error!",
175+
description=str(error).capitalize(),
176+
# We need to capitalize because the command arguments have no capital letter in the code.
177+
color=0xE02B2B
178+
)
179+
await context.send(embed=embed)
128180
raise error
129181

130182

0 commit comments

Comments
 (0)