Example #1
0
class HelpPages(MenuPages):
    def __init__(self, source):
        super().__init__(source, delete_message_after=True, timeout=60.0)

    @menus.button('\U00002754', position=menus.Last(4))
    async def show_bot_help(self, payload):
        """
		Shows the bot help message
		"""
        embed = discord.Embed(
            title="Bot help",
            description="Hello! Welcome to the bot help page.")
        embed.add_field(name="[arg]", value="Optional argument!", inline=False)
        embed.add_field(name="<arg>", value="Required argument!", inline=False)
        embed.add_field(
            name="What to do?",
            value=
            r"Use `{self.lmao.prefix}help [cmd]` for command help and `{self.lmao.prefix}help [module]` for module help."
        )
        await self.message.edit(content=None, embed=embed)

    @menus.button('\N{INFORMATION SOURCE}\ufe0f', position=menus.Last(3))
    async def show_help(self, payload):
        """Shows this message"""
        embed = discord.Embed(title='Paginator help',
                              description='Hello! Welcome to the help page.')
        messages = []
        for (emoji, button) in self.buttons.items():
            messages.append(f'{emoji}: {button.action.__doc__}')

        embed.add_field(name='What are these reactions for?',
                        value='\n'.join(messages),
                        inline=False)
        await self.message.edit(content=None, embed=embed)
Example #2
0
class Pages(menus.MenuPages):
    __slots__ = ()

    def __init__(self, source):
        super().__init__(source=source, check_embeds=1)

    async def finalize(self, timed_out):
        with suppress(discord.HTTPException):
            if timed_out: await self.message.clear_reactions()
            else: await self.message.delete()

    @menus.button('\N{INFORMATION SOURCE}\ufe0f', position=menus.Last(3))
    async def show_help(self, _):
        """shows this message"""
        embed = Embed(title='Помощь от Батиной книги')
        messages = []
        for emoji, button in self.buttons.items():
            messages.append(f'{emoji}: {button.action.__doc__}')
        embed.add_field(name=__('Для чего это кнопкочка?'),
                        value='\n'.join(messages),
                        inline=0)
        embed.set_footer(text=__('Ты на странице - {current_page}.').format(
            current_page=self.current_page + 1))
        await self.message.edit(content=None, embed=embed)

        async def go_back_to_current_page():
            await asyncio.sleep(30.0)
            await self.show_page(self.current_page)

        self.bot.loop.create_task(go_back_to_current_page())

    @menus.button('\N{INPUT SYMBOL FOR NUMBERS}', position=menus.Last(1.5))
    async def numbered_page(self, payload):
        """lets you type a page number to go to"""
        channel = self.message.channel
        author_id = payload.user_id
        to_delete = [
            await
            channel.send('Полистай побольше, может найдешь что то годное')
        ]

        def message_check(m):
            # check out, for author_id and channel, and content is it digit()
            return (m.author.id == author_id and channel == m.channel
                    and m.content.isdigit())

        try:
            msg = await self.bot.wait_for('message',
                                          check=message_check,
                                          timeout=30.0)
        except asyncio.TimeoutError:
            to_delete.append(
                await channel.send('Ты проебался, ты проебал страницу.'))
            await asyncio.sleep(5)
        else:
            page = int(msg.content)
            to_delete.append(msg)
            await self.show_checked_page(page - 1)
        with suppress(Exception):
            await channel.delete_messages(to_delete)
Example #3
0
class MenuPagesBase(menus.MenuPages, inherit_buttons=False):
    async def update(self, payload: discord.RawReactionActionEvent):
        if self._can_remove_reactions:
            if payload.event_type != 'REACTION_ADD':
                return

            await self.message.remove_reaction(payload.emoji, payload.member)
        await super().update(payload)

    async def send_initial_message(self, ctx: ErisContext,
                                   channel: discord.TextChannel):
        page = await self._source.get_page(0)
        kwargs = await self._get_kwargs_from_page(page)
        return await ctx.reply(**kwargs)

    async def show_page(self, page_number: int):
        page = await self._source.get_page(page_number)
        self.current_page = page_number
        kwargs = await self._get_kwargs_from_page(page)

        mentions = discord.AllowedMentions(replied_user=False)
        await self.message.edit(**kwargs, allowed_mentions=mentions)

    def _skip_double_arrows(self) -> bool:
        max_pages = self._source.get_max_pages()
        if max_pages is None:
            return True
        return max_pages <= 2

    @menus.button(DOUBLE_LEFT_EMOJI,
                  position=menus.First(0),
                  skip_if=_skip_double_arrows)
    async def go_to_first_page(self, payload: discord.RawReactionActionEvent):
        '''Vai para a primeira página.'''
        await self.show_page(0)

    @menus.button(LEFT_EMOJI, position=menus.First(0))
    async def go_to_previous_page(self,
                                  payload: discord.RawReactionActionEvent):
        '''Vai para a página anterior.'''
        await self.show_checked_page(self.current_page - 1)

    @menus.button(STOP_EMOJI)
    async def stop_pages(self, payload: discord.RawReactionActionEvent):
        '''Para a sessão de paginamento.'''
        self.stop()

    @menus.button(RIGHT_EMOJI, position=menus.Last(0))
    async def go_to_next_page(self, payload: discord.RawReactionActionEvent):
        '''Vai para a próxima página.'''
        await self.show_checked_page(self.current_page + 1)

    @menus.button(DOUBLE_RIGHT_EMOJI,
                  position=menus.Last(1),
                  skip_if=_skip_double_arrows)
    async def go_to_last_page(self, payload: discord.RawReactionActionEvent):
        '''Vai para a última página.'''
        await self.show_page(self._source.get_max_pages() - 1)
