How to get my bot to join a voice channel - discord.py

I'm trying to get my discord bot to connect to a voice channel like this currently:
#client.event
async def on_message(message):
message.content = message.content.lower()
if message.author == client.user:
return
if '-skip' in message.content:
await message.author.channel.connect
await message.channel.send (f"-p scotland forever")
await disconnect
Basically I want it to join a voice channel from the message author when they send the message "-skip" and then my bot joins, says -p scotland forever in chat, and then leaves. I get an error message saying things like "channel" not defined or "connect" not defined, ive tried doing it a few different ways, I think i just havent imported a plugin or whatever and thats probably my issue, but idk what plugin thing to use. Any help would be appreciated.

Try this:
#client.event
async def on_message(message):
message.content = message.content.lower()
if message.author == client.user:
return
if '-skip' in message.content:
channel = message.author.voice.channel
if channel is not None:
await channel.connect()
await message.channel.send (f"-p scotland forever")
await client.voice_clients[0].disconnect()
else:
await message.channel.send ("You need to join to voice channel")

Try this
#commands.command()
async def join_voice(self, ctx):
connected = ctx.author.voice
if connected:
await connected.channel.connect(put vc id here)
It may work
I guess?

Related

I want to my discord bot to forward the message to another channel after a user reacts to it Discord.py

