Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion redbot/cogs/audio/core/abc.py
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,9 @@ async def get_playlist_match(
raise NotImplementedError()

@abstractmethod
async def is_requester_alone(self, ctx: commands.Context) -> bool:
async def is_requester_alone(
self, ctx: commands.Context, channel: Optional[discord.VoiceChannel] = None
) -> bool:
raise NotImplementedError()

@abstractmethod
Expand Down
104 changes: 61 additions & 43 deletions redbot/cogs/audio/core/commands/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,52 +32,70 @@ async def command_disconnect(self, ctx: commands.Context):
"""Disconnect from the voice channel."""
if not self._player_check(ctx):
return await self.send_embed_msg(ctx, title=_("Nothing playing."))
else:
dj_enabled = self._dj_status_cache.setdefault(
ctx.guild.id, await self.config.guild(ctx.guild).dj_enabled()

player = lavalink.get_player(ctx.guild.id)
channel = player.channel
if not channel:
return await self.send_embed_msg(
ctx, title=_("The bot is not connected to a voice channel.")
)
vote_enabled = await self.config.guild(ctx.guild).vote_enabled()
player = lavalink.get_player(ctx.guild.id)
can_skip = await self._can_instaskip(ctx, ctx.author)
if (
(vote_enabled or (vote_enabled and dj_enabled))
and not can_skip
and not await self.is_requester_alone(ctx)
):
return await self.send_embed_msg(
ctx,
title=_("Unable To Disconnect"),
description=_("There are other people listening - vote to skip instead."),
)
if dj_enabled and not vote_enabled and not can_skip:
return await self.send_embed_msg(
ctx,
title=_("Unable To Disconnect"),
description=_("You need the DJ role to disconnect."),
)
if dj_enabled and not can_skip:
return await self.send_embed_msg(
ctx,
title=_("Unable to Disconnect"),
description=_("You need the DJ role to disconnect."),
)

await self.send_embed_msg(ctx, title=_("Disconnecting..."))
self.bot.dispatch("red_audio_audio_disconnect", ctx.guild)
self.update_player_lock(ctx, False)
eq = player.fetch("eq")
player.queue = []
player.store("playing_song", None)
player.store("autoplay_notified", False)
if eq:
await self.config.custom("EQUALIZER", ctx.guild.id).eq_bands.set(eq.bands)
await player.stop()
await player.disconnect()
await self.config.guild_from_id(guild_id=ctx.guild.id).currently_auto_playing_in.set(
[]
dj_enabled = self._dj_status_cache.setdefault(
ctx.guild.id, await self.config.guild(ctx.guild).dj_enabled()
)
vote_enabled = await self.config.guild(ctx.guild).vote_enabled()
can_skip = await self._can_instaskip(ctx, ctx.author)
is_alone = await self.is_requester_alone(ctx, channel)
if is_alone or can_skip:
# User can always disconnect the bot, if there is nobody else in the player's channel
# or when they can instaskip.
pass
# There is someone else in the player's channel and the author can't instaskip,
# we have to ensure that none of the following are true for them to be allowed to DC:
elif vote_enabled:
return await self.send_embed_msg(
ctx,
title=_("Unable To Disconnect"),
description=_("There are other people listening - vote to skip instead."),
)
self._ll_guild_updates.discard(ctx.guild.id)
await self.api_interface.persistent_queue_api.drop(ctx.guild.id)
elif dj_enabled:
# DJ role would have granted the user the ability to instaskip,
# so we know they don't have it
return await self.send_embed_msg(
ctx,
title=_("Unable To Disconnect"),
description=_("You need the DJ role to disconnect."),
)
elif not channel.permissions_for(ctx.author).connect and (
not ctx.author.voice or ctx.author.voice.channel != channel
):
# The user cannot connect to player's current channel,
# so they shouldn't be able to affect what the bot is doing there.
# As a special case, if the user is already connected to the channel
# (perhaps they were moved by a mod), we should assume they can tell the bot to DC,
# since they can already perform any other player action by being in its channel.
return await self.send_embed_msg(
ctx,
title=_("Unable To Disconnect"),
description=_(
"There are other people listening in a voice channel you cannot access."
),
)

await self.send_embed_msg(ctx, title=_("Disconnecting..."))
self.bot.dispatch("red_audio_audio_disconnect", ctx.guild)
self.update_player_lock(ctx, False)
eq = player.fetch("eq")
player.queue = []
player.store("playing_song", None)
player.store("autoplay_notified", False)
if eq:
await self.config.custom("EQUALIZER", ctx.guild.id).eq_bands.set(eq.bands)
await player.stop()
await player.disconnect()
await self.config.guild_from_id(guild_id=ctx.guild.id).currently_auto_playing_in.set([])
self._ll_guild_updates.discard(ctx.guild.id)
await self.api_interface.persistent_queue_api.drop(ctx.guild.id)

@commands.command(name="now")
@commands.guild_only()
Expand Down
7 changes: 5 additions & 2 deletions redbot/cogs/audio/core/utilities/player.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,11 @@ async def _can_instaskip(self, ctx: commands.Context, member: discord.Member) ->

return False

async def is_requester_alone(self, ctx: commands.Context) -> bool:
channel_members = self.rgetattr(ctx, "guild.me.voice.channel.members", [])
async def is_requester_alone(
self, ctx: commands.Context, channel: Optional[discord.VoiceChannel] = None
) -> bool:
channel = channel or self.rgetattr(ctx, "guild.me.voice.channel", None)
channel_members = self.rgetattr(channel, "members", [])
nonbots = sum(m.id != ctx.author.id for m in channel_members if not m.bot)
return not nonbots

Expand Down
Loading