I am trying to make a Discord bot with slash commands using Python's nextcord module. My invite link uses both bot and applications.commands scopes.
I've started with a ping command using examples I've found online. My code looks like this:
import nextcord, os
from dotenv import load_dotenv
from nextcord.ext import commands
from flask import Flask
from threading import Thread
load_dotenv()
app = Flask('')
#app.route('/')
def home() -> str:
return 'Running!'
def run() -> None:
app.run(port=int(os.environ.get('PORT', 33507)))
def keep_alive() -> None:
Thread(target=run).start()
TOKEN = os.environ['DISCORD_TOKEN']
description = '[bot name] [version]'
intents = nextcord.Intents.default()
intents.members = True
client = commands.Bot(command_prefix='/', description=description, intents=intents)
async def embed(title, description, reason) -> nextcord.Embed:
return nextcord.Embed(
title=title,
description=description,
color=0x00FF00
).set_author(
name='[bot name] [version]',
icon_url='[image link]'
).set_footer(
text=f'This message was sent because {reason}.'
)
#client.event
async def on_ready():
print(f'Logged in as {client.user} (ID: {client.user.id})')
await client.change_presence(activity=nextcord.Game(name='[version]'))
#client.slash_command(name='ping', description='Returns bot latency')
async def ping(interaction: nextcord.Interaction):
await client.process_application_commands(interaction)
await interaction.response.defer(with_message=True)
await interaction.followup.send(embed=embed(':ping_pong: Pong!', f'{client.latency * 100} ms', f'{interaction.user} used the "ping" command'))
if __name__ == '__main__':
keep_alive()
client.run(TOKEN)
I've used a function to return an embed object to use as message content.
When running /ping on Discord, it returns "[bot name] is thinking..." before eventually changing to "The application did not respond".
What am I doing wrong?
I've discovered the answer through this StackExchange post. I needed to use embed=await embed() as shown here:
await interaction.followup.send(embed=await embed(...))
Related
I am using the newest version of discord py and python. I wanted to make a custom bot with slash commands in cogs. For now my bot already has some cogs command but now slash commands thee commands work perfectly fine. I looked up some things and came up with this but as you can guess its not working. so far i wrote this code in my cog:
import discord
from discord import app_commands
from discord.ext import commands
class Slash(commands.Cog):
def __init__(self, client: commands.Bot):
self.client = client
#commands.Cog.listener()
async def on_ready(self):
print("Slash cog loaded")
#commands.command()
async def sync(self, ctx) -> None:
fmt = await ctx.client.tree.sync(guild=ctx.guild)
await ctx.send(f"Synced {len(fmt)} commands.")
#app_commands.command(name="slash", description="test slash command")
async def ping(self, interaction: discord.Interaction):
bot_latency = round(self.client.latency * 1000)
await interaction.response.send_message(f"Pong! {bot_latency} ms.")
async def setup(client):
await client.add_cog(Slash(client), guilds=[discord.Object(id="HEREISMYSERVERID")])
I also wrote this code in my main file:
import discord
from discord.ext import commands, tasks
from itertools import cycle
import os
import asyncio
import json
client = commands.Bot(command_prefix="!", intents=discord.Intents.all(), application_id=MYAPPPLICATIONID)
bot_status = cycle(["Secret Things...","cooking"])
#tasks.loop(seconds=18000)
async def change_status():
await client.change_presence(activity=discord.Game(next(bot_status)))
#client.event
async def on_ready():
print("Success: Bot is connected to Discord")
change_status.start()
async def load():
for filename in os.listdir("./cogs"):
if filename.endswith("py"):
await client.load_extension(f"cogs.{filename[:-3]}")
async def main():
async with client:
await load()
await client.start("MYTOKEN")
asyncio.run(main())```
I have also a bunch of normal cogs these work perfectly fine. also in my console i see that this slash cog was loaded. But when i try to use !sync nothing happens can someone please help me with this
The docs for add_cog say this about the guilds kwarg:
If the cog is an application command group, then this would be the guilds where the cog group would be added to. If not given then it becomes a global command instead.
Your cog is not an application command group (it's a regular cog), so this doesn't do anything. As a result, your slash command is registered as a global one. This means that syncing to the guild (sync(guild=...)) does nothing, as the command isn't registered to that guild.
You can either use app_commands.guilds to add one specific command to a guild, or create a GroupCog instead of a regular cog to do it for the entire cog.
I am trying to make a bot with a simple function of creating a channel, but it is unsuccessful.
Here's my code:
import os
import discord
from keep_alive import keep_alive
from discord.ext import commands
intents = discord.Intents.default()
intents.message_content = True
intents.members = True
client = discord.Client(intents=intents)
bot = commands.Bot(command_prefix='$',intents=intents)
guild = discord.Guild
#client.event
async def on_ready():
print("I'm in as " + str(client.user))
#bot.command(name = "hack")
async def court_create(ctx, msg):
print("Received: $hack") #output to console
channel_name = "hack-" + str(msg)
await ctx.send(channel_name) #output to channel
channel = await guild.create_text_channel(name = channel_name)
keep_alive()
Token = os.environ['Token']
client.run(Token)
Note that for debugging, I added two lines so that when it receives the command, it prints out to both the console and the channel. However, when I typed $hack 123 into the channel, it did nothing, not even outputting Received: $hack. Any ideas about this?
Bot has manage channel permission.
#bot.command(name = "hack")
async def court_create(ctx, msg):
The name in bot.command and the name of the function are two completely different names. It only reads what the function name is. If you want to add hack as another method of using the command you can use the aliases argument in bot.command()
Example:
#bot.command(aliases=["hack"])
async def court_create(ctx, msg):
I'm developing discord bot with discord.py==2.1.0.
I use cog to write the main function that I wanna use, but I found when the whole bot is wrapped in async function and called by asyncio.run(), my terminal won't show any error message when there is any runtime error in my cog script.
Here is the example application. I stored my bot token in environment variable.
bot.py
import os
import discord
from discord.ext import commands
import asyncio
token = os.environ["BOT_TOKEN"]
class Bot(commands.Bot):
def __init__(self):
intents = discord.Intents.default()
intents.members = True
intents.message_content = True
description = "bot example."
super().__init__(
command_prefix=commands.when_mentioned_or('!'),
intents=intents,
description=description
)
async def on_ready(self):
print(f'Logged in as {self.user} (ID: {self.user.id})')
print('------')
bot = Bot()
async def load_extensions():
for f in os.listdir("./cogs"):
if f.endswith(".py"):
await bot.load_extension("cogs." + f[:-3])
async def main():
async with bot:
await load_extensions()
await bot.start(token)
asyncio.run(main())
./cogs/my_cog.py
from discord.ext import commands
class Test(commands.Cog):
def __init__(self, client):
self.client = client
#commands.Cog.listener()
async def on_ready(self):
print("Ready")
#commands.command()
async def command(self, ctx):
test_error_message() # An runtime error example
print("Command")
async def setup(client):
await client.add_cog(Test(client))
Command that I run in terminal to start the bot.
python bot.py
When I type !command in the discord channel, there is no error message showing in the terminal, but there is no "Command" printed out so I'm sure the code stopped at the line I called test_error_message()
I expected that it should show error message normally, but I cannot find useful reference to make it work :(
There is one reason I need to use asyncio, I have a task loop to run in the bot, like the code below.
from discord.ext import tasks
#tasks.loop(seconds=10)
async def avatar_update():
# code here
async def main():
async with bot:
avatar_update.start()
await load_extensions()
await bot.start(token)
I would happy to know if there are some great practice to handle error in this situation.
Thanks!
Client.start() doesn't configure logging, so if you want to use that then you have to do it yourself (there's setup_logging to add a basic config). run() configures logging for you.
For more info, read the docs. https://discordpy.readthedocs.io/en/stable/logging.html?highlight=logging
Not sure that I need to use the both runs at the same time, but:
from multiprocessing.dummy.connection import Client
from telnetlib import DM
from typing_extensions import Required
import discord
from discord.utils import get
from discord.ext import commands
from dislash import InteractionClient, Option, OptionType
from dislash.interactions import *
client = discord.Client()
from message import *
#client.event
async def on_message(message):
if message.author == client.user:
return
User_id = message.author.id
if message.channel.id == 1009530463108476968:
NewMessage = message.content.split(' ', 1)[0]
LimitLenght = len(NewMessage) + 11
if len(message.clean_content) >= LimitLenght:
await message.delete()
await message.author.send("Hello, " + f"<#{User_id}>" + "\nPlease, don't send any messages that break the **Counting-game** rules!\nIt's forbidden to post a comment that is longer than 10 characters.")
# More code
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
bot = commands.Bot(command_prefix="!")
inter_client = InteractionClient(bot)
#inter_client.slash_command(name="help", description="Shows the help-menu")
async def help(ctx):
embedVar = discord.Embed(title="Test project", description="*The blue text is clickable.*\n⠀", color=0x0000ff)
embedVar.add_field(name="Rules", value='To see rules write **/Rules**\n⠀', inline=False)
await ctx.reply(embed=embedVar, delete_after=180)
bot.run('ToKeN')
client.run('ToKeN')
If you run this code and comment the "bot.run('ToKeN')", the first part of the code will work (def on_message), however the command '/help' will not work. If you change it (comment 'client.run('ToKeN')'), the command '/help' will work, but def on_message not.
What are the possible solutions? Thanks.
The .runs block each other and prevent from running. You shouldn't be using a client and a bot anyway. Use one commands.Bot instead. It subclasses a Client and it should be able to do everything you can do with the client.
bot = commands.Bot(command_prefix="!")
inter_client = InteractionClient(bot)
#bot.event
async def on_message(message):
...
#inter_client.slash_command(name="help", description="Shows the help-menu")
async def help(ctx):
...
bot.run(token)
I have a problem with my discord.py bot. Here's a part of the code:
import os, discord
from discord.ext import commands
from flask import Flask
from threading import Thread
PREFIX = '/'
client = commands.Bot(command_prefix=PREFIX)
app = Flask('')
#app.route('/')
def main():
return 'Bot is ready!'
def run():
app.run(host="0.0.0.0", port=8000)
def keep_alive():
server = Thread(target=run)
server.start()
#client.event
async def on_message(message):
if client.user.mentioned_in(message):
await message.channel.send(embed=infoEmbed) #infoEmbed is defined
#client.command()
async def test(ctx, txt):
await ctx.send('You said ' + txt)
keep_alive()
client.run(os.environ['bot_token'])
I run the code, but it doesn't respond to commands, just on mentions. I cannot find the bug. Can you help me?
I think I know. You made the prefix “/“. Discord recently added a feature where bots could respond to / commands, but only if you add certain code I believe. Try using a new prefix? If that helps let me know.