<commit_before>
import discord
from discord.ext import commands


class ButtonPaginator(discord.ui.View):

    # TODO: Track pages paginated and number of paginators

    def __init__(self, ctx_or_interaction, source, initial_page = 1):
        super().__init__(timeout = None)

        self.ctx = self.ctx_or_interaction = ctx_or_interaction
        self.source = source
        self.current_page = initial_page - 1

        if isinstance(ctx_or_interaction, commands.Context):
            self.bot = ctx_or_interaction.bot
            self.user = ctx_or_interaction.author
        elif isinstance(ctx_or_interaction, discord.Interaction):
            self.bot = ctx_or_interaction.client
            self.user = ctx_or_interaction.user
        else:
            raise RuntimeError(
                "ButtonPaginator passed neither Context nor Interaction"
            )

        self.message = None

    @discord.ui.button(
        style = discord.ButtonStyle.grey,
        emoji = (
            '\N{BLACK LEFT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR}'
            '\N{VARIATION SELECTOR-16}'
        )
    )
    async def start_button(self, interaction, button):
        await self.show_page(interaction, 0)

    @discord.ui.button(
        style = discord.ButtonStyle.grey,
        emoji = (
            '\N{LEFTWARDS BLACK ARROW}'
            '\N{VARIATION SELECTOR-16}'
        )
    )
    async def previous_button(self, interaction, button):
        await self.show_page(interaction, self.current_page - 1)

    @discord.ui.button(
        style = discord.ButtonStyle.blurple,
        disabled = True
    )
    async def current_button(self, interaction, button):
        return

    @discord.ui.button(
        style = discord.ButtonStyle.grey,
        emoji = (
            '\N{BLACK RIGHTWARDS ARROW}'
            '\N{VARIATION SELECTOR-16}'
        )
    )
    async def next_button(self, interaction, button):
        await self.show_page(interaction, self.current_page + 1)

    @discord.ui.button(
        style = discord.ButtonStyle.grey,
        emoji = (
            '\N{BLACK RIGHT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR}'
            '\N{VARIATION SELECTOR-16}'
        )
    )
    async def end_button(self, interaction, button):
        await self.show_page(interaction, self.source.get_max_pages() - 1)

    @discord.ui.button(
        style = discord.ButtonStyle.red,
        emoji = '\N{OCTAGONAL SIGN}'
    )
    async def stop_button(self, interaction, button):
        await self.stop(interaction = interaction)

    async def interaction_check(self, interaction):
        if interaction.user.id not in (self.user.id, self.bot.owner_id):
            await interaction.response.send_message(
                "You didn't invoke this command.",
                ephemeral = True
            )
            return False
        return True

    async def start(self):
        # TODO: Check embed permissions
        await self.source.prepare()

        if self.current_page <= 0:
            self.current_page = 0
            self.start_button.disabled = True
            self.previous_button.disabled = True
        elif self.current_page >= (
            max_page := self.source.get_max_pages() - 1
        ):
            self.current_page = max_page
            self.end_button.disabled = True
            self.next_button.disabled = True

        page = await self.source.get_page(self.current_page)
        kwargs = await self.source.format_page(self, page)

        if self.source.is_paginating():
            self.current_button.label = self.current_page + 1
            self.end_button.label = self.source.get_max_pages()
        else:
            self.clear_items()

        if isinstance(self.ctx_or_interaction, commands.Context):
            self.message = await self.ctx_or_interaction.send(
                **kwargs, view = self
            )
            await self.bot.attempt_delete_message(
                self.ctx_or_interaction.message
            )
        elif isinstance(self.ctx_or_interaction, discord.Interaction):
            if self.ctx_or_interaction.response.is_done():
                self.message = await self.ctx_or_interaction.followup.send(
                    **kwargs, view = self, wait = True
                )
            else:
                await self.ctx_or_interaction.response.send_message(
                    **kwargs, view = self
                )
                message = await self.ctx_or_interaction.original_message()
                self.message = await message.fetch()
        else:
            raise RuntimeError(
                "ButtonPaginator using neither Context nor Interaction"
            )

    async def show_page(self, interaction, page_number):
        self.current_page = page_number
        page = await self.source.get_page(page_number)<commit_msg>[Discord] Fetch ButtonPaginator.message for hybrid commands<commit_after>
import discord
from discord.ext import commands