Example #4
0
class NavMenuPages(menus.MenuPages):
    def __init__(self, source: menus.PageSource, **kwargs):
        super().__init__(source, **kwargs)
        self._in_info = False

    async def go_back_to_current_page(self):
        await asyncio.sleep(30.0)
        await self.show_current_page()

    @menus.button('\N{INPUT SYMBOL FOR NUMBERS}', position=menus.Last(1.5))
    async def pick_page(self, payload: discord.RawReactionActionEvent):
        """lets you type a page number to go to"""

        my_msg = await self.ctx.send('What page do you want to go to?')
        try:
            msg = await self.bot.wait_for(
                'message',
                check=lambda m: m.author == self.ctx.author and m.channel ==
                self.ctx.channel,
                timeout=30.0)
        except asyncio.TimeoutError:
            await self.ctx.send('Took too long.')
            return
        finally:
            await my_msg.delete()
        if msg.content.isdigit():
            page = int(msg.content)
            await self.show_checked_page(page - 1)

    @menus.button('\N{INFORMATION SOURCE}', position=menus.Last(3))
    async def info(self, payload: discord.RawReactionActionEvent):
        """shows this message"""

        self._in_info = not self._in_info
        if self._in_info:
            embed = discord.Embed(
                title='Paginator help',
                description='Hello! Welcome to the help page.')
            value = '\n'.join(f'{emoji}: {button.action.__doc__}'
                              for emoji, button in self.buttons.items())
            embed.add_field(name='What are these reactions for?', value=value)
            embed.set_footer(
                text=
                f'We were on page {self.current_page + 1} before this message.'
            )
            await self.message.edit(embed=embed)
            task = asyncio.create_task(self.go_back_to_current_page())

            def on_done(fut):
                self._in_info = False

            task.add_done_callback(on_done)
        else:
            await self.show_current_page()
Example #5
0
class MainMenu(menus.MenuPages):
    def __init__(self, source, **kwargs):
        super().__init__(source=source, check_embeds=True, **kwargs)

    @menus.button('\N{INPUT SYMBOL FOR NUMBERS}', position=menus.Last(1.5))
    async def numbered_page(self, payload):
        """lets you type a page number to go to"""
        channel = self.message.channel
        author_id = payload.user_id
        to_delete = [await channel.send('What page do you want to go to?')]

        def message_check(m):
            return m.author.id == author_id and channel == m.channel and m.content.isdigit(
            )

        try:
            msg = await self.bot.wait_for('message',
                                          check=message_check,
                                          timeout=30.0)
        except asyncio.TimeoutError:
            to_delete.append(await channel.send('Took too long.'))
            await asyncio.sleep(5)
        else:
            page = int(msg.content)
            to_delete.append(msg)
            await self.show_checked_page(page - 1)

        try:
            await channel.delete_messages(to_delete)
        except Exception:
            pass
Example #6
0
class HelpMenu(MenuPages):
    def __init__(self, src):
        super().__init__(src)

    @menus.button("\N{WHITE QUESTION MARK ORNAMENT}", position=menus.Last(5))
    async def show_signature_help(self, _):
        embed = discord.Embed(color=core.COLOR, timestamp=self.ctx.now)
        embed.set_author(name=f"{self.bot.user.name} - Help",
                         icon_url=self.bot.avatar)
        embed.set_footer(text=f"You were on page {self.current_page+1}.")

        for name, value in (
            ('<argument>', 'This is a required argument.'),
            ('[argument]', 'This is an optional argument.'),
            ('<A | B>', 'This means that this argument can either be A or B.'),
            ('[A | B]',
             'Similar to the previous one, but the argument is optional.'),
            ('<\'argument\'>',
             'This argument should be typed exactly as shown.'),
            ('<argument...>', 'You can use this argument multiple times.'),
            ('<argument=X>',
             'This means that X is the default value for the argument if none is passed.'
             )):
            embed.add_field(name=f'`{name}`', value=value, inline=False)

        no_mention = discord.AllowedMentions.none()
        await self.ctx.maybe_edit(self.message,
                                  embed=embed,
                                  allowed_mentions=no_mention)

        async def go_back():
            await asyncio.sleep(45)
            await self.show_page(self.current_page)

        self.bot.loop.create_task(go_back())
Example #7
0
    class HelpMenu(menus.Menu):
        def __init__(self, cogs, main_embed, instance):
            super().__init__(clear_reactions_after=True)
            self.cogs = cogs
            self.main_embed = main_embed
            self.instance = instance
            for cog in cogs:
                self.add_button(menus.Button(cog.emoji, self.cog_embed))

        async def send_initial_message(self, ctx, channel):
            return await ctx.send(embed=self.main_embed)

        @menus.button('↩️')
        async def main(self, payload):
            await self.message.edit(embed=self.main_embed)

        @menus.button('⏹️', position=menus.Last())
        async def end(self, payload):
            self.stop()

        async def cog_embed(self, payload):
            for cog in self.cogs:
                if payload.emoji.name == cog.emoji:
                    await self.message.edit(
                        embed=await self.instance.cog_embed(cog))
