mirror of
https://github.com/Cog-Creators/Red-DiscordBot.git
synced 2025-11-06 11:18:54 -05:00
[3.2]Audio] some hotfixes to avoid crashing the bot (#3286)
* Add a command to toggle daily queues, and restrict playlist length to 10k tracks and try to avoid some blocking calls Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * Add a command to toggle daily queues, and restrict playlist length to 10k tracks and try to avoid some blocking calls Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * indents Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * *sigh* forgot single tracks Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * formatting plus some other fixes Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com> * formatting plus some other fixes Signed-off-by: Drapersniper <27962761+drapersniper@users.noreply.github.com>
This commit is contained in:
parent
965416de73
commit
44e680ee41
1
changelog.d/audio/3286.bugfix.1.rst
Normal file
1
changelog.d/audio/3286.bugfix.1.rst
Normal file
@ -0,0 +1 @@
|
|||||||
|
Add more cooldown to playlist commands and restrict queue and playlist to 10k songs to avoid DOS attacks(User crashing your bot on purpose).
|
||||||
@ -318,6 +318,7 @@ class MusicCache:
|
|||||||
youtube_urls.append(val)
|
youtube_urls.append(val)
|
||||||
else:
|
else:
|
||||||
youtube_urls.append(track_info)
|
youtube_urls.append(track_info)
|
||||||
|
await asyncio.sleep(0)
|
||||||
track_count += 1
|
track_count += 1
|
||||||
if notifier and ((track_count % 2 == 0) or (track_count == total_tracks)):
|
if notifier and ((track_count % 2 == 0) or (track_count == total_tracks)):
|
||||||
await notifier.notify_user(current=track_count, total=total_tracks, key="youtube")
|
await notifier.notify_user(current=track_count, total=total_tracks, key="youtube")
|
||||||
@ -615,6 +616,8 @@ class MusicCache:
|
|||||||
continue
|
continue
|
||||||
track_list.append(single_track)
|
track_list.append(single_track)
|
||||||
if enqueue:
|
if enqueue:
|
||||||
|
if len(player.queue) >= 10000:
|
||||||
|
continue
|
||||||
if guild_data["maxlength"] > 0:
|
if guild_data["maxlength"] > 0:
|
||||||
if track_limit(single_track, guild_data["maxlength"]):
|
if track_limit(single_track, guild_data["maxlength"]):
|
||||||
enqueued_tracks += 1
|
enqueued_tracks += 1
|
||||||
|
|||||||
@ -94,6 +94,7 @@ class Audio(commands.Cog):
|
|||||||
self.config: Config = Config.get_conf(self, 2711759130, force_registration=True)
|
self.config: Config = Config.get_conf(self, 2711759130, force_registration=True)
|
||||||
self.skip_votes: MutableMapping[discord.Guild, List[discord.Member]] = {}
|
self.skip_votes: MutableMapping[discord.Guild, List[discord.Member]] = {}
|
||||||
self.play_lock: MutableMapping[int, bool] = {}
|
self.play_lock: MutableMapping[int, bool] = {}
|
||||||
|
self._daily_playlist_cache: MutableMapping[int, bool] = {}
|
||||||
self._dj_status_cache: MutableMapping[int, Optional[bool]] = {}
|
self._dj_status_cache: MutableMapping[int, Optional[bool]] = {}
|
||||||
self._dj_role_cache: MutableMapping[int, Optional[int]] = {}
|
self._dj_role_cache: MutableMapping[int, Optional[int]] = {}
|
||||||
self.session: aiohttp.ClientSession = aiohttp.ClientSession()
|
self.session: aiohttp.ClientSession = aiohttp.ClientSession()
|
||||||
@ -121,6 +122,7 @@ class Audio(commands.Cog):
|
|||||||
disconnect=False,
|
disconnect=False,
|
||||||
dj_enabled=False,
|
dj_enabled=False,
|
||||||
dj_role=None,
|
dj_role=None,
|
||||||
|
daily_playlists=False,
|
||||||
emptydc_enabled=False,
|
emptydc_enabled=False,
|
||||||
emptydc_timer=0,
|
emptydc_timer=0,
|
||||||
emptypause_enabled=False,
|
emptypause_enabled=False,
|
||||||
@ -183,6 +185,9 @@ class Audio(commands.Cog):
|
|||||||
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()
|
||||||
)
|
)
|
||||||
|
daily_cache = self._daily_playlist_cache.setdefault(
|
||||||
|
ctx.guild.id, await self.config.guild(ctx.guild).daily_playlists()
|
||||||
|
)
|
||||||
if dj_enabled:
|
if dj_enabled:
|
||||||
dj_role = self._dj_role_cache.setdefault(
|
dj_role = self._dj_role_cache.setdefault(
|
||||||
ctx.guild.id, await self.config.guild(ctx.guild).dj_role()
|
ctx.guild.id, await self.config.guild(ctx.guild).dj_role()
|
||||||
@ -249,8 +254,10 @@ class Audio(commands.Cog):
|
|||||||
"last_fetched": time_now,
|
"last_fetched": time_now,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
await asyncio.sleep(0)
|
||||||
if guild_playlist:
|
if guild_playlist:
|
||||||
all_playlist[str(guild_id)] = guild_playlist
|
all_playlist[str(guild_id)] = guild_playlist
|
||||||
|
await asyncio.sleep(0)
|
||||||
await self.config.custom(PlaylistScope.GUILD.value).set(all_playlist)
|
await self.config.custom(PlaylistScope.GUILD.value).set(all_playlist)
|
||||||
# new schema is now in place
|
# new schema is now in place
|
||||||
await self.config.schema_version.set(_SCHEMA_VERSION)
|
await self.config.schema_version.set(_SCHEMA_VERSION)
|
||||||
@ -658,6 +665,26 @@ class Audio(commands.Cog):
|
|||||||
async def audioset(self, ctx: commands.Context):
|
async def audioset(self, ctx: commands.Context):
|
||||||
"""Music configuration options."""
|
"""Music configuration options."""
|
||||||
|
|
||||||
|
@audioset.command(name="dailyqueue")
|
||||||
|
@checks.admin()
|
||||||
|
async def _audioset_historical_queue(self, ctx: commands.Context):
|
||||||
|
"""Toggle daily queues.
|
||||||
|
|
||||||
|
Daily queues creates a playlist for all tracks played today.
|
||||||
|
"""
|
||||||
|
daily_playlists = self._daily_playlist_cache.setdefault(
|
||||||
|
ctx.guild.id, await self.config.guild(ctx.guild).daily_playlists()
|
||||||
|
)
|
||||||
|
await self.config.guild(ctx.guild).daily_playlists.set(not daily_playlists)
|
||||||
|
self._daily_playlist_cache[ctx.guild.id] = not daily_playlists
|
||||||
|
await self._embed_msg(
|
||||||
|
ctx,
|
||||||
|
title=_("Setting Changed"),
|
||||||
|
description=_("Daily queues: {true_or_false}.").format(
|
||||||
|
true_or_false=_("Enabled") if not daily_playlists else _("Disabled")
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
@audioset.command()
|
@audioset.command()
|
||||||
@checks.mod_or_permissions(manage_messages=True)
|
@checks.mod_or_permissions(manage_messages=True)
|
||||||
async def dc(self, ctx: commands.Context):
|
async def dc(self, ctx: commands.Context):
|
||||||
@ -2493,6 +2520,7 @@ class Audio(commands.Cog):
|
|||||||
search_list.extend(
|
search_list.extend(
|
||||||
[i.track.to_string_user() for i in to_search if i.track.name == track_match]
|
[i.track.to_string_user() for i in to_search if i.track.name == track_match]
|
||||||
)
|
)
|
||||||
|
await asyncio.sleep(0)
|
||||||
return search_list
|
return search_list
|
||||||
|
|
||||||
@commands.command()
|
@commands.command()
|
||||||
@ -2658,6 +2686,7 @@ class Audio(commands.Cog):
|
|||||||
for track in queue_tracks:
|
for track in queue_tracks:
|
||||||
req_username = "{}#{}".format(track.requester.name, track.requester.discriminator)
|
req_username = "{}#{}".format(track.requester.name, track.requester.discriminator)
|
||||||
await _usercount(req_username)
|
await _usercount(req_username)
|
||||||
|
await asyncio.sleep(0)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
req_username = "{}#{}".format(
|
req_username = "{}#{}".format(
|
||||||
@ -2672,6 +2701,7 @@ class Audio(commands.Cog):
|
|||||||
requesters["total"]
|
requesters["total"]
|
||||||
)
|
)
|
||||||
requesters["users"][req_username]["percent"] = round(percentage * 100, 1)
|
requesters["users"][req_username]["percent"] = round(percentage * 100, 1)
|
||||||
|
await asyncio.sleep(0)
|
||||||
|
|
||||||
top_queue_users = heapq.nlargest(
|
top_queue_users = heapq.nlargest(
|
||||||
20,
|
20,
|
||||||
@ -2771,6 +2801,11 @@ class Audio(commands.Cog):
|
|||||||
query=query.to_string_user()
|
query=query.to_string_user()
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
if len(player.queue) >= 10000:
|
||||||
|
return await self._embed_msg(
|
||||||
|
ctx, title=_("Unable To Play Tracks"), description=_("Queue size limit reached.")
|
||||||
|
)
|
||||||
|
|
||||||
if not await self._currency_check(ctx, guild_data["jukebox_price"]):
|
if not await self._currency_check(ctx, guild_data["jukebox_price"]):
|
||||||
return
|
return
|
||||||
if query.is_spotify:
|
if query.is_spotify:
|
||||||
@ -2872,6 +2907,11 @@ class Audio(commands.Cog):
|
|||||||
query=query.to_string_user()
|
query=query.to_string_user()
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
if len(player.queue) >= 10000:
|
||||||
|
return await self._embed_msg(
|
||||||
|
ctx, title=_("Unable To Play Tracks"), description=_("Queue size limit reached.")
|
||||||
|
)
|
||||||
|
|
||||||
if not await self._currency_check(ctx, guild_data["jukebox_price"]):
|
if not await self._currency_check(ctx, guild_data["jukebox_price"]):
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
@ -3127,6 +3167,7 @@ class Audio(commands.Cog):
|
|||||||
ctx, category_list, page_num, _("Categories")
|
ctx, category_list, page_num, _("Categories")
|
||||||
)
|
)
|
||||||
category_search_page_list.append(embed)
|
category_search_page_list.append(embed)
|
||||||
|
await asyncio.sleep(0)
|
||||||
cat_menu_output = await menu(ctx, category_search_page_list, category_search_controls)
|
cat_menu_output = await menu(ctx, category_search_page_list, category_search_controls)
|
||||||
if not cat_menu_output:
|
if not cat_menu_output:
|
||||||
return await self._embed_msg(ctx, title=_("No categories selected, try again later."))
|
return await self._embed_msg(ctx, title=_("No categories selected, try again later."))
|
||||||
@ -3147,10 +3188,15 @@ class Audio(commands.Cog):
|
|||||||
playlist=True,
|
playlist=True,
|
||||||
)
|
)
|
||||||
playlists_search_page_list.append(embed)
|
playlists_search_page_list.append(embed)
|
||||||
|
await asyncio.sleep(0)
|
||||||
playlists_pick = await menu(ctx, playlists_search_page_list, playlist_search_controls)
|
playlists_pick = await menu(ctx, playlists_search_page_list, playlist_search_controls)
|
||||||
query = audio_dataclasses.Query.process_input(playlists_pick)
|
query = audio_dataclasses.Query.process_input(playlists_pick)
|
||||||
if not query.valid:
|
if not query.valid:
|
||||||
return await self._embed_msg(ctx, title=_("No tracks to play."))
|
return await self._embed_msg(ctx, title=_("No tracks to play."))
|
||||||
|
if len(player.queue) >= 10000:
|
||||||
|
return await self._embed_msg(
|
||||||
|
ctx, title=_("Unable To Play Tracks"), description=_("Queue size limit reached.")
|
||||||
|
)
|
||||||
if not await self._currency_check(ctx, guild_data["jukebox_price"]):
|
if not await self._currency_check(ctx, guild_data["jukebox_price"]):
|
||||||
return
|
return
|
||||||
if query.is_spotify:
|
if query.is_spotify:
|
||||||
@ -3206,6 +3252,7 @@ class Audio(commands.Cog):
|
|||||||
else:
|
else:
|
||||||
name = f"{list(entry.keys())[0]}"
|
name = f"{list(entry.keys())[0]}"
|
||||||
search_list += "`{}.` {}\n".format(search_track_num, name)
|
search_list += "`{}.` {}\n".format(search_track_num, name)
|
||||||
|
await asyncio.sleep(0)
|
||||||
|
|
||||||
embed = discord.Embed(
|
embed = discord.Embed(
|
||||||
colour=await ctx.embed_colour(), title=title, description=search_list
|
colour=await ctx.embed_colour(), title=title, description=search_list
|
||||||
@ -3278,9 +3325,12 @@ class Audio(commands.Cog):
|
|||||||
title=_("Unable To Play Tracks"),
|
title=_("Unable To Play Tracks"),
|
||||||
description=_("You must be in the voice channel to use the autoplay command."),
|
description=_("You must be in the voice channel to use the autoplay command."),
|
||||||
)
|
)
|
||||||
|
if len(player.queue) >= 10000:
|
||||||
|
return await self._embed_msg(
|
||||||
|
ctx, title=_("Unable To Play Tracks"), description=_("Queue size limit reached.")
|
||||||
|
)
|
||||||
if not await self._currency_check(ctx, guild_data["jukebox_price"]):
|
if not await self._currency_check(ctx, guild_data["jukebox_price"]):
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
await self.music_cache.autoplay(player)
|
await self.music_cache.autoplay(player)
|
||||||
except DatabaseError:
|
except DatabaseError:
|
||||||
@ -3436,6 +3486,7 @@ class Audio(commands.Cog):
|
|||||||
self._play_lock(ctx, True)
|
self._play_lock(ctx, True)
|
||||||
guild_data = await self.config.guild(ctx.guild).all()
|
guild_data = await self.config.guild(ctx.guild).all()
|
||||||
first_track_only = False
|
first_track_only = False
|
||||||
|
single_track = None
|
||||||
index = None
|
index = None
|
||||||
playlist_data = None
|
playlist_data = None
|
||||||
playlist_url = None
|
playlist_url = None
|
||||||
@ -3500,9 +3551,13 @@ class Audio(commands.Cog):
|
|||||||
# this is a Spotify playlist already made into a list of Tracks or a
|
# this is a Spotify playlist already made into a list of Tracks or a
|
||||||
# url where Lavalink handles providing all Track objects to use, like a
|
# url where Lavalink handles providing all Track objects to use, like a
|
||||||
# YouTube or Soundcloud playlist
|
# YouTube or Soundcloud playlist
|
||||||
|
if len(player.queue) >= 10000:
|
||||||
|
return await self._embed_msg(ctx, title=_("Queue size limit reached."))
|
||||||
track_len = 0
|
track_len = 0
|
||||||
empty_queue = not player.queue
|
empty_queue = not player.queue
|
||||||
for track in tracks:
|
for track in tracks:
|
||||||
|
if len(player.queue) >= 10000:
|
||||||
|
continue
|
||||||
if not await is_allowed(
|
if not await is_allowed(
|
||||||
ctx.guild,
|
ctx.guild,
|
||||||
(
|
(
|
||||||
@ -3526,6 +3581,7 @@ class Audio(commands.Cog):
|
|||||||
self.bot.dispatch(
|
self.bot.dispatch(
|
||||||
"red_audio_track_enqueue", player.channel.guild, track, ctx.author
|
"red_audio_track_enqueue", player.channel.guild, track, ctx.author
|
||||||
)
|
)
|
||||||
|
await asyncio.sleep(0)
|
||||||
player.maybe_shuffle(0 if empty_queue else 1)
|
player.maybe_shuffle(0 if empty_queue else 1)
|
||||||
|
|
||||||
if len(tracks) > track_len:
|
if len(tracks) > track_len:
|
||||||
@ -3563,6 +3619,10 @@ class Audio(commands.Cog):
|
|||||||
# this is in the case of [p]play <query>, a single Spotify url/code
|
# this is in the case of [p]play <query>, a single Spotify url/code
|
||||||
# or this is a localtrack item
|
# or this is a localtrack item
|
||||||
try:
|
try:
|
||||||
|
if len(player.queue) >= 10000:
|
||||||
|
|
||||||
|
return await self._embed_msg(ctx, title=_("Queue size limit reached."))
|
||||||
|
|
||||||
single_track = (
|
single_track = (
|
||||||
tracks
|
tracks
|
||||||
if isinstance(tracks, lavalink.rest_api.Track)
|
if isinstance(tracks, lavalink.rest_api.Track)
|
||||||
@ -4013,7 +4073,13 @@ class Audio(commands.Cog):
|
|||||||
ctx, title=_("Could not find a track matching your query.")
|
ctx, title=_("Could not find a track matching your query.")
|
||||||
)
|
)
|
||||||
track_list = playlist.tracks
|
track_list = playlist.tracks
|
||||||
|
current_count = len(track_list)
|
||||||
|
to_append_count = len(to_append)
|
||||||
tracks_obj_list = playlist.tracks_obj
|
tracks_obj_list = playlist.tracks_obj
|
||||||
|
not_added = 0
|
||||||
|
if current_count + to_append_count > 10000:
|
||||||
|
to_append = to_append[: 10000 - current_count]
|
||||||
|
not_added = to_append_count - len(to_append)
|
||||||
to_append_count = len(to_append)
|
to_append_count = len(to_append)
|
||||||
scope_name = humanize_scope(
|
scope_name = humanize_scope(
|
||||||
scope, ctx=guild if scope == PlaylistScope.GUILD.value else author
|
scope, ctx=guild if scope == PlaylistScope.GUILD.value else author
|
||||||
@ -4031,6 +4097,9 @@ class Audio(commands.Cog):
|
|||||||
).format(
|
).format(
|
||||||
track=to.title, playlist=playlist.name, id=playlist.id, scope=scope_name
|
track=to.title, playlist=playlist.name, id=playlist.id, scope=scope_name
|
||||||
),
|
),
|
||||||
|
footer=_("Playlist limit reached: Could not add track.").format(not_added)
|
||||||
|
if not_added > 0
|
||||||
|
else None,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
appended += 1
|
appended += 1
|
||||||
@ -4067,8 +4136,15 @@ class Audio(commands.Cog):
|
|||||||
)
|
)
|
||||||
|
|
||||||
embed = discord.Embed(title=_("Playlist Modified"), description=desc)
|
embed = discord.Embed(title=_("Playlist Modified"), description=desc)
|
||||||
await self._embed_msg(ctx, embed=embed)
|
await self._embed_msg(
|
||||||
|
ctx,
|
||||||
|
embed=embed,
|
||||||
|
footer=_("Playlist limit reached: Could not add track.").format(not_added)
|
||||||
|
if not_added > 0
|
||||||
|
else None,
|
||||||
|
)
|
||||||
|
|
||||||
|
@commands.cooldown(1, 300, commands.BucketType.member)
|
||||||
@playlist.command(name="copy", usage="<id_or_name> [args]")
|
@playlist.command(name="copy", usage="<id_or_name> [args]")
|
||||||
async def _playlist_copy(
|
async def _playlist_copy(
|
||||||
self,
|
self,
|
||||||
@ -4142,9 +4218,11 @@ class Audio(commands.Cog):
|
|||||||
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:
|
||||||
|
ctx.command.reset_cooldown(ctx)
|
||||||
return await self._embed_msg(ctx, title=str(e))
|
return await self._embed_msg(ctx, title=str(e))
|
||||||
|
|
||||||
if playlist_id is None:
|
if playlist_id is None:
|
||||||
|
ctx.command.reset_cooldown(ctx)
|
||||||
return await self._embed_msg(
|
return await self._embed_msg(
|
||||||
ctx,
|
ctx,
|
||||||
title=_("Playlist Not Found"),
|
title=_("Playlist Not Found"),
|
||||||
@ -4153,6 +4231,7 @@ class Audio(commands.Cog):
|
|||||||
|
|
||||||
temp_playlist = FakePlaylist(to_author.id, to_scope)
|
temp_playlist = FakePlaylist(to_author.id, to_scope)
|
||||||
if not await self.can_manage_playlist(to_scope, temp_playlist, ctx, to_author, to_guild):
|
if not await self.can_manage_playlist(to_scope, temp_playlist, ctx, to_author, to_guild):
|
||||||
|
ctx.command.reset_cooldown(ctx)
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -4160,6 +4239,7 @@ class Audio(commands.Cog):
|
|||||||
playlist_id, from_scope, self.bot, from_guild, from_author.id
|
playlist_id, from_scope, self.bot, from_guild, from_author.id
|
||||||
)
|
)
|
||||||
except RuntimeError:
|
except RuntimeError:
|
||||||
|
ctx.command.reset_cooldown(ctx)
|
||||||
return await self._embed_msg(
|
return await self._embed_msg(
|
||||||
ctx,
|
ctx,
|
||||||
title=_("Playlist Not Found"),
|
title=_("Playlist Not Found"),
|
||||||
@ -4168,6 +4248,7 @@ class Audio(commands.Cog):
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
except MissingGuild:
|
except MissingGuild:
|
||||||
|
ctx.command.reset_cooldown(ctx)
|
||||||
return await self._embed_msg(
|
return await self._embed_msg(
|
||||||
ctx, title=_("You need to specify the Guild ID for the guild to lookup.")
|
ctx, title=_("You need to specify the Guild ID for the guild to lookup.")
|
||||||
)
|
)
|
||||||
@ -4356,6 +4437,7 @@ class Audio(commands.Cog):
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@commands.cooldown(1, 30, commands.BucketType.member)
|
||||||
@playlist.command(name="dedupe", usage="<playlist_name_OR_id> [args]")
|
@playlist.command(name="dedupe", usage="<playlist_name_OR_id> [args]")
|
||||||
async def _playlist_remdupe(
|
async def _playlist_remdupe(
|
||||||
self,
|
self,
|
||||||
@ -4407,8 +4489,10 @@ class Audio(commands.Cog):
|
|||||||
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)
|
||||||
return await self._embed_msg(ctx, title=str(e))
|
return await self._embed_msg(ctx, title=str(e))
|
||||||
if playlist_id is None:
|
if playlist_id is None:
|
||||||
|
ctx.command.reset_cooldown(ctx)
|
||||||
return await self._embed_msg(
|
return await self._embed_msg(
|
||||||
ctx,
|
ctx,
|
||||||
title=_("Playlist Not Found"),
|
title=_("Playlist Not Found"),
|
||||||
@ -4420,6 +4504,7 @@ class Audio(commands.Cog):
|
|||||||
try:
|
try:
|
||||||
playlist = await get_playlist(playlist_id, scope, self.bot, guild, author)
|
playlist = await get_playlist(playlist_id, scope, self.bot, guild, author)
|
||||||
except RuntimeError:
|
except RuntimeError:
|
||||||
|
ctx.command.reset_cooldown(ctx)
|
||||||
return await self._embed_msg(
|
return await self._embed_msg(
|
||||||
ctx,
|
ctx,
|
||||||
title=_("Playlist Not Found"),
|
title=_("Playlist Not Found"),
|
||||||
@ -4428,12 +4513,14 @@ class Audio(commands.Cog):
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
except MissingGuild:
|
except MissingGuild:
|
||||||
|
ctx.command.reset_cooldown(ctx)
|
||||||
return await self._embed_msg(
|
return await self._embed_msg(
|
||||||
ctx,
|
ctx,
|
||||||
title=_("Missing Arguments"),
|
title=_("Missing Arguments"),
|
||||||
description=_("You need to specify the Guild ID for the guild to lookup."),
|
description=_("You need to specify the Guild ID for the guild to lookup."),
|
||||||
)
|
)
|
||||||
if not await self.can_manage_playlist(scope, playlist, ctx, author, guild):
|
if not await self.can_manage_playlist(scope, playlist, ctx, author, guild):
|
||||||
|
ctx.command.reset_cooldown(ctx)
|
||||||
return
|
return
|
||||||
|
|
||||||
track_objects = playlist.tracks_obj
|
track_objects = playlist.tracks_obj
|
||||||
@ -4538,8 +4625,10 @@ class Audio(commands.Cog):
|
|||||||
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)
|
||||||
return await self._embed_msg(ctx, title=str(e))
|
return await self._embed_msg(ctx, title=str(e))
|
||||||
if playlist_id is None:
|
if playlist_id is None:
|
||||||
|
ctx.command.reset_cooldown(ctx)
|
||||||
return await self._embed_msg(
|
return await self._embed_msg(
|
||||||
ctx,
|
ctx,
|
||||||
title=_("Playlist Not Found"),
|
title=_("Playlist Not Found"),
|
||||||
@ -4549,6 +4638,7 @@ class Audio(commands.Cog):
|
|||||||
try:
|
try:
|
||||||
playlist = await get_playlist(playlist_id, scope, self.bot, guild, author)
|
playlist = await get_playlist(playlist_id, scope, self.bot, guild, author)
|
||||||
except RuntimeError:
|
except RuntimeError:
|
||||||
|
ctx.command.reset_cooldown(ctx)
|
||||||
return await self._embed_msg(
|
return await self._embed_msg(
|
||||||
ctx,
|
ctx,
|
||||||
title=_("Playlist Not Found"),
|
title=_("Playlist Not Found"),
|
||||||
@ -4557,6 +4647,7 @@ class Audio(commands.Cog):
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
except MissingGuild:
|
except MissingGuild:
|
||||||
|
ctx.command.reset_cooldown(ctx)
|
||||||
return await self._embed_msg(
|
return await self._embed_msg(
|
||||||
ctx,
|
ctx,
|
||||||
title=_("Missing Arguments"),
|
title=_("Missing Arguments"),
|
||||||
@ -4567,6 +4658,7 @@ class Audio(commands.Cog):
|
|||||||
version = "v3" if v2 is False else "v2"
|
version = "v3" if v2 is False else "v2"
|
||||||
|
|
||||||
if not playlist.tracks:
|
if not playlist.tracks:
|
||||||
|
ctx.command.reset_cooldown(ctx)
|
||||||
return await self._embed_msg(ctx, title=_("That playlist has no tracks."))
|
return await self._embed_msg(ctx, title=_("That playlist has no tracks."))
|
||||||
if version == "v2":
|
if version == "v2":
|
||||||
v2_valid_urls = ["https://www.youtube.com/watch?v=", "https://soundcloud.com/"]
|
v2_valid_urls = ["https://www.youtube.com/watch?v=", "https://soundcloud.com/"]
|
||||||
@ -4574,6 +4666,7 @@ class Audio(commands.Cog):
|
|||||||
for track in playlist.tracks:
|
for track in playlist.tracks:
|
||||||
if track["info"]["uri"].startswith(tuple(v2_valid_urls)):
|
if track["info"]["uri"].startswith(tuple(v2_valid_urls)):
|
||||||
song_list.append(track["info"]["uri"])
|
song_list.append(track["info"]["uri"])
|
||||||
|
await asyncio.sleep(0)
|
||||||
playlist_data = {
|
playlist_data = {
|
||||||
"author": playlist.author,
|
"author": playlist.author,
|
||||||
"link": playlist.url,
|
"link": playlist.url,
|
||||||
@ -4622,6 +4715,7 @@ class Audio(commands.Cog):
|
|||||||
await ctx.send(file=discord.File(to_write, filename=f"{file_name}.txt"))
|
await ctx.send(file=discord.File(to_write, filename=f"{file_name}.txt"))
|
||||||
to_write.close()
|
to_write.close()
|
||||||
|
|
||||||
|
@commands.cooldown(1, 20, commands.BucketType.member)
|
||||||
@playlist.command(name="info", usage="<playlist_name_OR_id> [args]")
|
@playlist.command(name="info", usage="<playlist_name_OR_id> [args]")
|
||||||
async def _playlist_info(
|
async def _playlist_info(
|
||||||
self,
|
self,
|
||||||
@ -4672,8 +4766,10 @@ class Audio(commands.Cog):
|
|||||||
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)
|
||||||
return await self._embed_msg(ctx, title=str(e))
|
return await self._embed_msg(ctx, title=str(e))
|
||||||
if playlist_id is None:
|
if playlist_id is None:
|
||||||
|
ctx.command.reset_cooldown(ctx)
|
||||||
return await self._embed_msg(
|
return await self._embed_msg(
|
||||||
ctx,
|
ctx,
|
||||||
title=_("Playlist Not Found"),
|
title=_("Playlist Not Found"),
|
||||||
@ -4683,6 +4779,7 @@ class Audio(commands.Cog):
|
|||||||
try:
|
try:
|
||||||
playlist = await get_playlist(playlist_id, scope, self.bot, guild, author)
|
playlist = await get_playlist(playlist_id, scope, self.bot, guild, author)
|
||||||
except RuntimeError:
|
except RuntimeError:
|
||||||
|
ctx.command.reset_cooldown(ctx)
|
||||||
return await self._embed_msg(
|
return await self._embed_msg(
|
||||||
ctx,
|
ctx,
|
||||||
title=_("Playlist Not Found"),
|
title=_("Playlist Not Found"),
|
||||||
@ -4691,6 +4788,7 @@ class Audio(commands.Cog):
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
except MissingGuild:
|
except MissingGuild:
|
||||||
|
ctx.command.reset_cooldown(ctx)
|
||||||
return await self._embed_msg(
|
return await self._embed_msg(
|
||||||
ctx,
|
ctx,
|
||||||
title=_("Missing Arguments"),
|
title=_("Missing Arguments"),
|
||||||
@ -4722,6 +4820,7 @@ class Audio(commands.Cog):
|
|||||||
msg += "`{}.` **[{}]({})**\n".format(
|
msg += "`{}.` **[{}]({})**\n".format(
|
||||||
track_idx, track["info"]["title"], track["info"]["uri"]
|
track_idx, track["info"]["title"], track["info"]["uri"]
|
||||||
)
|
)
|
||||||
|
await asyncio.sleep(0)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
msg = "No tracks."
|
msg = "No tracks."
|
||||||
@ -4753,6 +4852,7 @@ class Audio(commands.Cog):
|
|||||||
page_list.append(embed)
|
page_list.append(embed)
|
||||||
await menu(ctx, page_list, DEFAULT_CONTROLS)
|
await menu(ctx, page_list, DEFAULT_CONTROLS)
|
||||||
|
|
||||||
|
@commands.cooldown(1, 30, commands.BucketType.guild)
|
||||||
@playlist.command(name="list", usage="[args]")
|
@playlist.command(name="list", usage="[args]")
|
||||||
@commands.bot_has_permissions(add_reactions=True)
|
@commands.bot_has_permissions(add_reactions=True)
|
||||||
async def _playlist_list(self, ctx: commands.Context, *, scope_data: ScopeParser = None):
|
async def _playlist_list(self, ctx: commands.Context, *, scope_data: ScopeParser = None):
|
||||||
@ -4793,6 +4893,7 @@ class Audio(commands.Cog):
|
|||||||
try:
|
try:
|
||||||
playlists = await get_all_playlist(scope, self.bot, guild, author, specified_user)
|
playlists = await get_all_playlist(scope, self.bot, guild, author, specified_user)
|
||||||
except MissingGuild:
|
except MissingGuild:
|
||||||
|
ctx.command.reset_cooldown(ctx)
|
||||||
return await self._embed_msg(
|
return await self._embed_msg(
|
||||||
ctx,
|
ctx,
|
||||||
title=_("Missing Arguments"),
|
title=_("Missing Arguments"),
|
||||||
@ -4807,6 +4908,7 @@ class Audio(commands.Cog):
|
|||||||
name = "Global"
|
name = "Global"
|
||||||
|
|
||||||
if not playlists and specified_user:
|
if not playlists and specified_user:
|
||||||
|
ctx.command.reset_cooldown(ctx)
|
||||||
return await self._embed_msg(
|
return await self._embed_msg(
|
||||||
ctx,
|
ctx,
|
||||||
title=_("Playlist Not Found"),
|
title=_("Playlist Not Found"),
|
||||||
@ -4815,6 +4917,7 @@ class Audio(commands.Cog):
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
elif not playlists:
|
elif not playlists:
|
||||||
|
ctx.command.reset_cooldown(ctx)
|
||||||
return await self._embed_msg(
|
return await self._embed_msg(
|
||||||
ctx,
|
ctx,
|
||||||
title=_("Playlist Not Found"),
|
title=_("Playlist Not Found"),
|
||||||
@ -4838,6 +4941,7 @@ class Audio(commands.Cog):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
await asyncio.sleep(0)
|
||||||
abc_names = sorted(playlist_list, key=str.lower)
|
abc_names = sorted(playlist_list, key=str.lower)
|
||||||
len_playlist_list_pages = math.ceil(len(abc_names) / 5)
|
len_playlist_list_pages = math.ceil(len(abc_names) / 5)
|
||||||
playlist_embeds = []
|
playlist_embeds = []
|
||||||
@ -4845,6 +4949,7 @@ class Audio(commands.Cog):
|
|||||||
for page_num in range(1, len_playlist_list_pages + 1):
|
for page_num in range(1, len_playlist_list_pages + 1):
|
||||||
embed = await self._build_playlist_list_page(ctx, page_num, abc_names, name)
|
embed = await self._build_playlist_list_page(ctx, page_num, abc_names, name)
|
||||||
playlist_embeds.append(embed)
|
playlist_embeds.append(embed)
|
||||||
|
await asyncio.sleep(0)
|
||||||
await menu(ctx, playlist_embeds, DEFAULT_CONTROLS)
|
await menu(ctx, playlist_embeds, DEFAULT_CONTROLS)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@ -4858,6 +4963,7 @@ class Audio(commands.Cog):
|
|||||||
):
|
):
|
||||||
item_idx = i + 1
|
item_idx = i + 1
|
||||||
plist += "`{}.` {}".format(item_idx, playlist_info)
|
plist += "`{}.` {}".format(item_idx, playlist_info)
|
||||||
|
await asyncio.sleep(0)
|
||||||
embed = discord.Embed(
|
embed = discord.Embed(
|
||||||
colour=await ctx.embed_colour(),
|
colour=await ctx.embed_colour(),
|
||||||
title=_("Playlists for {scope}:").format(scope=scope),
|
title=_("Playlists for {scope}:").format(scope=scope),
|
||||||
@ -4871,7 +4977,7 @@ class Audio(commands.Cog):
|
|||||||
return embed
|
return embed
|
||||||
|
|
||||||
@playlist.command(name="queue", usage="<name> [args]")
|
@playlist.command(name="queue", usage="<name> [args]")
|
||||||
@commands.cooldown(1, 15, commands.BucketType.guild)
|
@commands.cooldown(1, 600, commands.BucketType.member)
|
||||||
async def _playlist_queue(
|
async def _playlist_queue(
|
||||||
self, ctx: commands.Context, playlist_name: str, *, scope_data: ScopeParser = None
|
self, ctx: commands.Context, playlist_name: str, *, scope_data: ScopeParser = None
|
||||||
):
|
):
|
||||||
@ -4938,16 +5044,23 @@ class Audio(commands.Cog):
|
|||||||
tracklist = []
|
tracklist = []
|
||||||
np_song = track_creator(player, "np")
|
np_song = track_creator(player, "np")
|
||||||
tracklist.append(np_song)
|
tracklist.append(np_song)
|
||||||
for i, track in enumerate(player.queue, start=1):
|
queue_length = len(player.queue)
|
||||||
|
to_add = player.queue
|
||||||
|
not_added = 0
|
||||||
|
if queue_length > 10000:
|
||||||
|
to_add = player.queue[:10000]
|
||||||
|
not_added = queue_length - 10000
|
||||||
|
|
||||||
|
for i, track in enumerate(to_add, start=1):
|
||||||
if i % 500 == 0: # TODO: Improve when Toby menu's are merged
|
if i % 500 == 0: # TODO: Improve when Toby menu's are merged
|
||||||
await asyncio.sleep(0.02)
|
await asyncio.sleep(0.02)
|
||||||
queue_idx = player.queue.index(track)
|
queue_idx = player.queue.index(track)
|
||||||
track_obj = track_creator(player, queue_idx)
|
track_obj = track_creator(player, queue_idx)
|
||||||
tracklist.append(track_obj)
|
tracklist.append(track_obj)
|
||||||
|
|
||||||
playlist = await create_playlist(
|
playlist = await create_playlist(
|
||||||
ctx, scope, playlist_name, None, tracklist, author, guild
|
ctx, scope, playlist_name, None, tracklist, author, guild
|
||||||
)
|
)
|
||||||
|
await asyncio.sleep(0)
|
||||||
await self._embed_msg(
|
await self._embed_msg(
|
||||||
ctx,
|
ctx,
|
||||||
title=_("Playlist Created"),
|
title=_("Playlist Created"),
|
||||||
@ -4957,6 +5070,9 @@ class Audio(commands.Cog):
|
|||||||
).format(
|
).format(
|
||||||
name=playlist.name, num=len(playlist.tracks), id=playlist.id, scope=scope_name
|
name=playlist.name, num=len(playlist.tracks), id=playlist.id, scope=scope_name
|
||||||
),
|
),
|
||||||
|
footer=_("Playlist limit reached: Could not add {} tracks.").format(not_added)
|
||||||
|
if not_added > 0
|
||||||
|
else None,
|
||||||
)
|
)
|
||||||
|
|
||||||
@playlist.command(name="remove", usage="<playlist_name_OR_id> <url> [args]")
|
@playlist.command(name="remove", usage="<playlist_name_OR_id> <url> [args]")
|
||||||
@ -5073,7 +5189,7 @@ class Audio(commands.Cog):
|
|||||||
)
|
)
|
||||||
|
|
||||||
@playlist.command(name="save", usage="<name> <url> [args]")
|
@playlist.command(name="save", usage="<name> <url> [args]")
|
||||||
@commands.cooldown(1, 15, commands.BucketType.guild)
|
@commands.cooldown(1, 120, commands.BucketType.member)
|
||||||
async def _playlist_save(
|
async def _playlist_save(
|
||||||
self,
|
self,
|
||||||
ctx: commands.Context,
|
ctx: commands.Context,
|
||||||
@ -5146,6 +5262,12 @@ class Audio(commands.Cog):
|
|||||||
if isinstance(tracklist, discord.Message):
|
if isinstance(tracklist, discord.Message):
|
||||||
return None
|
return None
|
||||||
if tracklist is not None:
|
if tracklist is not None:
|
||||||
|
playlist_length = len(tracklist)
|
||||||
|
not_added = 0
|
||||||
|
if playlist_length > 10000:
|
||||||
|
tracklist = tracklist[:10000]
|
||||||
|
not_added = playlist_length - 10000
|
||||||
|
|
||||||
playlist = await create_playlist(
|
playlist = await create_playlist(
|
||||||
ctx, scope, playlist_name, playlist_url, tracklist, author, guild
|
ctx, scope, playlist_name, playlist_url, tracklist, author, guild
|
||||||
)
|
)
|
||||||
@ -5155,8 +5277,12 @@ class Audio(commands.Cog):
|
|||||||
description=_(
|
description=_(
|
||||||
"Playlist {name} (`{id}`) [**{scope}**] saved: {num} tracks added."
|
"Playlist {name} (`{id}`) [**{scope}**] saved: {num} tracks added."
|
||||||
).format(name=playlist.name, num=len(tracklist), id=playlist.id, scope=scope_name),
|
).format(name=playlist.name, num=len(tracklist), id=playlist.id, scope=scope_name),
|
||||||
|
footer=_("Playlist limit reached: Could not add {} tracks.").format(not_added)
|
||||||
|
if not_added > 0
|
||||||
|
else None,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@commands.cooldown(1, 60, commands.BucketType.member)
|
||||||
@playlist.command(name="start", aliases=["play"], usage="<playlist_name_OR_id> [args]")
|
@playlist.command(name="start", aliases=["play"], usage="<playlist_name_OR_id> [args]")
|
||||||
async def _playlist_start(
|
async def _playlist_start(
|
||||||
self,
|
self,
|
||||||
@ -5203,6 +5329,7 @@ class Audio(commands.Cog):
|
|||||||
)
|
)
|
||||||
if dj_enabled:
|
if dj_enabled:
|
||||||
if not await self._can_instaskip(ctx, ctx.author):
|
if not await self._can_instaskip(ctx, ctx.author):
|
||||||
|
ctx.command.reset_cooldown(ctx)
|
||||||
await self._embed_msg(
|
await self._embed_msg(
|
||||||
ctx,
|
ctx,
|
||||||
title=_("Unable To Play Tracks"),
|
title=_("Unable To Play Tracks"),
|
||||||
@ -5215,8 +5342,10 @@ class Audio(commands.Cog):
|
|||||||
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)
|
||||||
return await self._embed_msg(ctx, title=str(e))
|
return await self._embed_msg(ctx, title=str(e))
|
||||||
if playlist_id is None:
|
if playlist_id is None:
|
||||||
|
ctx.command.reset_cooldown(ctx)
|
||||||
return await self._embed_msg(
|
return await self._embed_msg(
|
||||||
ctx,
|
ctx,
|
||||||
title=_("Playlist Not Found"),
|
title=_("Playlist Not Found"),
|
||||||
@ -5224,9 +5353,11 @@ class Audio(commands.Cog):
|
|||||||
)
|
)
|
||||||
|
|
||||||
if not await self._playlist_check(ctx):
|
if not await self._playlist_check(ctx):
|
||||||
|
ctx.command.reset_cooldown(ctx)
|
||||||
return
|
return
|
||||||
jukebox_price = await self.config.guild(ctx.guild).jukebox_price()
|
jukebox_price = await self.config.guild(ctx.guild).jukebox_price()
|
||||||
if not await self._currency_check(ctx, jukebox_price):
|
if not await self._currency_check(ctx, jukebox_price):
|
||||||
|
ctx.command.reset_cooldown(ctx)
|
||||||
return
|
return
|
||||||
maxlength = await self.config.guild(ctx.guild).maxlength()
|
maxlength = await self.config.guild(ctx.guild).maxlength()
|
||||||
author_obj = self.bot.get_user(ctx.author.id)
|
author_obj = self.bot.get_user(ctx.author.id)
|
||||||
@ -5240,6 +5371,8 @@ class Audio(commands.Cog):
|
|||||||
for i, track in enumerate(tracks, start=1):
|
for i, track in enumerate(tracks, start=1):
|
||||||
if i % 500 == 0: # TODO: Improve when Toby menu's are merged
|
if i % 500 == 0: # TODO: Improve when Toby menu's are merged
|
||||||
await asyncio.sleep(0.02)
|
await asyncio.sleep(0.02)
|
||||||
|
if len(player.queue) >= 10000:
|
||||||
|
continue
|
||||||
if not await is_allowed(
|
if not await is_allowed(
|
||||||
ctx.guild,
|
ctx.guild,
|
||||||
(
|
(
|
||||||
@ -5265,6 +5398,7 @@ class Audio(commands.Cog):
|
|||||||
"red_audio_track_enqueue", player.channel.guild, track, ctx.author
|
"red_audio_track_enqueue", player.channel.guild, track, ctx.author
|
||||||
)
|
)
|
||||||
track_len += 1
|
track_len += 1
|
||||||
|
await asyncio.sleep(0)
|
||||||
player.maybe_shuffle(0 if empty_queue else 1)
|
player.maybe_shuffle(0 if empty_queue else 1)
|
||||||
if len(tracks) > track_len:
|
if len(tracks) > track_len:
|
||||||
maxlength_msg = " {bad_tracks} tracks cannot be queued.".format(
|
maxlength_msg = " {bad_tracks} tracks cannot be queued.".format(
|
||||||
@ -5297,6 +5431,7 @@ class Audio(commands.Cog):
|
|||||||
await player.play()
|
await player.play()
|
||||||
return
|
return
|
||||||
except RuntimeError:
|
except RuntimeError:
|
||||||
|
ctx.command.reset_cooldown(ctx)
|
||||||
return await self._embed_msg(
|
return await self._embed_msg(
|
||||||
ctx,
|
ctx,
|
||||||
title=_("Playlist Not Found"),
|
title=_("Playlist Not Found"),
|
||||||
@ -5305,6 +5440,7 @@ class Audio(commands.Cog):
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
except MissingGuild:
|
except MissingGuild:
|
||||||
|
ctx.command.reset_cooldown(ctx)
|
||||||
return await self._embed_msg(
|
return await self._embed_msg(
|
||||||
ctx,
|
ctx,
|
||||||
title=_("Missing Arguments"),
|
title=_("Missing Arguments"),
|
||||||
@ -5314,6 +5450,7 @@ class Audio(commands.Cog):
|
|||||||
if playlist:
|
if playlist:
|
||||||
return await ctx.invoke(self.play, query=playlist.url)
|
return await ctx.invoke(self.play, query=playlist.url)
|
||||||
|
|
||||||
|
@commands.cooldown(1, 60, commands.BucketType.member)
|
||||||
@playlist.command(name="update", usage="<playlist_name_OR_id> [args]")
|
@playlist.command(name="update", usage="<playlist_name_OR_id> [args]")
|
||||||
async def _playlist_update(
|
async def _playlist_update(
|
||||||
self,
|
self,
|
||||||
@ -5361,9 +5498,11 @@ class Audio(commands.Cog):
|
|||||||
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)
|
||||||
return await self._embed_msg(ctx, title=str(e))
|
return await self._embed_msg(ctx, title=str(e))
|
||||||
|
|
||||||
if playlist_id is None:
|
if playlist_id is None:
|
||||||
|
ctx.command.reset_cooldown(ctx)
|
||||||
return await self._embed_msg(
|
return await self._embed_msg(
|
||||||
ctx,
|
ctx,
|
||||||
title=_("Playlist Not Found"),
|
title=_("Playlist Not Found"),
|
||||||
@ -5371,6 +5510,7 @@ class Audio(commands.Cog):
|
|||||||
)
|
)
|
||||||
|
|
||||||
if not await self._playlist_check(ctx):
|
if not await self._playlist_check(ctx):
|
||||||
|
ctx.command.reset_cooldown(ctx)
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
playlist = await get_playlist(playlist_id, scope, self.bot, guild, author)
|
playlist = await get_playlist(playlist_id, scope, self.bot, guild, author)
|
||||||
@ -5380,12 +5520,14 @@ class Audio(commands.Cog):
|
|||||||
player = lavalink.get_player(ctx.guild.id)
|
player = lavalink.get_player(ctx.guild.id)
|
||||||
added, removed, playlist = await self._maybe_update_playlist(ctx, player, playlist)
|
added, removed, playlist = await self._maybe_update_playlist(ctx, player, playlist)
|
||||||
else:
|
else:
|
||||||
|
ctx.command.reset_cooldown(ctx)
|
||||||
return await self._embed_msg(
|
return await self._embed_msg(
|
||||||
ctx,
|
ctx,
|
||||||
title=_("Invalid Playlist"),
|
title=_("Invalid Playlist"),
|
||||||
description=_("Custom playlists cannot be updated."),
|
description=_("Custom playlists cannot be updated."),
|
||||||
)
|
)
|
||||||
except RuntimeError:
|
except RuntimeError:
|
||||||
|
ctx.command.reset_cooldown(ctx)
|
||||||
return await self._embed_msg(
|
return await self._embed_msg(
|
||||||
ctx,
|
ctx,
|
||||||
title=_("Playlist Not Found"),
|
title=_("Playlist Not Found"),
|
||||||
@ -5544,7 +5686,8 @@ class Audio(commands.Cog):
|
|||||||
else:
|
else:
|
||||||
uploaded_playlist_url = uploaded_playlist.get("link", None)
|
uploaded_playlist_url = uploaded_playlist.get("link", None)
|
||||||
track_list = uploaded_playlist.get("playlist", [])
|
track_list = uploaded_playlist.get("playlist", [])
|
||||||
|
if len(track_list) > 10000:
|
||||||
|
return await self._embed_msg(ctx, title=_("This playlist is too large."))
|
||||||
uploaded_playlist_name = uploaded_playlist.get(
|
uploaded_playlist_name = uploaded_playlist.get(
|
||||||
"name", (file_url.split("/")[6]).split(".")[0]
|
"name", (file_url.split("/")[6]).split(".")[0]
|
||||||
)
|
)
|
||||||
@ -5584,6 +5727,7 @@ class Audio(commands.Cog):
|
|||||||
scope_data=(scope, author, guild, specified_user),
|
scope_data=(scope, author, guild, specified_user),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@commands.cooldown(1, 60, commands.BucketType.member)
|
||||||
@playlist.command(name="rename", usage="<playlist_name_OR_id> <new_name> [args]")
|
@playlist.command(name="rename", usage="<playlist_name_OR_id> <new_name> [args]")
|
||||||
async def _playlist_rename(
|
async def _playlist_rename(
|
||||||
self,
|
self,
|
||||||
@ -5629,6 +5773,7 @@ class Audio(commands.Cog):
|
|||||||
|
|
||||||
new_name = new_name.split(" ")[0].strip('"')[:32]
|
new_name = new_name.split(" ")[0].strip('"')[:32]
|
||||||
if new_name.isnumeric():
|
if new_name.isnumeric():
|
||||||
|
ctx.command.reset_cooldown(ctx)
|
||||||
return await self._embed_msg(
|
return await self._embed_msg(
|
||||||
ctx,
|
ctx,
|
||||||
title=_("Invalid Playlist Name"),
|
title=_("Invalid Playlist Name"),
|
||||||
@ -5643,8 +5788,10 @@ class Audio(commands.Cog):
|
|||||||
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)
|
||||||
return await self._embed_msg(ctx, title=str(e))
|
return await self._embed_msg(ctx, title=str(e))
|
||||||
if playlist_id is None:
|
if playlist_id is None:
|
||||||
|
ctx.command.reset_cooldown(ctx)
|
||||||
return await self._embed_msg(
|
return await self._embed_msg(
|
||||||
ctx,
|
ctx,
|
||||||
title=_("Playlist Not Found"),
|
title=_("Playlist Not Found"),
|
||||||
@ -5654,6 +5801,7 @@ class Audio(commands.Cog):
|
|||||||
try:
|
try:
|
||||||
playlist = await get_playlist(playlist_id, scope, self.bot, guild, author)
|
playlist = await get_playlist(playlist_id, scope, self.bot, guild, author)
|
||||||
except RuntimeError:
|
except RuntimeError:
|
||||||
|
ctx.command.reset_cooldown(ctx)
|
||||||
return await self._embed_msg(
|
return await self._embed_msg(
|
||||||
ctx,
|
ctx,
|
||||||
title=_("Playlist Not Found"),
|
title=_("Playlist Not Found"),
|
||||||
@ -5662,6 +5810,7 @@ class Audio(commands.Cog):
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
except MissingGuild:
|
except MissingGuild:
|
||||||
|
ctx.command.reset_cooldown(ctx)
|
||||||
return await self._embed_msg(
|
return await self._embed_msg(
|
||||||
ctx,
|
ctx,
|
||||||
title=_("Missing Arguments"),
|
title=_("Missing Arguments"),
|
||||||
@ -5669,6 +5818,7 @@ class Audio(commands.Cog):
|
|||||||
)
|
)
|
||||||
|
|
||||||
if not await self.can_manage_playlist(scope, playlist, ctx, author, guild):
|
if not await self.can_manage_playlist(scope, playlist, ctx, author, guild):
|
||||||
|
ctx.command.reset_cooldown(ctx)
|
||||||
return
|
return
|
||||||
scope_name = humanize_scope(
|
scope_name = humanize_scope(
|
||||||
scope, ctx=guild if scope == PlaylistScope.GUILD.value else author
|
scope, ctx=guild if scope == PlaylistScope.GUILD.value else author
|
||||||
@ -5940,6 +6090,7 @@ class Audio(commands.Cog):
|
|||||||
for track in tracks:
|
for track in tracks:
|
||||||
track_obj = track_creator(player, other_track=track)
|
track_obj = track_creator(player, other_track=track)
|
||||||
tracklist.append(track_obj)
|
tracklist.append(track_obj)
|
||||||
|
await asyncio.sleep(0)
|
||||||
self._play_lock(ctx, False)
|
self._play_lock(ctx, False)
|
||||||
elif query.is_search:
|
elif query.is_search:
|
||||||
try:
|
try:
|
||||||
@ -5988,6 +6139,7 @@ class Audio(commands.Cog):
|
|||||||
for track in tracks:
|
for track in tracks:
|
||||||
track_obj = track_creator(player, other_track=track)
|
track_obj = track_creator(player, other_track=track)
|
||||||
tracklist.append(track_obj)
|
tracklist.append(track_obj)
|
||||||
|
await asyncio.sleep(0)
|
||||||
elif len(tracklist) == 0:
|
elif len(tracklist) == 0:
|
||||||
track_obj = track_creator(player, other_track=tracks[0])
|
track_obj = track_creator(player, other_track=tracks[0])
|
||||||
tracklist.append(track_obj)
|
tracklist.append(track_obj)
|
||||||
@ -6080,8 +6232,8 @@ class Audio(commands.Cog):
|
|||||||
if not self._player_check(ctx):
|
if not self._player_check(ctx):
|
||||||
return await self._embed_msg(ctx, title=_("There's nothing in the queue."))
|
return await self._embed_msg(ctx, title=_("There's nothing in the queue."))
|
||||||
player = lavalink.get_player(ctx.guild.id)
|
player = lavalink.get_player(ctx.guild.id)
|
||||||
if not player.queue:
|
|
||||||
if player.current:
|
if player.current and not player.queue:
|
||||||
arrow = await draw_time(ctx)
|
arrow = await draw_time(ctx)
|
||||||
pos = lavalink.utils.format_time(player.position)
|
pos = lavalink.utils.format_time(player.position)
|
||||||
if player.current.is_stream:
|
if player.current.is_stream:
|
||||||
@ -6157,6 +6309,7 @@ class Audio(commands.Cog):
|
|||||||
await self._clear_react(message, emoji)
|
await self._clear_react(message, emoji)
|
||||||
return await ctx.invoke(self.pause)
|
return await ctx.invoke(self.pause)
|
||||||
return
|
return
|
||||||
|
elif not player.current and not player.queue:
|
||||||
return await self._embed_msg(ctx, title=_("There's nothing in the queue."))
|
return await self._embed_msg(ctx, title=_("There's nothing in the queue."))
|
||||||
|
|
||||||
async with ctx.typing():
|
async with ctx.typing():
|
||||||
@ -6166,6 +6319,7 @@ class Audio(commands.Cog):
|
|||||||
for page_num in range(1, len_queue_pages + 1):
|
for page_num in range(1, len_queue_pages + 1):
|
||||||
embed = await self._build_queue_page(ctx, limited_queue, player, page_num)
|
embed = await self._build_queue_page(ctx, limited_queue, player, page_num)
|
||||||
queue_page_list.append(embed)
|
queue_page_list.append(embed)
|
||||||
|
await asyncio.sleep(0)
|
||||||
if page > len_queue_pages:
|
if page > len_queue_pages:
|
||||||
page = len_queue_pages
|
page = len_queue_pages
|
||||||
return await menu(ctx, queue_page_list, queue_controls, page=(page - 1))
|
return await menu(ctx, queue_page_list, queue_controls, page=(page - 1))
|
||||||
@ -6258,6 +6412,7 @@ class Audio(commands.Cog):
|
|||||||
else:
|
else:
|
||||||
queue_list += f"`{track_idx}.` **[{track_title}]({track.uri})**, "
|
queue_list += f"`{track_idx}.` **[{track_title}]({track.uri})**, "
|
||||||
queue_list += _("requested by **{user}**\n").format(user=req_user)
|
queue_list += _("requested by **{user}**\n").format(user=req_user)
|
||||||
|
await asyncio.sleep(0)
|
||||||
|
|
||||||
embed = discord.Embed(
|
embed = discord.Embed(
|
||||||
colour=await ctx.embed_colour(),
|
colour=await ctx.embed_colour(),
|
||||||
@ -6273,7 +6428,7 @@ class Audio(commands.Cog):
|
|||||||
).format(
|
).format(
|
||||||
page_num=humanize_number(page_num),
|
page_num=humanize_number(page_num),
|
||||||
total_pages=humanize_number(queue_num_pages),
|
total_pages=humanize_number(queue_num_pages),
|
||||||
num_tracks=len(player.queue) + 1,
|
num_tracks=len(player.queue),
|
||||||
num_remaining=queue_total_duration,
|
num_remaining=queue_total_duration,
|
||||||
)
|
)
|
||||||
text += (
|
text += (
|
||||||
@ -6315,6 +6470,7 @@ class Audio(commands.Cog):
|
|||||||
|
|
||||||
song_info = {str(queue_idx): track_title}
|
song_info = {str(queue_idx): track_title}
|
||||||
track_list.append(song_info)
|
track_list.append(song_info)
|
||||||
|
await asyncio.sleep(0)
|
||||||
search_results = process.extract(search_words, track_list, limit=50)
|
search_results = process.extract(search_words, track_list, limit=50)
|
||||||
search_list = []
|
search_list = []
|
||||||
for search, percent_match in search_results:
|
for search, percent_match in search_results:
|
||||||
@ -6340,6 +6496,7 @@ class Audio(commands.Cog):
|
|||||||
track_match += "`{}.` **{}**\n".format(track_idx, track_location)
|
track_match += "`{}.` **{}**\n".format(track_idx, track_location)
|
||||||
else:
|
else:
|
||||||
track_match += "`{}.` **{}**\n".format(track[0], track[1])
|
track_match += "`{}.` **{}**\n".format(track[0], track[1])
|
||||||
|
await asyncio.sleep(0)
|
||||||
embed = discord.Embed(
|
embed = discord.Embed(
|
||||||
colour=await ctx.embed_colour(), title=_("Matching Tracks:"), description=track_match
|
colour=await ctx.embed_colour(), title=_("Matching Tracks:"), description=track_match
|
||||||
)
|
)
|
||||||
@ -6797,6 +6954,8 @@ class Audio(commands.Cog):
|
|||||||
track_len = 0
|
track_len = 0
|
||||||
empty_queue = not player.queue
|
empty_queue = not player.queue
|
||||||
for track in tracks:
|
for track in tracks:
|
||||||
|
if len(player.queue) >= 10000:
|
||||||
|
continue
|
||||||
if not await is_allowed(
|
if not await is_allowed(
|
||||||
ctx.guild,
|
ctx.guild,
|
||||||
(
|
(
|
||||||
@ -6821,6 +6980,7 @@ class Audio(commands.Cog):
|
|||||||
)
|
)
|
||||||
if not player.current:
|
if not player.current:
|
||||||
await player.play()
|
await player.play()
|
||||||
|
await asyncio.sleep(0)
|
||||||
player.maybe_shuffle(0 if empty_queue else 1)
|
player.maybe_shuffle(0 if empty_queue else 1)
|
||||||
if len(tracks) > track_len:
|
if len(tracks) > track_len:
|
||||||
maxlength_msg = " {bad_tracks} tracks cannot be queued.".format(
|
maxlength_msg = " {bad_tracks} tracks cannot be queued.".format(
|
||||||
@ -6856,7 +7016,8 @@ class Audio(commands.Cog):
|
|||||||
ctx,
|
ctx,
|
||||||
title=_("Unable to Get Track"),
|
title=_("Unable to Get Track"),
|
||||||
description=_(
|
description=_(
|
||||||
"I'm unable get a track from Lavalink at the moment, try again in a few minutes."
|
"I'm unable get a track from Lavalink at the moment,"
|
||||||
|
"try again in a few minutes."
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
tracks = result.tracks
|
tracks = result.tracks
|
||||||
@ -6891,6 +7052,7 @@ class Audio(commands.Cog):
|
|||||||
for page_num in range(1, len_search_pages + 1):
|
for page_num in range(1, len_search_pages + 1):
|
||||||
embed = await self._build_search_page(ctx, tracks, page_num)
|
embed = await self._build_search_page(ctx, tracks, page_num)
|
||||||
search_page_list.append(embed)
|
search_page_list.append(embed)
|
||||||
|
await asyncio.sleep(0)
|
||||||
|
|
||||||
if dj_enabled and not await self._can_instaskip(ctx, ctx.author):
|
if dj_enabled and not await self._can_instaskip(ctx, ctx.author):
|
||||||
return await menu(ctx, search_page_list, DEFAULT_CONTROLS)
|
return await menu(ctx, search_page_list, DEFAULT_CONTROLS)
|
||||||
@ -6917,6 +7079,10 @@ class Audio(commands.Cog):
|
|||||||
)
|
)
|
||||||
player = lavalink.get_player(ctx.guild.id)
|
player = lavalink.get_player(ctx.guild.id)
|
||||||
guild_data = await self.config.guild(ctx.guild).all()
|
guild_data = await self.config.guild(ctx.guild).all()
|
||||||
|
if len(player.queue) >= 10000:
|
||||||
|
return await self._embed_msg(
|
||||||
|
ctx, title=_("Unable To Play Tracks"), description=_("Queue size limit reached.")
|
||||||
|
)
|
||||||
if not await self._currency_check(ctx, guild_data["jukebox_price"]):
|
if not await self._currency_check(ctx, guild_data["jukebox_price"]):
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
@ -7035,6 +7201,7 @@ class Audio(commands.Cog):
|
|||||||
search_list += "`{}.` **{}**\n".format(
|
search_list += "`{}.` **{}**\n".format(
|
||||||
search_track_num, track.to_string_user()
|
search_track_num, track.to_string_user()
|
||||||
)
|
)
|
||||||
|
await asyncio.sleep(0)
|
||||||
if hasattr(tracks[0], "uri") and hasattr(tracks[0], "track_identifier"):
|
if hasattr(tracks[0], "uri") and hasattr(tracks[0], "track_identifier"):
|
||||||
title = _("Tracks Found:")
|
title = _("Tracks Found:")
|
||||||
footer = _("search results")
|
footer = _("search results")
|
||||||
@ -7513,6 +7680,7 @@ class Audio(commands.Cog):
|
|||||||
can_skip = await self._can_instaskip(ctx, ctx.author)
|
can_skip = await self._can_instaskip(ctx, ctx.author)
|
||||||
if vote_enabled or (vote_enabled and dj_enabled):
|
if vote_enabled or (vote_enabled and dj_enabled):
|
||||||
if not can_skip and not is_alone:
|
if not can_skip and not is_alone:
|
||||||
|
ctx.command.reset_cooldown(ctx)
|
||||||
return await self._embed_msg(
|
return await self._embed_msg(
|
||||||
ctx,
|
ctx,
|
||||||
title=_("Unable To Join Voice Channel"),
|
title=_("Unable To Join Voice Channel"),
|
||||||
@ -7520,6 +7688,7 @@ class Audio(commands.Cog):
|
|||||||
)
|
)
|
||||||
if dj_enabled and not vote_enabled:
|
if dj_enabled and not vote_enabled:
|
||||||
if not (can_skip or is_requester) and not is_alone:
|
if not (can_skip or is_requester) and not is_alone:
|
||||||
|
ctx.command.reset_cooldown(ctx)
|
||||||
return await self._embed_msg(
|
return await self._embed_msg(
|
||||||
ctx,
|
ctx,
|
||||||
title=_("Unable To Join Voice Channel"),
|
title=_("Unable To Join Voice Channel"),
|
||||||
@ -8048,14 +8217,17 @@ class Audio(commands.Cog):
|
|||||||
async def on_red_audio_track_start(
|
async def on_red_audio_track_start(
|
||||||
self, guild: discord.Guild, track: lavalink.Track, requester: discord.Member
|
self, guild: discord.Guild, track: lavalink.Track, requester: discord.Member
|
||||||
):
|
):
|
||||||
|
daily_cache = self._daily_playlist_cache.setdefault(
|
||||||
|
guild.id, await self.config.guild(guild).daily_playlists()
|
||||||
|
)
|
||||||
scope = PlaylistScope.GUILD.value
|
scope = PlaylistScope.GUILD.value
|
||||||
today = datetime.date.today()
|
today = datetime.date.today()
|
||||||
midnight = datetime.datetime.combine(today, datetime.datetime.min.time())
|
midnight = datetime.datetime.combine(today, datetime.datetime.min.time())
|
||||||
|
if daily_cache:
|
||||||
name = f"Daily playlist - {today}"
|
name = f"Daily playlist - {today}"
|
||||||
today_id = int(time.mktime(today.timetuple()))
|
today_id = int(time.mktime(today.timetuple()))
|
||||||
track_identifier = track.track_identifier
|
track_identifier = track.track_identifier
|
||||||
track = track_to_json(track)
|
track = track_to_json(track)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
playlist = await get_playlist(
|
playlist = await get_playlist(
|
||||||
playlist_number=today_id,
|
playlist_number=today_id,
|
||||||
@ -8083,6 +8255,7 @@ class Audio(commands.Cog):
|
|||||||
guild=guild,
|
guild=guild,
|
||||||
)
|
)
|
||||||
await playlist.save()
|
await playlist.save()
|
||||||
|
|
||||||
with contextlib.suppress(Exception):
|
with contextlib.suppress(Exception):
|
||||||
too_old = midnight - datetime.timedelta(days=8)
|
too_old = midnight - datetime.timedelta(days=8)
|
||||||
too_old_id = int(time.mktime(too_old.timetuple()))
|
too_old_id = int(time.mktime(too_old.timetuple()))
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import asyncio
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
from typing import List, MutableMapping, Optional, Union, TYPE_CHECKING
|
from typing import List, MutableMapping, Optional, Union, TYPE_CHECKING
|
||||||
|
|
||||||
@ -478,12 +479,16 @@ async def get_all_playlist(
|
|||||||
playlists = await database.fetch_all(scope_standard, scope_id, author_id=user_id)
|
playlists = await database.fetch_all(scope_standard, scope_id, author_id=user_id)
|
||||||
else:
|
else:
|
||||||
playlists = await database.fetch_all(scope_standard, scope_id)
|
playlists = await database.fetch_all(scope_standard, scope_id)
|
||||||
return [
|
|
||||||
|
playlist_list = []
|
||||||
|
for playlist in playlists:
|
||||||
|
playlist_list.append(
|
||||||
await Playlist.from_json(
|
await Playlist.from_json(
|
||||||
bot, scope, playlist.playlist_id, playlist, guild=guild, author=author
|
bot, scope, playlist.playlist_id, playlist, guild=guild, author=author
|
||||||
)
|
)
|
||||||
for playlist in playlists
|
)
|
||||||
]
|
await asyncio.sleep(0)
|
||||||
|
return playlist_list
|
||||||
|
|
||||||
|
|
||||||
async def get_all_playlist_converter(
|
async def get_all_playlist_converter(
|
||||||
@ -524,12 +529,15 @@ async def get_all_playlist_converter(
|
|||||||
playlists = await database.fetch_all_converter(
|
playlists = await database.fetch_all_converter(
|
||||||
scope_standard, playlist_name=arg, playlist_id=arg
|
scope_standard, playlist_name=arg, playlist_id=arg
|
||||||
)
|
)
|
||||||
return [
|
playlist_list = []
|
||||||
|
for playlist in playlists:
|
||||||
|
playlist_list.append(
|
||||||
await Playlist.from_json(
|
await Playlist.from_json(
|
||||||
bot, scope, playlist.playlist_id, playlist, guild=guild, author=author
|
bot, scope, playlist.playlist_id, playlist, guild=guild, author=author
|
||||||
)
|
)
|
||||||
for playlist in playlists
|
)
|
||||||
]
|
await asyncio.sleep(0)
|
||||||
|
return playlist_list
|
||||||
|
|
||||||
|
|
||||||
async def create_playlist(
|
async def create_playlist(
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user