Skip to main content

🔢 Pagination Session

Pre-knowledge

It's recommended that you first read the ️👤 Session documentation, since this is an extension of it.

A PaginationSession is a special type of session made to be paginated (have pages).

From a manager's perspective, a pagination session is just a regular session. The pagination logic happens inside the session itself.

For the case of AbstractPaginationSession, it does it by implementing #update(), which does the following:

  1. It attempts to extract a referred page, depending on the interaction type:
    • Buttons: Extracts from #customId.
    • SelectMenu: Extracts from #customId. If no page is present there, it's a StringSelectMenu and only one value was selected, it extracts from the selected value.
    • Modal: Extracts from #customId. If no page is present there, it iterates through the modal's components, searching for a component whose customId is the session's customId. If there is one, the page is extracted from said component's value.
  2. If there's no referred page, it uses super.update(), which will call #handleButton(), #handleSelectMenu() or #handleModal() (like a regular AbstractSession).
  3. If there's a referred page, it updates its currentPage and calls #updatePage().
Overriding page resolving

You can change the page resolving behavior by overriding #update(), #extractPageFromInteraction(), #extractPageFromButton(), #extractPageFromSelectMenu() or #extractPageFromModal().

👷 Creation

You can create a paginated session by either:

  • Extending AbstractPaginationSession from @framework (recommended).
  • Implementing the PaginationSession interface from @core.

After creating it, start it via SessionManager#start().

import { AbstractPaginationSession, SessionUpdateInteraction } from '@nyx-discord/framework';

class MyPaginationSession extends AbstractPaginationSession {
public async handleStart() {
const page = this.createPage();

await this.startInteraction.reply(page);
}

protected async updatePage(interaction: SessionUpdateInteraction) {
const newPage = this.createPage();
await interaction.editReply(newPage);
return true;
}

protected createPage() {
const randomPage = Math.floor(Math.random() * 10);

const customIdBuilder = this.customId.clone();
const customId = customIdBuilder.setPage(randomPage).build();

const button = new ButtonBuilder()
.setCustomId(customId)
.setLabel('Go to a random page!')
.setStyle(ButtonStyle.Primary);
const buttonRow = new ActionRowBuilder<ButtonBuilder>().addComponents(button);

const pageRow = this.buildDefaultPageRow();

return {
content: `You're on page ${this.currentPage}`,
components: [buttonRow, pageRow]
};
}
}

// Somewhere in your code, like inside a command...

const sessionId = 'mySessionId'; // Ideally randomly generated
const session = new MyPaginationSession(bot, sessionId, interaction);
await bot.getSessionManager().start(session);

💬 Pagination Custom Ids

When using a pagination session the SessionCustomIdCodec can generate a PaginationCustomIdBuilder, an extension of CustomIdBuilder that supports adding a page reference to the customId being built.

const codec = bot.getSessionManager().getCustomIdCodec();

const builder = codec.createPageCustomIdBuilder(session);
builder.push('foo').push('bar').setPage(1);

const customId = builder.build();

For AbstractPaginationSession:

  • A customId not referring to a page is handled by AbstractSession#update() (see 👤 Session (📝 Updating)).
  • A customId referring to a page is handled by AbstractPaginationSession#updatePage().

✨ Component Examples

const buttonId = builder.cloneSetPage(3).build();

const button = new ButtonBuilder()
.setCustomId(buttonId)
.setLabel('Go to page 3')
.setStyle(ButtonStyle.Primary);

🧩 Utility methods

The AbstractPaginationSession provides the following protected utility methods:

  • #buildDefaultPageRow(): Builds a component row with default "next"/"previous" buttons.
  • #buildCustomIdForPage(page: number): Builds a customId for a specific page.