Example #8
0
class KalPages(menus.MenuPages):
    def __init__(self, source, **kwargs):
        super().__init__(source=source, check_embeds=True, **kwargs)

    async def finalize(self, timed_out):
        try:
            if timed_out:
                await self.message.clear_reactions()
            else:
                await self.message.delete()
        except discord.HTTPException:
            pass

    @menus.button("\N{PUBLIC ADDRESS LOUDSPEAKER}", position=menus.Last(6))
    async def announcements(self, payload):
        """Announcements go here"""

        embed = self.bot.embed(self.ctx)
        embed.title = self.bot.announcement["title"]
        embed.description = self.bot.announcement["message"]

        await self.message.edit(content=None, embed=embed)

        async def go_back_to_current_page():
            await asyncio.sleep(30.0)
            await self.show_page(self.current_page)

        self.bot.loop.create_task(go_back_to_current_page())
Example #9
0
class BaseChoiceMenu(menus.Menu, Generic[T]):
    options: list[T]

    def __init__(self, options: list[T]) -> None:
        super().__init__(delete_message_after=True)

        if len(options) > 9:
            raise RuntimeError("Too many options for choice menu.")

        self.options = options
        self.selection: Optional[T] = None

        for i, _ in enumerate(self.options, 1):
            emoji = f"{i}\ufe0f\N{COMBINING ENCLOSING KEYCAP}"
            self.add_button(menus.Button(emoji, self.choose))

    async def send_initial_message(self, ctx: Context, channel: discord.TextChannel) -> discord.Message:
        raise NotImplementedError

    async def choose(self, payload: discord.RawReactionActionEvent):
        self.selection = self.options[int(str(payload.emoji)[0]) - 1]
        self.stop()

    async def start(self, ctx, *, channel=None) -> Optional[T]:
        await super().start(ctx, channel=channel, wait=True)
        return self.selection

    @menus.button("\N{BLACK SQUARE FOR STOP}\ufe0f", position=menus.Last(0))
    async def cancel(self, payload):
        self.stop()
Example #10
0
class Game(menus.Menu):
    name: Optional[str] = "Foggle"
    footer: Optional[str] = None

    def __init__(self, *, size: int = ORIGINAL, base: int = 10, **kwargs):
        self.board = Board(size=size, base=base)
        self.setup()
        super().__init__(**kwargs)

    @property
    def state(self):
        state = ""

        for row in range(self.board.size):
            emoji = []
            for column in range(self.board.size):
                emoji.append(NUMBER_EMOJI[self.board.columns[column][row]])

            state = " ".join(emoji) + "\n" + state

        number = self.board.number
        if self.board.base == 2:
            number = bin(number)
        elif self.board.base == 16:
            number = hex(number)

        state += f"\n\n The magic number is **{number}**!"

        return discord.Embed(title=self.name, description=state).set_footer(text=self.footer)

    def setup(self):
        raise NotImplementedError

    async def send_initial_message(self, ctx, channel):
        return await channel.send(content="Foggle game started, you have 3 minutes!", embed=self.state)

    async def start(self, *args, **kwargs):
        await super().start(*args, **kwargs)
        # await self.bot.loop.run_in_executor(None, lambda: self.board.legal_equations)

    async def finalize(self, timed_out):
        self.bot.dispatch("foggle_game_complete", self.message.channel)

    def get_points(self, equations: Iterable[str]) -> int:
        return self.board.total_points(equations)

    def get_correct(self, equations: Iterable[str]):
        return sum(self.board.is_legal(equation) for equation in equations)

    def check_equation(self, equation: str) -> bool:
        return self.board.is_legal(equation)

    async def check_message(self, message: discord.Message):
        raise NotImplementedError

    @menus.button("\N{BLACK SQUARE FOR STOP}\ufe0f", position=menus.Last(0))
    async def cancel(self, payload):
        await self.message.edit(content="Game Cancelled.")
        self.stop()
Example #11
0
class PaginatedHelp(ViewMenuPages, inherit_buttons=False):  # type: ignore  ## mypy doesn't like metaclasses.
    def __init__(self, source, **kwargs):
        super().__init__(source, delete_message_after=True, timeout=30, **kwargs)

    @menus.button(EMOJIS["information"], position=menus.Last(4))
    async def on_questionmark(self, payload):
        embed = CustomEmbed(
            title="Help Info",
            description=(
                "```diff\n"
                "- <arg> Required \n"
                "- [arg] Optional \n"
                "- [arg..] Multiple Args\n"
                "```\n"
            ),
        )

        embed.add_field(
            name="What do the emojis do?",
            value=(
                f"{EMOJIS['arrow_left']} - Goes one page backward.\n"
                f"{EMOJIS['double_backward']} - Goes to the first page.\n"
                f"{EMOJIS['stop']} - Stops the menu.\n"
                f"{EMOJIS['double_forward']} - Goes to the last page.\n"
                f"{EMOJIS['arrow_right']} - Goes one page forward\n"
                f"{EMOJIS['information']} - Shows this page.\n"
            ),
        )

        if self.source.get_max_pages() == 1:
            embed.set_footer(text="To get back to the page, use the double arrows.")

        await self.message.edit(embed=embed)

    def should_add_reactions(self):
        return True

    @menus.button(EMOJIS["arrow_left"], position=menus.First(2))
    async def left_arrow(self, payload):
        await self.go_to_previous_page(payload)

    @menus.button(EMOJIS["stop"], position=menus.First(3))
    async def stop_emoji(self, payload):
        self.stop()

    @menus.button(EMOJIS["arrow_right"], position=menus.First(4))
    async def right_arrow(self, payload):
        await self.go_to_next_page(payload)

    @menus.button(EMOJIS["double_forward"], position=menus.First(5))
    async def double_forward(self, payload):
        await self.go_to_last_page(payload)

    @menus.button(EMOJIS["double_backward"], position=menus.First(1))
    async def double_backward(self, payload):
        await self.go_to_first_page(payload)
