From 7164f5d8da64687cf42611e1d7a23a1e4cc9f3ca Mon Sep 17 00:00:00 2001 From: Gareth Coles Date: Mon, 6 Nov 2023 12:38:40 +0000 Subject: [PATCH] Paginator mutators --- .../pagination/BaseButtonPaginator.kt | 4 ++- .../extensions/pagination/BasePaginator.kt | 9 ++++- .../pagination/EphemeralResponsePaginator.kt | 19 +++++----- .../pagination/MessageButtonPaginator.kt | 27 +++++++------- .../pagination/PublicFollowUpPaginator.kt | 21 ++++++----- .../pagination/PublicResponsePaginator.kt | 21 ++++++----- .../builders/PageTransitionCallback.kt | 35 +++++++++++++++++++ .../pagination/builders/PaginatorBuilder.kt | 18 ++++++++++ .../kord/extensions/pagination/pages/Page.kt | 18 ++++++---- 9 files changed, 126 insertions(+), 46 deletions(-) create mode 100644 kord-extensions/src/main/kotlin/com/kotlindiscord/kord/extensions/pagination/builders/PageTransitionCallback.kt diff --git a/kord-extensions/src/main/kotlin/com/kotlindiscord/kord/extensions/pagination/BaseButtonPaginator.kt b/kord-extensions/src/main/kotlin/com/kotlindiscord/kord/extensions/pagination/BaseButtonPaginator.kt index ca5ae7fe9d..7f51657e3b 100644 --- a/kord-extensions/src/main/kotlin/com/kotlindiscord/kord/extensions/pagination/BaseButtonPaginator.kt +++ b/kord-extensions/src/main/kotlin/com/kotlindiscord/kord/extensions/pagination/BaseButtonPaginator.kt @@ -11,6 +11,7 @@ import com.kotlindiscord.kord.extensions.components.ComponentContainer import com.kotlindiscord.kord.extensions.components.buttons.PublicInteractionButton import com.kotlindiscord.kord.extensions.components.publicButton import com.kotlindiscord.kord.extensions.components.types.emoji +import com.kotlindiscord.kord.extensions.pagination.builders.PageTransitionCallback import com.kotlindiscord.kord.extensions.pagination.pages.Pages import com.kotlindiscord.kord.extensions.utils.capitalizeWords import com.kotlindiscord.kord.extensions.utils.scheduling.Scheduler @@ -30,9 +31,10 @@ public abstract class BaseButtonPaginator( timeoutSeconds: Long? = null, keepEmbed: Boolean = true, switchEmoji: ReactionEmoji = if (pages.groups.size == 2) EXPAND_EMOJI else SWITCH_EMOJI, + mutator: PageTransitionCallback? = null, bundle: String? = null, locale: Locale? = null, -) : BasePaginator(pages, owner, timeoutSeconds, keepEmbed, switchEmoji, bundle, locale) { +) : BasePaginator(pages, owner, timeoutSeconds, keepEmbed, switchEmoji, mutator, bundle, locale) { /** [ComponentContainer] instance managing the buttons for this paginator. **/ public open var components: ComponentContainer = ComponentContainer() diff --git a/kord-extensions/src/main/kotlin/com/kotlindiscord/kord/extensions/pagination/BasePaginator.kt b/kord-extensions/src/main/kotlin/com/kotlindiscord/kord/extensions/pagination/BasePaginator.kt index 8d0647bcf2..229539cccf 100644 --- a/kord-extensions/src/main/kotlin/com/kotlindiscord/kord/extensions/pagination/BasePaginator.kt +++ b/kord-extensions/src/main/kotlin/com/kotlindiscord/kord/extensions/pagination/BasePaginator.kt @@ -9,6 +9,7 @@ package com.kotlindiscord.kord.extensions.pagination import com.kotlindiscord.kord.extensions.ExtensibleBot import com.kotlindiscord.kord.extensions.i18n.TranslationsProvider import com.kotlindiscord.kord.extensions.koin.KordExKoinComponent +import com.kotlindiscord.kord.extensions.pagination.builders.PageTransitionCallback import com.kotlindiscord.kord.extensions.pagination.pages.Page import com.kotlindiscord.kord.extensions.pagination.pages.Pages import dev.kord.core.Kord @@ -62,6 +63,7 @@ public abstract class BasePaginator( public open val timeoutSeconds: Long? = null, public open val keepEmbed: Boolean = true, public open val switchEmoji: ReactionEmoji = if (pages.groups.size == 2) EXPAND_EMOJI else SWITCH_EMOJI, + public open val mutator: PageTransitionCallback? = null, public open val bundle: String? = null, locale: Locale? = null @@ -118,8 +120,13 @@ public abstract class BasePaginator( pages.groups[currentGroup]!!.size, groupEmoji, allGroups.indexOf(currentGroup), - allGroups.size + allGroups.size, + mutator?.pageMutator )() + + mutator?.paginatorMutator?.let { + it(this@BasePaginator) + } } /** Send the paginator, given the current context. If it's already sent, update it. **/ diff --git a/kord-extensions/src/main/kotlin/com/kotlindiscord/kord/extensions/pagination/EphemeralResponsePaginator.kt b/kord-extensions/src/main/kotlin/com/kotlindiscord/kord/extensions/pagination/EphemeralResponsePaginator.kt index 492a9c28ab..f2585c421f 100644 --- a/kord-extensions/src/main/kotlin/com/kotlindiscord/kord/extensions/pagination/EphemeralResponsePaginator.kt +++ b/kord-extensions/src/main/kotlin/com/kotlindiscord/kord/extensions/pagination/EphemeralResponsePaginator.kt @@ -6,6 +6,7 @@ package com.kotlindiscord.kord.extensions.pagination +import com.kotlindiscord.kord.extensions.pagination.builders.PageTransitionCallback import com.kotlindiscord.kord.extensions.pagination.builders.PaginatorBuilder import com.kotlindiscord.kord.extensions.pagination.pages.Pages import dev.kord.core.behavior.UserBehavior @@ -21,15 +22,16 @@ import java.util.* * @param interaction Interaction response behaviour to work with. */ public class EphemeralResponsePaginator( - pages: Pages, - owner: UserBehavior? = null, - timeoutSeconds: Long? = null, - switchEmoji: ReactionEmoji = if (pages.groups.size == 2) EXPAND_EMOJI else SWITCH_EMOJI, - bundle: String? = null, - locale: Locale? = null, + pages: Pages, + owner: UserBehavior? = null, + timeoutSeconds: Long? = null, + switchEmoji: ReactionEmoji = if (pages.groups.size == 2) EXPAND_EMOJI else SWITCH_EMOJI, + mutator: PageTransitionCallback? = null, + bundle: String? = null, + locale: Locale? = null, - public val interaction: EphemeralMessageInteractionResponseBehavior, -) : BaseButtonPaginator(pages, owner, timeoutSeconds, true, switchEmoji, bundle, locale) { + public val interaction: EphemeralMessageInteractionResponseBehavior, +) : BaseButtonPaginator(pages, owner, timeoutSeconds, true, switchEmoji, mutator, bundle, locale) { /** Whether this paginator has been set up for the first time. **/ public var isSetup: Boolean = false @@ -77,6 +79,7 @@ public fun EphemeralResponsePaginator( pages = builder.pages, owner = builder.owner, timeoutSeconds = builder.timeoutSeconds, + mutator = builder.mutator, bundle = builder.bundle, locale = builder.locale, interaction = interaction, diff --git a/kord-extensions/src/main/kotlin/com/kotlindiscord/kord/extensions/pagination/MessageButtonPaginator.kt b/kord-extensions/src/main/kotlin/com/kotlindiscord/kord/extensions/pagination/MessageButtonPaginator.kt index acbd9cd111..c1a549f941 100644 --- a/kord-extensions/src/main/kotlin/com/kotlindiscord/kord/extensions/pagination/MessageButtonPaginator.kt +++ b/kord-extensions/src/main/kotlin/com/kotlindiscord/kord/extensions/pagination/MessageButtonPaginator.kt @@ -6,6 +6,7 @@ package com.kotlindiscord.kord.extensions.pagination +import com.kotlindiscord.kord.extensions.pagination.builders.PageTransitionCallback import com.kotlindiscord.kord.extensions.pagination.builders.PaginatorBuilder import com.kotlindiscord.kord.extensions.pagination.pages.Pages import dev.kord.core.behavior.UserBehavior @@ -28,18 +29,19 @@ import java.util.* * @param targetChannel Target channel to send the paginator to, if [targetMessage] isn't provided. */ public class MessageButtonPaginator( - pages: Pages, - owner: UserBehavior? = null, - timeoutSeconds: Long? = null, - keepEmbed: Boolean = true, - switchEmoji: ReactionEmoji = if (pages.groups.size == 2) EXPAND_EMOJI else SWITCH_EMOJI, - bundle: String? = null, - locale: Locale? = null, - - public val pingInReply: Boolean = true, - public val targetChannel: MessageChannelBehavior? = null, - public val targetMessage: Message? = null, -) : BaseButtonPaginator(pages, owner, timeoutSeconds, keepEmbed, switchEmoji, bundle, locale) { + pages: Pages, + owner: UserBehavior? = null, + timeoutSeconds: Long? = null, + keepEmbed: Boolean = true, + switchEmoji: ReactionEmoji = if (pages.groups.size == 2) EXPAND_EMOJI else SWITCH_EMOJI, + mutator: PageTransitionCallback? = null, + bundle: String? = null, + locale: Locale? = null, + + public val pingInReply: Boolean = true, + public val targetChannel: MessageChannelBehavior? = null, + public val targetMessage: Message? = null, +) : BaseButtonPaginator(pages, owner, timeoutSeconds, keepEmbed, switchEmoji, mutator, bundle, locale) { init { if (targetChannel == null && targetMessage == null) { throw IllegalArgumentException("Must provide either a target channel or target message") @@ -115,6 +117,7 @@ public fun MessageButtonPaginator( owner = builder.owner, timeoutSeconds = builder.timeoutSeconds, keepEmbed = builder.keepEmbed, + mutator = builder.mutator, bundle = builder.bundle, locale = builder.locale, diff --git a/kord-extensions/src/main/kotlin/com/kotlindiscord/kord/extensions/pagination/PublicFollowUpPaginator.kt b/kord-extensions/src/main/kotlin/com/kotlindiscord/kord/extensions/pagination/PublicFollowUpPaginator.kt index 7ca6548de2..acf02e0414 100644 --- a/kord-extensions/src/main/kotlin/com/kotlindiscord/kord/extensions/pagination/PublicFollowUpPaginator.kt +++ b/kord-extensions/src/main/kotlin/com/kotlindiscord/kord/extensions/pagination/PublicFollowUpPaginator.kt @@ -6,6 +6,7 @@ package com.kotlindiscord.kord.extensions.pagination +import com.kotlindiscord.kord.extensions.pagination.builders.PageTransitionCallback import com.kotlindiscord.kord.extensions.pagination.builders.PaginatorBuilder import com.kotlindiscord.kord.extensions.pagination.pages.Pages import dev.kord.core.behavior.UserBehavior @@ -25,16 +26,17 @@ import java.util.* * @param interaction Interaction response behaviour to work with. */ public class PublicFollowUpPaginator( - pages: Pages, - owner: UserBehavior? = null, - timeoutSeconds: Long? = null, - keepEmbed: Boolean = true, - switchEmoji: ReactionEmoji = if (pages.groups.size == 2) EXPAND_EMOJI else SWITCH_EMOJI, - bundle: String? = null, - locale: Locale? = null, + pages: Pages, + owner: UserBehavior? = null, + timeoutSeconds: Long? = null, + keepEmbed: Boolean = true, + switchEmoji: ReactionEmoji = if (pages.groups.size == 2) EXPAND_EMOJI else SWITCH_EMOJI, + mutator: PageTransitionCallback? = null, + bundle: String? = null, + locale: Locale? = null, - public val interaction: FollowupPermittingInteractionResponseBehavior, -) : BaseButtonPaginator(pages, owner, timeoutSeconds, keepEmbed, switchEmoji, bundle, locale) { + public val interaction: FollowupPermittingInteractionResponseBehavior, +) : BaseButtonPaginator(pages, owner, timeoutSeconds, keepEmbed, switchEmoji, mutator, bundle, locale) { /** Follow-up interaction to use for this paginator's embeds. Will be created by [send]. **/ public var embedInteraction: PublicFollowupMessage? = null @@ -92,6 +94,7 @@ public fun PublicFollowUpPaginator( owner = builder.owner, timeoutSeconds = builder.timeoutSeconds, keepEmbed = builder.keepEmbed, + mutator = builder.mutator, bundle = builder.bundle, locale = builder.locale, interaction = interaction, diff --git a/kord-extensions/src/main/kotlin/com/kotlindiscord/kord/extensions/pagination/PublicResponsePaginator.kt b/kord-extensions/src/main/kotlin/com/kotlindiscord/kord/extensions/pagination/PublicResponsePaginator.kt index 37932fe7bf..4018818a0e 100644 --- a/kord-extensions/src/main/kotlin/com/kotlindiscord/kord/extensions/pagination/PublicResponsePaginator.kt +++ b/kord-extensions/src/main/kotlin/com/kotlindiscord/kord/extensions/pagination/PublicResponsePaginator.kt @@ -6,6 +6,7 @@ package com.kotlindiscord.kord.extensions.pagination +import com.kotlindiscord.kord.extensions.pagination.builders.PageTransitionCallback import com.kotlindiscord.kord.extensions.pagination.builders.PaginatorBuilder import com.kotlindiscord.kord.extensions.pagination.pages.Pages import dev.kord.core.behavior.UserBehavior @@ -21,16 +22,17 @@ import java.util.* * @param interaction Interaction response behaviour to work with. */ public class PublicResponsePaginator( - pages: Pages, - owner: UserBehavior? = null, - timeoutSeconds: Long? = null, - keepEmbed: Boolean = true, - switchEmoji: ReactionEmoji = if (pages.groups.size == 2) EXPAND_EMOJI else SWITCH_EMOJI, - bundle: String? = null, - locale: Locale? = null, + pages: Pages, + owner: UserBehavior? = null, + timeoutSeconds: Long? = null, + keepEmbed: Boolean = true, + switchEmoji: ReactionEmoji = if (pages.groups.size == 2) EXPAND_EMOJI else SWITCH_EMOJI, + mutator: PageTransitionCallback? = null, + bundle: String? = null, + locale: Locale? = null, - public val interaction: PublicMessageInteractionResponseBehavior, -) : BaseButtonPaginator(pages, owner, timeoutSeconds, keepEmbed, switchEmoji, bundle, locale) { + public val interaction: PublicMessageInteractionResponseBehavior, +) : BaseButtonPaginator(pages, owner, timeoutSeconds, keepEmbed, switchEmoji, mutator, bundle, locale) { /** Whether this paginator has been set up for the first time. **/ public var isSetup: Boolean = false @@ -79,6 +81,7 @@ public fun PublicResponsePaginator( owner = builder.owner, timeoutSeconds = builder.timeoutSeconds, keepEmbed = builder.keepEmbed, + mutator = builder.mutator, bundle = builder.bundle, locale = builder.locale, interaction = interaction, diff --git a/kord-extensions/src/main/kotlin/com/kotlindiscord/kord/extensions/pagination/builders/PageTransitionCallback.kt b/kord-extensions/src/main/kotlin/com/kotlindiscord/kord/extensions/pagination/builders/PageTransitionCallback.kt new file mode 100644 index 0000000000..c426d618bf --- /dev/null +++ b/kord-extensions/src/main/kotlin/com/kotlindiscord/kord/extensions/pagination/builders/PageTransitionCallback.kt @@ -0,0 +1,35 @@ +package com.kotlindiscord.kord.extensions.pagination.builders + +import com.kotlindiscord.kord.extensions.pagination.BasePaginator +import com.kotlindiscord.kord.extensions.pagination.pages.Page +import dev.kord.rest.builder.message.EmbedBuilder + +public typealias PageMutator = suspend EmbedBuilder.(page: Page) -> Unit +public typealias PaginatorMutator = suspend BasePaginator.() -> Unit + +/** Builder containing callbacks used to modify paginators and their page content. **/ +public class PageTransitionCallback { + /** @suppress Variable storing the page mutator. **/ + public var pageMutator: PageMutator? = null + + /** @suppress Variable storing the paginator mutator. **/ + public var paginatorMutator: PaginatorMutator? = null + + /** + * Set the page mutator callback. + * + * Called just after we apply the page's embed builder, and just before the page modifies the embed's footer. + */ + public fun page(body: PageMutator) { + pageMutator = body + } + + /** + * Set the paginator mutator callback. + * + * Called just after we build a page embed, and just before that page is sent on Discord. + */ + public fun paginator(body: PaginatorMutator) { + paginatorMutator = body + } +} diff --git a/kord-extensions/src/main/kotlin/com/kotlindiscord/kord/extensions/pagination/builders/PaginatorBuilder.kt b/kord-extensions/src/main/kotlin/com/kotlindiscord/kord/extensions/pagination/builders/PaginatorBuilder.kt index 8fbae05516..412ea16e8b 100644 --- a/kord-extensions/src/main/kotlin/com/kotlindiscord/kord/extensions/pagination/builders/PaginatorBuilder.kt +++ b/kord-extensions/src/main/kotlin/com/kotlindiscord/kord/extensions/pagination/builders/PaginatorBuilder.kt @@ -41,6 +41,9 @@ public class PaginatorBuilder( /** Translations bundle to use for page groups, if any. **/ public var bundle: String? = null + /** Object containing paginator mutation functions. **/ + public var mutator: PageTransitionCallback? = null + /** Add a page to [pages], using the default group. **/ public fun page(page: Page): Unit = pages.addPage(page) @@ -61,4 +64,19 @@ public class PaginatorBuilder( builder: suspend EmbedBuilder.() -> Unit ): Unit = page(group, Page(builder = builder, bundle = bundle)) + + /** + * Mutate the paginator and pages, as pages are generated and sent. + * + * @see PageTransitionCallback + */ + public suspend fun mutate( + body: suspend PageTransitionCallback.() -> Unit + ) { + val obj = PageTransitionCallback() + + body(obj) + + this.mutator = obj + } } diff --git a/kord-extensions/src/main/kotlin/com/kotlindiscord/kord/extensions/pagination/pages/Page.kt b/kord-extensions/src/main/kotlin/com/kotlindiscord/kord/extensions/pagination/pages/Page.kt index 9d090ecf63..11e7790e93 100644 --- a/kord-extensions/src/main/kotlin/com/kotlindiscord/kord/extensions/pagination/pages/Page.kt +++ b/kord-extensions/src/main/kotlin/com/kotlindiscord/kord/extensions/pagination/pages/Page.kt @@ -9,6 +9,7 @@ package com.kotlindiscord.kord.extensions.pagination.pages import com.kotlindiscord.kord.extensions.ExtensibleBot import com.kotlindiscord.kord.extensions.i18n.TranslationsProvider import com.kotlindiscord.kord.extensions.koin.KordExKoinComponent +import com.kotlindiscord.kord.extensions.pagination.builders.PageMutator import com.kotlindiscord.kord.extensions.utils.capitalizeWords import com.kotlindiscord.kord.extensions.utils.textOrNull import dev.kord.rest.builder.message.EmbedBuilder @@ -33,15 +34,20 @@ public open class Page( /** Create an embed builder for this page. **/ public open suspend fun build( - locale: Locale, - pageNum: Int, - pages: Int, - group: String?, - groupIndex: Int, - groups: Int, + locale: Locale, + pageNum: Int, + pages: Int, + group: String?, + groupIndex: Int, + groups: Int, + mutator: PageMutator? = null, ): suspend EmbedBuilder.() -> Unit = { builder() + if (mutator != null) { + mutator(this, this@Page) + } + val curFooterText = footer?.textOrNull() val curFooterIcon = footer?.icon