[Audio] Allow lazy searching for playlist across scopes (#3430)

* Allow lazy searching for playlist cross scope

* Chore
This commit is contained in:
Draper 2020-01-26 21:38:49 +00:00 committed by Michael H
parent 068585379a
commit 8654924869
3 changed files with 83 additions and 54 deletions

View File

@ -0,0 +1 @@
Playlist no longer default to the Server scope, and will not return matches across multiple scopes.

View File

@ -67,7 +67,7 @@ from .utils import *
_ = Translator("Audio", __file__) _ = Translator("Audio", __file__)
__version__ = "1.1.0" __version__ = "1.1.1"
__author__ = ["aikaterna", "Draper"] __author__ = ["aikaterna", "Draper"]
log = logging.getLogger("red.audio") log = logging.getLogger("red.audio")
@ -1150,11 +1150,11 @@ class Audio(commands.Cog):
`[p]audioset autoplay PersonalPlaylist --scope User --author Draper` `[p]audioset autoplay PersonalPlaylist --scope User --author Draper`
""" """
if scope_data is None: if scope_data is None:
scope_data = [PlaylistScope.GUILD.value, ctx.author, ctx.guild, False] scope_data = [None, ctx.author, ctx.guild, False]
scope, author, guild, specified_user = scope_data scope, author, guild, specified_user = scope_data
try: try:
playlist_id, playlist_arg = await self._get_correct_playlist_id( playlist_id, playlist_arg, scope = await self._get_correct_playlist_id(
ctx, playlist_matches, scope, author, guild, specified_user ctx, playlist_matches, scope, author, guild, specified_user
) )
except TooManyMatches as e: except TooManyMatches as e:
@ -3833,7 +3833,7 @@ class Audio(commands.Cog):
author: discord.User, author: discord.User,
guild: discord.Guild, guild: discord.Guild,
specified_user: bool = False, specified_user: bool = False,
) -> Tuple[Optional[int], str]: ) -> Tuple[Optional[int], str, str]:
""" """
Parameters Parameters
---------- ----------
@ -3862,34 +3862,57 @@ class Audio(commands.Cog):
""" """
correct_scope_matches: List[Playlist] correct_scope_matches: List[Playlist]
original_input = matches.get("arg") original_input = matches.get("arg")
correct_scope_matches_temp: MutableMapping = matches.get(scope) lazy_match = False
if scope is None:
correct_scope_matches_temp: MutableMapping = matches.get("all")
lazy_match = True
else:
correct_scope_matches_temp: MutableMapping = matches.get(scope)
guild_to_query = guild.id guild_to_query = guild.id
user_to_query = author.id user_to_query = author.id
correct_scope_matches_user = []
correct_scope_matches_guild = []
correct_scope_matches_global = []
if not correct_scope_matches_temp: if not correct_scope_matches_temp:
return None, original_input return None, original_input, scope or PlaylistScope.GUILD.value
if scope == PlaylistScope.USER.value: if lazy_match or (scope == PlaylistScope.USER.value):
correct_scope_matches = [ correct_scope_matches_user = [
p for p in correct_scope_matches_temp if user_to_query == p.scope_id p for p in matches.get(PlaylistScope.USER.value) if user_to_query == p.scope_id
] ]
elif scope == PlaylistScope.GUILD.value: if lazy_match or (scope == PlaylistScope.GUILD.value and not correct_scope_matches_user):
if specified_user: if specified_user:
correct_scope_matches = [ correct_scope_matches_guild = [
p p
for p in correct_scope_matches_temp for p in matches.get(PlaylistScope.GUILD.value)
if guild_to_query == p.scope_id and p.author == user_to_query if guild_to_query == p.scope_id and p.author == user_to_query
] ]
else: else:
correct_scope_matches = [ correct_scope_matches_guild = [
p for p in correct_scope_matches_temp if guild_to_query == p.scope_id p
for p in matches.get(PlaylistScope.GUILD.value)
if guild_to_query == p.scope_id
] ]
else: if lazy_match or (
scope == PlaylistScope.GLOBAL.value
and not correct_scope_matches_user
and not correct_scope_matches_guild
):
if specified_user: if specified_user:
correct_scope_matches = [ correct_scope_matches_global = [
p for p in correct_scope_matches_temp if p.author == user_to_query p
for p in matches.get(PlaylistScope.USGLOBALER.value)
if p.author == user_to_query
] ]
else: else:
correct_scope_matches = [p for p in correct_scope_matches_temp] correct_scope_matches_global = [p for p in matches.get(PlaylistScope.GLOBAL.value)]
correct_scope_matches = [
*correct_scope_matches_global,
*correct_scope_matches_guild,
*correct_scope_matches_user,
]
match_count = len(correct_scope_matches) match_count = len(correct_scope_matches)
if match_count > 1: if match_count > 1:
correct_scope_matches2 = [ correct_scope_matches2 = [
@ -3916,14 +3939,15 @@ class Audio(commands.Cog):
).format(match_count=match_count, original_input=original_input) ).format(match_count=match_count, original_input=original_input)
) )
elif match_count == 1: elif match_count == 1:
return correct_scope_matches[0].id, original_input return correct_scope_matches[0].id, original_input, correct_scope_matches[0].scope
elif match_count == 0: elif match_count == 0:
return None, original_input return None, original_input, scope
# TODO : Convert this section to a new paged reaction menu when Toby Menus are Merged # TODO : Convert this section to a new paged reaction menu when Toby Menus are Merged
pos_len = 3 pos_len = 3
playlists = f"{'#':{pos_len}}\n" playlists = f"{'#':{pos_len}}\n"
number = 0 number = 0
correct_scope_matches = sorted(correct_scope_matches, key=lambda x: x.name.lower())
for number, playlist in enumerate(correct_scope_matches, 1): for number, playlist in enumerate(correct_scope_matches, 1):
author = self.bot.get_user(playlist.author) or playlist.author or _("Unknown") author = self.bot.get_user(playlist.author) or playlist.author or _("Unknown")
line = _( line = _(
@ -3936,7 +3960,7 @@ class Audio(commands.Cog):
).format( ).format(
number=number, number=number,
playlist=playlist, playlist=playlist,
scope=humanize_scope(scope), scope=humanize_scope(playlist.scope),
tracks=len(playlist.tracks), tracks=len(playlist.tracks),
author=author, author=author,
) )
@ -3972,7 +3996,11 @@ class Audio(commands.Cog):
) )
with contextlib.suppress(discord.HTTPException): with contextlib.suppress(discord.HTTPException):
await msg.delete() await msg.delete()
return correct_scope_matches[pred.result].id, original_input return (
correct_scope_matches[pred.result].id,
original_input,
correct_scope_matches[pred.result].scope,
)
@commands.group() @commands.group()
@commands.guild_only() @commands.guild_only()
@ -4035,12 +4063,12 @@ class Audio(commands.Cog):
`[p]playlist append MyGlobalPlaylist Hello by Adele --scope Global --Author Draper#6666` `[p]playlist append MyGlobalPlaylist Hello by Adele --scope Global --Author Draper#6666`
""" """
if scope_data is None: if scope_data is None:
scope_data = [PlaylistScope.GUILD.value, ctx.author, ctx.guild, False] scope_data = [None, ctx.author, ctx.guild, False]
(scope, author, guild, specified_user) = scope_data (scope, author, guild, specified_user) = scope_data
if not await self._playlist_check(ctx): if not await self._playlist_check(ctx):
return return
try: try:
(playlist_id, playlist_arg) = await self._get_correct_playlist_id( (playlist_id, playlist_arg, scope) = await self._get_correct_playlist_id(
ctx, playlist_matches, scope, author, guild, specified_user ctx, playlist_matches, scope, author, guild, specified_user
) )
except TooManyMatches as e: except TooManyMatches as e:
@ -4222,7 +4250,7 @@ class Audio(commands.Cog):
) = scope_data ) = scope_data
try: try:
playlist_id, playlist_arg = await self._get_correct_playlist_id( playlist_id, playlist_arg, scope = await self._get_correct_playlist_id(
ctx, playlist_matches, from_scope, from_author, from_guild, specified_from_user ctx, playlist_matches, from_scope, from_author, from_guild, specified_from_user
) )
except TooManyMatches as e: except TooManyMatches as e:
@ -4400,11 +4428,11 @@ class Audio(commands.Cog):
`[p]playlist delete MyPersonalPlaylist --scope User` `[p]playlist delete MyPersonalPlaylist --scope User`
""" """
if scope_data is None: if scope_data is None:
scope_data = [PlaylistScope.GUILD.value, ctx.author, ctx.guild, False] scope_data = [None, ctx.author, ctx.guild, False]
scope, author, guild, specified_user = scope_data scope, author, guild, specified_user = scope_data
try: try:
playlist_id, playlist_arg = await self._get_correct_playlist_id( playlist_id, playlist_arg, scope = await self._get_correct_playlist_id(
ctx, playlist_matches, scope, author, guild, specified_user ctx, playlist_matches, scope, author, guild, specified_user
) )
except TooManyMatches as e: except TooManyMatches as e:
@ -4488,19 +4516,18 @@ class Audio(commands.Cog):
""" """
async with ctx.typing(): async with ctx.typing():
if scope_data is None: if scope_data is None:
scope_data = [PlaylistScope.GUILD.value, ctx.author, ctx.guild, False] scope_data = [None, ctx.author, ctx.guild, False]
scope, author, guild, specified_user = scope_data scope, author, guild, specified_user = scope_data
scope_name = humanize_scope(
scope, ctx=guild if scope == PlaylistScope.GUILD.value else author
)
try: try:
playlist_id, playlist_arg = await self._get_correct_playlist_id( playlist_id, playlist_arg, scope = await self._get_correct_playlist_id(
ctx, playlist_matches, scope, author, guild, specified_user ctx, playlist_matches, scope, author, guild, specified_user
) )
except TooManyMatches as e: except TooManyMatches as e:
ctx.command.reset_cooldown(ctx) ctx.command.reset_cooldown(ctx)
return await self._embed_msg(ctx, title=str(e)) return await self._embed_msg(ctx, title=str(e))
scope_name = humanize_scope(
scope, ctx=guild if scope == PlaylistScope.GUILD.value else author
)
if playlist_id is None: if playlist_id is None:
ctx.command.reset_cooldown(ctx) ctx.command.reset_cooldown(ctx)
return await self._embed_msg( return await self._embed_msg(
@ -4631,11 +4658,11 @@ class Audio(commands.Cog):
`[p]playlist download MyPersonalPlaylist --scope User` `[p]playlist download MyPersonalPlaylist --scope User`
""" """
if scope_data is None: if scope_data is None:
scope_data = [PlaylistScope.GUILD.value, ctx.author, ctx.guild, False] scope_data = [None, ctx.author, ctx.guild, False]
scope, author, guild, specified_user = scope_data scope, author, guild, specified_user = scope_data
try: try:
playlist_id, playlist_arg = await self._get_correct_playlist_id( playlist_id, playlist_arg, scope = await self._get_correct_playlist_id(
ctx, playlist_matches, scope, author, guild, specified_user ctx, playlist_matches, scope, author, guild, specified_user
) )
except TooManyMatches as e: except TooManyMatches as e:
@ -4771,19 +4798,19 @@ class Audio(commands.Cog):
`[p]playlist info MyPersonalPlaylist --scope User` `[p]playlist info MyPersonalPlaylist --scope User`
""" """
if scope_data is None: if scope_data is None:
scope_data = [PlaylistScope.GUILD.value, ctx.author, ctx.guild, False] scope_data = [None, ctx.author, ctx.guild, False]
scope, author, guild, specified_user = scope_data scope, author, guild, specified_user = scope_data
scope_name = humanize_scope(
scope, ctx=guild if scope == PlaylistScope.GUILD.value else author
)
try: try:
playlist_id, playlist_arg = await self._get_correct_playlist_id( playlist_id, playlist_arg, scope = await self._get_correct_playlist_id(
ctx, playlist_matches, scope, author, guild, specified_user ctx, playlist_matches, scope, author, guild, specified_user
) )
except TooManyMatches as e: except TooManyMatches as e:
ctx.command.reset_cooldown(ctx) ctx.command.reset_cooldown(ctx)
return await self._embed_msg(ctx, title=str(e)) return await self._embed_msg(ctx, title=str(e))
scope_name = humanize_scope(
scope, ctx=guild if scope == PlaylistScope.GUILD.value else author
)
if playlist_id is None: if playlist_id is None:
ctx.command.reset_cooldown(ctx) ctx.command.reset_cooldown(ctx)
return await self._embed_msg( return await self._embed_msg(
@ -5131,18 +5158,18 @@ class Audio(commands.Cog):
`[p]playlist remove MyPersonalPlaylist https://www.youtube.com/watch?v=MN3x-kAbgFU --scope User` `[p]playlist remove MyPersonalPlaylist https://www.youtube.com/watch?v=MN3x-kAbgFU --scope User`
""" """
if scope_data is None: if scope_data is None:
scope_data = [PlaylistScope.GUILD.value, ctx.author, ctx.guild, False] scope_data = [None, ctx.author, ctx.guild, False]
scope, author, guild, specified_user = scope_data scope, author, guild, specified_user = scope_data
scope_name = humanize_scope(
scope, ctx=guild if scope == PlaylistScope.GUILD.value else author
)
try: try:
playlist_id, playlist_arg = await self._get_correct_playlist_id( playlist_id, playlist_arg, scope = await self._get_correct_playlist_id(
ctx, playlist_matches, scope, author, guild, specified_user ctx, playlist_matches, scope, author, guild, specified_user
) )
except TooManyMatches as e: except TooManyMatches as e:
return await self._embed_msg(ctx, title=str(e)) return await self._embed_msg(ctx, title=str(e))
scope_name = humanize_scope(
scope, ctx=guild if scope == PlaylistScope.GUILD.value else author
)
if playlist_id is None: if playlist_id is None:
return await self._embed_msg( return await self._embed_msg(
ctx, ctx,
@ -5338,7 +5365,7 @@ class Audio(commands.Cog):
`[p]playlist start MyPersonalPlaylist --scope User` `[p]playlist start MyPersonalPlaylist --scope User`
""" """
if scope_data is None: if scope_data is None:
scope_data = [PlaylistScope.GUILD.value, ctx.author, ctx.guild, False] scope_data = [None, ctx.author, ctx.guild, False]
scope, author, guild, specified_user = scope_data scope, author, guild, specified_user = scope_data
dj_enabled = self._dj_status_cache.setdefault( dj_enabled = self._dj_status_cache.setdefault(
ctx.guild.id, await self.config.guild(ctx.guild).dj_enabled() ctx.guild.id, await self.config.guild(ctx.guild).dj_enabled()
@ -5354,7 +5381,7 @@ class Audio(commands.Cog):
return False return False
try: try:
playlist_id, playlist_arg = await self._get_correct_playlist_id( playlist_id, playlist_arg, scope = await self._get_correct_playlist_id(
ctx, playlist_matches, scope, author, guild, specified_user ctx, playlist_matches, scope, author, guild, specified_user
) )
except TooManyMatches as e: except TooManyMatches as e:
@ -5509,10 +5536,10 @@ class Audio(commands.Cog):
""" """
if scope_data is None: if scope_data is None:
scope_data = [PlaylistScope.GUILD.value, ctx.author, ctx.guild, False] scope_data = [None, ctx.author, ctx.guild, False]
scope, author, guild, specified_user = scope_data scope, author, guild, specified_user = scope_data
try: try:
playlist_id, playlist_arg = await self._get_correct_playlist_id( playlist_id, playlist_arg, scope = await self._get_correct_playlist_id(
ctx, playlist_matches, scope, author, guild, specified_user ctx, playlist_matches, scope, author, guild, specified_user
) )
except TooManyMatches as e: except TooManyMatches as e:
@ -5788,7 +5815,7 @@ class Audio(commands.Cog):
`[p]playlist rename MyPersonalPlaylist RenamedPersonalPlaylist --scope User` `[p]playlist rename MyPersonalPlaylist RenamedPersonalPlaylist --scope User`
""" """
if scope_data is None: if scope_data is None:
scope_data = [PlaylistScope.GUILD.value, ctx.author, ctx.guild, False] scope_data = [None, ctx.author, ctx.guild, False]
scope, author, guild, specified_user = scope_data scope, author, guild, specified_user = scope_data
new_name = new_name.split(" ")[0].strip('"')[:32] new_name = new_name.split(" ")[0].strip('"')[:32]
@ -5804,7 +5831,7 @@ class Audio(commands.Cog):
) )
try: try:
playlist_id, playlist_arg = await self._get_correct_playlist_id( playlist_id, playlist_arg, scope = await self._get_correct_playlist_id(
ctx, playlist_matches, scope, author, guild, specified_user ctx, playlist_matches, scope, author, guild, specified_user
) )
except TooManyMatches as e: except TooManyMatches as e:

View File

@ -158,6 +158,7 @@ class PlaylistConverter(commands.Converter):
PlaylistScope.GLOBAL.value: global_matches, PlaylistScope.GLOBAL.value: global_matches,
PlaylistScope.GUILD.value: guild_matches, PlaylistScope.GUILD.value: guild_matches,
PlaylistScope.USER.value: user_matches, PlaylistScope.USER.value: user_matches,
"all": [*global_matches, *guild_matches, *user_matches],
"arg": arg, "arg": arg,
} }
@ -170,7 +171,7 @@ class NoExitParser(argparse.ArgumentParser):
class ScopeParser(commands.Converter): class ScopeParser(commands.Converter):
async def convert( async def convert(
self, ctx: commands.Context, argument: str self, ctx: commands.Context, argument: str
) -> Tuple[str, discord.User, Optional[discord.Guild], bool]: ) -> Tuple[Optional[str], discord.User, Optional[discord.Guild], bool]:
target_scope: Optional[str] = None target_scope: Optional[str] = None
target_user: Optional[Union[discord.Member, discord.User]] = None target_user: Optional[Union[discord.Member, discord.User]] = None
@ -261,7 +262,7 @@ class ScopeParser(commands.Converter):
elif any(x in argument for x in ["--author", "--user", "--member"]): elif any(x in argument for x in ["--author", "--user", "--member"]):
raise commands.ArgParserFailure("--scope", "Nothing", custom_help=_USER_HELP) raise commands.ArgParserFailure("--scope", "Nothing", custom_help=_USER_HELP)
target_scope: str = target_scope or PlaylistScope.GUILD.value target_scope: str = target_scope or None
target_user: Union[discord.Member, discord.User] = target_user or ctx.author target_user: Union[discord.Member, discord.User] = target_user or ctx.author
target_guild: discord.Guild = target_guild or ctx.guild target_guild: discord.Guild = target_guild or ctx.guild