Add events slash command

This commit is contained in:
NovaFox161
2021-08-06 15:09:02 -04:00
parent 1deec97062
commit 8dfbf29d34
12 changed files with 327 additions and 13 deletions
@@ -0,0 +1,134 @@
package org.dreamexposure.discal.client.commands
import discord4j.core.event.domain.interaction.SlashCommandEvent
import org.dreamexposure.discal.client.message.Responder
import org.dreamexposure.discal.client.message.embed.EventEmbed
import org.dreamexposure.discal.core.`object`.GuildSettings
import org.dreamexposure.discal.core.extensions.discord4j.getCalendar
import org.dreamexposure.discal.core.utils.getCommonMsg
import org.springframework.stereotype.Component
import reactor.core.publisher.Flux
import reactor.core.publisher.Mono
import reactor.function.TupleUtils
import java.time.Instant
@Component
class EventsCommand : SlashCommand {
override val name = "events"
override val ephemeral = false
override fun handle(event: SlashCommandEvent, settings: GuildSettings): Mono<Void> {
return when (event.options[0].name) {
"upcoming" -> upcomingEventsSubcommand(event, settings)
"ongoing" -> ongoingEventsSubcommand(event, settings)
"today" -> eventsTodaySubcommand(event, settings)
else -> Mono.empty() //Never can reach this, makes compiler happy.
}
}
private fun upcomingEventsSubcommand(event: SlashCommandEvent, settings: GuildSettings): Mono<Void> {
//Determine which calendar they want to use...
val calNumMono = Mono.justOrEmpty(event.options[0].getOption("calendar").flatMap { it.value })
.map { it.asLong().toInt() }
.defaultIfEmpty(1)
val amountMono = Mono.justOrEmpty(event.options[0].getOption("amount").flatMap { it.value })
.map { it.asLong().toInt() }
.defaultIfEmpty(1)
return Mono.zip(calNumMono, amountMono).flatMap(TupleUtils.function { calNumb, amount ->
if (amount < 1 || amount > 15) {
Responder.followupEphemeral(event, getMessage("upcoming.failure.outOfRange", settings))
}
event.interaction.guild.flatMap { guild ->
guild.getCalendar(calNumb).flatMap { cal ->
cal.getUpcomingEvents(amount).collectList().flatMap { events ->
if (events.isEmpty()) {
Responder.followup(event, getMessage("upcoming.success.none", settings))
} else if (events.size == 1) {
Responder.followup(
event,
getMessage("upcoming.success.one", settings),
EventEmbed.getFull(guild, settings, events[0])
)
} else {
Responder.followup(event, getMessage("upcoming.success.many", settings, "${events.size}"))
.flatMapMany {
Flux.fromIterable(events)
}.flatMap {
Responder.followup(event, EventEmbed.getCondensed(guild, settings, it))
}.then()
}
}
}.switchIfEmpty(Responder.followupEphemeral(event, getCommonMsg("error.notFound.calendar", settings)))
}
}).then()
}
private fun ongoingEventsSubcommand(event: SlashCommandEvent, settings: GuildSettings): Mono<Void> {
return Mono.justOrEmpty(event.options[0].getOption("calendar").flatMap { it.value })
.map { it.asLong().toInt() }
.defaultIfEmpty(1).flatMap { calNum ->
event.interaction.guild.flatMap { guild ->
guild.getCalendar(calNum).flatMap { cal ->
cal.getOngoingEvents().collectList().flatMap { events ->
if (events.isEmpty()) {
Responder.followupEphemeral(
event,
getMessage("ongoing.success.none", settings)
)
} else if (events.size == 1) {
Responder.followup(
event,
getMessage("ongoing.success.one", settings),
EventEmbed.getFull(guild, settings, events[0])
)
} else {
Responder.followup(event,
getMessage("ongoing.success.many", settings, "${events.size}")
).flatMapMany {
Flux.fromIterable(events)
}.flatMap {
Responder.followup(event, EventEmbed.getCondensed(guild, settings, it))
}.then()
}
}
}
}
}.then()
}
private fun eventsTodaySubcommand(event: SlashCommandEvent, settings: GuildSettings): Mono<Void> {
return Mono.justOrEmpty(event.options[0].getOption("calendar").flatMap { it.value })
.map { it.asLong().toInt() }
.defaultIfEmpty(1).flatMap { calNum ->
event.interaction.guild.flatMap { guild ->
guild.getCalendar(calNum).flatMap { cal ->
cal.getEventsInNext24HourPeriod(Instant.now()).collectList().flatMap { events ->
if (events.isEmpty()) {
Responder.followupEphemeral(
event,
getMessage("today.success.none", settings)
)
} else if (events.size == 1) {
Responder.followup(
event,
getMessage("today.success.one", settings),
EventEmbed.getFull(guild, settings, events[0])
)
} else {
Responder.followup(event,
getMessage("today.success.many", settings, "${events.size}")
).flatMapMany {
Flux.fromIterable(events)
}.flatMap {
Responder.followup(event, EventEmbed.getCondensed(guild, settings, it))
}.then()
}
}
}
}
}.then()
}
}
@@ -24,6 +24,15 @@ object Responder {
return sendFollowup(event, spec)
}
fun followup(event: InteractionCreateEvent, message: String, embed: EmbedCreateSpec): Mono<MessageData> {
val spec = WebhookExecuteRequest.builder()
.content(message)
.addEmbed(embed.asRequest())
.build()
return sendFollowup(event, spec)
}
fun followupEphemeral(event: InteractionCreateEvent, embed: EmbedCreateSpec): Mono<MessageData> {
val spec = WebhookExecuteRequest.builder()
.addEmbed(embed.asRequest())
@@ -40,6 +49,14 @@ object Responder {
return sendFollowupEphemeral(event, spec)
}
fun followupEphemeral(event: InteractionCreateEvent, message: String, embed: EmbedCreateSpec): Mono<MessageData> {
val spec = WebhookExecuteRequest.builder()
.content(message)
.addEmbed(embed.asRequest())
.build()
return sendFollowupEphemeral(event, spec)
}
private fun sendFollowup(event: InteractionCreateEvent, request: WebhookExecuteRequest) =
event.interactionResponse.createFollowupMessage(MultipartRequest.ofRequest(request))
@@ -0,0 +1,57 @@
package org.dreamexposure.discal.client.message.embed
import discord4j.core.`object`.entity.Guild
import discord4j.core.spec.EmbedCreateSpec
import org.dreamexposure.discal.core.`object`.GuildSettings
import org.dreamexposure.discal.core.entities.Event
import java.time.Instant
object EventEmbed : EmbedMaker {
fun getFull(guild: Guild, settings: GuildSettings, event: Event): EmbedCreateSpec {
val builder = defaultBuilder(guild, settings)
.title(getMessage("event", "full.title", settings))
.footer(getMessage("event", "full.footer", settings, event.eventId), null)
.color(event.color.asColor())
if (event.name.isNotEmpty())
builder.addField(getMessage("event", "full.field.name", settings), event.name, false)
if (event.description.isNotEmpty())
builder.addField(getMessage("event", "full.field.desc", settings), event.description, false)
builder.addField(getMessage("event", "full.field.start", settings), timestamp(event.start), true)
builder.addField(getMessage("event", "full.field.end", settings), timestamp(event.end), true)
if (event.location.isNotEmpty())
builder.addField(getMessage("event", "full.field.location", settings), event.location, false)
builder.addField(getMessage("event", "full.field.cal", settings), "${event.calendar.calendarNumber}", false)
if (event.image.isNotEmpty())
builder.image(event.image)
return builder.build()
}
fun getCondensed(guild: Guild, settings: GuildSettings, event: Event): EmbedCreateSpec {
val builder = defaultBuilder(guild, settings)
.title(getMessage("event", "con.title", settings))
.footer(getMessage("event", "con.footer", settings, event.eventId), null)
.color(event.color.asColor())
if (event.name.isNotEmpty())
builder.addField(getMessage("event", "con.field.name", settings), event.name, false)
builder.addField(getMessage("event", "con.field.start", settings), timestamp(event.start), true)
if (event.location.isNotEmpty())
builder.addField(getMessage("event", "con.field.location", settings), event.location, false)
if (event.image.isNotEmpty())
builder.thumbnail(event.image)
return builder.build()
}
private fun timestamp(time: Instant): String = "<t:${time.toEpochMilli() / 1000}:F>"
}