from discord.ext import commands
from discord import FFmpegPCMAudio
from asyncio import run
FFMPEG_OPTIONS = {'before_options': '-avioflags direct', 'options': '-vn -sn -dn -movflags +faststart -b:a 49k'}
class Play(commands.Cog):
def __init__(self, bot):
self.bot = bot
self.run = False
self.voice = ""
async def play_song(self, ctx ,data=()):
if data != ():
data = "+".join(data)
print(data)
else:
print("Passes Automatically")
await ctx.send("auto pass")
await ctx.send("playing")
source = FFmpegPCMAudio("https://www2.iis.fraunhofer.de/AAC/ChID-BLITS-EBU-Narration.mp4", **FFMPEG_OPTIONS)
await self.voice.play(source, after=lambda x=None: run(self.play_song(ctx)))
@commands.Cog.listener()
async def on_ready(self):
print("Play is working")
@commands.command(pass_context=True)
async def play(self, ctx, *initial_user_input):
if not self.run:
if ctx.author.voice:
channel = ctx.message.author.voice.channel
self.voice = await channel.connect()
self.run = True
await self.play_song(ctx, initial_user_input)
else:
await ctx.send("Channel Not Found")
else:
await self.play_song(ctx, initial_user_input)
async def setup(bot):
await bot.add_cog(Play(bot))
The above code is what I'm using it works fine (the message sending etc) when the play_song is called from the play command. when the play_song method is called from the lambda function. it works as expected until reaching await ctx.send("testing"). It should obviously send the message in the discord channel but it hangs indefinetely.
Ive tried calling the play function from the lambda function (same problem). I've tried passing in the channel id instead of the context but neither works. I've ran it without the await at which point it just says it was never awaited. I've also tested it with an async generator in case it was the asyncio.run but same problem. Help appreciated.
its probably because running the song is like the main task the bot is working on so it cant do anything else until it completes or smth so instead of asyncio.run use self.bot.loop.create_task
and i recommend adding a song_finished methodso you know when its done helps for debugging overall and you can change things anytime heres the modified code
from discord.ext import commands
from discord import FFmpegPCMAudio
import asyncio
FFMPEG_OPTIONS = {'before_options': '-avioflags direct', 'options': '-vn -sn -dn -movflags +faststart -b:a 49k'}
class Play(commands.Cog):
def __init__(self, bot):
self.bot = bot
self.run = False
self.voice = None
async def play_song(self, ctx, data=()):
if data:
data = "+".join(data)
print(data)
else:
print("Passes Automatically")
await ctx.send("auto pass")
await ctx.send("playing")
source = FFmpegPCMAudio("https://www2.iis.fraunhofer.de/AAC/ChIDBLITS-EBU-Narration.mp4", **FFMPEG_OPTIONS)
self.voice.play(source, after=lambda e:self.bot.loop.create_task(self.song_finished(ctx)))
async def song_finished(self, ctx):
await ctx.send("Song finished playing")
# Optionally, you can call play_song again if you have more songs to play
@commands.Cog.listener()
async def on_ready(self):
print("Play is working")
@commands.command(pass_context=True)
async def play(self, ctx, *initial_user_input):
if not self.run:
if ctx.author.voice:
channel = ctx.message.author.voice.channel
self.voice = await channel.connect()
self.run = True
await self.play_song(ctx, initial_user_input)
else:
await ctx.send("Channel Not Found")
else:
await self.play_song(ctx, initial_user_input)
async def setup(bot):
await bot.add_cog(Play(bot))