I know next to nothing about coding in Python but I created this bot from tutorials I found online and it does little things in my private server.
One thing we'd love to do is to react to certain messages so they will be collected in a specific channel. I've seen a few servers do this, like a highlights kind of thing.
I found something promising here in Stackoverflow but it's in javascript :<
Edit: 2023-01-19 08:53 GMT+8
#client.event
async def on_reaction_add(reaction, member):
if str(reaction.emoji) == "⭐":
channel = await bot.get_channel(channel_id)
await channel.send(reaction.message.content)
Final code
edited: 2023-01-20 17:14 GMT+8
#bot.event
async def on_reaction_add(reaction, user):
if reaction.emoji == "⭐":
astrometrics = bot.get_channel(channel id here)
embed = discord.Embed(color = 0xFEE75C)
embed.set_author(name = reaction.message.author.name, icon_url = reaction.message.author.display_avatar)
embed.add_field(name = "Message Content", value = reaction.message.content)
if len(reaction.message.attachments) > 0:
embed.set_image(url = reaction.message.attachments[0].url)
embed.add_field(name = "Go to message", value = reaction.message.jump_url, inline = False)
await astrometrics.send(embed = embed)
You can check certain messages in on_message event. And for getting a specific channel in your server, you need to have the channel id. link
Something like this:
#bot.event
async def on_message(message):
if message.content == 'the certain message':
specific_channel = await bot.get_channel(channel_id)
await specific_channel.send(message.content)
But this might have some rate-limited consequence if the 'certain message' was too much and sent at a high rate. (If yes, then there's nothing you can do since rate-limited is a discord limitation).

Discord py delete voicechannel if its empty

Well im trying to create a voice channel by command so i can join it.
And as soon i leave the channel its supposed to get deleted.
What i tried:
if message.content.startswith('/voice'):
guild = message.guild
voicechannel = await guild.create_voice_channel(f"{str(message.author)}")
await asyncio.sleep(5)
while True:
if len(voicechannel.voice_states) == 0:
await voicechannel.delete()
break
doesnt even work tho
I believe that your issue is that you are stuck in an infinite while True loop. I would first suggest that you switch to using discord.ext.commands, it simplifies the process of creating a Discord Bot by a great deal. If you were using discord.ext.commands.Bot, you would be able to use the wait_for() function to wait until the voice channel is empty.
from discord.ext.commands import Bot
client = Bot(command_prefix="/")
#client.command(name="voice")
async def voice(ctx):
guild = ctx.guild
voice_channel = await guild.create_voice_channel(f"{str(ctx.author)}")
def check(member, before, after):
return member == ctx.author and before.channel == voice_channel and after.channel is None
await client.wait_for("voice_state_update", check=check)
await voice_channel.delete()
client.run("TOKEN")
The only issue that I think could happen, is if the member never joins the voice channel. To counter this, we can set up another wait_for() function to determine if the member ever joins before waiting for the member to leave the voice channel.
from asyncio import TimeoutError
#client.command(name="voice")
async def voice(ctx):
guild = ctx.guild
voice_channel = await guild.create_voice_channel(f"{str(ctx.author)}")
def check(member, before, after):
return member == ctx.author and before.channel is None and after.channel == voice_channel
try:
await client.wait_for("voice_state_update", check=check, timeout=60)
except TimeoutError:
await voice_channel.delete()
return

Cooldown on on_message event discord.py

I'm trying to make a suggestion system with discord.py. A user DMs the bot a message and the bot sends that message in a specific channel. The code works, I wanted to understand if it is possible to add a cooldown in sending DMs to the bot and how to do it.
#client.event
async def on_message(message):
if not message.author.bot:
if isinstance(message.channel, DMChannel):
if len(message.content) > 700:
await message.channel.send("Suggerimento troppo lungo")
else:
embedMod= discord.Embed(title="Suggerimento:", description=message.content, colour=0xfc5a50, timestamp=datetime.utcnow())
embedMod.set_footer(icon_url="https://s3.us-west-2.amazonaws.com/cdn.lnk.bio/profilepics/-1230732_20210524863.jpg")
embedMod.set_author(name=f'{message.author}', icon_url=f'{message.author.avatar_url}')
mod = client.get_channel(900085945414582312)
await mod.send(embed=embedMod)
await message.channel.send('Suggerimento registrato con successo, grazie mille.')
Update, is correct?
#client.event # Suggerimenti
async def on_message(message):
bucket = cd_mapping.get_bucket(message)
retry_after = bucket.update_rate_limit()
if retry_after:
await message.channel.send("Scimmia")
else:
if not message.author.bot:
if isinstance(message.channel, DMChannel):
if len(message.content) > 700:
await message.channel.send("Suggerimento troppo lungo")
else:
embedMod= discord.Embed(title="Suggerimento:", description=message.content, colour=0xfc5a50, timestamp=datetime.utcnow())
embedMod.set_footer(icon_url="https://s3.us-west-2.amazonaws.com/cdn.lnk.bio/profilepics/-1230732_20210524863.jpg")
embedMod.set_author(name=f'{message.author}', icon_url=f'{message.author.avatar_url}')
mod = client.get_channel(900085945414582312)
await mod.send(embed=embedMod)
await message.channel.send('Suggerimento registrato con successo, grazie mille.')
else:
await client.process_commands(message)
You can do it with discord.py cooldowns:
from discord.ext import commands
cd_mapping = commands.CooldownMapping.from_cooldown(1, 60, commands.BucketType.user)
#client.event
async def on_message(message):
bucket = cd_mapping.get_bucket(message)
retry_after = bucket.update_rate_limit()
if retry_after:
# rate limited
else:
# not rate limited

I want to make a command that deletes a channel discord.py

Here is what I got so far
It is saying that "await" is outside of async function and I am just confused on how to fix this. I copied part of the code from a giveaway command because that is my only source of Q&A code I have
#commands.has_permissions(administrator = True)
async def cdelete(ctx):
embed=discord.Embed(title = Which channel would you like to delete?)
await ctx.send(embed=embed)
answer = []
def check(m):
return m.author == cx.author and m.channel == ctx.channel
try:
await client.wait_for('message', timeout=15, check=check)
except asyncio.TimeoutError:
await ctx.send("Timeout. Please run the command again")
else:
answer.append(message.content)
try:
c_id= int(answer[0][2:-1])
await ctx.channel.delete
await ctx.send("Channel Deleted")
except:
await ctx.send("Thats not a valid channel!")```
If you just want a command you can make it a lot easier if you just execute a command with the channel name. You can have a look at the following:
#client.command()
#commands.has_permissions(administrator=True)
async def cdelete(ctx, channel_name):
"""Deletes a channel by name or ID."""
channel_id = int(''.join(i for i in channel_name if i.isdigit())) # Get channel ID
existing_channel = client.get_channel(channel_id) # Get channel ID with defined method
if existing_channel: # If channel with the name/ID exists
await existing_channel.delete()
else: # If the channel does not exist
await ctx.send(f'**No channel named `{channel_name}` was found.**')
We have a method to catch the channel ID and also pass that in as a valid argument. If the ID or channel name then exists we delete the channel.
You can here either mention the channel or pass in the ID.
Usage would be: cdelete #channel/ID.
If you want to avoid a long console output if you input no channel/ID/name you can build in an error handler:
#cdelete.error
async def cdelete_error(ctx, error):
if isinstance(error, commands.MissingRequiredArgument):
await ctx.send("You need to name a channel.")
The problem you have here is with the check() function. According to the doc you only can use await inside of an async function. To solve the problem change def check(m): into async def check(m):

allocating bot to single channel discord.py

I want to ensure my bot only responds to commands/messages and responds only in 1 specific channel is this possible I have tried multiple variations to no success. even better if I could define it for any event. Anyone got any ideas?
You can check message.channel in the on_message event and if it matches your criteria, in this case a specific channel, then do process_commands.
Below is an example where the !ping command will only work when channel.name is "general".
from discord.ext import commands
client = commands.Bot(command_prefix='!')
#client.command()
async def ping():
await client.say('Pong')
#client.event
async def on_message(message):
if message.channel.name == 'general':
await client.process_commands(message)
client.run('token')

Resources