Calendar creation supports multi-cal

This also makes several changes to database stuff:
moves queries to own read-only variables in class
and optimizes the db ops that need to be performed on calendar delete.
This commit is contained in:
NovaFox161
2021-10-07 15:22:09 -05:00
parent 14146c0a00
commit d42ec7b441
10 changed files with 665 additions and 550 deletions

View File

@@ -158,16 +158,18 @@ class CalendarCommand(val wizard: CalendarWizard) : SlashCommand {
event.interaction.guild.flatMap { guild ->
if (!pre.editing) {
// New calendar
guild.createCalendar(pre.createSpec()).flatMap {
event.followupEphemeral(
getMessage("confirm.success.create", settings),
CalendarEmbed.link(guild, settings, it)
)
}.doOnError {
LOGGER.error("Create calendar with command failure", it)
}.onErrorResume {
event.followupEphemeral(getMessage("confirm.failure.create", settings))
}
pre.createSpec(guild)
.flatMap(guild::createCalendar)
.flatMap {
event.followupEphemeral(
getMessage("confirm.success.create", settings),
CalendarEmbed.link(guild, settings, it)
)
}.doOnError {
LOGGER.error("Create calendar with command failure", it)
}.onErrorResume {
event.followupEphemeral(getMessage("confirm.failure.create", settings))
}
} else {
// Editing
pre.calendar!!.update(pre.updateSpec())

View File

@@ -1,31 +0,0 @@
package org.dreamexposure.discal.core.utils;
import org.dreamexposure.discal.core.database.DatabaseManager;
import org.dreamexposure.discal.core.object.calendar.CalendarData;
import org.dreamexposure.discal.core.wrapper.google.CalendarWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import reactor.core.publisher.Mono;
/**
* Created by Nova Fox on 11/10/17.
* Website: www.cloudcraftgaming.com
* For Project: DisCal-Discord-Bot
*/
@Deprecated
public class CalendarUtils {
private final static Logger LOGGER = LoggerFactory.getLogger(CalendarUtils.class);
@Deprecated
public static Mono<Boolean> deleteCalendar(final CalendarData data) {
return CalendarWrapper.INSTANCE.deleteCalendar(data).then(
Mono.when(
DatabaseManager.INSTANCE.deleteCalendar(data),
DatabaseManager.INSTANCE.deleteAllEventData(data.getGuildId(), data.getCalendarNumber()),
DatabaseManager.INSTANCE.deleteAllRsvpData(data.getGuildId(), data.getCalendarNumber()),
DatabaseManager.INSTANCE.deleteAllAnnouncementData(data.getGuildId(), data.getCalendarNumber())
)).thenReturn(true)
.doOnError(e -> LOGGER.error(GlobalVal.getDEFAULT(), "Calendar delete failure", e))
.onErrorReturn(false);
}
}

View File

@@ -43,8 +43,12 @@ object DiscalCache {
}
}
fun removeCalendar(guildId: Snowflake, calNum: Int) {
if (calendars.containsKey(guildId))
calendars[guildId]!!.remove(calNum)
fun handleCalendarDelete(guildId: Snowflake) {
removeCalendars(guildId)
//Eventually other cached things will be here, like events, rsvp data, etc
}
fun removeCalendars(guildId: Snowflake) {
calendars.remove(guildId)
}
}

View File

@@ -45,16 +45,11 @@ class GoogleCalendar internal constructor(
override fun delete(): Mono<Boolean> {
//Delete self from cache
DiscalCache.removeCalendar(guildId, calendarNumber)
DiscalCache.handleCalendarDelete(guildId)
return CalendarWrapper.deleteCalendar(calendarData).then(
Mono.`when`(
DatabaseManager.deleteCalendar(calendarData),
DatabaseManager.deleteAllEventData(guildId, calendarNumber),
DatabaseManager.deleteAllRsvpData(guildId, calendarNumber),
DatabaseManager.deleteAllAnnouncementData(guildId, calendarNumber)
)).thenReturn(true)
.defaultIfEmpty(false)
return CalendarWrapper.deleteCalendar(calendarData)
.then(DatabaseManager.deleteCalendarAndRelatedData(calendarData))
.thenReturn(true)
}
override fun update(spec: UpdateCalendarSpec): Mono<UpdateCalendarResponse> {

View File

@@ -30,6 +30,8 @@ fun Guild.hasCalendar(): Mono<Boolean> = getRestGuild().hasCalendar()
fun Guild.canAddCalendar(): Mono<Boolean> = getRestGuild().canAddCalendar()
fun Guild.determineNextCalendarNumber(): Mono<Int> = getRestGuild().determineNextCalendarNumber()
/**
* Attempts to retrieve this [Guild]'s main [Calendar] (calendar 1, this guild's first/primary calendar)
* If an error occurs, it is emitted through the [Mono]

View File

@@ -44,6 +44,12 @@ fun RestGuild.canAddCalendar(): Mono<Boolean> {
}
}
fun RestGuild.determineNextCalendarNumber(): Mono<Int> {
return DatabaseManager.getAllCalendars(this.id)
.map(List<CalendarData>::size)
.map { it + 1 }
}
/**
* Attempts to retrieve this [Guild]'s main [Calendar] (calendar 1, this guild's first/primary calendar)
* If an error occurs, it is emitted through the [Mono]

View File

@@ -34,7 +34,7 @@ data class CalendarData(
var encryptedRefreshToken: String = "N/a",
@Transient
var expiresAt: Instant = Instant.now()
) {
): Comparable<CalendarData> {
constructor(guildId: Snowflake, calendarNumber: Int, host: CalendarHost, calendarId: String,
calendarAddress: String, credentialId: Int) :
this(guildId, calendarNumber, host, calendarId, calendarAddress, false, credentialId)
@@ -47,4 +47,10 @@ data class CalendarData(
}
fun expired() = Instant.now().isAfter(expiresAt)
override fun compareTo(other: CalendarData): Int {
if (this.calendarNumber > other.calendarNumber) return 1
if (this.calendarNumber < other.calendarNumber) return -1
return 0
}
}

View File

@@ -1,10 +1,13 @@
package org.dreamexposure.discal.core.`object`.calendar
import discord4j.common.util.Snowflake
import discord4j.core.`object`.entity.Guild
import org.dreamexposure.discal.core.entities.Calendar
import org.dreamexposure.discal.core.entities.spec.create.CreateCalendarSpec
import org.dreamexposure.discal.core.entities.spec.update.UpdateCalendarSpec
import org.dreamexposure.discal.core.enums.calendar.CalendarHost
import org.dreamexposure.discal.core.extensions.discord4j.determineNextCalendarNumber
import reactor.core.publisher.Mono
import java.time.Instant
import java.time.ZoneId
@@ -28,10 +31,8 @@ data class PreCalendar private constructor(
return this.name.isNotEmpty() && this.timezone != null
}
fun createSpec(): CreateCalendarSpec {
// TODO: Determine calendar number...
return CreateCalendarSpec(host, 1, name, description, timezone!!)
fun createSpec(guild: Guild): Mono<CreateCalendarSpec> {
return guild.determineNextCalendarNumber().map { CreateCalendarSpec(host, it, name, description, timezone!!) }
}
fun updateSpec() = UpdateCalendarSpec(name, description, timezone)

View File

@@ -112,12 +112,8 @@ object GoogleAuthWrapper {
if ("invalid_grant".equals(errorBody.getString("error"), true)) {
//User revoked access to calendar, delete our reference as they need to re-auth it.
return@flatMap Mono.`when`(
DatabaseManager.deleteCalendar(calData),
DatabaseManager.deleteAllEventData(calData.guildId, calData.calendarNumber),
DatabaseManager.deleteAllRsvpData(calData.guildId, calData.calendarNumber),
DatabaseManager.deleteAllAnnouncementData(calData.guildId, calData.calendarNumber)
).then(Mono.empty())
return@flatMap DatabaseManager.deleteCalendarAndRelatedData(calData)
.then(Mono.empty())
} else {
LOGGER.debug(DEFAULT, "[!DGC!] err requesting new access token. " +
"Code: ${response.code} | ${response.message} | $errorBody")