ModalPaginator

class discord.ext.modal_paginator.core.ModalPaginator[source]

Bases: View

A paginator for discord.ui.Modal

iter(x)

Returns an iterator of (PaginatorModal, List[discord.ui.TextInput]) for each modal in the paginator.

Added in version 1.3.

Example

1for modal, text_inputs in paginator:
2    print(modal.title)
3    for text_input in text_inputs:
4        print(text_input.label)
Parameters:
  • modals (Optional[Sequence[discord.ui.Modal]]) – The modals to add to the paginator. Modals can be added later using ModalPaginator.add_modal().

  • author_id (Optional[int]) – ID of the author that can interact with the paginator. Defaults to everyone can interact.

  • auto_finish (bool) –

    Whether the paginator should automatically finish when all required modals are filled in. Defaults to False. All modals must be required if this is True.

    This changes the following:

    1. Remove the “Finish” button.

    2. Call ModalPaginator.on_finish() when all required modals are filled in.

    Added in version 1.1.

  • check (Optional[Callable[[ModalPaginator, discord.Interaction], bool]]) – A check that is run when the paginator is interacted with (interaction_check). Defaults to None.

  • finish_callback (Optional[Callable[[ModalPaginator, discord.Interaction], Coroutine[Any, Any, Any]]]) – A callback that is run when the paginator is finished (on_finish). Defaults to None.

  • can_go_back (bool) – Whether the user can go back to previous pages using the “Previous” button. Defaults to True.

  • disable_after (bool) – Whether the paginator should disable all buttons after it’s finished or cancelled. Defaults to True.

  • timeout (float) – The timeout of the paginator. Defaults to None. Timeouts aren’t really handled.

  • sort_modals (bool) – Whether the modals should be sorted by required. Defaults to True.

  • buttons (Optional[Dict[str, Optional[discord.ui.Button]]]) –

    A dictionary of buttons to customize the default buttons of the paginator with.

    Valid keys are: "OPEN", "NEXT", "PREVIOUS", "CANCEL" and "FINISH". It’s recommended to use CustomButton instead of discord.ui.Button to customize the buttons.

    Example:

    1buttons = {
    2    # change the previous button's style to red
    3    "PREVIOUS": CustomButton(style=discord.ButtonStyle.red),
    4    # change the finish button's label to "Done"
    5    "FINISH": CustomButton(label="Done"),
    6    # remove the cancel button
    7    "CANCEL": None,
    8}
    

    See CustomButton for more info.

author_id

ID of the author that can interact with the paginator. Defaults to everyone can interact.

Type:

Optional[int]

auto_finish

Whether the paginator should automatically finish when all required modals are filled in. Defaults to False.

Added in version 1.1.

Type:

bool

Example

 1paginator = ModalPaginator(
 2    modals=[
 3        discord.ui.Modal(title="Modal 1", custom_id="modal1"),
 4        discord.ui.Modal(title="Modal 2", custom_id="modal2"),
 5        ...
 6    ],
 7    author_id=000000000000000000,
 8)
 9await paginator.send(<messageable or Interaction>)
10# don't want to use the send method? and want to send it yourself?
11# call paginator.validate_pages() before sending the view (paginator):
12# paginator.validate_pages()
13# await messageable.send("...", view=paginator)
__init__(modals=None, *, author_id=None, auto_finish=False, check=None, finish_callback=None, timeout=None, can_go_back=True, disable_after=True, sort_modals=True, buttons=None)[source]
add_modal(modal)[source]

Adds a modal to the paginator.

Parameters:

modal (discord.ui.Modal) – The modal to add.

Raises:

NotAModal – The modal is not an instance/subclass of discord.ui.Modal.

Return type:

None

property current_modal

The current modal of the paginator.

Type:

Optional[PaginatorModal]

async disable_all_buttons(interaction)[source]

Disables all buttons.

Uses the interaction if not responded else calls .edit on the ModalPaginator.message.

Parameters:

interaction (discord.Interaction) – The interaction to edit.

Return type:

None

