For my discord bot, I want it to send a message after it has left a voice channel to only the text channel that the command was used. I've tried doing this through an event, but that sent a message to every channel.
Here is my code:
class Commands(commands.Cog):
def __init__(self, bot):
self.bot = bot
@commands.Cog.listener()
async def on_voice_state_update(self, member, before, after):
if not member.id == self.bot.user.id:
return
elif before.channel is None:
voice = after.channel.guild.voice_client
time = 0
while True:
await asyncio.sleep(1)
time += 1
if voice.is_playing() and not voice.is_paused():
time = 0
if time == 10:
await voice.disconnect()
if not voice.is_connected:
break
@commands.command(pass_context = True)
async def play(self, ctx):
if ctx.author.voice:
channel = ctx.message.author.voice.channel
await channel.connect()
Is there a way to detect when the bot leaves within the play command?
The on_voice_state_update
event handler should handle any type of VoiceState
change, and before
and after
hold data about the VoiceState
before and after the change. In particular, after.channel
is None
if member
got disconnected from before.channel
. You can simply add the line at the beginning of your function.
VOICE_CHANNELS = {}
@commands.Cog.listener()
async def on_voice_state_update(self, member, before, after):
# Make sure the member is the bot
if not member.id == self.bot.user.id:
return
# Bot got disconnected
if after.channel is None:
text_channel = VOICE_CHANNELS.pop(before.channel.id)
if text_channel:
await text_channel.send("Disconnected!")
# Bot got connected
elif before.channel is None:
voice = after.channel.guild.voice_client
time = 0
while True:
await asyncio.sleep(1)
time += 1
if voice.is_playing() and not voice.is_paused():
time = 0
if time == 10:
await voice.disconnect()
if not voice.is_connected:
break
@commands.command(pass_context = True)
async def play(self, ctx):
if ctx.author.voice:
channel = ctx.message.author.voice.channel
await channel.connect()
VOICE_CHANNELS[channel.id] = ctx.channel