How do I make it so that ctx is not of type 'interaction' (nextcord slash commands)? - nextcord

I'm trying to create a music bot using nextcord slash commands and interactions. The command isn't fully finished yet, as I am having trouble getting it to even join the voice channel. I don't exactly know how interactions work yet but I'm assuming it's a similar concept as ctx. Below is my music.py cog:
import nextcord
from nextcord.ext import commands
from nextcord import Interaction
class Music(commands.Cog):
def __init__(self, client):
self.client = client
guild_ids = ["Guild Ids Go Here"]
#slash commands go under here
#nextcord.slash_command(name="play", description="plays music in vc", guild_ids = guild_ids)
async def play(self, interaction : Interaction, query: str):
channel = interaction.author.voice.channel #ERROR IS HERE
try:
await channel.connect()
await interaction.response.send_message("The bot has joined vc.")
except:
await interaction.response.send_message("Failed to find voice channel.")
def setup(client):
client.add_cog(Music(client))
I'm getting an error that says "'Interaction' object has no attribute 'author'. It occurs on line 15 in 'play' when it says 'channel = interaction.author.voice.channel'. I think this means that this isn't the right way to go about getting the author's voice channel. If this is the case, is there a better, working method?

In nextcord interaction, message author is interaction.user,
channel is interaction.channel.
You also can send interaction message by interaction.send instead
of interaction.response.send_message. It's much shorter and easier
to read.
If you want to send a normal message without using interaction, try
interaction.channel.send. It's similar to ctx.channel.send in application command

Related

Sending a user specified message into a specified channel

This bot is only going to be for personal use, so I don't need to make it customizable from discord itself. I was wondering if I can use ctx.send and channel.send somehow together if this makes sense. Here is my code to help you understand what I mean:
client = commands.Bot(command_prefix='!')
channel = client.get_channel(883389016819511296)
#client.command(name='say')
async def say(ctx, *, content):
await ctx.send(content) # here I want to send it to the channel I already defined
channel.send would be an option, but I also want to send the message, so if I am right I need to use ctx.
No, you need to use channel.send as you are sending the content to the specified channel. If you use ctx.send it will just send in the same channel as the command was executed in. And theres an easier way to do this if you wanna see and example i have one here
#client.command() async def say(ctx, channel: discord.TextChannel, *, message: str): await channel.send(message)
That is an easier way and you can "#" the text channel so for example if you want to send a message in general for your bot it would be: !say #general hello
However if you only wish to do that and not use my example then you should do it like this:
#client.command(name='say') async def say(ctx, *, content): channel = client.get_channel(883389016819511296) await channel.send(content)

I am trying to make my bot be able to respond to a command that starts with a certain set of characters instead of having an exact command

