0
votes

I'm currently trying to code a discord bot in python and am trying to make it join a channel, play a sound and then leave.

I came up with this code :

@bot.command()
async def sound(ctx):
    channel = ctx.author.voice.channel
    await join(ctx)
    voice = get(bot.voice_clients, guild=ctx.guild)
    source = FFmpegPCMAudio('sound.mp3')
    await voice.play(source)
    await channel.disconnect()

However, when I try it, after playing the sound, it doesn't disconnect and there is in my shell an error :

discord.ext.commands.errors.CommandInvokeError: Command raised an exception: TypeError: object NoneType can't be used in 'await' expression

I saw on forums that it could be a asyncio problem but I don't know how to resolve it.

Could someone help me please ?

Edit : my imports on my program :

import discord
import asyncio
from discord.ext import commands
from discord.utils import get
from discord import FFmpegPCMAudio

Edit v2 : the join() command :

@bot.command(pass_context=True)
async def join(ctx):
    channel = ctx.author.voice.channel
    voice = get(bot.voice_clients, guild=ctx.guild)
    if not channel:
        await ctx.send("You are not in a vocal channel.")
        return
    if voice and voice.is_connected():
        await voice.move_to(channel)
    elif voice == channel:
        return
    else:
        await channel.connect()

2
Please update your question to include all code needed to run this. For example, you have await join(ctx) but not what join does since it's not included. This is just a guess, but try await voice.disconnet()Benjin
Hey, first of all, thanks for your time. I edited my post with the join() fonction at the bottom. I also tried to run my code with voice.disconnect() but I ended having the same error messageBaptiste
Does it also show on what line the error occured?Deru
The error was at the "await channel.disconnect()" lineBaptiste

2 Answers

2
votes

You can have your join command return the VoiceClient object and use it directly to play the sound instead of using discord.utils.get. You can also get the VoiceClient object directly from the bot.voice_clients list instead of using get when checking if the bot is connected to a voice channel already.

Note that voice.play does not need await as it is not a coroutine. You also need to check if the bot stops playing audio using while voice.is_playing() before disconnecting, otherwise it will disconnect immediately after starting to play the sound.

from discord.ext import commands
from discord import FFmpegPCMAudio

bot = commands.Bot(command_prefix='?')


@bot.command()
async def join(ctx):
    channel = ctx.author.voice.channel

    voice = None
    for vc in bot.voice_clients:
        if vc.guild == ctx.guild:
            voice = vc

    if not channel:
        await ctx.send("You are not in a vocal channel.")
        return
    if voice and voice.is_connected():
        vc = await voice.move_to(channel)
    elif voice == channel:
        return
    else:
        vc = await channel.connect()
    return vc


@bot.command()
async def sound(ctx):
    voice = await join(ctx)
    source = FFmpegPCMAudio('sound.m4a')
    voice.play(source)
    while voice.is_playing():
        continue
    await voice.disconnect()

bot.run('token')
0
votes

The

while voice.is_playing():
        continue
    await voice.disconnect()

will mess up the audio.

Do this instead:

while voice.is_playing():
        time.sleep(1)