Example #12
0
 def __init__(self, source):
     super().__init__(source=source, check_embeds=False)
     EmojiB = namedtuple("EmojiB", "emoji position explain")
     def_dict_emoji = {
         "\N{BLACK LEFT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR}\ufe0f":
         EmojiB(
             "<:backward2:816457785167314987>",
             menus.First(0),
             "Goes to the first page.",
         ),
         "\N{BLACK LEFT-POINTING TRIANGLE}\ufe0f":
         EmojiB(
             "<:backward:816458218145579049>",
             menus.First(1),
             "Goes to the previous page.",
         ),
         "\N{BLACK RIGHT-POINTING TRIANGLE}\ufe0f":
         EmojiB("<:forward:816458167835820093>", menus.Last(0),
                "Goes to the next page."),
         "\N{BLACK RIGHT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR}\ufe0f":
         EmojiB(
             "<:forward2:816457685905440850>",
             menus.Last(1),
             "Goes to the last page.",
         ),
         "\N{BLACK SQUARE FOR STOP}\ufe0f":
         EmojiB("<:trash:816463111958560819>", menus.Last(4),
                "Remove this message."),
     }
     self.dict_emoji = def_dict_emoji
     for emoji in self.buttons:
         callback = self.buttons[emoji].action
         if emoji.name not in self.dict_emoji:
             continue
         new_but = self.dict_emoji[emoji.name]
         new_button = menus.Button(new_but.emoji,
                                   callback,
                                   position=new_but.position)
         del self.dict_emoji[emoji.name]
         self.dict_emoji[new_but.emoji] = new_but
         self.add_button(new_button)
         self.remove_button(emoji)
Example #13
0
class PaginatedHelpCommand(menus.MenuPages):
    """
    Paginated help command.
    """
    @menus.button('\U00002139', position=menus.Last(2))
    async def on_info(self, _):
        embed = discord.Embed(title="How to Use the Paginator",
                              color=self.ctx.bot.embed_colour)
        embed.add_field(
            name="Add and Remove Reactions to Navigate the Help Menu:",
            value="➡️ next page\n"
            "⬅️ previous page\n"
            "⏮️ first page\n"
            "⏭️ last page\n"
            "ℹ️ shows this message\n"
            "❔    shows how to read the bot's signature\n"
            "⏹️ closes the paginator")
        embed.set_thumbnail(url=self.ctx.bot.user.avatar_url)
        embed.set_footer(
            text=
            f"You were on page {self.current_page + 1} before this message.")
        await self.message.edit(embed=embed)

    @menus.button('\U00002754', position=menus.Last(3))
    async def on_question_mark(self, _):
        embed = discord.Embed(
            title="How to read the Bot's Signature",
            description="`<argument>`: required argument\n"
            "`[argument]`: optional argument (These arguments will usually have an '=' followed by their default value.)\n"
            "`argument...`: multiple arguments can be provided",
            color=self.ctx.bot.embed_colour)
        embed.set_thumbnail(url=self.ctx.bot.user.avatar_url)
        embed.set_footer(
            text=
            f"You were on page {self.current_page + 1} before this message.")
        await self.message.edit(embed=embed)

    @menus.button('\N{BLACK SQUARE FOR STOP}\ufe0f', position=menus.Last(4))
    async def end_menu(self, _):
        self.stop()
Example #14
0
class Game(menus.Menu):
    name = 'Boggle'
    footer = None

    def __init__(self, *, size=ORIGINAL, **kwargs):
        self.board = Board(size=size)
        self.setup()
        super().__init__(**kwargs)

    @property
    def state(self):
        state = ''

        for row in range(self.board.size):
            emoji = []
            for column in range(self.board.size):
                emoji.append(LETTERS_EMOJI[self.board.columns[column][row]])

            state = ' '.join(emoji) + '\n' + state

        return discord.Embed(title=self.name,
                             description=state).set_footer(text=self.footer)

    def setup(self):
        raise NotImplementedError

    async def send_initial_message(self, ctx, channel):
        return await channel.send(
            content='Boggle game started, you have 3 minutes!',
            embed=self.state)

    async def start(self, *args, **kwargs):
        await super().start(*args, **kwargs)
        # await self.bot.loop.run_in_executor(None, lambda: self.board.legal_words)

    async def finalize(self, timed_out):
        self.bot.dispatch('boggle_game_complete', self.message.channel)

    def get_points(self, words: List[str]) -> int:
        return self.board.total_points(words)

    def check_word(self, word: str) -> bool:
        return self.board.is_legal(word)

    async def check_message(self, message: discord.Message):
        raise NotImplementedError

    @menus.button('\N{BLACK SQUARE FOR STOP}\ufe0f', position=menus.Last(0))
    async def cancel(self, payload):
        await self.message.edit(content='Game Cancelled.')
        self.stop()
Example #15
0
class HelpPages(MenuPages):
	def __init__(self, source):	
		super().__init__(source, delete_message_after=True, timeout=60.0)
		
	
	@menus.button('\N{INFORMATION SOURCE}\ufe0f', position=menus.Last(3))
	async def show_help(self, payload):
	       """Shows this message"""
	       embed = discord.Embed(title='Paginator help', description='Hello! Welcome to the help page.')
	       messages = []
	       for (emoji, button) in self.buttons.items():
	       	messages.append(f'{emoji}: {button.action.__doc__}')
	       	
	       embed.add_field(name='What are these reactions for?', value='\n'.join(messages), inline=False)
	       await self.message.edit(content=None, embed=embed)					