I am trying to make my bot be able to respond to a command that starts with a certain set of characters instead of having an exact command. I figured out how to use it with client.event but I can't figure out how to do it using client.command.
As an example let's say I want it to send a message that says "Hello!" when the command ".hi" is sent. I want it to work even if a user sends ".hii" or maybe ".hi!". I can get this to work by using the startswith command. Below is my working client.event code and my broken client.command code:
client.event code:
import discord
client = discord.Client()
#client.event
async def on_message(message):
if message.content.lower().startswith('.hi'):
await message.channel.send('Hello!')
client.command code:
import discord
from discord.ext import commands
client = commands.Bot(command_prefix = '.', case_insensitive=True)
#client.command()
async def hi(message):
if message.content.startswith('hi'):
print('Hello!')
If you are using the command, you could specify the aliases of the command like this:
#client.command(aliases=['hii', 'hi!'])
async def hi(ctx):
print('Hello!')
https://discordpy.readthedocs.io/en/latest/ext/commands/api.html?highlight=aliases#discord.ext.commands.Command.aliases
Also your command is broken because you need to pass in ctx as a parameter for a command, not message.
Your #client.command() won't work because you never passed in ctx, by the way, to send a message you might want to use await ctx.send("Hello!").
The "full command" would look something like this, though its not really what you want as you would have to type .hi hi
#client.command()
async def hi(ctx, message):
if message.startswith('hi'):
await ctx.send('Hello!')
If you actually want to do that you should try using your #client.event (with on_message, basically the one you already have) as I dont think that you can do that unless you use aliases (Which is not a good option though):
#client.command(aliases=['hi!', 'hiiiiii', 'hello'])
async def hi(ctx):
await ctx.send('Hello!')
In conclusion, if you really want to do something like this, use your exsistent #client.event with on_message
(Just as #moinierer3000 said)

Trying to make a suggestion but channel id gives an error for the command

I've got an issue but I am getting no errors and from the code I just wrote as shown below
#client.commands
async def hello():
channel = int(797915093954199565)
await channel.send('Hey what are you doing?')
I am trying to make a command where the user can talk to the bot, and it responds back with something, its just a starting command but I'm having trouble with these small things, the rest of the bot works but its just this issue i'm having please help!
So assuming the rest of your bot and code works, your "hello" command isn't working because you have
#client.commands #its client.command in this case, as it seems you are not using any cogs, and you must call the client with () these double parentheses
async def hello(): #Here you have not passed ctx
channel = int(793744805615632394) #It seems what you would like to do here is send it to a specific channel, however, in the code below, I have set it so it just sends to the channel it was used in. The correct use is client.get_channel(793744805615632394)
await channel.send('Hey what are you doing?')
Here is the command but fixed:
So assuming the rest of your bot and code works, your "hello" command isn't working because you have
#client.command()
async def hello(ctx):
await ctx.send('Hey what are you doing?')
You should also refer to the py docs to learn more about it: https://discordpy.readthedocs.io/en/latest/

Bot wont properly print member_count

So I'm new to Python and I decided to take the plunge and make a Discord bot for personal use in my server. I like the idea of having full control over what features my bot will have so I'm slowly building the bot. Currently I want my bot to show the current number of members in the server when called with a command
import discord
from discord.ext import commands
#botbot.command()
async def server(ctx):
guild = discord.Guild.member_count
await ctx.send(guild)
I know I'm most likely way off with my code here.
While the bot is sending a message into the chat, its formatted as:
<property object at 0x046036C0>
While I would like to have it say something like "This server has {some number} members."
Any advice is really appreciated!
Thank you for your time.
Edit: botbot is the name for my bot, just so thats clear.
discord.Guild is the class. You want to get the guild the command is in from the invocation context:
#botbot.command()
async def server(ctx):
await ctx.send(f"This server has {ctx.guild.member_count} members.")
The method member_count is not really what you want in this occasion, the guild object has a list called members, so it's as easy as getting the length of that list like so:
#botbot.command()
async def server(ctx):
guild = len(discord.guild.members)
await ctx.send(guild)
EDIT: And indeed you have a typo with using "Guild" instead of "guild"

'NoneType' object has no attribute 'send' - Discord Bot

What I'm trying to do is to make my discord bot send a message to a channel in my server when I supply it the command "!say" through DM.
I've tried a lot of different codes, but usually, it ends up with the Attribute Error "X object has no attribute Y"
from discord.ext import commands
bot = commands.Bot(command_prefix='!')
#bot.command()
async def say(ctx):
channel = bot.get_channel('584307345065246725')
await channel.send(ctx)
The error message always shows up when I DM the bot, expecting for it to send the required message.
There is a pretty simple thing going on with your code snippet that needs to be corrected before it'll do what you're attempting to make it do.
First off, take a look at the API section for Client.get_channel (which you're calling):
get_channel(id)
Returns a channel with the given ID.
Parameters
id (int) – The ID to search for.
Returns
The returned channel or None if not found.
Return type
Optional[Union[abc.GuildChannel, abc.PrivateChannel]]
So, when you do this: channel = bot.get_channel('584307345065246725'), you're passing an incorrect argument. As per the API, the only parameter must be an int, but you are passing a string. Simply get rid of the single quotes and that should be fine.
Protip: Under "Returns," the API states that it can return None if the channel isn't found, which is what is happening to you, since you're passing in a string. Hence, channel becomes the NoneType object you see in the error. So when you do channel.send... you get the picture.
The channel id is an int, not a string
#bot.command()
async def say(ctx):
channel = bot.get_channel(584307345065246725)
await channel.send(ctx)
What I didn't quite understand is why you couldn't just do:
from discord.ext import commands
bot = commands.Bot(command_prefix='!')
#bot.command(pass_context=True)
async def say(ctx):
await ctx.send(ctx)
But I could be mistaken about what you are trying to do.

Resources