Baptiste
Baptiste

Reputation: 68

Discord.py error : object NoneType can't be used in "await" expression when trying to make the bot leave a voice channel

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()

Upvotes: 0

Views: 5546

Answers (2)

Alexander Dudin
Alexander Dudin

Reputation: 9

The

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

will mess up the audio.

Do this instead:

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

Upvotes: 0

Benjin
Benjin

Reputation: 3497

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')

Upvotes: 3

Related Questions