Create Slash Command for a Discord Bot and Have It Connect to a Voice Channel to Play an Audio File

Me and my friend want to make another Discord bot that, when a user uses /playmusic, the bot joins a specified voice channel and plays an audio file in it.

I would search this in the discord.py docs, but I don’t understand them.

Here is the code I have so far, it obviously doesn’t work (see traceback below):

import os, re, discord
from discord.ext import commands
from discord.utils import get
import ffmpeg
import asyncio

DISCORD_TOKEN = os.getenv("DISCORD_TOKEN")

intents = discord.Intents.default()
intents.message_content = True
client = commands.Bot(command_prefix='/', intents=intents)

@client.event
async def on_ready():
    await client.tree.sync()
    print(f'We have logged in as {client.user}')

@client.event
async def on_message(message):
    print("message was: " + message.content)
    msg = message.content
    lowered = msg.lower()
    if message.author == client.user:
        return

    if lowered == 'i love baguettes!' or lowered == 'i love baguettes':
        role = message.guild.get_role(1085983212855115887)
        await message.author.add_roles(role, reason="You said the magic words!", atomic=True)
        await message.channel.send('So do I! In fact, I have given you the Baguette Team role!')

@client.tree.command(name="kill", description="Kills Blockcoin Bot.")
async def _space(ctx: discord.interactions.Interaction):
    await ctx.response.send_message(content="How dare you try to kill me!")

    
@client.tree.command(name="give-lollipop", description="Gives Blockcoin Bot a lollipop.")
async def _space(ctx: discord.interactions.Interaction):
    await ctx.response.send_message(content="Thank you for the lollipop!")


@client.tree.command(name="playmusic", description="Starts playing music in the music channel.")
async def _space(ctx: discord.interactions.Interaction):
    voice_channel = ctx.response.author.voice.channel
    voice_client = await voice_channel.connect()
    source = discord.PCMVolumeTransformer(discord.FFmpegPCMAudio('sample-15s.mp3'))
    voice_client.play(source)
    while voice_client.is_playing():
        await asyncio.sleep(1)
    await voice_client.disconnect()

def start():
    client.run(DISCORD_TOKEN)

Traceback

  raise CommandInvokeError(self, e) from e discord.app_commands.errors.CommandlnvokeError: Command 'playmusic' raised an exception: AttributeError: 'InteractionResponse' object has no attribute 'author' 
  1. Name the functions different things, I am surprised it is not erroring because of these names.
  1. The error has nothing to do with voice. It is this line that is the problem. First of all, interactions response will only be available once you have responded. Use ctx.user and that should fix it.
2 Likes

So use ctx.user.voice.channel?

And in

async def _space(ctx: discord.interactions.Interaction):

I change the _space to something different? I get a notice in the Replit IDE, but no errors in the console.

For each command name it something related to the command.

Yes!

It fixed the problem I think, but it says it needs a module named “PyNaCl” to play music, but the module is unknown to Replit.

You installed discord.py wrong for voice, you need to run this:

pip install -U "discord.py[voice]"

Or as @UMARismyname said

poetry add "discord.py[voice]"
1 Like

try after running in shell

poetry add "discord.py[voice]"
1 Like

Well that fixed it, but now this happens:

I have:

import ffmpeg

but it says ffmpeg module not found.

Try installing that:
This:

pip install ffmpeg

Or this:

poetry add ffmpeg

I tried both, they say it is already installed, but I still get the error.

The bot joins the channel but plays no audio.

Now what?

What is the exact error the code provides for ffmpeg?

You need to use the nix package ffmpeg most likely, not the pypi one

And how do I install that?

image

And the error when trying to install it? (Preferably ones from pip and poetry, but just one or the other is fine.)

Add pkgs.ffmpeg to replit.nix or run ffmpeg -h in shell and follow the installation steps.

Also, when providing errors, please provide the first error, not the second one (there should be two). The first error is way more helpful.

I am using a Python template, so I ran ffmpeg -h. It did something, but didn’t fix the problem.

I get no installation errors from pip when trying to instal ffmpeg, just a notice saying the requirement is already satisfied.

Here are the errors - Error 1:

Error 2:
image

And two notices proceeding the error:
image

Also, here is my new code so far:

# Import various libraries.
import os, discord, urllib.request, asyncio
from discord.ext import commands

# Set the token.
DISCORD_TOKEN = os.getenv("DISCORD_TOKEN")

# Define whatever this is.
intents = discord.Intents.default()
intents.message_content = True
client = commands.Bot(command_prefix='/', intents=intents)

#Commands
@client.tree.command(name="info", description="Display invite and support server links.")
async def info(ctx: discord.interactions.Interaction):
    await ctx.response.send_message(content="**R4DIO Bot**\nSupport Server: https://discord.gg/fkWkj7Wuvp\nInvite Link: [invite link here]")

@client.tree.command(name="playmusic", description="Starts playing music in the music channel.")
async def _space(ctx: discord.interactions.Interaction):
    voice_channel = ctx.user.voice.channel
    voice_client = await voice_channel.connect()
    source = discord.PCMVolumeTransformer(discord.FFmpegPCMAudio('smoke-143172.mp3'))
    voice_client.play(source)
    while voice_client.is_playing():
        await asyncio.sleep(1)
    await voice_client.disconnect()

@client.event
async def on_ready():
    await client.tree.sync()
    print(f'We have logged in as {client.user}')

# Command to start the bot.
def start(): 
    client.run(DISCORD_TOKEN)

What did it do? Any output? And also make sure it is installed in replit.nix as I said.

Here is the output. It said it successfully was installed in replit.nix.

What happens when you try to play something in VC? Do you still get errors?