classmethod from_text_inputs(*inputs, author_id=None, auto_finish=False, check=None, finish_callback=None, timeout=None, can_go_back=True, disable_after=True, sort_modals=True, buttons=None, titles=..., default_title='Enter your input', max_inputs_per_modal=5, titles_steps=1)[source]

A shortcut method to create a ModalPaginator with a list of text inputs.

Parameters:
  • *inputs (Union[discord.ui.TextInput, str]) –

    The text inputs to add to the modals. This can be a discord.ui.TextInput or a string which will be converted to a discord.ui.TextInput with the string as the label.

    Changed in version 1.2: This can now also take a string to convert to a discord.ui.TextInput.

  • default_title (str) –

    The default title of the modals. This is used as the title of the modals if titles is not given or is less than the amount of modals required.

    Defaults to “Enter your input”.

  • titles (Union[str, Sequence[str]]) –

    The title(s) of the modals. This can be a single string which will be used for all modals or a tuple of strings in the same order as the text inputs per 5.

    Defaults to default_title for all modals if not given.

    Example:

     1# All modals with the ``default_title`` title
     2paginator = ModalPaginator.from_text_inputs(
     3    ..., # text inputs
     4    # other parameters
     5)
     6# All modals with the same title "Waiting for input"
     7paginator = ModalPaginator.from_text_inputs(
     8    ..., # text inputs
     9    titles="Waiting for input",
    10    # other parameters
    11)
    12# First modal with title "Personal questions" and second modal with title "Hobbies questions"
    13# and the others modals with the ``default_title`` title
    14paginator = ModalPaginator.from_text_inputs(
    15    *[
    16        # text inputs for first modal
    17        text_input1, text_input2, text_input3, text_input4, text_input5,
    18        # text inputs for second modal
    19        text_input6, text_input7, text_input8, text_input9, text_input10,
    20    ],
    21    titles=("Personal questions", "Hobbies questions"),
    22    # other parameters
    23)
    24# Changing the default title
    25paginator = ModalPaginator.from_text_inputs(
    26    ..., # text inputs
    27    default_title="Please answer the following questions",
    28    # other parameters
    29)
    

  • max_inputs_per_modal (int) –

    The maximum inputs to add per each modal created. Must be between 1 and 5, both included. Defaults to 5.

    Added in version 1.3.

  • titles_step (int) –

    How much to increase the search index used on titles, if applicable. Defaults to 1.

    Added in version 1.3.

Other parameters are the same as ModalPaginator.

Added in version 1.1.

Returns:

The constructed paginator with the modals.

Return type:

ModalPaginator

get_finish_button_error_message()[source]

The error message to send when the user tries to press the “Finish” button but not all required modals are finished.

You can override this to change the error message that is sent using a dictonary with the same keys as interaction.response.send_message.

This is called in the “Finish” button.

The default implementation is the following:

{"content": "You shouldn't be able to press this button... please finish all required modals.", "ephemeral": True, "delete_after": 5}

This should be overriden in a subclass and is optional async.

Added in version 1.1.

Returns:

The error message to send.

Return type:

dict

get_modal()[source]

Returns the current modal according to the current page.

This is called in ModalPaginator.update(), ModalPaginator.validate_pages() and the “Open” button.

Returns:

The modal.

Return type:

PaginatorModal

get_next_button_error_message()[source]

The error message to send when the user tries to go to the next page but has to complete the current modal first.

You can override this to change the error message that is sent using a dictonary with the same keys as interaction.response.send_message.

This is called in the “Next” button.

The default implementation is the following:

{"content": "Please complete the current modal before going to the next one.", "ephemeral": True, "delete_after": 5}

This should be overriden in a subclass and is optional async.

Added in version 1.1.

Returns:

The error message to send.

Return type:

dict

get_open_button_error_message()[source]

The error message to send when the user tries to open the modal but ModalPaginator.current_modal is None.

You can override this to change the error message that is sent using a dictonary with the same keys as interaction.response.send_message.

This is called in the “Open” button.

The default implementation is the following:

{"content": "Please complete the current modal before going to the next one.", "ephemeral": True, "delete_after": 5}