Example #16
0
class GelbooruMenuPages(dmenus.MenuPages):
    def __init__(self, source, **kwargs):
        super().__init__(source, **kwargs)

    @dmenus.button("\N{LABEL}", position=dmenus.Last(3))
    async def show_tags(self, payload) -> None:
        """Shows all tags for this post"""
        embed = self.message.embeds[0]
        if "See all tags" in embed.description:
            return
        all_tags = "\n".join(self.source.entries[self.current_page].tags)
        link = await helpers.haste(self.ctx.bot.aiosession,
                                   f"All Tags:\n{all_tags}")
        embed.description = (
            f"{embed.description[:-22]} [See all tags]({link})")
        await self.message.edit(embed=embed)
Example #17
0
class DeleteNotes(menus.MenuPages):
    def __init__(self, source):
        super().__init__(source=source, timeout=60, delete_message_after=True)

    async def finalize(self, timed_out):
        try:
            if timed_out:
                await self.message.clear_reactions()
            else:
                await self.message.delete()
        except discord.HTTPException:
            pass

    @menus.button('<:cancel:851278899270909993>', position=menus.Last(0))
    async def on_cancel(self, payload):
        self.stop()
Example #18
0
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.selection = None

        def action_maker(selection_num):
            async def action(_, payload):
                page = await self.source.get_page(self.current_page)
                self.selection = page[selection_num - 1]
                self.stop()

            return action

        for i in range(1, self.source.per_page + 1):
            button = menus.Button(NUMBER_TO_EMOJI[i],
                                  action_maker(i),
                                  position=menus.Last(1))
            self.add_button(button)
Example #19
0
class HelpPaginatorMenu(InfoMenuPages):
    def __init__(self, help_command, ctx, source, **kwargs):
        super().__init__(source,
                         clear_reactions_after=True,
                         check_embeds=True,
                         **kwargs)
        self.help_command = help_command
        self.total = len(source.entries)
        self.ctx = ctx
        self.is_bot = False

    @menus.button("\N{WHITE QUESTION MARK ORNAMENT}", position=menus.Last(5))
    async def show_bot_help(self, payload) -> None:
        """shows how to use the bot"""
        embed = discord.Embed(color=discord.Color.blurple())
        embed.title = 'Using the bot'
        embed.description = 'Hello! Welcome to the help page.'

        entries = (
            ('<argument>', 'This means the argument is __**required**__.'),
            ('[argument]', 'This means the argument is __**optional**__.'),
            ('[A|B]', 'This means it can be __**either A or B**__.'),
            ('[argument...]', 'This means you can have multiple arguments.\n'
             'Now that you know the basics, it should be noted that...\n'
             '__**You do not type in the brackets!**__'))

        embed.add_field(name='How do I use this bot?',
                        value='Reading the bot signature is pretty simple.')

        for name, value in entries:
            embed.add_field(name=name, value=value, inline=False)

        embed.set_footer(
            text=f'We were on page {self.current_page + 1} before this message.'
        )
        await self.message.edit(embed=embed)

        async def go_back_to_current_page():
            await asyncio.sleep(30.0)
            await self.show_page(self.current_page)

        self.bot.loop.create_task(go_back_to_current_page())

    async def paginate(self, **kwargs) -> None:
        await super().start(self.ctx, **kwargs)
Example #20
0
class ListItem(menus.MenuPages):
    def __init__(self, data, ctx, desc):
        super().__init__(source=MySource(data), clear_reactions_after=True)
        self.data = data
        self.sort = "time"
        self.ctx = ctx
        self.desc = desc

    @menus.button('\U0001f503', position=menus.Last(1.2))
    async def sort_by(self, _):
        """Lets you sort the results    """
        sort = ['time', 'quantity', 'price']
        sort_id = sort.index(self.sort)
        if sort_id == 2:
            self.sort = 'time'
        else:
            self.sort = sort[sort_id + 1]
        data = sorted(self.data, key=lambda x: x[self.sort])
        await self.change_source(source=MySource(data))
Example #21
0
class HelpMenu(Pages):
    def __init__(self, source):
        super().__init__(source)

    @menus.button("\N{WHITE QUESTION MARK ORNAMENT}", position=menus.Last(5))
    async def show_bot_help(self, payload):
        """shows how to use the bot"""

        embed = discord.Embed(title="Using the bot", colour=color.invis(self))
        embed.title = "Using the bot"
        embed.description = "Hello! Welcome to the help page."

        entries = (
            ("<argument>", "This means the argument is __**required**__."),
            ("[argument]", "This means the argument is __**optional**__."),
            ("[A|B]", "This means that it can be __**either A or B**__."),
            (
                "[argument...]",
                "This means you can have multiple arguments.\n"
                "Now that you know the basics, it should be noted that...\n"
                "__**You do not type in the brackets!**__",
            ),
        )

        embed.add_field(
            name="How do I use this bot?",
            value="Reading the bot signature is pretty simple.",
        )

        for name, value in entries:
            embed.add_field(name=name, value=value, inline=False)

        embed.set_footer(
            text=f"We were on page {self.current_page + 1} before this message."
        )
        await self.message.edit(embed=embed)

        async def go_back_to_current_page():
            await asyncio.sleep(30.0)
            await self.show_page(self.current_page)

        self.bot.loop.create_task(go_back_to_current_page())