class ButtonPaginator(discord.ui.View):

    # TODO: Track pages paginated and number of paginators

    def __init__(self, ctx_or_interaction, source, initial_page = 1):
        super().__init__(timeout = None)

        self.ctx = self.ctx_or_interaction = ctx_or_interaction
        self.source = source
        self.current_page = initial_page - 1

        if isinstance(ctx_or_interaction, commands.Context):
            self.bot = ctx_or_interaction.bot
            self.user = ctx_or_interaction.author
        elif isinstance(ctx_or_interaction, discord.Interaction):
            self.bot = ctx_or_interaction.client
            self.user = ctx_or_interaction.user
        else:
            raise RuntimeError(
                "ButtonPaginator passed neither Context nor Interaction"
            )

        self.message = None

    @discord.ui.button(
        style = discord.ButtonStyle.grey,
        emoji = (
            '\N{BLACK LEFT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR}'
            '\N{VARIATION SELECTOR-16}'
        )
    )
    async def start_button(self, interaction, button):
        await self.show_page(interaction, 0)

    @discord.ui.button(
        style = discord.ButtonStyle.grey,
        emoji = (
            '\N{LEFTWARDS BLACK ARROW}'
            '\N{VARIATION SELECTOR-16}'
        )
    )
    async def previous_button(self, interaction, button):
        await self.show_page(interaction, self.current_page - 1)

    @discord.ui.button(
        style = discord.ButtonStyle.blurple,
        disabled = True
    )
    async def current_button(self, interaction, button):
        return

    @discord.ui.button(
        style = discord.ButtonStyle.grey,
        emoji = (
            '\N{BLACK RIGHTWARDS ARROW}'
            '\N{VARIATION SELECTOR-16}'
        )
    )
    async def next_button(self, interaction, button):
        await self.show_page(interaction, self.current_page + 1)

    @discord.ui.button(
        style = discord.ButtonStyle.grey,
        emoji = (
            '\N{BLACK RIGHT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR}'
            '\N{VARIATION SELECTOR-16}'
        )
    )
    async def end_button(self, interaction, button):
        await self.show_page(interaction, self.source.get_max_pages() - 1)

    @discord.ui.button(
        style = discord.ButtonStyle.red,
        emoji = '\N{OCTAGONAL SIGN}'
    )
    async def stop_button(self, interaction, button):
        await self.stop(interaction = interaction)

    async def interaction_check(self, interaction):
        if interaction.user.id not in (self.user.id, self.bot.owner_id):
            await interaction.response.send_message(
                "You didn't invoke this command.",
                ephemeral = True
            )
            return False
        return True

    async def start(self):
        # TODO: Check embed permissions
        await self.source.prepare()

        if self.current_page <= 0:
            self.current_page = 0
            self.start_button.disabled = True
            self.previous_button.disabled = True
        elif self.current_page >= (
            max_page := self.source.get_max_pages() - 1
        ):
            self.current_page = max_page
            self.end_button.disabled = True
            self.next_button.disabled = True

        page = await self.source.get_page(self.current_page)
        kwargs = await self.source.format_page(self, page)

        if self.source.is_paginating():
            self.current_button.label = self.current_page + 1
            self.end_button.label = self.source.get_max_pages()
        else:
            self.clear_items()

        if isinstance(self.ctx_or_interaction, commands.Context):
            self.message = await self.ctx_or_interaction.send(
                **kwargs, view = self
            )
            if self.ctx_or_interaction.interaction:
                self.message = await self.message.fetch()
            await self.bot.attempt_delete_message(
                self.ctx_or_interaction.message
            )
        elif isinstance(self.ctx_or_interaction, discord.Interaction):
            if self.ctx_or_interaction.response.is_done():
                self.message = await self.ctx_or_interaction.followup.send(
                    **kwargs, view = self, wait = True
                )
            else:
                await self.ctx_or_interaction.response.send_message(
                    **kwargs, view = self
                )
                message = await self.ctx_or_interaction.original_message()
                self.message = await message.fetch()
        else:
            raise RuntimeError(
                "ButtonPaginator using neither Context nor Interaction"
            )

    async def show_page(self, interaction, page_number):
        self.current_page = page_number
        page = await self.source.get_page(page_number)
{'fraction_non_alphanumeric': 0.08708891595615104, 'fraction_numerical': 0.0036540803897685747, 'mean_word_length': 1.971351025331725, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5876172', 'n_tokens_mistral': 2855, 'n_tokens_neox': 2722, 'n_words': 581}