From 981db7b43f03d47db274b83d7b527f2736eee319 Mon Sep 17 00:00:00 2001 From: Sheldan <5037282+Sheldan@users.noreply.github.com> Date: Thu, 18 May 2023 22:49:50 +0200 Subject: [PATCH] [SIS-20] adding feature to attach an ics file to meetups can be toggled via feature mode --- .../meetup/config/MeetupFeatureConfig.java | 10 ++++++ .../meetup/config/MeetupFeatureMode.java | 15 ++++++++ .../listener/MeetupConfirmationListener.java | 7 ++++ .../meetup/model/template/MeetupIcsModel.java | 17 +++++++++ .../model/template/MeetupMessageModel.java | 1 + .../meetup/service/MeetupServiceBean.java | 36 ++++++++++++++++++- .../src/main/resources/meetup.properties | 6 +++- pom.xml | 4 +-- .../general/meetup_display_embed_en_US.ftl | 8 +++++ .../meetup_ice_file_download_en_US.ftl | 13 +++++++ .../general/meetup_ics_file_name_en_US.ftl | 1 + 11 files changed, 114 insertions(+), 4 deletions(-) create mode 100644 application/sissi-modules/meetup/src/main/java/dev/sheldan/sissi/module/meetup/config/MeetupFeatureMode.java create mode 100644 application/sissi-modules/meetup/src/main/java/dev/sheldan/sissi/module/meetup/model/template/MeetupIcsModel.java create mode 100644 templates/sissi-templates/module-templates/meetup-templates/src/main/resources/en_US/general/meetup_ice_file_download_en_US.ftl create mode 100644 templates/sissi-translations/module-translations/meetup-translations/src/main/resources/en_US/general/meetup_ics_file_name_en_US.ftl diff --git a/application/sissi-modules/meetup/src/main/java/dev/sheldan/sissi/module/meetup/config/MeetupFeatureConfig.java b/application/sissi-modules/meetup/src/main/java/dev/sheldan/sissi/module/meetup/config/MeetupFeatureConfig.java index efc85e15..2ba383c9 100644 --- a/application/sissi-modules/meetup/src/main/java/dev/sheldan/sissi/module/meetup/config/MeetupFeatureConfig.java +++ b/application/sissi-modules/meetup/src/main/java/dev/sheldan/sissi/module/meetup/config/MeetupFeatureConfig.java @@ -2,8 +2,14 @@ package dev.sheldan.sissi.module.meetup.config; import dev.sheldan.abstracto.core.config.FeatureConfig; import dev.sheldan.abstracto.core.config.FeatureDefinition; +import dev.sheldan.abstracto.core.config.FeatureMode; import org.springframework.stereotype.Component; +import java.util.Arrays; +import java.util.List; + +import static dev.sheldan.sissi.module.meetup.config.MeetupFeatureMode.ATTACH_ICS_FILE; + @Component public class MeetupFeatureConfig implements FeatureConfig { @Override @@ -11,4 +17,8 @@ public class MeetupFeatureConfig implements FeatureConfig { return MeetupFeatureDefinition.MEETUP; } + @Override + public List getAvailableModes() { + return Arrays.asList(ATTACH_ICS_FILE); + } } diff --git a/application/sissi-modules/meetup/src/main/java/dev/sheldan/sissi/module/meetup/config/MeetupFeatureMode.java b/application/sissi-modules/meetup/src/main/java/dev/sheldan/sissi/module/meetup/config/MeetupFeatureMode.java new file mode 100644 index 00000000..fc2b1bb3 --- /dev/null +++ b/application/sissi-modules/meetup/src/main/java/dev/sheldan/sissi/module/meetup/config/MeetupFeatureMode.java @@ -0,0 +1,15 @@ +package dev.sheldan.sissi.module.meetup.config; + +import dev.sheldan.abstracto.core.config.FeatureMode; +import lombok.Getter; + +@Getter +public enum MeetupFeatureMode implements FeatureMode { + ATTACH_ICS_FILE("attachIcsFile"); + + private final String key; + + MeetupFeatureMode(String key) { + this.key = key; + } +} diff --git a/application/sissi-modules/meetup/src/main/java/dev/sheldan/sissi/module/meetup/listener/MeetupConfirmationListener.java b/application/sissi-modules/meetup/src/main/java/dev/sheldan/sissi/module/meetup/listener/MeetupConfirmationListener.java index c8c2d167..de3c0047 100644 --- a/application/sissi-modules/meetup/src/main/java/dev/sheldan/sissi/module/meetup/listener/MeetupConfirmationListener.java +++ b/application/sissi-modules/meetup/src/main/java/dev/sheldan/sissi/module/meetup/listener/MeetupConfirmationListener.java @@ -16,6 +16,7 @@ import dev.sheldan.abstracto.core.service.MessageService; import dev.sheldan.abstracto.core.service.management.ChannelManagementService; import dev.sheldan.abstracto.core.service.management.ServerManagementService; import dev.sheldan.abstracto.core.templating.model.MessageToSend; +import dev.sheldan.abstracto.core.utils.FileService; import dev.sheldan.abstracto.core.utils.FutureUtils; import dev.sheldan.sissi.module.meetup.config.MeetupFeatureDefinition; import dev.sheldan.sissi.module.meetup.model.database.Meetup; @@ -76,6 +77,9 @@ public class MeetupConfirmationListener implements ButtonClickedListener { @Autowired private MeetupComponentManagementServiceBean meetupComponentManagementServiceBean; + @Autowired + private FileService fileService; + @Override public ButtonClickedListenerResult execute(ButtonClickedListenerModel model) { MeetupConfirmationPayload payload = (MeetupConfirmationPayload) model.getDeserializedPayload(); @@ -115,6 +119,9 @@ public class MeetupConfirmationListener implements ButtonClickedListener { List> messageFutures = channelService.sendMessageToSendToChannel(messageToSend, model.getEvent().getMessageChannel()); FutureUtils.toSingleFutureGeneric(messageFutures).thenAccept(unused -> { messageService.deleteMessage(model.getEvent().getMessage()); + messageToSend.getAttachedFiles().forEach(attachedFile -> { + fileService.safeDeleteIgnoreException(attachedFile.getFile()); + }); Message meetupMessage = messageFutures.get(0).join(); messageService.pinMessage(meetupMessage); self.persistPayloads(meetupId, serverId, yesButtonId, noButtonId, maybeButtonId, noTimeButtonId, meetupMessage); diff --git a/application/sissi-modules/meetup/src/main/java/dev/sheldan/sissi/module/meetup/model/template/MeetupIcsModel.java b/application/sissi-modules/meetup/src/main/java/dev/sheldan/sissi/module/meetup/model/template/MeetupIcsModel.java new file mode 100644 index 00000000..d0f42dad --- /dev/null +++ b/application/sissi-modules/meetup/src/main/java/dev/sheldan/sissi/module/meetup/model/template/MeetupIcsModel.java @@ -0,0 +1,17 @@ +package dev.sheldan.sissi.module.meetup.model.template; + +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + + +@Getter +@Builder +@Setter +public class MeetupIcsModel { + private Boolean attachIcsFile; + private String iceFileName; + private String icsFormattedCreationTime; + private String icsFormattedStartTime; + private String icsFormattedEndTime; +} diff --git a/application/sissi-modules/meetup/src/main/java/dev/sheldan/sissi/module/meetup/model/template/MeetupMessageModel.java b/application/sissi-modules/meetup/src/main/java/dev/sheldan/sissi/module/meetup/model/template/MeetupMessageModel.java index 994e3786..0d3a6d4d 100644 --- a/application/sissi-modules/meetup/src/main/java/dev/sheldan/sissi/module/meetup/model/template/MeetupMessageModel.java +++ b/application/sissi-modules/meetup/src/main/java/dev/sheldan/sissi/module/meetup/model/template/MeetupMessageModel.java @@ -27,4 +27,5 @@ public class MeetupMessageModel { private List maybeParticipants; private List noTimeParticipants; private List declinedParticipants; + private MeetupIcsModel meetupIcsModel; } diff --git a/application/sissi-modules/meetup/src/main/java/dev/sheldan/sissi/module/meetup/service/MeetupServiceBean.java b/application/sissi-modules/meetup/src/main/java/dev/sheldan/sissi/module/meetup/service/MeetupServiceBean.java index 6c8001bc..cc554947 100644 --- a/application/sissi-modules/meetup/src/main/java/dev/sheldan/sissi/module/meetup/service/MeetupServiceBean.java +++ b/application/sissi-modules/meetup/src/main/java/dev/sheldan/sissi/module/meetup/service/MeetupServiceBean.java @@ -10,9 +10,12 @@ import dev.sheldan.abstracto.core.service.*; import dev.sheldan.abstracto.core.service.management.ServerManagementService; import dev.sheldan.abstracto.core.templating.model.MessageToSend; import dev.sheldan.abstracto.core.templating.service.TemplateService; +import dev.sheldan.abstracto.core.utils.FileService; import dev.sheldan.abstracto.core.utils.FutureUtils; import dev.sheldan.abstracto.scheduling.model.JobParameters; import dev.sheldan.abstracto.scheduling.service.SchedulerService; +import dev.sheldan.sissi.module.meetup.config.MeetupFeatureDefinition; +import dev.sheldan.sissi.module.meetup.config.MeetupFeatureMode; import dev.sheldan.sissi.module.meetup.model.command.MeetupChangeTimeConfirmationModel; import dev.sheldan.sissi.module.meetup.model.command.MeetupConfirmationModel; import dev.sheldan.sissi.module.meetup.model.database.Meetup; @@ -21,6 +24,7 @@ import dev.sheldan.sissi.module.meetup.model.database.MeetupParticipant; import dev.sheldan.sissi.module.meetup.model.database.MeetupState; import dev.sheldan.sissi.module.meetup.model.payload.MeetupChangeTimeConfirmationPayload; import dev.sheldan.sissi.module.meetup.model.payload.MeetupConfirmationPayload; +import dev.sheldan.sissi.module.meetup.model.template.MeetupIcsModel; import dev.sheldan.sissi.module.meetup.model.template.MeetupMessageModel; import dev.sheldan.sissi.module.meetup.model.template.MeetupNotificationModel; import dev.sheldan.sissi.module.meetup.model.template.MeetupTimeChangedNotificationModel; @@ -38,6 +42,9 @@ import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.time.Instant; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoUnit; import java.util.*; import java.util.concurrent.CompletableFuture; @@ -79,6 +86,9 @@ public class MeetupServiceBean { @Autowired private MeetupServiceBean self; + @Autowired + private FileService fileService; + @Autowired private ChannelService channelService; @@ -91,11 +101,16 @@ public class MeetupServiceBean { @Autowired private SchedulerService schedulerService; + @Autowired + private FeatureModeService featureModeService; + @Autowired private MeetupParticipatorManagementServiceBean meetupParticipatorManagementServiceBean; @Autowired private MeetupComponentManagementServiceBean meetupComponentManagementServiceBean; + private static final String ICS_TIME_STAMP_FORMAT = "yMMdd'T'kkmmss'Z'"; + private static final DateTimeFormatter ICS_DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern(ICS_TIME_STAMP_FORMAT); public void storeMeetupConfirmation(MeetupConfirmationModel model) { AServer server = serverManagementService.loadServer(model.getGuildId()); @@ -126,6 +141,22 @@ public class MeetupServiceBean { componentPayloadService.createButtonPayload(model.getCancelId(), confirmationPayload, MEETUP_CHANGE_TIME_CONFIRMATION_BUTTON, server); } + private MeetupIcsModel getMeetupICSModel(Meetup meetup) { + ZonedDateTime startTime = meetup.getMeetupTime().atZone(ZoneId.of("UTC")); + ZonedDateTime endTime = meetup.getMeetupTime().plus(1, ChronoUnit.HOURS).atZone(ZoneId.of("UTC")); + String icsFormattedStartTime = startTime.format(ICS_DATE_TIME_FORMATTER); + String icsFormattedEndTime = endTime.format(ICS_DATE_TIME_FORMATTER); + String icsFormattedMeetupCreationTime = Instant.now().atZone(ZoneId.of("UTC")) + .format(ICS_DATE_TIME_FORMATTER); + boolean attachIcsFile = featureModeService.featureModeActive(MeetupFeatureDefinition.MEETUP, meetup.getServer().getId(), MeetupFeatureMode.ATTACH_ICS_FILE); + return MeetupIcsModel + .builder() + .attachIcsFile(attachIcsFile) + .icsFormattedCreationTime(icsFormattedMeetupCreationTime) + .icsFormattedStartTime(icsFormattedStartTime) + .icsFormattedEndTime(icsFormattedEndTime) + .build(); + } public MeetupMessageModel getMeetupMessageModel(Meetup meetup) { List allParticipants = meetup.getParticipants(); @@ -162,6 +193,7 @@ public class MeetupServiceBean { .maybeParticipants(getMemberDisplays(maybe)) .cancelled(meetup.getState().equals(MeetupState.CANCELLED)) .organizer(MemberDisplay.fromAUserInAServer(meetup.getOrganizer())) + .meetupIcsModel(getMeetupICSModel(meetup)) .build(); } @@ -391,8 +423,9 @@ public class MeetupServiceBean { MessageToSend updatedMeetupMessage = getMeetupMessage(meetupMessageModel); GuildMessageChannel meetupChannel = channelService.getMessageChannelFromServer(serverId, meetup.getMeetupChannel().getId()); - return channelService.editEmbedMessageInAChannel(updatedMeetupMessage.getEmbeds().get(0), meetupChannel, meetup.getMessageId()) + return channelService.editMessageInAChannelFuture(updatedMeetupMessage, meetupChannel, meetup.getMessageId()) .thenAccept(message -> log.info("Updated message of meetup {} in channel {} in server {}.", meetupId, meetup.getMeetupChannel().getId(), serverId)) + .thenAccept(unused -> fileService.safeDeleteIgnoreException(updatedMeetupMessage.getAttachedFiles().get(0).getFile())) .exceptionally(throwable -> { log.info("Failed to update message of meetup {} in channel {} in server {}.", meetupId, meetup.getMeetupChannel().getId(), serverId, throwable); return null; @@ -426,6 +459,7 @@ public class MeetupServiceBean { GuildMessageChannel meetupChannel = channelService.getMessageChannelFromServer(serverId, meetup.getMeetupChannel().getId()); return channelService.editMessageInAChannelFuture(updatedMeetupMessage, meetupChannel, meetup.getMessageId()) .thenAccept(message -> log.info("Updated message of meetup {} in channel {} in server {}.", meetupId, meetup.getMeetupChannel().getId(), serverId)) + .thenAccept(unused -> fileService.safeDeleteIgnoreException(updatedMeetupMessage.getAttachedFiles().get(0).getFile())) .exceptionally(throwable -> { log.info("Failed to update message of meetup {} in channel {} in server {}.", meetupId, meetup.getMeetupChannel().getId(), serverId, throwable); return null; diff --git a/application/sissi-modules/meetup/src/main/resources/meetup.properties b/application/sissi-modules/meetup/src/main/resources/meetup.properties index c38770ee..bc397966 100644 --- a/application/sissi-modules/meetup/src/main/resources/meetup.properties +++ b/application/sissi-modules/meetup/src/main/resources/meetup.properties @@ -5,4 +5,8 @@ abstracto.systemConfigs.meetupEarlyReminderSeconds.name=meetupEarlyReminderSecon abstracto.systemConfigs.meetupEarlyReminderSeconds.longValue=604800 abstracto.systemConfigs.meetupLateReminderSeconds.name=meetupLateReminderSeconds -abstracto.systemConfigs.meetupLateReminderSeconds.longValue=86400 \ No newline at end of file +abstracto.systemConfigs.meetupLateReminderSeconds.longValue=86400 + +abstracto.featureModes.attachIcsFile.featureName=meetup +abstracto.featureModes.attachIcsFile.mode=attachIcsFile +abstracto.featureModes.attachIcsFile.enabled=false \ No newline at end of file diff --git a/pom.xml b/pom.xml index 3a42721f..50c98a78 100644 --- a/pom.xml +++ b/pom.xml @@ -20,8 +20,8 @@ 1.8 - 1.4.22 - 1.4.15 + 1.4.23 + 1.4.16 diff --git a/templates/sissi-templates/module-templates/meetup-templates/src/main/resources/en_US/general/meetup_display_embed_en_US.ftl b/templates/sissi-templates/module-templates/meetup-templates/src/main/resources/en_US/general/meetup_display_embed_en_US.ftl index 568b2b7e..c43dbb29 100644 --- a/templates/sissi-templates/module-templates/meetup-templates/src/main/resources/en_US/general/meetup_display_embed_en_US.ftl +++ b/templates/sissi-templates/module-templates/meetup-templates/src/main/resources/en_US/general/meetup_display_embed_en_US.ftl @@ -49,6 +49,14 @@ } ], + <#if meetupIcsModel.attachIcsFile> + "files": [ + { + "fileName": "<@safe_include "meetup_ics_file_name"/>.ics", + "fileContent": "<@safe_include "meetup_ice_file_download"/>" + } + ], + "messageConfig": { "allowsRoleMention": true } diff --git a/templates/sissi-templates/module-templates/meetup-templates/src/main/resources/en_US/general/meetup_ice_file_download_en_US.ftl b/templates/sissi-templates/module-templates/meetup-templates/src/main/resources/en_US/general/meetup_ice_file_download_en_US.ftl new file mode 100644 index 00000000..06bd4fbc --- /dev/null +++ b/templates/sissi-templates/module-templates/meetup-templates/src/main/resources/en_US/general/meetup_ice_file_download_en_US.ftl @@ -0,0 +1,13 @@ +BEGIN:VCALENDAR +VERSION:2.0 +PRODID:Sissi-Bot +BEGIN:VEVENT +UID:sissi-meetup-${meetupId} +DTSTAMP:${meetupIcsModel.icsFormattedCreationTime} +DTSTART:${meetupIcsModel.icsFormattedStartTime} +DTEND:${meetupIcsModel.icsFormattedEndTime} +SUMMARY:${topic} +<#if description?has_content>DESCRIPTION:${description} +<#if location?? && location != "%22%22">LOCATION:${location} +END:VEVENT +END:VCALENDAR \ No newline at end of file diff --git a/templates/sissi-translations/module-translations/meetup-translations/src/main/resources/en_US/general/meetup_ics_file_name_en_US.ftl b/templates/sissi-translations/module-translations/meetup-translations/src/main/resources/en_US/general/meetup_ics_file_name_en_US.ftl new file mode 100644 index 00000000..7baa355d --- /dev/null +++ b/templates/sissi-translations/module-translations/meetup-translations/src/main/resources/en_US/general/meetup_ics_file_name_en_US.ftl @@ -0,0 +1 @@ +meetup-${meetupId} \ No newline at end of file