Example #22
0
class HelpMenu(ViewMenuPages):
    @menus.button("🔢", position=menus.Last(1))
    async def select_page(self, payload):
        channel = self.bot.get_channel(payload.channel_id)
        i = await channel.send("Please enter the page you want to skip to:",
                               delete_after=30)

        def check(msg):
            return (msg.channel.id == payload.channel_id
                    and msg.author.id == self.ctx.author.id)

        try:
            message = await self.bot.wait_for("message",
                                              check=check,
                                              timeout=30)
        except Exception:
            # timeout
            return
        else:
            await i.delete()
        await message.delete()
        try:
            msg_int = int(message.content)
            await self.show_checked_page(msg_int - 1)
        except Exception:
            await self.ctx.send("Please enter a valid number...",
                                delete_after=30)

    async def show_checked_page(self, page_number):
        max_pages = self._source.get_max_pages()
        try:
            if max_pages is None:
                # If it doesn't give maximum pages, it cannot be checked
                await self.show_page(page_number)
            elif max_pages > page_number >= 0:
                await self.show_page(page_number)
        except IndexError:
            # An error happened that can be handled, so ignore it.
            await self.ctx.send("This page doesn't exist...", delete_after=30)
Example #23
0
class HelpMenu(RoboPages):
    def __init__(self, source):
        super().__init__(source)

    @menus.button("\N{WHITE QUESTION MARK ORNAMENT}", position=menus.Last(5))
    async def show_bot_help(self, payload):
        """Shows how to use the bot."""
        embed = discord.Embed(colour=discord.Colour.blurple())
        embed.title = "How Interpret The Help Pages"

        entries = (
            ("<argument>", "This means the argument is __**required**__."),
            ("[argument]", "This means the argument is __**optional**__."),
            ("[A|B]", "This means that it can be __**either A or B**__."),
            (
                "[argument...]",
                "This means you can have multiple arguments.\n"
                "Now that you know the basics, it should be noted that...\n"
                "__**You do not type in the brackets!**__",
            ),
        )

        for name, value in entries:
            embed.add_field(name=name, value=value, inline=False)

        embed.set_footer(
            text=f"We were on page {self.current_page + 1} before this message."
        )
        await self.message.edit(embed=embed)

        async def go_back_to_current_page():
            await asyncio.sleep(30.0)
            try:
                await self.show_page(self.current_page)
            except discord.errors.NotFound:
                return

        self.bot.loop.create_task(go_back_to_current_page())
Example #24
0
    def __init__(
        self,
        *,
        main_source: menus.ListPageSource,
        extra_sources: Union[Tuple[menus.ListPageSource], tuple] = (),
        **options,
    ):

        self.initial_source = main_source
        super().__init__(self.initial_source,
                         delete_message_after=True,
                         timeout=60,
                         **options)

        self.extra_sources = {}

        for index, source in enumerate(extra_sources, 3):
            self.extra_sources[source.emoji] = source
            position = menus.Last(index)
            button = menus.Button(source.emoji,
                                  self._extra_source_button,
                                  position=position)
            self.add_button(button)
Example #25
0
class HelpMenu(Pages):
    def __init__(self, source):
        super().__init__(source)

    @menus.button('\N{WHITE QUESTION MARK ORNAMENT}', position=menus.Last(5))
    async def show_bot_help(self, payload):
        """shows how to use the bot"""

        embed = discord.Embed(title='Comment utiliser le bot',
                              colour=discord.Colour.blurple())
        embed.title = 'Comment utiliser le bot'
        embed.description = "Salut ! Bienvenue sur l'aide du bot."

        entries = (
            ('<argument>', "Cela signifie que l'argument est __**requis**__."),
            ('[argument]', "Cela signifie que l'argument est __**optionel**__."),
            ('[A|B]', "Cela signifie qu'il peut s'agir de __**A ou B**__."),
            ('[argument...]', 'Cela signifie que vous pouvez avoir plusieurs arguments.\n' \
                              'Maintenant que vous connaissez les bases, il faut noter que ...\n' \
                              '__**Vous ne tapez pas entre parenthèses!**__')
        )

        embed.add_field(name="Comment j'utilise ce bot ?",
                        value='Comprendre le bot est assez simple.')

        for name, value in entries:
            embed.add_field(name=name, value=value, inline=False)

        embed.set_footer(
            text=f'Nous somme à la page {self.current_page + 1} .')
        await self.message.edit(embed=embed)

        async def go_back_to_current_page():
            await asyncio.sleep(30.0)
            await self.show_page(self.current_page)

        self.bot.loop.create_task(go_back_to_current_page())
Example #26
0
class HelpMenu(RoboPages):
    def __init__(self, source):
        super().__init__(source)

    @menus.button('\N{WHITE QUESTION MARK ORNAMENT}', position=menus.Last(5))
    async def show_bot_help(self, payload):
        """shows how to use the bot"""

        embed = discord.Embed(title='Using the bot',
                              colour=discord.Colour.from_rgb(48, 162, 242))
        embed.title = 'Using the bot'
        embed.description = 'Hello! Welcome to the help page.'

        entries = (
            ('<argument>', 'This means the argument is __**required**__.'),
            ('[argument]', 'This means the argument is __**optional**__.'),
            ('[A|B]', 'This means that it can be __**either A or B**__.'),
            ('[argument...]', 'This means you can have multiple arguments.\n'
             'Now that you know the basics, it should be noted that...\n'
             '__**You do not type in the brackets!**__'))

        embed.add_field(name='How do I use this bot?',
                        value='Reading the bot signature is pretty simple.')

        for name, value in entries:
            embed.add_field(name=name, value=value, inline=False)

        embed.set_footer(
            text=f'We were on page {self.current_page + 1} before this message.'
        )
        await self.message.edit(embed=embed)

        async def go_back_to_current_page():
            await asyncio.sleep(30.0)
            await self.show_page(self.current_page)

        self.bot.loop.create_task(go_back_to_current_page())
