Skip to content

Commit 8170aad

Browse files
committed
Fancy registration button for botfest (as a treat)
1 parent 396f9cd commit 8170aad

File tree

5 files changed

+173
-74
lines changed

5 files changed

+173
-74
lines changed

botfest/src/main/kotlin/net/modfest/botfest/App.kt

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,10 @@ package net.modfest.botfest
22

33
import com.google.gson.Gson
44
import dev.kord.common.entity.Snowflake
5-
import dev.kord.gateway.ALL
6-
import dev.kord.gateway.Intent
7-
import dev.kord.gateway.Intents
85
import dev.kordex.core.ExtensibleBot
96
import dev.kordex.core.utils.env
107
import dev.kordex.core.utils.envOrNull
11-
import dev.kordex.core.utils.extraData
128
import dev.kordex.core.utils.loadModule
13-
import kotlinx.coroutines.flow.launchIn
14-
import kotlinx.coroutines.flow.subscribe
159
import net.modfest.botfest.extensions.*
1610
import net.modfest.botfest.i18n.Translations
1711
import net.modfest.platform.pojo.PlatformErrorResponse
@@ -37,6 +31,9 @@ suspend fun main() {
3731
single {
3832
Platform(PLATFORM_API_URL)
3933
}
34+
single {
35+
CommandReferences()
36+
}
4037
}
4138
}
4239
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package net.modfest.botfest
2+
3+
import dev.kordex.core.commands.application.slash.SlashCommand
4+
5+
class CommandReferences {
6+
var registerCommand: SlashCommand<*, *, *>? = null
7+
var unregisterCommand: SlashCommand<*, *, *>? = null
8+
}

botfest/src/main/kotlin/net/modfest/botfest/extensions/AdminCommands.kt

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,22 @@
11
package net.modfest.botfest.extensions
22

3+
import dev.kord.common.entity.ButtonStyle
4+
import dev.kord.core.behavior.channel.createMessage
5+
import dev.kord.rest.builder.message.actionRow
6+
import dev.kord.rest.builder.message.embed
37
import dev.kordex.core.commands.Arguments
48
import dev.kordex.core.commands.application.slash.ephemeralSubCommand
9+
import dev.kordex.core.commands.application.slash.publicSubCommand
510
import dev.kordex.core.commands.converters.impl.attachment
611
import dev.kordex.core.commands.converters.impl.optionalString
12+
import dev.kordex.core.components.components
713
import dev.kordex.core.extensions.Extension
814
import dev.kordex.core.extensions.ephemeralSlashCommand
915
import dev.kordex.core.i18n.withContext
1016
import dev.kordex.core.koin.KordExKoinComponent
1117
import dev.kordex.core.utils.suggestStringCollection
18+
import dev.kordex.modules.dev.unsafe.annotations.UnsafeAPI
19+
import net.modfest.botfest.CommandReferences
1220
import net.modfest.botfest.MAIN_GUILD_ID
1321
import net.modfest.botfest.Platform
1422
import net.modfest.botfest.i18n.Translations
@@ -21,7 +29,9 @@ import org.koin.core.component.inject
2129
class AdminCommands : Extension(), KordExKoinComponent {
2230
override val name = "admin"
2331
val platform: Platform by inject()
32+
val commands: CommandReferences by inject()
2433

34+
@OptIn(UnsafeAPI::class)
2535
override suspend fun setup() {
2636
ephemeralSlashCommand {
2737
name = Translations.Commands.Group.Admin.name
@@ -69,6 +79,41 @@ class AdminCommands : Extension(), KordExKoinComponent {
6979
}
7080
}
7181
}
82+
83+
// Sends the message where users can press a button to update
84+
ephemeralSubCommand {
85+
name = Translations.Commands.Admin.Registermsg.name
86+
description = Translations.Commands.Admin.Registermsg.description
87+
88+
action {
89+
val curEvent = platform.getCurrentEvent().event!!
90+
val eventData = platform.getEvent(curEvent)
91+
this.channel.createMessage {
92+
embed {
93+
title = Translations.Commands.Admin.Registermsg.Embed.title
94+
.translateNamed(
95+
"event_name" to eventData.name
96+
)
97+
description = Translations.Commands.Admin.Registermsg.Embed.content
98+
.translateNamed(
99+
"event_name" to eventData.name,
100+
"cmdRegister" to (commands.registerCommand?.mention ?: "/register"),
101+
"cmdUnregister" to (commands.unregisterCommand?.mention ?: "/event unregister"),
102+
)
103+
color = dev.kord.common.Color(Integer.parseInt(eventData.colors.primary, 16))
104+
}
105+
actionRow {
106+
interactionButton(ButtonStyle.Primary, "modfest-registration-button") {
107+
label = Translations.Commands.Admin.Registermsg.button
108+
.translateNamed()
109+
}
110+
}
111+
}
112+
respond {
113+
content = "Done"
114+
}
115+
}
116+
}
72117
}
73118
}
74119