This should be overriden in a subclass and is optional async.

Added in version 1.1.

Returns:

The error message to send.

Return type:

dict

get_previous_button_error_message()[source]

The error message to send when the user tries to go back to a previous page but has to complete the current modal first.

You can override this to change the error message that is sent using a dictonary with the same keys as interaction.response.send_message.

This is called in the “Previous” button.

The default implementation is the following:

{"content": "Please complete the current modal before going back.", "ephemeral": True, "delete_after": 5}

This should be overriden in a subclass and is optional async.

Added in version 1.1.

Returns:

The error message to send.

Return type:

dict

async interaction_check(interaction)[source]

This is called by the library when the paginator is interacted with and when the modals are interacted with.

The default implementation is the following:

  • Check if a check was passed to the paginator. If so, run it.

else:

  • Check if the author ID is set. If so, check if the interaction’s user ID is the same as the author ID.

else:

Parameters:

interaction (discord.Interaction) – The interaction to check.

Returns:

Whether the interaction should be processed.

Return type:

bool

property message

Optional[Union[Message, WebhookMessage, InteractionMessage]]: The message that the paginator is attached to. This is set in ModalPaginator.send().

This is None if the paginator is not sent using ModalPaginator.send().

property modals

The modals in the paginator.

Type:

List[PaginatorModal]

async on_cancel(interaction)[source]

A callback that is called when the paginator is cancelled. This is called when the “Cancel” button is pressed.

The default implementation does nothing.

Parameters:

interaction (discord.Interaction) – The last interaction that was used for the paginator.

Return type:

None

async on_finish(interaction)[source]

A callback that is called when the paginator is finished. This is called when the “Finish” button is pressed.

The default implementation does nothing.

Parameters:

interaction (discord.Interaction) – The last interaction that was used for the paginator.

Return type:

None

property page_string

String that represents the current page.

By default, this is {current_modal.title}\n\n{current_page + 1}/{len(modals)} if the current modal is not None else {current_page + 1}/{len(modals)}.

Type:

str

remove_modal(modal)[source]

Removes a modal from the paginator. Nothing happens if the modal is not in the paginator.

Parameters:

modal (PaginatorModal) – The modal to remove.

Return type:

None

async send(obj, *, add_page_string=True, return_message=False, **kwargs)[source]

Sends the paginator.

This calls ModalPaginator.validate_pages() before sending the paginator. Make sure to call said method if subclassing and overriding this method.

Changed in version 1.2: This now can return None if return_message is False.

Changed in version 1.3: This always returns the message/callback that was sent now.

Parameters:
  • obj (Union[Messageable, Interaction, Context]) – The desination to send the paginator to. if Interaction is passed, the paginator will be sent as a response to the interaction or as a followup if the interaction is already responded to.

  • add_page_string (bool) –

    Whether to add the ModalPaginator.page_string to the message/response’s content. Defaults to True. Will be appended to the content if content is given in kwargs as {page_string}\n\n{content}.

    You can set this to False if you want to add the page string anywhere else in the content yourself or if you don’t want to add it at all.

    Added in version 1.2.

  • return_message (bool) –

    Whether to return the message that was sent. Defaults to False.

    This is useful if you don’t want to fetch the interaction’s message after sending the paginator or other reasons.

    Added in version 1.2.

    Deprecated since version 1.3: This is deprecated as the method now returns the message/callback that was sent.

  • **kwargs (Any) –

    Additional keyword arguments to the destination’s sending method.

    Beware that the kwargs may differ depending on the destination. E.g, interaction followup vs message sending.

    Changed in version 1.2: These are now passed to the destination’s sending method. A bug was fixed where the kwargs were not passed.

Returns:

The message that was sent.

discord.Interaction.original_response() is used if obj is an discord.Interaction and the interaction was not responded to. Set return_message to disable this.

Return type:

Union[Message, WebhookMessage, InteractionMessage]

property text_inputs

The text inputs in the paginator.

This basically returns a list of all PaginatorModal.text_inputs from all ModalPaginator.modals together in one list.

