Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generic interaction create events #520

Closed

Conversation

lukellmann
Copy link
Member

Changes

  • make InteractionCreateEvent generic over its interaction property
  • change superinterface of GuildComponentInteractionCreateEvent and GlobalComponentInteractionCreateEvent

before

Event <- InteractionCreateEvent <- [Guild|Global]ComponentInteractionCreateEvent

after

Event <- InteractionCreateEvent <- ComponentInteractionCreateEvent <- [Guild|Global]ComponentInteractionCreateEvent

Example where you can benefit from a generic interaction property

Without generic interaction

suspend inline fun <E : InteractionCreateEvent> E.foo(ack: E.() -> InteractionResponseBehavior) {
    val response = this.ack()
    response.edit { /* ... */ }
}

suspend fun ButtonInteractionCreateEvent.bar() {
    // you have to obtain `interaction` here to access all its methods
    foo { interaction.acknowledgePublicDeferredMessageUpdate() }
}

suspend fun ChatInputCommandInteractionCreateEvent.baz() {
    foo { interaction.acknowledgePublic() }
}

With generic interaction

suspend inline fun <I : Interaction, E : InteractionCreateEvent<I>> E.foo(ack: I.() -> InteractionResponseBehavior) {
    val response = interaction.ack()
    response.edit { /* ... */ }
}

suspend fun ButtonInteractionCreateEvent<*>.bar() {
    // access methods of interaction directly, its type is know through generics
    foo { acknowledgePublicDeferredMessageUpdate() }
}

suspend fun ChatInputCommandInteractionCreateEvent<*>.baz() {
    foo { acknowledgePublic() }
}

@HopeBaron
Copy link
Member

I don't get it; you are calling the function in their class
For example

suspend fun ChatInputCommandInteractionCreateEvent<*>.baz() {
    foo { acknowledgePublic() }
}

You already assume it's type is ChatInputCommandInteraction at the very least

@lukellmann
Copy link
Member Author

I don't get it; you are calling the function in their class
For example

suspend fun ChatInputCommandInteractionCreateEvent<*>.baz() {
    foo { acknowledgePublic() }
}

You already assume it's type is ChatInputCommandInteraction at the very least

Yes, but acknowledgePublic() is still a method on the interaction of the event, not the event itself. If it isn't generic, there would be no way to have the correct interaction type directly in scope of the lambda in foo().

@lukellmann lukellmann marked this pull request as draft February 11, 2022 00:16
@lukellmann
Copy link
Member Author

waiting for #531

@lukellmann
Copy link
Member Author

lukellmann commented Feb 26, 2022

After thinking about this for a while I'm not sure if this change is actually a good idea. The major downside comes with Kotlin's syntax for generic is checks. If you want to listen for an event that isn't a concrete class (e.g. ButtonInteractionCreateEvent), you would have to add a star projection:

kord.on<ButtonInteractionCreateEvent<*>> {
    // ...
}

This does not only look somewhat strange but will also break the compilation for a lot of (if not all) projects using kord.

Combined with the rather small benefits of this approach (see PR description) it's probably not worth the hassle.

@lukellmann
Copy link
Member Author

I'm closing this for now, we can reopen it if needed.

@lukellmann lukellmann closed this Mar 3, 2022
@lukellmann lukellmann deleted the changes/generic-interaction branch March 12, 2022 02:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants