Skip to content

Commit cc80d5b

Browse files
committed
Hoping this is all it takes to add a week display static message
1 parent 50f7bc9 commit cc80d5b

6 files changed

Lines changed: 153 additions & 14 deletions

File tree

client/src/main/kotlin/org/dreamexposure/discal/client/commands/global/DisplayCalendarCommand.kt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import org.dreamexposure.discal.core.business.CalendarService
99
import org.dreamexposure.discal.core.business.PermissionService
1010
import org.dreamexposure.discal.core.business.StaticMessageService
1111
import org.dreamexposure.discal.core.`object`.new.GuildSettings
12+
import org.dreamexposure.discal.core.`object`.new.StaticMessage
1213
import org.dreamexposure.discal.core.utils.getCommonMsg
1314
import org.springframework.stereotype.Component
1415

@@ -31,6 +32,12 @@ class DisplayCalendarCommand(
3132
}
3233

3334
private suspend fun new(event: ChatInputInteractionEvent, settings: GuildSettings) {
35+
val type = event.options[0].getOption("type")
36+
.flatMap(ApplicationCommandInteractionOption::getValue)
37+
.map(ApplicationCommandInteractionOptionValue::asLong)
38+
.map(Long::toInt)
39+
.map(StaticMessage.Type::getByValue)
40+
.get()
3441
val hour = event.options[0].getOption("time")
3542
.flatMap(ApplicationCommandInteractionOption::getValue)
3643
.map(ApplicationCommandInteractionOptionValue::asLong)
@@ -60,7 +67,7 @@ class DisplayCalendarCommand(
6067
}
6168

6269
// Create and respond
63-
staticMessageService.createStaticMessage(settings.guildId, event.interaction.channelId, calendarNumber, hour)
70+
staticMessageService.createStaticMessage(settings.guildId, event.interaction.channelId, calendarNumber, type, hour)
6471

6572
event.createFollowup(getCommonMsg("success.generic", settings.locale))
6673
.withEphemeral(ephemeral)

core/src/main/kotlin/org/dreamexposure/discal/core/business/EmbedService.kt

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,96 @@ class EmbedService(
208208
.build()
209209
}
210210

211+
suspend fun calendarWeekOverviewEmbed(calendar: Calendar, events: List<Event>, showUpdate: Boolean): EmbedCreateSpec {
212+
val settings = settingsService.getSettings(calendar.metadata.guildId)
213+
val builder = defaultEmbedBuilder(settings)
214+
215+
// This is used to truncate how many events are displayed to prevent going over the 6000 character count limit
216+
var calculatedEmbedCharacterLength = 0
217+
218+
// Get events sorted and grouped
219+
val groupedEvents = events.groupByDate(filterEmptyDates = false) // We want to display the days of the week with no events
220+
221+
//Handle optional fields
222+
if (calendar.name.isNotBlank()) {
223+
builder.title(calendar.name.toMarkdown().embedTitleSafe())
224+
calculatedEmbedCharacterLength += calendar.name.toMarkdown().embedTitleSafe().length
225+
}
226+
if (calendar.description.isNotBlank()) {
227+
builder.description(calendar.description.toMarkdown().embedDescriptionSafe())
228+
calculatedEmbedCharacterLength += calendar.description.toMarkdown().embedDescriptionSafe().length
229+
}
230+
231+
// Show events
232+
groupedEvents.forEach { date ->
233+
val title = date.key.toInstant().humanReadableDate(calendar.timezone, settings.interfaceStyle.timeFormat, longDay = true)
234+
235+
// sort events
236+
val sortedEvents = date.value.sortedBy { it.start }
237+
238+
val content = StringBuilder()
239+
240+
sortedEvents.forEach {
241+
// Start event
242+
content.append("```\n")
243+
244+
// determine time length
245+
val timeDisplayLen = ("${it.start.humanReadableTime(it.timezone, settings.interfaceStyle.timeFormat)} -" +
246+
" ${it.end.humanReadableTime(it.timezone, settings.interfaceStyle.timeFormat)} ").length
247+
248+
// Displaying time
249+
if (it.isAllDay()) {
250+
content.append(getCommonMsg("generic.time.allDay", settings.locale).padCenter(timeDisplayLen))
251+
.append("| ")
252+
} else {
253+
// Add start text
254+
var str = if (it.start.isBefore(date.key.toInstant())) {
255+
"${getCommonMsg("generic.time.continued", settings.locale)} - "
256+
} else {
257+
"${it.start.humanReadableTime(it.timezone, settings.interfaceStyle.timeFormat)} - "
258+
}
259+
// Add end text
260+
str += if (it.end.isAfter(date.key.toInstant().plus(1, ChronoUnit.DAYS))) {
261+
getCommonMsg("generic.time.continued", settings.locale)
262+
} else {
263+
"${it.end.humanReadableTime(it.timezone, settings.interfaceStyle.timeFormat)} "
264+
}
265+
content.append(str.padCenter(timeDisplayLen))
266+
.append("| ")
267+
}
268+
// Display name or ID if not set
269+
if (it.name.isNotBlank()) content.append(it.name)
270+
else content.append(getEmbedMessage("calendar", "link.field.id", settings.locale)).append(" ${it.id}")
271+
content.append("\n")
272+
if (it.location.isNotBlank()) content.append(" Location: ")
273+
.append(it.location.embedFieldSafe())
274+
.append("\n")
275+
276+
// Finish event
277+
content.append("```\n")
278+
}
279+
calculatedEmbedCharacterLength += title.length + content.toString().embedFieldSafe().length
280+
281+
// max embed length is 6000 characters, we are going to go a bit under that in just for extra safety
282+
if (content.isNotBlank() && calculatedEmbedCharacterLength <= 5750)
283+
builder.addField(title, content.toString().embedFieldSafe(), false)
284+
}
285+
286+
// set footer
287+
if (showUpdate) {
288+
val lastUpdate = Instant.now().asDiscordTimestamp(DiscordTimestampFormat.RELATIVE_TIME)
289+
builder.footer(getEmbedMessage("calendar", "link.footer.update", settings.locale, lastUpdate), null)
290+
.timestamp(Instant.now())
291+
} else builder.footer(getEmbedMessage("calendar", "link.footer.default", settings.locale), null)
292+
293+
// finish and return
294+
return builder.addField(getEmbedMessage("calendar", "link.field.timezone", settings.locale), calendar.timezone.id, true)
295+
.addField(getEmbedMessage("calendar", "link.field.number", settings.locale), "${calendar.metadata.number}", true)
296+
.url(calendar.link)
297+
.color(GlobalVal.discalColor)
298+
.build()
299+
}
300+
211301
suspend fun linkCalendarEmbed(calendar: Calendar, events: List<Event>?): EmbedCreateSpec {
212302
return if (events != null) calendarOverviewEmbed(calendar, events, showUpdate = false)
213303
else linkCalendarEmbed(calendar)

core/src/main/kotlin/org/dreamexposure/discal/core/business/StaticMessageService.kt

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -73,26 +73,32 @@ class StaticMessageService(
7373
.awaitSingle()
7474
}
7575

76-
///////////////////////////////////////////////////////////////////////////////////////////
77-
////// TODO: Need to be able to break some of this out for when I support more types //////
78-
///////////////////////////////////////////////////////////////////////////////////////////
7976
suspend fun createStaticMessage(
8077
guildId: Snowflake,
8178
channelId: Snowflake,
8279
calendarNumber: Int,
80+
type: StaticMessage.Type,
8381
updateHour: Long
8482
): StaticMessage {
85-
8683
// Gather everything we need
8784
val calendar = calendarService.getCalendar(guildId, calendarNumber) ?: throw NotFoundException("Calendar not found")
88-
val events = calendarService.getUpcomingEvents(guildId, calendarNumber, OVERVIEW_EVENT_COUNT)
8985
val channel = discordClient.getChannelById(channelId)
90-
val embed = embedService.calendarOverviewEmbed(calendar, events, showUpdate = true)
9186
val nextUpdate = ZonedDateTime.now(calendar.timezone)
9287
.truncatedTo(ChronoUnit.DAYS)
9388
.plusHours(updateHour + 24)
9489
.toInstant()
9590

91+
val embed = when (type) {
92+
StaticMessage.Type.CALENDAR_OVERVIEW -> {
93+
val events = calendarService.getUpcomingEvents(guildId, calendarNumber, OVERVIEW_EVENT_COUNT)
94+
embedService.calendarOverviewEmbed(calendar, events, showUpdate = true)
95+
}
96+
StaticMessage.Type.CALENDAR_WEEKLY -> {
97+
val events = calendarService.getEventsInNextNDays(guildId, calendarNumber, 7)
98+
embedService.calendarWeekOverviewEmbed(calendar, events, showUpdate = true)
99+
}
100+
}
101+
96102

97103
// Finally create the message
98104
val message = channel.createMessage(
@@ -166,10 +172,18 @@ class StaticMessageService(
166172
}
167173

168174
val calendar = calendarService.getCalendar(guildId, old.calendarNumber) ?: throw NotFoundException("Calendar not found")
169-
val events = calendarService.getUpcomingEvents(guildId, old.calendarNumber, OVERVIEW_EVENT_COUNT, MAX_CUTOFF_DAYS)
170175

171176
// Finally update the message
172-
val embed = embedService.calendarOverviewEmbed(calendar, events, showUpdate = true)
177+
val embed = when (old.type) {
178+
StaticMessage.Type.CALENDAR_OVERVIEW -> {
179+
val events = calendarService.getUpcomingEvents(guildId, old.calendarNumber, OVERVIEW_EVENT_COUNT, MAX_CUTOFF_DAYS)
180+
embedService.calendarOverviewEmbed(calendar, events, showUpdate = true)
181+
}
182+
StaticMessage.Type.CALENDAR_WEEKLY -> {
183+
val events = calendarService.getEventsInNextNDays(guildId, old.calendarNumber, 7)
184+
embedService.calendarWeekOverviewEmbed(calendar, events, showUpdate = true)
185+
}
186+
}
173187

174188
discordClient.getMessageById(old.channelId, old.messageId).edit(
175189
MessageEditRequest.builder()
@@ -207,8 +221,6 @@ class StaticMessageService(
207221

208222
val oldVersions = getStaticMessagesForCalendar(guildId, calendarNumber).filter { it.enabled }
209223
val calendar = calendarService.getCalendar(guildId, calendarNumber) ?: throw NotFoundException("Calendar not found")
210-
val events = calendarService.getUpcomingEvents(guildId, calendarNumber, OVERVIEW_EVENT_COUNT)
211-
val embed = embedService.calendarOverviewEmbed(calendar, events, showUpdate = true)
212224

213225
oldVersions.forEach { old ->
214226
val existingData = discordClient.getMessageById(old.channelId, old.messageId)
@@ -251,6 +263,17 @@ class StaticMessageService(
251263
return@forEach
252264
}
253265

266+
val embed = when (old.type) {
267+
StaticMessage.Type.CALENDAR_OVERVIEW -> {
268+
val events = calendarService.getUpcomingEvents(guildId, calendarNumber, OVERVIEW_EVENT_COUNT)
269+
embedService.calendarOverviewEmbed(calendar, events, showUpdate = true)
270+
}
271+
StaticMessage.Type.CALENDAR_WEEKLY -> {
272+
val events = calendarService.getEventsInNextNDays(guildId, calendarNumber, 7)
273+
embedService.calendarWeekOverviewEmbed(calendar, events, showUpdate = true)
274+
}
275+
}
276+
254277
discordClient.getMessageById(old.channelId, old.messageId).edit(
255278
MessageEditRequest.builder()
256279
.addEmbed(embed.asRequest())

core/src/main/kotlin/org/dreamexposure/discal/core/extensions/MutableList.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ fun List<String>.asStringList(): String {
1919
return builder.toString()
2020
}
2121

22-
fun List<Event>.groupByDate(): Map<ZonedDateTime, List<Event>> {
22+
fun List<Event>.groupByDate(filterEmptyDates: Boolean = true): Map<ZonedDateTime, List<Event>> {
2323
if (this.isEmpty()) return emptyMap()
2424

2525
// Get a list of all distinct days events take place on (the first start date and the last end date)
@@ -60,5 +60,7 @@ fun List<Event>.groupByDate(): Map<ZonedDateTime, List<Event>> {
6060
}
6161
multi[it] = events.sortedBy(Event::start)
6262
}
63-
return multi.filter { it.value.isNotEmpty() }.toSortedMap()
63+
64+
return if (filterEmptyDates) multi.filter { it.value.isNotEmpty() }.toSortedMap()
65+
else multi.toSortedMap()
6466
}

core/src/main/kotlin/org/dreamexposure/discal/core/object/new/StaticMessage.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ data class StaticMessage(
3535

3636

3737
enum class Type(val value: Int) {
38-
CALENDAR_OVERVIEW(1);
38+
CALENDAR_OVERVIEW(1),
39+
CALENDAR_WEEKLY(2);
3940

4041
companion object {
4142
fun getByValue(value: Int) = entries.first { it.value == value }

core/src/main/resources/commands/global/displayCal.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,22 @@
77
"type": 1,
88
"description": "Create a new static calendar overview message",
99
"options": [
10+
{
11+
"name": "type",
12+
"type": 4,
13+
"description": "The type of display to create",
14+
"required": true,
15+
"choices": [
16+
{
17+
"name": "Calendar Overview",
18+
"value": 1
19+
},
20+
{
21+
"name": "Weekly Overview",
22+
"value": 2
23+
}
24+
]
25+
},
1026
{
1127
"name": "time",
1228
"type": 4,

0 commit comments

Comments
 (0)