Added in version 1.1.

Changed in version 1.2: PaginatorModal.text_inputs is used over discord.ui.Modal.children.

Type:

List[discord.ui.TextInput]

async update(interaction)[source]

Updates the paginator’s message.

Parameters:

interaction (discord.Interaction) – The interaction to use for the paginator.

Return type:

None

validate_pages()[source]

Validates all modals in the paginator. Basically checks if all modals are instances of discord.ui.Modal and outputs a friendly error message if not.

This is called in ModalPaginator.send().

This does the following:

  1. Checks if all modals are instances of discord.ui.Modal.

  2. Checks whether auto_finish is True and if so, checks if each modal is required.

  3. Sorts the modals by required if sort_modals is True.

  4. Sets the ModalPaginator.current_modal to the first modal in the list.

  5. Handles the button states.

This should be called before sending the paginator if subclassing and overriding send.

Raises:
Return type:

None

PaginatorModal

class discord.ext.modal_paginator.core.PaginatorModal[source]

Bases: Modal

Represents a modal that can be used in a ModalPaginator.

Parameters:
  • *inputs (discord.ui.TextInput) – The inputs to add to the modal.

  • title (str) – The title of the modal.

  • custom_id (Optional[str]) – The custom ID of the modal. Defaults to discord.utils.MISSING.

  • timeout (float) – The timeout of the modal. Defaults to 180.0.

  • callback (Optional[Callable[[PaginatorModal, discord.Interaction], Coroutine[Any, Any, Any]]]) – A callback that is run when the modal is interacted with (on_submit). Defaults to None.

  • required (bool) – Whether the modal is required to be filled out before the paginator can be finished / user can go to the next/previous page. Defaults to False.

add_input(*, label, style=('short', 1), custom_id=..., placeholder=None, default=None, required=True, min_length=None, max_length=None, row=None)[source]

Adds a text input to the modal. This an easy way to add a text input to the modal.

The added text input is returned.

Parameters below are copied from discord.ui.TextInput.

Parameters:
  • label (str) – The label to display above the text input.

  • custom_id (str) – The ID of the text input that gets received during an interaction. If not given then one is generated for you.

  • style (discord.TextStyle) – The style of the text input.

  • placeholder (Optional[str]) – The placeholder text to display when the text input is empty.

  • default (Optional[str]) – The default value of the text input.

  • required (bool) – Whether the text input is required.

  • min_length (Optional[int]) – The minimum length of the text input.

  • max_length (Optional[int]) – The maximum length of the text input.

  • row (Optional[int]) – The relative row this text input belongs to. A Discord component can only have 5 rows. By default, items are arranged automatically into those 5 rows. If you’d like to control the relative positioning of the row then passing an index is advised. For example, row=1 will show up before row=2. Defaults to None, which is automatic ordering. The row number must be between 0 and 4 (i.e. zero indexed).

Returns:

The text input that was added.

Return type:

discord.ui.TextInput

append_input(text_input, /)[source]

Appends a text input to the modal. Technically an alias for discord.ui.Modal.add_item() but this returns the text input instead of the modal.

Parameters:

text_input (discord.ui.TextInput) – The text input to append.

Returns:

The text input that was appended.

Return type:

discord.ui.TextInput

async interaction_check(interaction)[source]

This is called by the library when the modal is interacted with.

The default implementation calls ModalPaginator.interaction_check.

Parameters:

interaction (discord.Interaction) – The interaction to check.

Returns:

Whether the interaction should be processed.

Return type:

bool

async on_submit(interaction)[source]

Called when the modal is submitted.

The default implementation is the following:

  1. Increment the current page of the paginator.

  2. Stop the paginator using the stop method.

  • If a callback was passed to the modal, run it.

else:

Parameters:

interaction (discord.Interaction) – The interaction to use for the paginator.

Return type:

None

property paginator

The paginator of the modal.

Type:

ModalPaginator

property text_inputs

The text inputs in the modal.

This basically gets all discord.ui.TextInput’s from the modal’s children.

Added in version 1.2.

Type:

List[discord.ui.TextInput]