async def user_info(self, ctx,
                        member: typing.Optional[typing.Union[discord.Member,
                                                             discord.User]]):
        member = member or ctx.author

        embed = SaturnEmbed(description=member.mention,
                            colour=member.colour if isinstance(
                                member, discord.Member) else MAIN,
                            timestamp=utc())

        embed.set_thumbnail(url=member.avatar_url)
        embed.set_author(icon_url=member.avatar_url, name=member)

        created_delta = (utc() - member.created_at.replace(
            tzinfo=datetime.timezone.utc)).total_seconds()

        embed.add_field(name="ID", value=member.id)
        embed.add_field(name="Joined Discord",
                        value=general_convert_time(created_delta) + ' ago',
                        inline=True)
        if isinstance(member, discord.Member):
            join_delta = (utc() - member.joined_at.replace(
                tzinfo=datetime.timezone.utc)).total_seconds()
            member_roles = member.roles[1:]
            roles = " ".join(reversed([f"<@&{r.id}>" for r in member_roles]))

            embed.add_field(name=f"Joined {ctx.guild}",
                            value=general_convert_time(join_delta) + ' ago',
                            inline=True)
            if roles:
                embed.add_field(name="Roles ({})".format(int(
                    len(member_roles))),
                                value=roles)

            member_perms = await get_permissions(ctx, member)
            display_perms = []

            for permission, value in member_perms.items():
                if value:
                    display_perms.append(' '.join(
                        [item.title() for item in str(permission).split('_')]))

                continue

            embed.add_field(name="Permissions ({})".format(
                int(len(display_perms))),
                            value=", ".join(display_perms))

        await ctx.send(embed=embed)
    async def prompt(self, ctx):
        em = discord.Embed(
            description=f'{WARNING} Are you sure you want to {self.msg}?',
            colour=GOLD,
            timestamp=utc())
        msg = await ctx.send(embed=em)
        await msg.add_reaction(CHECK)
        await msg.add_reaction(CROSS)

        def check(r, u):
            return u == ctx.author and str(r.emoji) in (CHECK, CROSS)

        try:
            reaction, user = await ctx.bot.wait_for('reaction_add',
                                                    timeout=30.0,
                                                    check=check)

        except asyncio.TimeoutError:
            return False

        else:
            if str(reaction.emoji) == CHECK:
                return True

            else:
                em = SaturnEmbed(description=f"{INFO} Action cancelled.",
                                 colour=BLUE)
                await ctx.send(embed=em)
                return False
    async def view_uptime(self, ctx):
        time = (utc() - self.bot.start_time).total_seconds()
        formatted_time = str(general_convert_time(time))

        await ctx.reply(embed=SaturnEmbed(
            description=
            f"{self.bot.__name__} has been online for **{formatted_time}**",
            colour=MAIN))
    async def clear_snipe_cache(self):
        current_time = utc()
        snipes = deepcopy(self.bot.snipes)

        for key, value in snipes.items():
            clear_time = value['time'] + relativedelta(seconds=600)

            if current_time >= clear_time:
                self.bot.snipes.pop(value['_id'])
    async def view_roles(self, ctx,
                         member: typing.Optional[typing.Union[discord.Member,
                                                              discord.User]]):
        member = member or ctx.author

        roles = " ".join(reversed([f"<@&{r.id}>" for r in member.roles[1:]]))
        em = SaturnEmbed(description=str(
            roles if roles else f"{member.mention} has no roles!"),
                         colour=member.colour,
                         timestamp=utc())
        em.set_image(url=member.avatar_url)
        em.set_author(icon_url=member.avatar_url,
                      name=f"{member.name}'s roles")
        await ctx.send(embed=em)
    async def export_channel_contents(
            self,
            ctx,
            channel: typing.Optional[discord.TextChannel],
            limit: typing.Optional[int] = 100):
        channel = channel or ctx.channel

        em = SaturnEmbed(
            description=f"{INFO} This might take a while, please wait...",
            colour=BLUE)
        msg = await ctx.send(embed=em)
        async with channel.typing():
            messages = await channel.history(limit=limit,
                                             oldest_first=True).flatten()

            try:
                await create_export_file(self.bot, ctx, messages, channel)

            except FileNotFoundError:
                await asyncio.sleep(0.5)
                await create_export_file(self.bot, ctx, messages, channel)

            file = discord.File(
                f'{self.bot.path}/assets/txt_files/{channel.id}-export.txt')

        try:
            await msg.delete()

        except (discord.NotFound, discord.Forbidden):
            pass

        em = SaturnEmbed(
            title='Channel Export',
            description=f"Message contents of <#{channel.id}>\n"
            f"Download the attached .txt file to view the contents.",
            colour=MAIN,
            timestamp=utc())
        em.set_thumbnail(
            url="https://emojipedia-us.s3.dualstack.us-west-1.amazonaws.com/"
            "thumbs/120/mozilla/36/memo_1f4dd.png")
        await ctx.send(embed=em)
        await asyncio.sleep(0.5)
        await ctx.send(file=file)
    async def _paginate(self, ctx: commands.Context) -> None:
        if not self.entries and not self.extra_pages:
            raise AttributeError(
                'You must provide at least one entry or page for pagination.'
            )  # ^^

        if self.entries:
            self.entries = [self.formatting(entry) for entry in self.entries]
            entries = list(self.chunker())
        else:
            entries = []

        for i, chunk in enumerate(entries, start=1):
            if not self.use_embed:
                self._pages.append(self.joiner.join(chunk))
            else:
                title = self.title or (self.change_title[i - 1]
                                       if self.change_title else None)
                em = discord.Embed(
                    title=title,
                    description=self.joiner.join(chunk),
                    colour=self.colour,
                    timestamp=self.timestamp or utc(),
                )

                em.set_footer(
                    text=
                    f"Page {i} out of {len(entries)} pages {f'| {self.footer}' if self.footer else ''}"
                )

                if self.thumbnail:
                    em.set_thumbnail(url=self.thumbnail)

                self._pages.append(em)

        self._pages += self.extra_pages

        if isinstance(self._pages[0], discord.Embed):
            self.page = await ctx.send(embed=self._pages[0])
        else:
            self.page = await ctx.send(self._pages[0])

        self._session_task = ctx.bot.loop.create_task(self._session(ctx))
    async def yes_no_poll(self, ctx,
                          channel: typing.Optional[discord.TextChannel], *,
                          question):
        channel = channel or ctx.channel

        em = SaturnEmbed(title=question,
                         description=":thumbsup: Yes\n\n:thumbsdown: No",
                         colour=GOLD,
                         timestamp=utc())
        em.set_footer(text=f"Yes/no poll by {ctx.author}")
        msg = await channel.send(embed=em)
        self.polls[msg.id] = {
            "type": "ynpoll",
            "question": question,
            "choices": ("Yes", "No"),
            "channel": msg.channel.id,
            "author": ctx.author.id,
            "guild": ctx.guild.id,
        }
        for emoji in self.yes_no:
            await msg.add_reaction(emoji)
    async def poll(self, ctx, channel: typing.Optional[discord.TextChannel],
                   question, *choices):
        channel = channel or ctx.channel

        if not len(choices) or not len(question):
            em = SaturnEmbed(
                description=
                f"{CROSS} Please include both a question and choices. Format looks like\n"
                f'```poll "dogs or cats?" dogs cats```',
                color=RED)
            return await ctx.send(embed=em)
        if len(choices) > 10 or len(choices) < 2:
            em = SaturnEmbed(
                description=
                f"{CROSS} The amount of choices provided is not within acceptable boundaries.\n"
                f"```Number of choices must be in between 1 and 10```",
                color=RED)
            return await ctx.send(embed=em)

        em = SaturnEmbed(title=question,
                         description='\n\n'.join([
                             "{0} {1}".format(self.numbers[num],
                                              choice.replace('"', ''))
                             for num, choice in enumerate(choices)
                         ]),
                         colour=BLUE,
                         timestamp=utc())
        em.set_footer(text=f"Poll by {ctx.author}")
        msg = await channel.send(embed=em)
        self.polls[msg.id] = {
            "type": "poll",
            "question": question,
            "choices": choices,
            "channel": msg.channel.id,
            "author": ctx.author.id,
            "guild": ctx.guild.id,
        }
        valid_emotes = self.numbers[:(len(choices))]
        for emoji in valid_emotes:
            await msg.add_reaction(emoji)
    async def member_count(self, ctx):
        async with ctx.channel.typing():
            bots = len([m for m in ctx.guild.members if m.bot])
            bots_with_perms = len([
                m for m in ctx.guild.members
                if m.bot and m.guild_permissions.kick_members
            ])
            users = len(ctx.guild.members) - bots
            mods = len([
                m
                for m in ctx.guild.members if m.guild_permissions.kick_members
            ]) - bots_with_perms

            em = SaturnEmbed(colour=MAIN, timestamp=utc())
            em.description = f"""
            **Members** - {users}
            **Bots** - {bots}
            **Moderators** - {mods}
            """
            em.set_author(name=f'Member Statistics for {ctx.guild}',
                          icon_url=ctx.guild.icon_url)
            await ctx.send(embed=em)