Example #27
0
class HelpMenu(NavMenuPages):
    @menus.button('\N{WHITE QUESTION MARK ORNAMENT}', position=menus.Last(5))
    async def using_the_bot(self, payload):
        """shows how to use the bot"""

        embed = discord.Embed(
            title='Using the bot',
            description='Hello! Welcome to the help page'
        ).add_field(
            name='How do I use the bot?',
            value='Reading the bot signature is pretty simple.',
            inline=False
        ).add_field(
            name='<argument>',
            value='This means the argument is required.',
            inline=False
        ).add_field(
            name='[argument]',
            value='This means the argument is optional.',
            inline=False
        ).add_field(
            name='[A|B]',
            value='This means that it can be either A or B.',
            inline=False
        ).add_field(
            name='[argument...]',
            value='This means you can have multiple arguments.',
            inline=False
        ).add_field(
            name='Now that you know the basics, it should be noted that...',
            value='You do not type in the brackets!',
            inline=False
        ).set_footer(
            text=f'We were on page {self.current_page + 1} before this message.'
        )
        await self.message.edit(embed=embed)
        asyncio.create_task(self.go_back_to_current_page())
Example #28
0
class InfoMenuPages(ViewMenuPages):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    @menus.button("\N{INFORMATION SOURCE}\ufe0f", position=menus.Last(3))
    async def info_page(self, payload) -> None:
        """shows you this message"""
        messages = ['Welcome to the interactive paginator!\n']
        messages.append('This interactively allows you to see pages of text by navigating with '
                        'reactions. They are as follows:\n')
        for emoji, button in self.buttons.items():
            messages.append(f'{str(emoji)} {button.action.__doc__}')

        embed = discord.Embed(color=discord.Color.blurple())
        embed.clear_fields()
        embed.description = '\n'.join(messages)
        embed.set_footer(text=f"We were on page {self.current_page + 1} before this message.")
        await self.message.edit(content=None, embed=embed)

        async def go_back_to_current_page():
            await asyncio.sleep(60.0)
            await self.show_page(self.current_page)

        self.ctx.bot.loop.create_task(go_back_to_current_page())
Example #29
0
class MafiaMenu(menus.MenuPages):
    amount_of_players = 0
    amount_of_mafia = 0

    @property
    def allowed_mafia(self):
        """The amount of mafia roles allowed to add"""
        # Subtract an extra one, because one of them HAS to be Godfather
        return (self.amount_of_mafia -
                sum([v for k, v in self.source.entries if k.is_mafia]) - 1)

    @property
    def allowed_non_mafia(self):
        """The amount of non-mafia roles allowed to add"""
        return (self.amount_of_players - self.amount_of_mafia -
                sum([v for k, v in self.source.entries if not k.is_mafia]))

    async def finalize(self, timed_out):
        if timed_out:
            raise asyncio.TimeoutError

    def should_add_reactions(self):
        return True

    def _should_not_paginate(self):
        return not self._source.is_paginating()

    def _should_skip_0(self):
        return len(self._get_pages(self.current_page)) < 1

    def _should_skip_1(self):
        return len(self._get_pages(self.current_page)) < 2

    def _should_skip_2(self):
        return len(self._get_pages(self.current_page)) < 3

    def _should_skip_3(self):
        return len(self._get_pages(self.current_page)) < 4

    def _should_skip_4(self):
        return len(self._get_pages(self.current_page)) < 5

    def _get_pages(self, page_number):
        base = page_number * self.source.per_page
        return self.source.entries[base:base + self.source.per_page]

    @menus.button(
        "0\N{variation selector-16}\N{combining enclosing keycap}",
        skip_if=_should_skip_0,
    )
    async def _0_click_passthrough(self, payload):
        await self.handle_click(payload)

    @menus.button(
        "1\N{variation selector-16}\N{combining enclosing keycap}",
        skip_if=_should_skip_1,
    )
    async def _1_click_passthrough(self, payload):
        await self.handle_click(payload)

    @menus.button(
        "2\N{variation selector-16}\N{combining enclosing keycap}",
        skip_if=_should_skip_2,
    )
    async def _2_click_passthrough(self, payload):
        await self.handle_click(payload)

    @menus.button(
        "3\N{variation selector-16}\N{combining enclosing keycap}",
        skip_if=_should_skip_3,
    )
    async def _3_click_passthrough(self, payload):
        await self.handle_click(payload)

    @menus.button(
        "4\N{variation selector-16}\N{combining enclosing keycap}",
        skip_if=_should_skip_4,
    )
    async def _4_click_passthrough(self, payload):
        await self.handle_click(payload)

    async def handle_click(self, payload):
        # Get the number that was clicked
        num = int(str(payload.emoji)[0])
        index = num + self.source.per_page * self.current_page
        role, current_num = self.source.entries[index]
        # Only allow up to how many members can remain
        if role.is_mafia:
            amt_allowed = self.allowed_mafia + current_num
        else:
            amt_allowed = self.allowed_non_mafia + current_num
        # Make sure to limit to the role's limit
        if role.limit:
            amt_allowed = min(role.limit, amt_allowed)

        # No need to get answer if can't add any anymore
        if not amt_allowed:
            await self.ctx.send("Cannot add any more of that role",
                                delete_after=5)
            return

        msg = await self.ctx.send(
            f"{role.__name__}: How many? 0 - {amt_allowed}")
        answer = await self.ctx.bot.wait_for("message",
                                             check=self.ctx.bot.min_max_check(
                                                 self.ctx, 0, amt_allowed))
        # Delete and set answer
        self.source.entries[index] = (role, int(answer.content))
        await self.ctx.channel.delete_messages([msg, answer])
        # Refresh
        await self.show_page(self.current_page)

    @menus.button(
        "\N{BLACK LEFT-POINTING TRIANGLE}\ufe0f",
        position=menus.First(1),
        skip_if=_should_not_paginate,
    )
    async def go_to_previous_page(self, payload):
        """go to the previous page"""
        await self.show_checked_page(self.current_page - 1)

    @menus.button(
        "\N{BLACK RIGHT-POINTING TRIANGLE}\ufe0f",
        position=menus.Last(0),
        skip_if=_should_not_paginate,
    )
    async def go_to_next_page(self, payload):
        """go to the next page"""
        await self.show_checked_page(self.current_page + 1)

    @menus.button(
        "\N{BLACK SQUARE FOR STOP}\ufe0f",
        position=menus.Last(2),
        skip_if=lambda x: True,
    )
    async def stop_pages(self, payload):
        pass

    @menus.button("\N{WHITE HEAVY CHECK MARK}", position=menus.Last(2))
    async def accept_setings(self, payload):
        self.stop()