botfest/src/main/kotlin/net/modfest/botfest/extensions/EventCommands.kt

Lines changed: 110 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,35 @@
11
package net.modfest.botfest.extensions
22

3+
import dev.kord.common.annotation.KordUnsafe
4+
import dev.kord.core.behavior.interaction.ActionInteractionBehavior
5+
import dev.kord.core.behavior.interaction.respondEphemeral
6+
import dev.kord.core.behavior.interaction.response.EphemeralMessageInteractionResponseBehavior
37
import dev.kord.core.behavior.interaction.response.edit
8+
import dev.kord.core.entity.User
9+
import dev.kord.core.event.interaction.ButtonInteractionCreateEvent
10+
import dev.kord.core.event.interaction.GuildButtonInteractionCreateEvent
11+
import dev.kord.core.event.interaction.InteractionCreateEvent
12+
import dev.kord.rest.builder.message.create.InteractionResponseCreateBuilder
13+
import dev.kordex.core.commands.Arguments
14+
import dev.kordex.core.commands.application.slash.EphemeralSlashCommand
415
import dev.kordex.core.commands.application.slash.ephemeralSubCommand
516
import dev.kordex.core.commands.application.slash.group
617
import dev.kordex.core.components.forms.ModalForm
18+
import dev.kordex.core.events.EventContext
719
import dev.kordex.core.extensions.Extension
820
import dev.kordex.core.extensions.ephemeralSlashCommand
21+
import dev.kordex.core.extensions.event
922
import dev.kordex.core.i18n.toKey
1023
import dev.kordex.core.i18n.types.Key
1124
import dev.kordex.core.i18n.withContext
1225
import dev.kordex.core.koin.KordExKoinComponent
26+
import dev.kordex.core.types.TranslatableContext
1327
import dev.kordex.modules.dev.unsafe.annotations.UnsafeAPI
1428
import dev.kordex.modules.dev.unsafe.commands.slash.InitialSlashCommandResponse
29+
import dev.kordex.modules.dev.unsafe.commands.slash.UnsafeSlashCommand
30+
import dev.kordex.modules.dev.unsafe.components.forms.UnsafeModalForm
1531
import dev.kordex.modules.dev.unsafe.extensions.unsafeSlashCommand
32+
import net.modfest.botfest.CommandReferences
1633
import net.modfest.botfest.MAIN_GUILD_ID
1734
import net.modfest.botfest.Platform
1835
import net.modfest.botfest.i18n.Translations
@@ -25,14 +42,30 @@ import java.util.regex.Pattern
2542
/**
2643
* Provides various debugging commands
2744
*/
45+
@OptIn(UnsafeAPI::class)
2846
class EventCommands : Extension(), KordExKoinComponent {
47+
val cmds: CommandReferences by inject()
2948
override val name = "event"
3049
val platform: Platform by inject()
3150

32-
@OptIn(UnsafeAPI::class)
51+
@OptIn(KordUnsafe::class)
3352
override suspend fun setup() {
3453
// Register command
35-
unsafeSlashCommand {
54+
event<GuildButtonInteractionCreateEvent> {
55+
check {
56+
failIfNot(event.interaction.componentId == "modfest-registration-button")
57+
}
58+
action {
59+
doRegister(
60+
{ event.interaction.respondEphemeral(it) },
61+
{ event.interaction.deferEphemeralResponseUnsafe() },
62+
{ it.sendAndDeferEphemeral(this@action) },
63+
event.interaction.user
64+
)
65+
}
66+
}
67+
68+
cmds.registerCommand = unsafeSlashCommand {
3669
name = Translations.Commands.Register.name
3770
description = Translations.Commands.Register.description
3871
guild(MAIN_GUILD_ID)
@@ -44,70 +77,12 @@ class EventCommands : Extension(), KordExKoinComponent {
4477
initialResponse = InitialSlashCommandResponse.None
4578

4679
action {
47-
val curEvent = platform.getCurrentEvent().event;
48-
if (curEvent == null) {
49-
ackEphemeral {
50-
content = Translations.Commands.Register.Response.noevent
51-
.withContext(this@action)
52-
.translateNamed()
53-
}
54-
return@action // Do *not* try to send any modals, we've already replied
55-
}
56-
57-
var platformUser = platform.getUser(this.user)
58-
59-
var message = if (platformUser == null) {
60-
val modal = RegisterModal()
61-
62-
modal.displayName.initialValue = this.member?.asMember()?.effectiveName?.toKey(Locale.UK)
63-
modal.displayName.translateInitialValue = false
64-
65-
val result = modal.sendAndDeferEphemeral(this)
66-
67-
// Result will be null if the user didn't enter anything
68-
// or if the modal timed out
69-
if (result == null) {
70-
return@action
71-
}
72-
73-
platformUser = platform.authenticatedAsBotFest().createUser(UserCreateData(
74-
modal.displayName.value,
75-
modal.pronouns.value,
76-
modal.modrinthSlug.value,
77-
this.user.id.value.toString()
78-
))
79-
80-
result
81-
} else {
82-
// User already has their data registered in platform
83-
// Ack immediately: we only have 5 seconds for any ack
84-
ackEphemeral()
85-
}
86-
87-
// Okay, we now have a user that's registered. And we have a
88-
// message we can edit to respond to the user
89-
// let's perform the actual registration
90-
val event = platform.getEvent(curEvent)
91-
92-
if (platformUser.registered.contains(curEvent)) {
93-
message.edit {
94-
content = Translations.Commands.Register.Response.already
95-
.withContext(this@action)
96-
.translateNamed(
97-
"event" to event.name
98-
)
99-
}
100-
return@action
101-
}
102-
103-
platform.withAuth(user).registerMe(event)
104-
message.edit {
105-
content = Translations.Commands.Register.Response.success
106-
.withContext(this@action)
107-
.translateNamed(
108-
"event" to event.name
109-
)
110-
}
80+
doRegister(
81+
{ ackEphemeral(it) },
82+
{ ackEphemeral() },
83+
{ it.sendAndDeferEphemeral(this@action) },
84+
this.user.asUser()
85+
)
11186
}
11287
}
11388

@@ -119,7 +94,7 @@ class EventCommands : Extension(), KordExKoinComponent {
11994
guild(MAIN_GUILD_ID)
12095

12196
// unregister command
122-
ephemeralSubCommand {
97+
cmds.unregisterCommand = ephemeralSubCommand {
12398
name = Translations.Commands.Event.Unregister.name
12499
description = Translations.Commands.Event.Unregister.description
125100

@@ -161,6 +136,74 @@ class EventCommands : Extension(), KordExKoinComponent {
161136
}
162137
}
163138

139+
suspend inline fun TranslatableContext.doRegister(respond: (InteractionResponseCreateBuilder.() -> Unit) -> EphemeralMessageInteractionResponseBehavior, ackBlank: () -> EphemeralMessageInteractionResponseBehavior, sendModal: (ModalForm) -> EphemeralMessageInteractionResponseBehavior?, user: User) {
140+
val curEvent = platform.getCurrentEvent().event;
141+
if (curEvent == null) {
142+
val c = Translations.Commands.Register.Response.noevent
143+
.withContext(this@doRegister)
144+
.translateNamed()
145+
respond {
146+
content = c
147+
}
148+
return // Do *not* try to send any modals, we've already replied
149+
}
150+
151+
var platformUser = platform.getUser(user)
152+
153+
var message = if (platformUser == null) {
154+
val modal = RegisterModal()
155+
156+
modal.displayName.initialValue = user.asMember(MAIN_GUILD_ID).effectiveName.toKey(Locale.UK)
157+
modal.displayName.translateInitialValue = false
158+
159+
val result = sendModal(modal)
160+
161+
// Result will be null if the user didn't enter anything
162+
// or if the modal timed out
163+
if (result == null) {
164+
return
165+
}
166+
167+
platformUser = platform.authenticatedAsBotFest().createUser(UserCreateData(
168+
modal.displayName.value,
169+
modal.pronouns.value,
170+
modal.modrinthSlug.value,
171+
user.id.value.toString()
172+
))
173+
174+
result
175+
} else {
176+
// User already has their data registered in platform
177+
// Ack immediately: we only have 5 seconds for any ack
178+
ackBlank()
179+
}
180+
181+
// Okay, we now have a user that's registered. And we have a
182+
// message we can edit to respond to the user
183+
// let's perform the actual registration
184+
val event = platform.getEvent(curEvent)
185+
186+
if (platformUser.registered.contains(curEvent)) {
187+
message.edit {
188+
content = Translations.Commands.Register.Response.already
189+
.withContext(this@doRegister)
190+
.translateNamed(
191+
"event" to event.name
192+
)
193+
}
194+
return
195+
}
196+
197+
platform.withAuth(user).registerMe(event)
198+
message.edit {
199+
content = Translations.Commands.Register.Response.success
200+
.withContext(this@doRegister)
201+
.translateNamed(
202+
"event" to event.name
203+
)
204+
}
205+
}
206+
164207
class RegisterModal : ModalForm() {
165208
override var title: Key = Translations.Modal.Register.title
166209

botfest/src/main/resources/translations/botfest/strings.properties

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,13 @@ commands.getcurrentevent.response=The current event is `{event}`
1515
commands.setcurrentevent.name=SetCurrentEvent
1616
commands.setcurrentevent.description=Sets the current event. Can be set to null. Will affect all commands that influence events.
1717
commands.setcurrentevent.response=Set current event to `{event}`
18+
commands.admin.registermsg.name=sendregistrationmessage
19+
commands.admin.registermsg.description=Adds a registration message and button to this channel
20+
commands.admin.registermsg.embed.title=Register for {event_name}!
21+
commands.admin.registermsg.embed.content=Registrations are now open! Click on the button below (or use the {cmdRegister} command) to register yourself for {event_name}. If this is your first time registering, you will be prompted with a form to collect your preferred name, pronouns, and your Modrinth slug.\n\
22+
\n\
23+
If you change your mind about participating, you can use the {cmdUnregister} command to remove yourself from {event_name}.
24+
commands.admin.registermsg.button=Register
1825
commands.reload.name=Reload
1926
commands.reload.description=Invalidates the in-memory caches, reloads all files from disk.
2027
commands.reload.response=Successfully reloaded `{numStores}` data stores
@@ -77,7 +84,6 @@ commands.submission.edit_image.icon.description=Change your submission's icon
7784
commands.submission.edit_image.screenshot.label=banner
7885
commands.submission.edit_image.screenshot.description=Change your submission's banner
7986
commands.submission.edit_image.response.success=Your image is being downloaded
80-
8187
commands.fix.name=fixmyroles
8288
commands.fix.description=Corrects any errors with your roles. Use after re-joining the server
8389
commands.fix.response.success=Done! Your roles should be fixed! Contact a team member if something is still wrong

0 commit comments

Comments
 (0)