Exemple #11
0
	async def on_ready(self):
		self.default_guild = self.get_guild(793577103794634842)
		self.stdout = self.default_guild.get_channel(833871407544008704)
		self.start_time = utc()

		if not self.ready:
			self.ready = True
			for _file in os.listdir(self.path + '/cogs'):
				if _file.endswith('.py') and not _file.startswith('_'):
					print(f"Loading {_file[:-3]} cog...")
					# load all of the cogs
					self.load_extension(f"cogs.{_file[:-3]}")

			# i have jishaku here because i find it quite useful
			self.load_extension('jishaku')

			mutes, bans = [], []
			print("Initializing mute and ban cache...")
			async for _doc in self.mutes.find({}):
				mutes.append(_doc)
			for mute in mutes:
				self.muted_users[mute["_id"]] = mute
			async for _doc in self.bans.find({}):
				bans.append(_doc)
			for ban in bans:
				self.banned_users[ban["_id"]] = ban

			print(f"{self.__name__} is ready")
			em = SaturnEmbed(
				description=f"{CHECK} Connected and ready!",
				colour=GREEN)
			await self.stdout.send(embed=em)

		else:
			print(f"{self.__name__} reconnected")
			em = SaturnEmbed(
				description=f"{INFO} Reconnected!",
				colour=BLUE)
			await self.stdout.send(embed=em)
    async def _default_indexer(self, control, ctx, member):
        previous = self._index

        if control == 'stop':
            return await self.cancel()

        if control == 'end':
            self._index = len(self._pages) - 1
        elif control == 'start':
            self._index = 0

        elif control == 'info':
            # info embed yay?
            em = discord.Embed(description=f"""
                {PAG_FRONT} - Go to the first page.
                {PAG_PREVIOUS} - Go back one page.
                {PAG_NEXT} - Go forward one page.
                {PAG_BACK} - Go to the last page.
                {PAG_STOP} - Stop the menu.
                {PAG_INFO} - Shows this message.
                {PAG_NUMBERS} - Type a page number in chat to go to.    
                
                Press any button to continue.
                """,
                               timestamp=utc(),
                               colour=BLUE)
            em.set_author(name="How to use the Interactive Menu",
                          icon_url=INFO_URL)
            return await self.page.edit(embed=em)

        elif control == 'number':
            em = discord.Embed(
                description=
                f'{INFO} Please specify which page you want to go to in the chat.',
                colour=BLUE)
            await ctx.send(embed=em)
            try:
                msg = await ctx.bot.wait_for(
                    'message', check=lambda m: m.author == ctx.author)

            except asyncio.TimeoutError:
                em = discord.Embed(
                    description=f'{INFO} User did not respond in time.',
                    colour=BLUE)
                await ctx.send(embed=em)

            else:
                try:
                    _int = int(msg.content)

                except ValueError:
                    em = discord.Embed(
                        description=f'{CROSS} Invalid page number given.\n'
                        f'```Page must be between 1 and {len(self._pages)}```',
                        colour=RED)
                    return await ctx.send(embed=em)

                if (len(self._pages) < _int or _int < 1):
                    em = discord.Embed(
                        description=f'{CROSS} Invalid page number given.\n'
                        f'```Page must be between 1 and {len(self._pages)}```',
                        colour=RED)
                    return await ctx.send(embed=em)

                self._index = _int - 1
                em = discord.Embed(
                    description=f'{CHECK} Switched to page `{_int}`',
                    colour=GREEN)
                await ctx.send(embed=em)

        else:
            self._index += control

        if self._index > len(self._pages) - 1 or self._index < 0:
            self._index = previous

        if self._index == previous:
            pass

        if isinstance(self._pages[self._index], discord.Embed):
            await self.page.edit(embed=self._pages[self._index])
        else:
            await self.page.edit(content=self._pages[self._index])