mirror of
https://github.com/DreamExposure/DisCal-Discord-Bot.git
synced 2026-02-07 20:09:01 -06:00
Add calendar overview to /linkcal
This commit is contained in:
@@ -17,6 +17,11 @@ class LinkCalendarCommand : SlashCommand {
|
||||
override val ephemeral = false
|
||||
|
||||
override fun handle(event: ChatInputInteractionEvent, settings: GuildSettings): Mono<Message> {
|
||||
val showOverview = event.getOption("overview")
|
||||
.flatMap(ApplicationCommandInteractionOption::getValue)
|
||||
.map(ApplicationCommandInteractionOptionValue::asBoolean)
|
||||
.orElse(true)
|
||||
|
||||
val calendarNumber = event.getOption("calendar")
|
||||
.flatMap(ApplicationCommandInteractionOption::getValue)
|
||||
.map(ApplicationCommandInteractionOptionValue::asLong)
|
||||
@@ -24,7 +29,7 @@ class LinkCalendarCommand : SlashCommand {
|
||||
.orElse(1)
|
||||
|
||||
return event.interaction.guild.flatMap { guild ->
|
||||
CalendarEmbed.link(guild, settings, calendarNumber)
|
||||
CalendarEmbed.link(guild, settings, calendarNumber, showOverview)
|
||||
.flatMap(event::followup)
|
||||
}.switchIfEmpty(event.followup(getCommonMsg("error.notFound.calendar", settings)))
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import org.dreamexposure.discal.core.`object`.announcement.Announcement
|
||||
import org.dreamexposure.discal.core.entities.Event
|
||||
import org.dreamexposure.discal.core.enums.announcement.AnnouncementStyle
|
||||
import org.dreamexposure.discal.core.enums.announcement.AnnouncementType
|
||||
import org.dreamexposure.discal.core.extensions.DiscordTimestampFormat.LONG_DATETIME
|
||||
import org.dreamexposure.discal.core.extensions.asDiscordTimestamp
|
||||
import org.dreamexposure.discal.core.extensions.discord4j.getSettings
|
||||
import org.dreamexposure.discal.core.extensions.embedFieldSafe
|
||||
@@ -40,12 +41,12 @@ object AnnouncementEmbed : EmbedMaker {
|
||||
|
||||
builder.addField(
|
||||
getMessage("announcement", "full.field.start", settings),
|
||||
event.start.asDiscordTimestamp(),
|
||||
event.start.asDiscordTimestamp(LONG_DATETIME),
|
||||
true
|
||||
)
|
||||
builder.addField(
|
||||
getMessage("announcement", "full.field.end", settings),
|
||||
event.end.asDiscordTimestamp(),
|
||||
event.end.asDiscordTimestamp(LONG_DATETIME),
|
||||
true
|
||||
)
|
||||
|
||||
@@ -84,7 +85,7 @@ object AnnouncementEmbed : EmbedMaker {
|
||||
|
||||
builder.addField(
|
||||
getMessage("announcement", "simple.field.start", settings),
|
||||
event.start.asDiscordTimestamp(),
|
||||
event.start.asDiscordTimestamp(LONG_DATETIME),
|
||||
true
|
||||
)
|
||||
|
||||
@@ -116,12 +117,12 @@ object AnnouncementEmbed : EmbedMaker {
|
||||
|
||||
builder.addField(
|
||||
getMessage("announcement", "event.field.start", settings),
|
||||
event.start.asDiscordTimestamp(),
|
||||
event.start.asDiscordTimestamp(LONG_DATETIME),
|
||||
true
|
||||
)
|
||||
builder.addField(
|
||||
getMessage("announcement", "event.field.end", settings),
|
||||
event.end.asDiscordTimestamp(),
|
||||
event.end.asDiscordTimestamp(LONG_DATETIME),
|
||||
true
|
||||
)
|
||||
|
||||
|
||||
@@ -6,21 +6,20 @@ import org.dreamexposure.discal.core.`object`.GuildSettings
|
||||
import org.dreamexposure.discal.core.`object`.calendar.PreCalendar
|
||||
import org.dreamexposure.discal.core.entities.Calendar
|
||||
import org.dreamexposure.discal.core.enums.time.TimeFormat
|
||||
import org.dreamexposure.discal.core.extensions.*
|
||||
import org.dreamexposure.discal.core.extensions.discord4j.getCalendar
|
||||
import org.dreamexposure.discal.core.extensions.embedDescriptionSafe
|
||||
import org.dreamexposure.discal.core.extensions.embedFieldSafe
|
||||
import org.dreamexposure.discal.core.extensions.embedTitleSafe
|
||||
import org.dreamexposure.discal.core.extensions.toMarkdown
|
||||
import org.dreamexposure.discal.core.utils.GlobalVal.discalColor
|
||||
import org.dreamexposure.discal.core.utils.getCommonMsg
|
||||
import reactor.core.publisher.Mono
|
||||
import java.time.Instant
|
||||
import java.time.LocalDateTime
|
||||
import java.time.format.DateTimeFormatter
|
||||
|
||||
object CalendarEmbed : EmbedMaker {
|
||||
fun link(guild: Guild, settings: GuildSettings, calNumber: Int): Mono<EmbedCreateSpec> {
|
||||
return guild.getCalendar(calNumber).map {
|
||||
link(guild, settings, it)
|
||||
fun link(guild: Guild, settings: GuildSettings, calNumber: Int, overview: Boolean): Mono<EmbedCreateSpec> {
|
||||
return guild.getCalendar(calNumber).flatMap {
|
||||
if (overview) overview(guild, settings, it, false)
|
||||
else Mono.just(link(guild, settings, it))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +41,54 @@ object CalendarEmbed : EmbedMaker {
|
||||
.build()
|
||||
}
|
||||
|
||||
fun overview(guild: Guild, settings: GuildSettings, calendar: Calendar, showUpdate: Boolean): Mono<EmbedCreateSpec> {
|
||||
return calendar.getUpcomingEvents(15).collectList().map { it.groupByDate() }.map { events ->
|
||||
val builder = defaultBuilder(guild, settings)
|
||||
|
||||
//Handle optional fields
|
||||
if (calendar.name.isNotBlank())
|
||||
builder.title(calendar.name.toMarkdown().embedTitleSafe())
|
||||
if (calendar.description.isNotBlank())
|
||||
builder.description(calendar.description.toMarkdown().embedDescriptionSafe())
|
||||
|
||||
// Show events
|
||||
events.forEach { date ->
|
||||
val fieldTitle = getMessage(
|
||||
"calendar", "link.field.date",
|
||||
settings,
|
||||
Instant.from(date.key).asDiscordTimestamp(DiscordTimestampFormat.LONG_DATE)
|
||||
)
|
||||
|
||||
val content = StringBuilder().append("```\n")
|
||||
date.value.forEach {
|
||||
content.append(it.start.asDiscordTimestamp(DiscordTimestampFormat.SHORT_TIME))
|
||||
.append(" - ")
|
||||
.append(it.end.asDiscordTimestamp(DiscordTimestampFormat.SHORT_TIME))
|
||||
.append(" | ")
|
||||
if (it.name.isNotBlank()) content.append(it.name).append(" | ")
|
||||
content.append(it.eventId).append("\n")
|
||||
}
|
||||
content.append("```")
|
||||
|
||||
builder.addField(fieldTitle, content.toString(), false)
|
||||
}
|
||||
|
||||
|
||||
// set footer
|
||||
if (showUpdate) {
|
||||
val lastUpdate = Instant.now().asDiscordTimestamp(DiscordTimestampFormat.RELATIVE_TIME)
|
||||
builder.footer(getMessage("calendar", "link.footer.update", settings, lastUpdate), null)
|
||||
} else builder.footer(getMessage("calendar", "link.footer.default", settings), null)
|
||||
|
||||
// finish and return
|
||||
builder.addField(getMessage("calendar", "link.field.timezone", settings), calendar.zoneName, true)
|
||||
.addField(getMessage("calendar", "link.field.number", settings), "${calendar.calendarNumber}", true)
|
||||
.url(calendar.link)
|
||||
.color(discalColor)
|
||||
.build()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun time(guild: Guild, settings: GuildSettings, calNumber: Int): Mono<EmbedCreateSpec> {
|
||||
return guild.getCalendar(calNumber).map { cal ->
|
||||
|
||||
@@ -6,6 +6,7 @@ import org.dreamexposure.discal.core.`object`.GuildSettings
|
||||
import org.dreamexposure.discal.core.`object`.event.PreEvent
|
||||
import org.dreamexposure.discal.core.entities.Event
|
||||
import org.dreamexposure.discal.core.extensions.*
|
||||
import org.dreamexposure.discal.core.extensions.DiscordTimestampFormat.LONG_DATETIME
|
||||
import org.dreamexposure.discal.core.utils.getCommonMsg
|
||||
|
||||
object EventEmbed : EmbedMaker {
|
||||
@@ -19,8 +20,15 @@ object EventEmbed : EmbedMaker {
|
||||
if (event.description.isNotBlank())
|
||||
builder.description(event.description.toMarkdown().embedDescriptionSafe())
|
||||
|
||||
builder.addField(getMessage("event", "full.field.start", settings), event.start.asDiscordTimestamp(), true)
|
||||
builder.addField(getMessage("event", "full.field.end", settings), event.end.asDiscordTimestamp(), true)
|
||||
builder.addField(
|
||||
getMessage("event", "full.field.start", settings),
|
||||
event.start.asDiscordTimestamp(LONG_DATETIME),
|
||||
true)
|
||||
builder.addField(
|
||||
getMessage("event", "full.field.end", settings),
|
||||
event.end.asDiscordTimestamp(LONG_DATETIME),
|
||||
true
|
||||
)
|
||||
|
||||
if (event.location.isNotBlank()) builder.addField(
|
||||
getMessage("event", "full.field.location", settings),
|
||||
@@ -44,7 +52,11 @@ object EventEmbed : EmbedMaker {
|
||||
if (event.name.isNotBlank())
|
||||
builder.title(event.name.toMarkdown().embedTitleSafe())
|
||||
|
||||
builder.addField(getMessage("event", "con.field.start", settings), event.start.asDiscordTimestamp(), true)
|
||||
builder.addField(
|
||||
getMessage("event", "con.field.start", settings),
|
||||
event.start.asDiscordTimestamp(LONG_DATETIME),
|
||||
true
|
||||
)
|
||||
|
||||
if (event.location.isNotBlank()) builder.addField(
|
||||
getMessage("event", "con.field.location", settings),
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package org.dreamexposure.discal.core.extensions
|
||||
|
||||
enum class DiscordTimestampFormat(val value: String) {
|
||||
SHORT_TIME("t"),
|
||||
LONG_TIME("T"),
|
||||
SHORT_DATE("d"),
|
||||
LONG_DATE("D"),
|
||||
SHORT_DATETIME("f"),
|
||||
LONG_DATETIME("F"),
|
||||
RELATIVE_TIME("R"),
|
||||
}
|
||||
@@ -5,7 +5,7 @@ import java.time.Instant
|
||||
import java.time.ZoneId
|
||||
import java.time.format.DateTimeFormatter
|
||||
|
||||
fun Instant.asDiscordTimestamp(): String = "<t:${this.toEpochMilli() / 1000}:F>"
|
||||
fun Instant.asDiscordTimestamp(fmt: DiscordTimestampFormat) = "<t:${this.toEpochMilli() / 1000}:${fmt.value}>"
|
||||
|
||||
fun Instant.humanReadableFull(timezone: ZoneId, format: TimeFormat): String {
|
||||
return DateTimeFormatter.ofPattern(format.full).withZone(timezone).format(this)
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
package org.dreamexposure.discal.core.extensions
|
||||
|
||||
import org.dreamexposure.discal.core.entities.Event
|
||||
import java.time.LocalDate
|
||||
import java.time.temporal.TemporalAdjusters
|
||||
import java.util.stream.Collectors
|
||||
|
||||
|
||||
fun MutableList<String>.asStringList(): String {
|
||||
val builder = StringBuilder()
|
||||
@@ -13,3 +18,13 @@ fun MutableList<String>.asStringList(): String {
|
||||
|
||||
return builder.toString()
|
||||
}
|
||||
|
||||
|
||||
fun MutableList<Event>.groupByDate(): Map<LocalDate, List<Event>> {
|
||||
return this.stream()
|
||||
.collect(Collectors.groupingBy {
|
||||
LocalDate.ofInstant(it.start, it.timezone)
|
||||
.with(TemporalAdjusters.ofDateAdjuster { identity -> identity })
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
@@ -2,6 +2,12 @@
|
||||
"name": "linkcal",
|
||||
"description": "Provides info and a link to the Guild's Calendar",
|
||||
"options": [
|
||||
{
|
||||
"name": "overview",
|
||||
"type": 5,
|
||||
"description": "Whether to display the next 15 upcoming events in the response (default true).",
|
||||
"required": false
|
||||
},
|
||||
{
|
||||
"name": "calendar",
|
||||
"type": 4,
|
||||
|
||||
@@ -3,7 +3,9 @@ link.field.timezone=Time Zone
|
||||
link.field.host=Host
|
||||
link.field.number=Number
|
||||
link.field.id=ID
|
||||
link.footer=View the entire calendar with events by clicking the title
|
||||
link.field.date=%s (Local)
|
||||
link.footer.default=View the entire calendar with events by clicking the title
|
||||
link.footer.update=Last Updated \u22C4 %s
|
||||
|
||||
wizard.title=Calendar Wizard
|
||||
wizard.field.name=* Name
|
||||
|
||||
Reference in New Issue
Block a user