Esempio n. 1
0
    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")
Esempio n. 2
0
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))
Esempio n. 3
0
    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
Esempio n. 4
0
    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
Esempio n. 5
0
    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)
Esempio n. 7
0
 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
Esempio n. 8
0
 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
Esempio n. 9
0
    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),
            )
Esempio n. 10
0
 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."))
Esempio n. 11
0
    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]"
Esempio n. 12
0
    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
Esempio n. 13
0
    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
Esempio n. 14
0
 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
Esempio n. 15
0
    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)
Esempio n. 16
0
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
Esempio n. 18
0
    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
Esempio n. 19
0
 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
Esempio n. 20
0
    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()
Esempio n. 21
0
    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
Esempio n. 22
0
 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
     ]
Esempio n. 23
0
 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
Esempio n. 24
0
 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
Esempio n. 25
0
    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))
Esempio n. 26
0
    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
Esempio n. 27
0
    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)
Esempio n. 28
0
 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
Esempio n. 29
0
 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