Example #30
0
class Game(menus.Menu):
    ranked = True

    async def start(self, ctx, opponent, *, channel=None, wait=False):
        if random.random() < 0.5:
            self.players = (ctx.author, opponent)
        else:
            self.players = (opponent, ctx.author)

        for player in self.players:
            async with ctx.db as connection:
                await Ranking.insert(connection,
                                     ignore_on_conflict=True,
                                     user_id=player.id)

        self.board = Board()
        self.current_player = 0

        # Setup buttons
        for emoji in REGIONAL_INDICATOR_EMOJI:
            self.add_button(menus.Button(emoji, self.place))

        await super().start(ctx, channel=channel, wait=wait)

    async def send_initial_message(self, ctx, channel):
        current_player = self.current_player
        return await channel.send(
            content=
            f"{self.players[current_player].mention}'s ({DISCS[current_player]}) turn!",
            embed=self.state,
        )

    def reaction_check(self, payload):
        if payload.message_id != self.message.id:
            return False

        current_player = self.current_player
        if payload.user_id != self.players[current_player].id:
            return False

        return payload.emoji in self.buttons

    @property
    def state(self):
        return discord.Embed(description=self.board.state)

    async def _end_game(self, resignation: int = None):
        winner: Optional[int]

        if resignation is not None:
            winner = not resignation
            content = f"Game cancelled by {self.players[resignation].mention} ({DISCS[resignation]})!"
        elif self.board.winner is not None:
            winner = self.board.winner
            content = f"{self.players[self.board.winner].mention} ({DISCS[self.board.winner]})  Wins!"
        else:
            winner = None
            content = "Draw!"

        await self.message.edit(content=f"Game Over! {content}",
                                embed=self.state)
        self.stop()

        if not self.ranked:
            return

        # Calulate new ELO
        async with self.ctx.db as connection:

            await Games.insert(
                connection=connection,
                players=[p.id for p in self.players],
                winner=winner,
                finished=resignation is None,
            )

            record_1 = await Ranking.fetch_row(connection,
                                               user_id=self.players[0].id)
            record_2 = await Ranking.fetch_row(connection,
                                               user_id=self.players[1].id)

            R1 = 10**(record_1["ranking"] / 400)
            R2 = 10**(record_2["ranking"] / 400)

            E1 = R1 / (R1 + R2)
            E2 = R2 / (R1 + R2)

            S1 = self.board.winner == 0 if self.board.winner is not None else 0.5
            S2 = self.board.winner == 1 if self.board.winner is not None else 0.5

            r1 = record_1["ranking"] + K * (S1 - E1)
            r2 = record_2["ranking"] + K * (S2 - E2)

            await Ranking.update_record(
                connection,
                record_1,
                ranking=round(r1),
                games=record_1["games"] + 1,
                wins=record_1["wins"] + self.board.winner == 0,
                losses=record_1["losses"] + self.board.winner != 0,
            )

            await Ranking.update_record(
                connection,
                record_2,
                ranking=round(r2),
                games=record_2["games"] + 1,
                wins=record_2["wins"] + self.board.winner == 1,
                losses=record_2["losses"] + self.board.winner != 1,
            )

    async def place(self, payload):
        column = REGIONAL_INDICATOR_EMOJI.index(str(payload.emoji))
        if column not in self.board.legal_moves:
            return ...

        self.board = self.board.move(column, DISCS[self.current_player])

        if self.board.game_over:
            return await self._end_game()

        self.current_player = not self.current_player
        await self.message.edit(
            content=
            f"{self.players[self.current_player].mention}'s ({DISCS[self.current_player]}) turn!",
            embed=self.state,
        )

    @menus.button("\N{BLACK SQUARE FOR STOP}\ufe0f", position=menus.Last(0))
    async def cancel(self, payload):
        await self._end_game(resignation=self.current_player)