1

So I have a discord bot that has music commands in it. Today I added that if the bot doesn't play anthing in 5 mins, it will leave the voice channel.

def search(arg):
    global last_played
    last_played = arg
    try:
        requests.get("".join(arg))
    except:
        arg = " ".join(arg)
    else:
        arg = "".join(arg)
    with youtube_dl.YoutubeDL(YDL_OPTIONS) as ydl:
        info = ydl.extract_info(f"ytsearch:{arg}", download=False)['entries'][0]

    return {'source': info['formats'][0]['url'], 'title': info['title']}


async def check_timer(ctx):
    global last_played
    guild = ctx.message.guild
    voice_client = guild.voice_client
    voice = discord.utils.get(client.voice_clients, guild=ctx.guild)
    music_check = last_played
    await asyncio.sleep(300)
    if not voice.is_playing() and music_check == last_played:
        await voice_client.disconnect()
        await ctx.send("No song is queued for 5 minutes. Left the voice channel!")


def play_next(ctx):
    voice = discord.utils.get(client.voice_clients, guild=ctx.guild)
    if len(song_queue) > 1:
        del song_queue[0]
        voice.play(discord.FFmpegPCMAudio(song_queue[0]['source'], **FFMPEG_OPTIONS), after=lambda e: play_next(ctx))
        voice.is_playing()
    else:
        asyncio.create_task(check_timer(ctx))


@client.command()
async def play(ctx, *arg):
    channel = ctx.message.author.voice.channel

    if channel:
        voice = discord.utils.get(client.voice_clients, guild=ctx.guild)
        song = search(arg)
        song_queue.append(song)

        if voice and voice.is_connected():
            await voice.move_to(channel)
        else:
            voice = await channel.connect()

        if not voice.is_playing():
            voice.play(discord.FFmpegPCMAudio(song_queue[0]['source'], **FFMPEG_OPTIONS), after=lambda e: play_next(ctx))
            voice.is_playing()
        else:
            await ctx.send("Added to queue")
    else:
        await ctx.send("You're not connected to any channel!")

And the thing is when I run the bot. I get this error

2021-01-02T14:49:20.462802+00:00 app[worker.1]: Traceback (most recent call last):
2021-01-02T14:49:20.462823+00:00 app[worker.1]:   File "/app/.heroku/python/lib/python3.9/site-packages/discord/player.py", line 611, in _call_after
2021-01-02T14:49:20.462824+00:00 app[worker.1]:     self.after(error)
2021-01-02T14:49:20.462825+00:00 app[worker.1]:   File "/app/main.py", line 219, in <lambda>
2021-01-02T14:49:20.462834+00:00 app[worker.1]:     voice.play(discord.FFmpegPCMAudio(song_queue[0]['source'], **FFMPEG_OPTIONS), after=lambda e: play_next(ctx))
2021-01-02T14:49:20.462837+00:00 app[worker.1]:   File "/app/main.py", line 201, in play_next
2021-01-02T14:49:20.462838+00:00 app[worker.1]:     asyncio.create_task(check_timer(ctx))
2021-01-02T14:49:20.462838+00:00 app[worker.1]:   File "/app/.heroku/python/lib/python3.9/asyncio/tasks.py", line 360, in create_task
2021-01-02T14:49:20.462839+00:00 app[worker.1]:     loop = events.get_running_loop()
2021-01-02T14:49:20.462859+00:00 app[worker.1]: RuntimeError: no running event loop
2021-01-02T14:49:20.470913+00:00 app[worker.1]: /app/.heroku/python/lib/python3.9/site-packages/discord/player.py:615: RuntimeWarning: coroutine 'check_timer' was never awaited
2021-01-02T14:49:20.470914+00:00 app[worker.1]:   traceback.print_exception(type(exc), exc, exc.__traceback__)
2021-01-02T14:49:20.470915+00:00 app[worker.1]: RuntimeWarning: Enable tracemalloc to get the object allocation traceback

I searched up in the net and saw some people with the same error but their solution was to put await somewhere, I couldn't see any place that needs an await.

PS I'm using heroku to host the bot.

1 Answer 1

0

This is the line that's causing the error

asyncio.create_task(check_timer(ctx))

Here's explained why.

To fix it:

task = client.loop.create_task(check_timer(ctx))
# or
loop = asyncio.get_event_loop()
task = loop.create_task(check_timer(ctx))

await task

Reference:

Sign up to request clarification or add additional context in comments.

1 Comment

Nonsensical answer. You're mixing and matching structured and unstructured concurrency here, which is semantically awful. Although technically valid, there is no pragmatic reason whatsoever to await a task; just await the underlying coroutine directly (e.g., await check_timer(ctx)). If you're going to perform unstructured concurrency by calling create_task() (...which you generally shouldn't, if you can help it), you should immediately follow-up by calling either asyncio.gather() or asyncio.wait(). That's the only use case for create_task(). All other uses are harmful.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.