async def run_all_pending_tasks(self) -> None: """Run all pending tasks left in the cache, called on cog_unload.""" async with self._lock: if IS_DEBUG: log.debug("Running pending writes to database") try: tasks: MutableMapping = { "update": [], "insert": [], "global": [] } async for k, task in AsyncIter(self._tasks.items()): async for t, args in AsyncIter(task.items()): tasks[t].append(args) self._tasks = {} coro_tasks = [self.route_tasks(a, tasks[a]) for a in tasks] await asyncio.gather(*coro_tasks, return_exceptions=False) except Exception as exc: debug_exc_log(log, exc, "Failed database writes") else: if IS_DEBUG: log.debug( "Completed pending writes to database have finished")
async def global_unique_user_finder( ctx: commands.Context, arg: str, guild: discord.guild = None) -> discord.abc.User: bot: Red = ctx.bot guild = guild or ctx.guild _id = _match_id(arg) if _id is not None: user: discord.User = bot.get_user(_id) if user is not None: return user maybe_matches = [] async for user in AsyncIter( bot.users).filter(lambda u: u.name == arg or f"{u}" == arg): maybe_matches.append(user) if guild is not None: async for member in AsyncIter( guild.members).filter(lambda m: m.nick == arg and not any( obj.id == m.id for obj in maybe_matches)): maybe_matches.append(member) if not maybe_matches: raise NoMatchesFound( _('"{arg}" was not found. It must be the ID or name or ' "mention a user which the bot can see.").format(arg=arg)) elif len(maybe_matches) == 1: return maybe_matches[0] else: raise TooManyMatches( _('"{arg}" does not refer to a unique server. ' "Please use the ID for the server you're trying to specify."). format(arg=arg))
async def _build_queue_search_list( self, queue_list: List[lavalink.Track], search_words: str) -> List[Tuple[int, str]]: track_list = [] async for queue_idx, track in AsyncIter(queue_list).enumerate(start=1): if not self.match_url(track.uri): query = Query.process_input(track, self.local_folder_current_path) if (query.is_local and query.local_track_path is not None and track.title == "Unknown title"): track_title = query.local_track_path.to_string_user() else: track_title = "{} - {}".format(track.author, track.title) else: track_title = track.title song_info = {str(queue_idx): track_title} track_list.append(song_info) search_results = process.extract(search_words, track_list, limit=50) search_list = [] async for search, percent_match in AsyncIter(search_results): async for queue_position, title in AsyncIter(search.items()): if percent_match > 89: search_list.append((queue_position, title)) return search_list
async def red_delete_data_for_user( self, *, requester: Literal["discord_deleted_user", "owner", "user", "user_strict"], user_id: int, ): if requester != "discord_deleted_user": return all_members = await self.config.all_members() async for guild_id, guild_data in AsyncIter(all_members.items(), steps=100): if user_id in guild_data: await self.config.member_from_ids(guild_id, user_id).clear() await self.config.user_from_id(user_id).clear() guild_data = await self.config.all_guilds() async for guild_id, guild_data in AsyncIter(guild_data.items(), steps=100): if user_id in guild_data["current_tempbans"]: async with self.config.guild_from_id( guild_id).current_tempbans() as tbs: try: tbs.remove(user_id) except ValueError: pass
async def convert( self, ctx: commands.Context, arg: str ) -> Union[discord.Guild, discord.abc.GuildChannel, discord.abc.User, discord.Role]: bot: commands.Bot = ctx.bot _id = _match_id(arg) if _id is not None: guild: discord.Guild = bot.get_guild(_id) if guild is not None: return guild channel: discord.abc.GuildChannel = bot.get_channel(_id) if channel is not None: return channel user: discord.User = bot.get_user(_id) if user is not None: return user async for guild in AsyncIter(bot.guilds, steps=100): role: discord.Role = guild.get_role(_id) if role is not None: return role all_roles = [ filter(lambda r: not r.is_default(), guild.roles) async for guild in AsyncIter(bot.guilds, steps=100) ] objects = itertools.chain(bot.get_all_channels(), bot.users, bot.guilds, *all_roles) maybe_matches = [] async for obj in AsyncIter(objects, steps=100): if obj.name == arg or str(obj) == arg: maybe_matches.append(obj) if ctx.guild is not None: async for member in AsyncIter(ctx.guild.members, steps=100): if member.nick == arg and not any(obj.id == member.id for obj in maybe_matches): maybe_matches.append(member) if not maybe_matches: raise commands.BadArgument( _('"{arg}" was not found. It must be the ID, mention, or name of a server, ' "channel, user or role which the bot can see.").format( arg=arg)) elif len(maybe_matches) == 1: return maybe_matches[0] else: raise commands.BadArgument( _('"{arg}" does not refer to a unique server, channel, user or role. Please use ' "the ID for whatever/whoever you're trying to specify, or mention it/them." ).format(arg=arg))
async def command_percent(self, ctx: commands.Context): """Queue percentage.""" if not self._player_check(ctx): return await self.send_embed_msg(ctx, title=_("Nothing playing.")) player = lavalink.get_player(ctx.guild.id) queue_tracks = player.queue requesters = {"total": 0, "users": {}} async def _usercount(req_username): if req_username in requesters["users"]: requesters["users"][req_username]["songcount"] += 1 requesters["total"] += 1 else: requesters["users"][req_username] = {} requesters["users"][req_username]["songcount"] = 1 requesters["total"] += 1 async for track in AsyncIter(queue_tracks): req_username = "******".format(track.requester.name, track.requester.discriminator) await _usercount(req_username) try: req_username = "******".format( player.current.requester.name, player.current.requester.discriminator) await _usercount(req_username) except AttributeError: return await self.send_embed_msg( ctx, title=_("There's nothing in the queue.")) async for req_username in AsyncIter(requesters["users"]): percentage = float( requesters["users"][req_username]["songcount"]) / float( requesters["total"]) requesters["users"][req_username]["percent"] = round( percentage * 100, 1) top_queue_users = heapq.nlargest( 20, [(x, requesters["users"][x][y]) for x in requesters["users"] for y in requesters["users"][x] if y == "percent"], key=lambda x: x[1], ) queue_user = ["{}: {:g}%".format(x[0], x[1]) for x in top_queue_users] queue_user_list = "\n".join(queue_user) await self.send_embed_msg(ctx, title=_("Queued and playing tracks:"), description=queue_user_list)
async def _multiglob(self, pattern: str, folder: bool, method: Callable): async for rp in AsyncIter(method(pattern)): rp_local = LocalPath(rp, self._localtrack_folder) if ((folder and rp_local.is_dir() and rp_local.exists()) or (not folder and rp_local.suffix in self._all_music_ext and rp_local.is_file()) and rp_local.exists()): yield rp_local
async def _build_playlist_list_page(self, ctx: commands.Context, page_num: int, abc_names: List, scope: Optional[str]) -> discord.Embed: plist_num_pages = math.ceil(len(abc_names) / 5) plist_idx_start = (page_num - 1) * 5 plist_idx_end = plist_idx_start + 5 plist = "" async for i, playlist_info in AsyncIter( abc_names[plist_idx_start:plist_idx_end]).enumerate( start=plist_idx_start): item_idx = i + 1 plist += "`{}.` {}".format(item_idx, playlist_info) if scope is None: embed = discord.Embed( colour=await ctx.embed_colour(), title=_("Playlists you can access in this server:"), description=plist, ) else: embed = discord.Embed( colour=await ctx.embed_colour(), title=_("Playlists for {scope}:").format(scope=scope), description=plist, ) embed.set_footer( text=_("Page {page_num}/{total_pages} | {num} playlists.").format( page_num=page_num, total_pages=plist_num_pages, num=len(abc_names))) return embed
async def command_queue_cleanself(self, ctx: commands.Context): """Removes all tracks you requested from the queue.""" try: player = lavalink.get_player(ctx.guild.id) except KeyError: return await self.send_embed_msg( ctx, title=_("There's nothing in the queue.")) if not self._player_check(ctx) or not player.queue: return await self.send_embed_msg( ctx, title=_("There's nothing in the queue.")) clean_tracks = [] removed_tracks = 0 async for track in AsyncIter(player.queue): if track.requester != ctx.author: clean_tracks.append(track) else: removed_tracks += 1 await self.api_interface.persistent_queue_api.played( ctx.guild.id, track.extras.get("enqueue_time")) player.queue = clean_tracks if removed_tracks == 0: await self.send_embed_msg(ctx, title=_("Removed 0 tracks.")) else: await self.send_embed_msg( ctx, title=_("Removed Tracks From The Queue"), description= _("Removed {removed_tracks} tracks queued by {member.display_name}." ).format(removed_tracks=removed_tracks, member=ctx.author), )
async def command_queue_clear(self, ctx: commands.Context): """Clears the queue.""" try: player = lavalink.get_player(ctx.guild.id) except KeyError: return await self.send_embed_msg( ctx, title=_("There's nothing in the queue.")) dj_enabled = self._dj_status_cache.setdefault( ctx.guild.id, await self.config.guild(ctx.guild).dj_enabled()) if not self._player_check(ctx) or not player.queue: return await self.send_embed_msg( ctx, title=_("There's nothing in the queue.")) if (dj_enabled and not await self._can_instaskip(ctx, ctx.author) and not await self.is_requester_alone(ctx)): return await self.send_embed_msg( ctx, title=_("Unable To Clear Queue"), description=_("You need the DJ role to clear the queue."), ) async for track in AsyncIter(player.queue): await self.api_interface.persistent_queue_api.played( ctx.guild.id, track.extras.get("enqueue_time")) player.queue.clear() await self.send_embed_msg(ctx, title=_("Queue Modified"), description=_("The queue has been cleared."))
async def red_delete_data_for_user( self, *, requester: Literal["discord_deleted_user", "owner", "user", "user_strict"], user_id: int, ): if requester != "discord_deleted_user": return all_reports = await self.config.custom("REPORT").all() steps = 0 paths = [] # this doesn't use async iter intentionally due to the nested iterations for guild_id_str, tickets in all_reports.items(): for ticket_number, ticket in tickets.items(): steps += 1 if not steps % 100: await asyncio.sleep(0) # yield context if ticket.get("report", {}).get("user_id", 0) == user_id: paths.append((guild_id_str, ticket_number)) async with self.config.custom("REPORT").all() as all_reports: async for guild_id_str, ticket_number in AsyncIter(paths, steps=100): r = all_reports[guild_id_str][ticket_number]["report"] r["user_id"] = 0xDE1 # this might include EUD, and a report of a deleted user # that's been unhandled for long enough for the # user to be deleted and the bot receive a request like this... r["report"] = "[REPORT DELETED DUE TO DISCORD REQUEST]"
async def _build_genre_search_page( self, ctx: commands.Context, tracks: List, page_num: int, title: str, playlist: bool = False, ) -> discord.Embed: search_num_pages = math.ceil(len(tracks) / 5) search_idx_start = (page_num - 1) * 5 search_idx_end = search_idx_start + 5 search_list = "" async for i, entry in AsyncIter( tracks[search_idx_start:search_idx_end]).enumerate( start=search_idx_start): search_track_num = i + 1 if search_track_num > 5: search_track_num = search_track_num % 5 if search_track_num == 0: search_track_num = 5 if playlist: name = "**[{}]({})** - {} {}".format(entry.get("name"), entry.get("url"), str(entry.get("tracks")), _("tracks")) else: name = f"{list(entry.keys())[0]}" search_list += f"`{search_track_num}.` {name}\n" embed = discord.Embed(colour=await ctx.embed_colour(), title=title, description=search_list) embed.set_footer(text=_("Page {page_num}/{total_pages}").format( page_num=page_num, total_pages=search_num_pages)) return embed
async def announcer(self): guild_list = self.ctx.bot.guilds failed = [] async for g in AsyncIter(guild_list, delay=0.5): if not self.active: return channel = await self._get_announce_channel(g) if channel: if channel.permissions_for(g.me).send_messages: try: await channel.send(self.message) except discord.Forbidden: failed.append(str(g.id)) else: failed.append(str(g.id)) if failed: msg = (_("I could not announce to the following server: ") if len(failed) == 1 else _("I could not announce to the following servers: ")) msg += humanize_list(tuple(map(inline, failed))) await self.ctx.bot.send_to_owners(msg) self.active = False
async def _build_queue_search_page( self, ctx: commands.Context, page_num: int, search_list: List[Tuple[int, str]]) -> discord.Embed: search_num_pages = math.ceil(len(search_list) / 10) search_idx_start = (page_num - 1) * 10 search_idx_end = search_idx_start + 10 track_match = "" async for i, track in AsyncIter( search_list[search_idx_start:search_idx_end]).enumerate( start=search_idx_start): track_idx = i + 1 if type(track) is str: track_location = LocalPath( track, self.local_folder_current_path).to_string_user() track_match += "`{}.` **{}**\n".format(track_idx, track_location) else: track_match += "`{}.` **{}**\n".format(track[0], track[1]) embed = discord.Embed(colour=await ctx.embed_colour(), title=_("Matching Tracks:"), description=track_match) embed.set_footer(text=_( "Page {page_num}/{total_pages} | {num_tracks} tracks").format( page_num=humanize_number(page_num), total_pages=humanize_number(search_num_pages), num_tracks=len(search_list), )) return embed
async def anonymize_aliases(self, user_id: int): async with self.config.entries() as global_aliases: for a in global_aliases: if a.get("creator", 0) == user_id: a["creator"] = 0xDE1 if self._cache_enabled: self._aliases[None][a["name"]] = AliasEntry.from_json( a) all_guilds = await self.config.all_guilds() async for guild_id, guild_data in AsyncIter(all_guilds.items(), steps=100): for a in guild_data["entries"]: if a.get("creator", 0) == user_id: break else: continue # basically, don't build a context manager without a need. async with self.config.guild_from_id( guild_id).entries() as entry_list: for a in entry_list: if a.get("creator", 0) == user_id: a["creator"] = 0xDE1 if self._cache_enabled: self._aliases[guild_id][ a["name"]] = AliasEntry.from_json(a)
async def global_unique_guild_finder(ctx: commands.Context, arg: str) -> discord.Guild: bot: Red = ctx.bot _id = _match_id(arg) if _id is not None: guild: discord.Guild = bot.get_guild(_id) if guild is not None: return guild maybe_matches = [] async for obj in AsyncIter(bot.guilds): if obj.name == arg or str(obj) == arg: maybe_matches.append(obj) if not maybe_matches: raise NoMatchesFound( _('"{arg}" was not found. It must be the ID or ' "complete name of a server which the bot can see.").format( arg=arg)) elif len(maybe_matches) == 1: return maybe_matches[0] else: raise TooManyMatches( _('"{arg}" does not refer to a unique server. ' "Please use the ID for the server you're trying to specify."). format(arg=arg))
async def get_all_playlist( scope: str, bot: Red, playlist_api: PlaylistWrapper, guild: Union[discord.Guild, int] = None, author: Union[discord.abc.User, int] = None, specified_user: bool = False, ) -> List[Playlist]: """ Gets all playlist for the specified scope. Parameters ---------- scope: str The custom config scope. One of 'GLOBALPLAYLIST', 'GUILDPLAYLIST' or 'USERPLAYLIST'. guild: discord.Guild The guild to get the playlist from if scope is GUILDPLAYLIST. author: int The ID of the user to get the playlist from if scope is USERPLAYLIST. bot: Red The bot's instance playlist_api: PlaylistWrapper The Playlist API interface. specified_user:bool Whether or not user ID was passed as an argparse. Returns ------- list A list of all playlists for the specified scope Raises ------ `InvalidPlaylistScope` Passing a scope that is not supported. `MissingGuild` Trying to access the Guild scope without a guild. `MissingAuthor` Trying to access the User scope without an user id. """ scope_standard, scope_id = prepare_config_scope(bot, scope, author, guild) if specified_user: user_id = getattr(author, "id", author) playlists = await playlist_api.fetch_all(scope_standard, scope_id, author_id=user_id) else: playlists = await playlist_api.fetch_all(scope_standard, scope_id) playlist_list = [] async for playlist in AsyncIter(playlists): playlist_list.append(await Playlist.from_json( bot, playlist_api, scope, playlist.playlist_id, playlist, guild=guild, author=author, )) return playlist_list
async def discover_guild( self, author: discord.User, *, mod: bool = False, permissions: Union[discord.Permissions, dict] = None, prompt: str = "", ): """ discovers which of shared guilds between the bot and provided user based on conditions (mod or permissions is an or) prompt is for providing a user prompt for selection """ shared_guilds = [] if permissions is None: perms = discord.Permissions() elif isinstance(permissions, discord.Permissions): perms = permissions else: perms = discord.Permissions(**permissions) async for guild in AsyncIter(self.bot.guilds, steps=100): x = guild.get_member(author.id) if x is not None: if await self.internal_filter(x, mod, perms): shared_guilds.append(guild) if len(shared_guilds) == 0: raise ValueError("No Qualifying Shared Guilds") if len(shared_guilds) == 1: return shared_guilds[0] output = "" guilds = sorted(shared_guilds, key=lambda g: g.name) for i, guild in enumerate(guilds, 1): output += "{}: {}\n".format(i, guild.name) output += "\n{}".format(prompt) for page in pagify(output, delims=["\n"]): await author.send(box(page)) try: message = await self.bot.wait_for( "message", check=MessagePredicate.same_context(channel=author.dm_channel, user=author), timeout=45, ) except asyncio.TimeoutError: await author.send(_("You took too long to select. Try again later.")) return None try: message = int(message.content.strip()) guild = guilds[message - 1] except (ValueError, IndexError): await author.send(_("That wasn't a valid choice.")) return None else: return guild
async def clear_react(self, message: discord.Message, emoji: MutableMapping = None) -> None: try: await message.clear_reactions() except discord.Forbidden: if not emoji: return with contextlib.suppress(discord.HTTPException): async for key in AsyncIter(emoji.values(), delay=0.2): await message.remove_reaction(key, self.bot.user) except discord.HTTPException: return
async def red_delete_data_for_user( self, *, requester: Literal["discord_deleted_user", "owner", "user", "user_strict"], user_id: int, ): if requester != "discord_deleted_user": return all_members = await self.config.all_members() async for guild_id, guild_data in AsyncIter(all_members.items(), steps=100): if user_id in guild_data: await self.config.member_from_ids(guild_id, user_id).clear()
async def load_aliases(self): if not self._cache_enabled: self._loaded = True return for alias in await self.config.entries(): self._aliases[None][alias["name"]] = AliasEntry.from_json(alias) all_guilds = await self.config.all_guilds() async for guild_id, guild_data in AsyncIter(all_guilds.items(), steps=100): if guild_id not in self._aliases: self._aliases[guild_id] = {} for alias in guild_data["entries"]: self._aliases[guild_id][alias["name"]] = AliasEntry.from_json( alias) self._loaded = True
async def get_playlist_from_category(self, category: str, ctx: Context = None): """Get spotify playlists for the specified category.""" url = f"{CATEGORY_ENDPOINT}/{category}/playlists" country_code = await self.get_country_code(ctx=ctx) params: MutableMapping = {"country": country_code} if country_code else {} result = await self.make_get_call(url, params=params) playlists = result.get("playlists", {}).get("items", []) return [ { "name": c["name"], "uri": c["uri"], "url": c.get("external_urls", {}).get("spotify"), "tracks": c.get("tracks", {}).get("total", "Unknown"), } async for c in AsyncIter(playlists) if c ]
async def _build_local_search_list(self, to_search: List[Query], search_words: str) -> List[str]: to_search_string = { i.local_track_path.name for i in to_search if i.local_track_path is not None } search_results = process.extract(search_words, to_search_string, limit=50) search_list = [] async for track_match, percent_match in AsyncIter(search_results): if percent_match > 85: search_list.extend([ i.to_string_user() for i in to_search if i.local_track_path is not None and i.local_track_path.name == track_match ]) return search_list
async def queue_duration(self, ctx: commands.Context) -> int: player = lavalink.get_player(ctx.guild.id) dur = [ i.length async for i in AsyncIter(player.queue, steps=50).filter(lambda x: not x.is_stream) ] queue_dur = sum(dur) if not player.queue: queue_dur = 0 try: if not player.current.is_stream: remain = player.current.length - player.position else: remain = 0 except AttributeError: remain = 0 queue_total_duration = remain + queue_dur return queue_total_duration
async def convert( self, ctx: commands.Context, arg: str ) -> Union[discord.abc.GuildChannel, discord.Member, discord.Role]: guild: discord.Guild = ctx.guild _id = _match_id(arg) if _id is not None: channel: discord.abc.GuildChannel = guild.get_channel(_id) if channel is not None: return channel member: discord.Member = guild.get_member(_id) if member is not None: return member role: discord.Role = guild.get_role(_id) if role is not None and not role.is_default(): return role objects = itertools.chain( guild.channels, guild.members, filter(lambda r: not r.is_default(), guild.roles)) maybe_matches = [] async for obj in AsyncIter(objects, steps=100): if obj.name == arg or str(obj) == arg: maybe_matches.append(obj) try: if obj.nick == arg: maybe_matches.append(obj) except AttributeError: pass if not maybe_matches: raise commands.BadArgument( _('"{arg}" was not found. It must be the ID, mention, or name of a channel, ' "user or role in this server.").format(arg=arg)) elif len(maybe_matches) == 1: return maybe_matches[0] else: raise commands.BadArgument( _('"{arg}" does not refer to a unique channel, user or role. Please use the ID ' "for whatever/whoever you're trying to specify, or mention it/them." ).format(arg=arg))
async def redact_author_ids(self, user_id: int): all_guilds = await self.config.all_guilds() for guild_id in all_guilds.keys(): await asyncio.sleep(0) async with self.config.guild_from_id(guild_id).commands() as all_commands: async for com_name, com_info in AsyncIter(all_commands.items(), steps=100): if not com_info: continue if com_info.get("author", {}).get("id", 0) == user_id: com_info["author"]["id"] = 0xDE1 com_info["author"]["name"] = "Deleted User" if editors := com_info.get("editors", None): for index, editor_id in enumerate(editors): if editor_id == user_id: editors[index] = 0xDE1
async def command_audiostats(self, ctx: commands.Context): """Audio stats.""" server_num = len(lavalink.active_players()) total_num = len(lavalink.all_players()) msg = "" async for p in AsyncIter(lavalink.all_players()): connect_start = p.fetch("connect") connect_dur = self.get_time_string( int((datetime.datetime.utcnow() - connect_start).total_seconds())) try: if not p.current: raise AttributeError current_title = await self.get_track_description( p.current, self.local_folder_current_path) msg += "{} [`{}`]: {}\n".format(p.channel.guild.name, connect_dur, current_title) except AttributeError: msg += "{} [`{}`]: **{}**\n".format(p.channel.guild.name, connect_dur, _("Nothing playing.")) if total_num == 0: return await self.send_embed_msg( ctx, title=_("Not connected anywhere.")) servers_embed = [] pages = 1 for page in pagify(msg, delims=["\n"], page_length=1500): em = discord.Embed( colour=await ctx.embed_colour(), title=_("Playing in {num}/{total} servers:").format( num=humanize_number(server_num), total=humanize_number(total_num)), description=page, ) em.set_footer(text=_("Page {}/{}").format( humanize_number(pages), humanize_number((math.ceil(len(msg) / 1500))))) pages += 1 servers_embed.append(em) await menu(ctx, servers_embed, DEFAULT_CONTROLS)
async def fetch_all_for_global( self) -> List[LavalinkCacheFetchForGlobalResult]: """Get all entries from the Lavalink table""" output: List[LavalinkCacheFetchForGlobalResult] = [] row_result = [] if self.fetch_for_global is None: return [] with concurrent.futures.ThreadPoolExecutor(max_workers=1) as executor: for future in concurrent.futures.as_completed([ executor.submit(self.database.cursor().execute, self.statement.get_all_global) ]): try: row_result = future.result() except Exception as exc: debug_exc_log(log, exc, "Failed to completed fetch from database") async for row in AsyncIter(row_result): output.append(self.fetch_for_global(*row)) return output
async def command_queue_clean(self, ctx: commands.Context): """Removes songs from the queue if the requester is not in the voice channel.""" try: player = lavalink.get_player(ctx.guild.id) except KeyError: return await self.send_embed_msg( ctx, title=_("There's nothing in the queue.")) dj_enabled = self._dj_status_cache.setdefault( ctx.guild.id, await self.config.guild(ctx.guild).dj_enabled()) if not self._player_check(ctx) or not player.queue: return await self.send_embed_msg( ctx, title=_("There's nothing in the queue.")) if (dj_enabled and not await self._can_instaskip(ctx, ctx.author) and not await self.is_requester_alone(ctx)): return await self.send_embed_msg( ctx, title=_("Unable To Clean Queue"), description=_("You need the DJ role to clean the queue."), ) clean_tracks = [] removed_tracks = 0 listeners = player.channel.members async for track in AsyncIter(player.queue): if track.requester in listeners: clean_tracks.append(track) else: await self.api_interface.persistent_queue_api.played( ctx.guild.id, track.extras.get("enqueue_time")) removed_tracks += 1 player.queue = clean_tracks if removed_tracks == 0: await self.send_embed_msg(ctx, title=_("Removed 0 tracks.")) else: await self.send_embed_msg( ctx, title=_("Removed Tracks From The Queue"), description=_( "Removed {removed_tracks} tracks queued by members " "outside of the voice channel.").format( removed_tracks=removed_tracks), )
async def fetch_all(self) -> List[QueueFetchResult]: """Fetch all playlists""" output = [] with concurrent.futures.ThreadPoolExecutor(max_workers=1) as executor: for future in concurrent.futures.as_completed([ executor.submit( self.database.cursor().execute, self.statement.get_all, ) ]): try: row_result = future.result() except Exception as exc: debug_exc_log( log, exc, "Failed to complete playlist fetch from database") return [] async for index, row in AsyncIter(row_result).enumerate(start=1): output.append(QueueFetchResult(*row)) return output