mirror of
https://github.com/Cog-Creators/Red-DiscordBot.git
synced 2025-11-06 03:08:55 -05:00
[Audio] Fix Attribute error raised by is_alone method when channel was None (#3122)
* Fix attribute Fixes #3120 Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Chore Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com>
This commit is contained in:
parent
61f467a323
commit
0b042532fd
1
changelog.d/3120.bugfix.rst
Normal file
1
changelog.d/3120.bugfix.rst
Normal file
@ -0,0 +1 @@
|
||||
Fixed an issue when calling audio commands when not in a voice channel could result in a crash.
|
||||
@ -5,7 +5,7 @@ import datetime
|
||||
import heapq
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import math
|
||||
import random
|
||||
import re
|
||||
import time
|
||||
@ -17,7 +17,6 @@ from typing import List, Optional, Tuple, Union, cast
|
||||
import aiohttp
|
||||
import discord
|
||||
import lavalink
|
||||
import math
|
||||
from fuzzywuzzy import process
|
||||
|
||||
import redbot.core
|
||||
@ -34,8 +33,9 @@ from redbot.core.utils.menus import (
|
||||
start_adding_reactions,
|
||||
)
|
||||
from redbot.core.utils.predicates import MessagePredicate, ReactionPredicate
|
||||
|
||||
from . import audio_dataclasses
|
||||
from .apis import MusicCache, HAS_SQL, _ERROR
|
||||
from .apis import _ERROR, HAS_SQL, MusicCache
|
||||
from .checks import can_have_caching
|
||||
from .converters import ComplexScopeParser, ScopeParser, get_lazy_converter, get_playlist_converter
|
||||
from .equalizer import Equalizer
|
||||
@ -57,8 +57,26 @@ from .playlists import (
|
||||
get_playlist,
|
||||
humanize_scope,
|
||||
)
|
||||
from .utils import *
|
||||
|
||||
from .utils import (
|
||||
CacheLevel,
|
||||
Notifier,
|
||||
clear_react,
|
||||
draw_time,
|
||||
dynamic_time,
|
||||
get_description,
|
||||
is_allowed,
|
||||
match_url,
|
||||
match_yt_playlist,
|
||||
pass_config_to_dependencies,
|
||||
queue_duration,
|
||||
remove_react,
|
||||
rgetattr,
|
||||
time_convert,
|
||||
track_creator,
|
||||
track_limit,
|
||||
url_check,
|
||||
userlimit,
|
||||
)
|
||||
|
||||
_ = Translator("Audio", __file__)
|
||||
|
||||
@ -1669,9 +1687,7 @@ class Audio(commands.Cog):
|
||||
if dj_enabled:
|
||||
if not await self._can_instaskip(ctx, ctx.author):
|
||||
return await self._embed_msg(ctx, _("You need the DJ role to disconnect."))
|
||||
if not await self._can_instaskip(ctx, ctx.author) and not await self._is_alone(
|
||||
ctx, ctx.author
|
||||
):
|
||||
if not await self._can_instaskip(ctx, ctx.author) and not await self._is_alone(ctx):
|
||||
return await self._embed_msg(ctx, _("There are other people listening to music."))
|
||||
else:
|
||||
await self._embed_msg(ctx, _("Disconnecting..."))
|
||||
@ -2270,9 +2286,7 @@ class Audio(commands.Cog):
|
||||
dj_enabled = await self.config.guild(ctx.guild).dj_enabled()
|
||||
vote_enabled = await self.config.guild(ctx.guild).vote_enabled()
|
||||
if dj_enabled or vote_enabled:
|
||||
if not await self._can_instaskip(ctx, ctx.author) and not await self._is_alone(
|
||||
ctx, ctx.author
|
||||
):
|
||||
if not await self._can_instaskip(ctx, ctx.author) and not await self._is_alone(ctx):
|
||||
return
|
||||
|
||||
if player.current:
|
||||
@ -2322,9 +2336,7 @@ class Audio(commands.Cog):
|
||||
ctx, _("You must be in the voice channel pause or resume.")
|
||||
)
|
||||
if dj_enabled:
|
||||
if not await self._can_instaskip(ctx, ctx.author) and not await self._is_alone(
|
||||
ctx, ctx.author
|
||||
):
|
||||
if not await self._can_instaskip(ctx, ctx.author) and not await self._is_alone(ctx):
|
||||
return await self._embed_msg(
|
||||
ctx, _("You need the DJ role to pause or resume tracks.")
|
||||
)
|
||||
@ -5202,9 +5214,7 @@ class Audio(commands.Cog):
|
||||
dj_enabled = await self.config.guild(ctx.guild).dj_enabled()
|
||||
player = lavalink.get_player(ctx.guild.id)
|
||||
if dj_enabled:
|
||||
if not await self._can_instaskip(ctx, ctx.author) and not await self._is_alone(
|
||||
ctx, ctx.author
|
||||
):
|
||||
if not await self._can_instaskip(ctx, ctx.author) and not await self._is_alone(ctx):
|
||||
return await self._embed_msg(ctx, _("You need the DJ role to skip tracks."))
|
||||
if (
|
||||
not ctx.author.voice or ctx.author.voice.channel != player.channel
|
||||
@ -5522,10 +5532,9 @@ class Audio(commands.Cog):
|
||||
dj_enabled = await self.config.guild(ctx.guild).dj_enabled()
|
||||
if not self._player_check(ctx) or not player.queue:
|
||||
return await self._embed_msg(ctx, _("There's nothing in the queue."))
|
||||
|
||||
if dj_enabled:
|
||||
if not await self._can_instaskip(ctx, ctx.author) and not await self._is_alone(
|
||||
ctx, ctx.author
|
||||
):
|
||||
if not await self._can_instaskip(ctx, ctx.author) and not await self._is_alone(ctx):
|
||||
return await self._embed_msg(ctx, _("You need the DJ role to clear the queue."))
|
||||
player.queue.clear()
|
||||
await self._embed_msg(ctx, _("The queue has been cleared."))
|
||||
@ -5542,9 +5551,7 @@ class Audio(commands.Cog):
|
||||
if not self._player_check(ctx) or not player.queue:
|
||||
return await self._embed_msg(ctx, _("There's nothing in the queue."))
|
||||
if dj_enabled:
|
||||
if not await self._can_instaskip(ctx, ctx.author) and not await self._is_alone(
|
||||
ctx, ctx.author
|
||||
):
|
||||
if not await self._can_instaskip(ctx, ctx.author) and not await self._is_alone(ctx):
|
||||
return await self._embed_msg(ctx, _("You need the DJ role to clean the queue."))
|
||||
clean_tracks = []
|
||||
removed_tracks = 0
|
||||
@ -5624,10 +5631,8 @@ class Audio(commands.Cog):
|
||||
"""Shuffles the queue."""
|
||||
dj_enabled = await self.config.guild(ctx.guild).dj_enabled()
|
||||
if dj_enabled:
|
||||
if not await self._can_instaskip(ctx, ctx.author) and not await self._is_alone(
|
||||
ctx, ctx.author
|
||||
):
|
||||
return await self._embed_msg(ctx, _("You need the DJ role to clean the queue."))
|
||||
if not await self._can_instaskip(ctx, ctx.author) and not await self._is_alone(ctx):
|
||||
return await self._embed_msg(ctx, _("You need the DJ role to shuffle the queue."))
|
||||
if not self._player_check(ctx):
|
||||
return await self._embed_msg(ctx, _("There's nothing in the queue."))
|
||||
try:
|
||||
@ -6090,7 +6095,7 @@ class Audio(commands.Cog):
|
||||
Accepts seconds or a value formatted like 00:00:00 (`hh:mm:ss`) or 00:00 (`mm:ss`)."""
|
||||
dj_enabled = await self.config.guild(ctx.guild).dj_enabled()
|
||||
vote_enabled = await self.config.guild(ctx.guild).vote_enabled()
|
||||
is_alone = await self._is_alone(ctx, ctx.author)
|
||||
is_alone = await self._is_alone(ctx)
|
||||
is_requester = await self.is_requester(ctx, ctx.author)
|
||||
can_skip = await self._can_instaskip(ctx, ctx.author)
|
||||
|
||||
@ -6212,10 +6217,9 @@ class Audio(commands.Cog):
|
||||
return await self._embed_msg(ctx, _("Nothing playing."))
|
||||
dj_enabled = await self.config.guild(ctx.guild).dj_enabled()
|
||||
vote_enabled = await self.config.guild(ctx.guild).vote_enabled()
|
||||
is_alone = await self._is_alone(ctx, ctx.author)
|
||||
is_alone = await self._is_alone(ctx)
|
||||
is_requester = await self.is_requester(ctx, ctx.author)
|
||||
can_skip = await self._can_instaskip(ctx, ctx.author)
|
||||
|
||||
if dj_enabled and not vote_enabled:
|
||||
if not (can_skip or is_requester) and not is_alone:
|
||||
return await self._embed_msg(
|
||||
@ -6228,7 +6232,6 @@ class Audio(commands.Cog):
|
||||
and skip_to_track > 1
|
||||
):
|
||||
return await self._embed_msg(ctx, _("You can only skip the current track."))
|
||||
|
||||
if vote_enabled:
|
||||
if not can_skip:
|
||||
if skip_to_track is not None:
|
||||
@ -6296,40 +6299,21 @@ class Audio(commands.Cog):
|
||||
|
||||
return False
|
||||
|
||||
async def _is_alone(self, ctx: commands.Context, member: discord.Member):
|
||||
try:
|
||||
user_voice = ctx.guild.get_member(member.id).voice
|
||||
bot_voice = ctx.guild.get_member(self.bot.user.id).voice
|
||||
nonbots = sum(not m.bot for m in user_voice.channel.members)
|
||||
if user_voice.channel != bot_voice.channel:
|
||||
nonbots = nonbots + 1
|
||||
except AttributeError:
|
||||
if ctx.guild.get_member(self.bot.user.id).voice is not None:
|
||||
nonbots = sum(
|
||||
not m.bot for m in ctx.guild.get_member(self.bot.user.id).voice.channel.members
|
||||
)
|
||||
if nonbots == 1:
|
||||
nonbots = 2
|
||||
elif ctx.guild.get_member(member.id).voice.channel.members == 1:
|
||||
nonbots = 1
|
||||
else:
|
||||
nonbots = 0
|
||||
return nonbots <= 1
|
||||
async def _is_alone(self, ctx: commands.Context):
|
||||
channel_members = rgetattr(ctx, "guild.me.voice.channel.members", [])
|
||||
nonbots = sum(m.id != ctx.author.id for m in channel_members if not m.bot)
|
||||
return nonbots < 1
|
||||
|
||||
async def _has_dj_role(self, ctx: commands.Context, member: discord.Member):
|
||||
dj_role_obj = ctx.guild.get_role(await self.config.guild(ctx.guild).dj_role())
|
||||
if dj_role_obj in ctx.guild.get_member(member.id).roles:
|
||||
return True
|
||||
return False
|
||||
return dj_role_obj in ctx.guild.get_member(member.id).roles
|
||||
|
||||
@staticmethod
|
||||
async def is_requester(ctx: commands.Context, member: discord.Member):
|
||||
try:
|
||||
player = lavalink.get_player(ctx.guild.id)
|
||||
log.debug(f"Current requester is {player.current}")
|
||||
if player.current.requester.id == member.id:
|
||||
return True
|
||||
return False
|
||||
return player.current.requester.id == member.id
|
||||
except Exception as e:
|
||||
log.error(e)
|
||||
return False
|
||||
@ -6422,9 +6406,7 @@ class Audio(commands.Cog):
|
||||
ctx, _("You must be in the voice channel to stop the music.")
|
||||
)
|
||||
if vote_enabled or vote_enabled and dj_enabled:
|
||||
if not await self._can_instaskip(ctx, ctx.author) and not await self._is_alone(
|
||||
ctx, ctx.author
|
||||
):
|
||||
if not await self._can_instaskip(ctx, ctx.author) and not await self._is_alone(ctx):
|
||||
return await self._embed_msg(
|
||||
ctx, _("There are other people listening - vote to skip instead.")
|
||||
)
|
||||
@ -6754,9 +6736,6 @@ class Audio(commands.Cog):
|
||||
log.error(
|
||||
"Exception raised in Audio's emptypause_timer.", exc_info=True
|
||||
)
|
||||
finally:
|
||||
pause_times.pop(server.id, None)
|
||||
else:
|
||||
pause_times.pop(server.id, None)
|
||||
servers = stop_times.copy()
|
||||
servers.update(pause_times)
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import asyncio
|
||||
import contextlib
|
||||
import functools
|
||||
import os
|
||||
import re
|
||||
import time
|
||||
@ -10,10 +11,9 @@ import lavalink
|
||||
|
||||
from redbot.core import Config, commands
|
||||
from redbot.core.bot import Red
|
||||
|
||||
from . import audio_dataclasses
|
||||
|
||||
from .converters import _pass_config_to_converters
|
||||
|
||||
from .playlists import _pass_config_to_playlist
|
||||
|
||||
__all__ = [
|
||||
@ -32,6 +32,7 @@ __all__ = [
|
||||
"url_check",
|
||||
"userlimit",
|
||||
"is_allowed",
|
||||
"rgetattr",
|
||||
"CacheLevel",
|
||||
"Notifier",
|
||||
]
|
||||
@ -240,6 +241,18 @@ def userlimit(channel):
|
||||
return True
|
||||
|
||||
|
||||
def rsetattr(obj, attr, val):
|
||||
pre, _, post = attr.rpartition(".")
|
||||
return setattr(rgetattr(obj, pre) if pre else obj, post, val)
|
||||
|
||||
|
||||
def rgetattr(obj, attr, *args):
|
||||
def _getattr(obj2, attr2):
|
||||
return getattr(obj2, attr2, *args)
|
||||
|
||||
return functools.reduce(_getattr, [obj] + attr.split("."))
|
||||
|
||||
|
||||
class CacheLevel:
|
||||
__slots__ = ("value",)
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user