Compare commits

..

12 Commits

Author SHA1 Message Date
Sheldan
4bfa706e7c [maven-release-plugin] prepare release sissi-1.2.0 2022-07-17 21:58:44 +02:00
Sheldan
2485bf4113 [SIS-xxxx] prepare for release 2022-07-17 21:58:06 +02:00
Sheldan
48e2e705c2 [SIS-6] adding ability to declare "no_time" for a meetup
adding meetup id to meetup message
refactoring meetup cancellation to be a command
adding command to change the meetup time and notify meetup members
fixing meetup components not being cleaned when cancelling or cleaning up
changing label for no button
2022-07-17 21:55:30 +02:00
Sheldan
f688a066b4 [maven-release-plugin] prepare for next development iteration 2022-07-16 13:49:32 +02:00
Sheldan
1e8a01dccc [maven-release-plugin] prepare release sissi-1.1.0 2022-07-16 13:49:23 +02:00
Sheldan
e7fb1857b0 prepare for release 2022-07-16 13:48:56 +02:00
Sheldan
b5498ab79a [SIS-7] only showing confirmed meetups in meetup list command, fixing #7 2022-07-04 23:04:39 +02:00
Sheldan
1f5aebef1c [SIS-xxx] fixing cancelling a meetup trying to insert a wrong decision 2022-06-24 20:52:39 +02:00
Sheldan
b0bb0e02d1 [SIS-4] adding organizer to meetup message, fixes #4 2022-06-24 18:42:03 +02:00
Sheldan
9bc4ec0253 [SIS-3] adding cleanup of cancelled meetups to job 2022-06-20 20:12:41 +02:00
Sheldan
533c9e3a63 [SIS-3] adding separator for the meetup members
adding member counter to message display
only notify member with yes/maybe decision of meetup cancellation
2022-06-20 19:15:30 +02:00
Sheldan
6ae631c78d [maven-release-plugin] prepare for next development iteration 2022-06-20 00:46:14 +02:00
81 changed files with 1172 additions and 98 deletions

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.sissi.application</groupId>
<artifactId>application</artifactId>
<version>1.1.0.RC1</version>
<version>1.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>executable</artifactId>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.sissi</groupId>
<artifactId>sissi</artifactId>
<version>1.1.0.RC1</version>
<version>1.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.sissi.application</groupId>
<artifactId>sissi-modules</artifactId>
<version>1.1.0.RC1</version>
<version>1.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -0,0 +1,111 @@
package dev.sheldan.sissi.module.meetup.commands;
import dev.sheldan.abstracto.core.command.UtilityModuleDefinition;
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.config.SlashCommandConfig;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.command.slash.parameter.SlashCommandParameterService;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.interaction.InteractionService;
import dev.sheldan.abstracto.core.utils.FutureUtils;
import dev.sheldan.sissi.module.meetup.config.MeetupFeatureDefinition;
import dev.sheldan.sissi.module.meetup.config.MeetupSlashCommandNames;
import dev.sheldan.sissi.module.meetup.exception.NotMeetupOrganizerException;
import dev.sheldan.sissi.module.meetup.model.database.Meetup;
import dev.sheldan.sissi.module.meetup.service.MeetupServiceBean;
import dev.sheldan.sissi.module.meetup.service.management.MeetupManagementServiceBean;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@Component
public class CancelMeetup extends AbstractConditionableCommand {
private static final String MEETUP_ID_PARAMETER = "meetupId";
private static final String CANCEL_MEETUP_COMMAND = "cancelMeetup";
private static final String CANCEL_MEETUP_RESPONSE = "cancelMeetup_response";
@Autowired
private MeetupServiceBean meetupServiceBean;
@Autowired
private SlashCommandParameterService slashCommandParameterService;
@Autowired
private InteractionService interactionService;
@Autowired
private MeetupManagementServiceBean meetupManagementServiceBean;
@Override
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
Long meetupId = (Long) commandContext.getParameters().getParameters().get(0);
Meetup meetup = meetupManagementServiceBean.getMeetup(meetupId, commandContext.getGuild().getIdLong());
if(!meetup.getOrganizer().getUserReference().getId().equals(commandContext.getAuthor().getIdLong())) {
throw new NotMeetupOrganizerException();
}
return meetupServiceBean.cancelMeetup(meetup)
.thenApply(interactionHook -> CommandResult.fromSuccess());
}
@Override
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
event.deferReply().queue();
Long meetupId = slashCommandParameterService.getCommandOption(MEETUP_ID_PARAMETER, event, Integer.class).longValue();
Meetup meetup = meetupManagementServiceBean.getMeetup(meetupId, event.getGuild().getIdLong());
if(!meetup.getOrganizer().getUserReference().getId().equals(event.getMember().getIdLong())) {
throw new NotMeetupOrganizerException();
}
return meetupServiceBean.cancelMeetup(meetup)
.thenCompose(unused -> FutureUtils.toSingleFutureGeneric(interactionService.sendMessageToInteraction(CANCEL_MEETUP_RESPONSE, new Object(), event.getHook())))
.thenApply(interactionHook -> CommandResult.fromSuccess());
}
@Override
public CommandConfiguration getConfiguration() {
Parameter meetupIdParameter = Parameter
.builder()
.templated(true)
.name(MEETUP_ID_PARAMETER)
.type(Long.class)
.build();
List<Parameter> parameters = Arrays.asList(meetupIdParameter);
HelpInfo helpInfo = HelpInfo
.builder()
.templated(true)
.build();
SlashCommandConfig slashCommandConfig = SlashCommandConfig
.builder()
.enabled(true)
.rootCommandName(MeetupSlashCommandNames.MEETUP)
.commandName("cancel")
.build();
return CommandConfiguration.builder()
.name(CANCEL_MEETUP_COMMAND)
.module(UtilityModuleDefinition.UTILITY)
.templated(true)
.slashCommandConfig(slashCommandConfig)
.async(true)
.supportsEmbedException(true)
.causesReaction(true)
.parameters(parameters)
.help(helpInfo)
.build();
}
@Override
public FeatureDefinition getFeature() {
return MeetupFeatureDefinition.MEETUP;
}
}

View File

@@ -0,0 +1,173 @@
package dev.sheldan.sissi.module.meetup.commands;
import dev.sheldan.abstracto.core.command.UtilityModuleDefinition;
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.config.SlashCommandConfig;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.command.slash.parameter.SlashCommandParameterService;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.interaction.InteractionService;
import dev.sheldan.abstracto.core.service.ChannelService;
import dev.sheldan.abstracto.core.service.ComponentService;
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
import dev.sheldan.abstracto.core.templating.service.TemplateService;
import dev.sheldan.abstracto.core.utils.FutureUtils;
import dev.sheldan.sissi.module.meetup.config.MeetupFeatureDefinition;
import dev.sheldan.sissi.module.meetup.config.MeetupSlashCommandNames;
import dev.sheldan.sissi.module.meetup.exception.MeetupPastTimeException;
import dev.sheldan.sissi.module.meetup.exception.NotMeetupOrganizerException;
import dev.sheldan.sissi.module.meetup.model.command.MeetupChangeTimeConfirmationModel;
import dev.sheldan.sissi.module.meetup.model.database.Meetup;
import dev.sheldan.sissi.module.meetup.service.MeetupServiceBean;
import dev.sheldan.sissi.module.meetup.service.management.MeetupManagementServiceBean;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.time.Instant;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@Component
public class ChangeMeetupTime extends AbstractConditionableCommand {
private static final String CHANGE_MEETUP_TIME_COMMAND = "changeMeetupTime";
private static final String MEETUP_ID_PARAMETER = "meetupId";
private static final String MEETUP_NEW_TIMESTAMP_PARAMETER = "newTimeStamp";
private static final String CHANGE_MEETUP_TIME_CONFIRMATION = "changeMeetupTime_confirmation";
@Autowired
private SlashCommandParameterService slashCommandParameterService;
@Autowired
private MeetupManagementServiceBean meetupManagementServiceBean;
@Autowired
private ComponentService componentService;
@Autowired
private InteractionService interactionService;
@Autowired
private MeetupServiceBean meetupServiceBean;
@Autowired
private ChannelService channelService;
@Autowired
private TemplateService templateService;
@Override
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
List<Object> parameters = commandContext.getParameters().getParameters();
Long meetupId = (Long) parameters.get(0);
Meetup meetup = meetupManagementServiceBean.getMeetup(meetupId, commandContext.getGuild().getIdLong());
if(!meetup.getOrganizer().getUserReference().getId().equals(commandContext.getAuthor().getIdLong())) {
throw new NotMeetupOrganizerException();
}
Long newTimestamp = (Long) parameters.get(1);
Instant newMeetupTime = Instant.ofEpochSecond(newTimestamp);
if(newMeetupTime.isBefore(Instant.now())) {
throw new MeetupPastTimeException();
}
String confirmationId = componentService.generateComponentId();
String cancelId = componentService.generateComponentId();
MeetupChangeTimeConfirmationModel model = MeetupChangeTimeConfirmationModel
.builder()
.meetupTime(newMeetupTime)
.topic(meetup.getTopic())
.description(meetup.getDescription())
.userId(commandContext.getAuthor().getIdLong())
.guildId(commandContext.getGuild().getIdLong())
.meetupId(meetupId)
.confirmationId(confirmationId)
.cancelId(cancelId)
.build();
MessageToSend messageToSend = templateService.renderEmbedTemplate(CHANGE_MEETUP_TIME_CONFIRMATION, model, commandContext.getGuild().getIdLong());
return FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, commandContext.getChannel()))
.thenAccept(unused -> meetupServiceBean.storeMeetupChangeTimeConfirmation(model))
.thenApply(unused -> CommandResult.fromSuccess());
}
@Override
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
Long meetupId = slashCommandParameterService.getCommandOption(MEETUP_ID_PARAMETER, event, Integer.class).longValue();
Meetup meetup = meetupManagementServiceBean.getMeetup(meetupId, event.getGuild().getIdLong());
if(!meetup.getOrganizer().getUserReference().getId().equals(event.getMember().getIdLong())) {
throw new NotMeetupOrganizerException();
}
Integer time = slashCommandParameterService.getCommandOption(MEETUP_NEW_TIMESTAMP_PARAMETER, event, Long.class, Integer.class);
Instant meetupTime = Instant.ofEpochSecond(time);
if(meetupTime.isBefore(Instant.now())) {
throw new MeetupPastTimeException();
}
String confirmationId = componentService.generateComponentId();
String cancelId = componentService.generateComponentId();
MeetupChangeTimeConfirmationModel model = MeetupChangeTimeConfirmationModel
.builder()
.meetupTime(meetupTime)
.topic(meetup.getTopic())
.description(meetup.getDescription())
.userId(event.getMember().getIdLong())
.guildId(event.getGuild().getIdLong())
.meetupId(meetupId)
.confirmationId(confirmationId)
.cancelId(cancelId)
.build();
return interactionService.replyEmbed(CHANGE_MEETUP_TIME_CONFIRMATION, model, event)
.thenAccept(interactionHook -> meetupServiceBean.storeMeetupChangeTimeConfirmation(model))
.thenApply(interactionHook -> CommandResult.fromSuccess());
}
@Override
public CommandConfiguration getConfiguration() {
Parameter meetupIdParameter = Parameter
.builder()
.templated(true)
.name(MEETUP_ID_PARAMETER)
.type(Long.class)
.build();
Parameter newTimeStampParameter = Parameter
.builder()
.templated(true)
.name(MEETUP_NEW_TIMESTAMP_PARAMETER)
.type(Long.class)
.build();
List<Parameter> parameters = Arrays.asList(meetupIdParameter, newTimeStampParameter);
HelpInfo helpInfo = HelpInfo
.builder()
.templated(true)
.build();
SlashCommandConfig slashCommandConfig = SlashCommandConfig
.builder()
.enabled(true)
.rootCommandName(MeetupSlashCommandNames.MEETUP)
.commandName("changeTime")
.build();
return CommandConfiguration.builder()
.name(CHANGE_MEETUP_TIME_COMMAND)
.module(UtilityModuleDefinition.UTILITY)
.templated(true)
.async(true)
.slashCommandConfig(slashCommandConfig)
.supportsEmbedException(true)
.causesReaction(true)
.parameters(parameters)
.help(helpInfo)
.build();
}
@Override
public FeatureDefinition getFeature() {
return MeetupFeatureDefinition.MEETUP;
}
}

View File

@@ -61,7 +61,7 @@ public class ListMeetups extends AbstractConditionableCommand {
}
private MessageToSend getMessageToSend(Long serverId) {
List<Meetup> meetups = meetupManagementServiceBean.getFutureMeetups();
List<Meetup> meetups = meetupManagementServiceBean.getIncomingMeetups();
List<MeetupListItemModel> listItems = meetups
.stream()
.map(MeetupListItemModel::fromMeetup)
@@ -86,7 +86,7 @@ public class ListMeetups extends AbstractConditionableCommand {
SlashCommandConfig slashCommandConfig = SlashCommandConfig
.builder()
.enabled(true)
.rootCommandName(MeetupSlashCommandNames.MEETUP)
.rootCommandName(MeetupSlashCommandNames.MEETUP_PUBLIC)
.commandName("list")
.build();

View File

@@ -0,0 +1,121 @@
package dev.sheldan.sissi.module.meetup.commands;
import dev.sheldan.abstracto.core.command.UtilityModuleDefinition;
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.config.SlashCommandConfig;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.command.slash.parameter.SlashCommandParameterService;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.interaction.InteractionService;
import dev.sheldan.sissi.module.meetup.config.MeetupFeatureDefinition;
import dev.sheldan.sissi.module.meetup.config.MeetupSlashCommandNames;
import dev.sheldan.sissi.module.meetup.exception.NotMeetupOrganizerException;
import dev.sheldan.sissi.module.meetup.model.database.Meetup;
import dev.sheldan.sissi.module.meetup.service.MeetupServiceBean;
import dev.sheldan.sissi.module.meetup.service.management.MeetupManagementServiceBean;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@Component
public class NotifyMeetupParticipants extends AbstractConditionableCommand {
@Autowired
private SlashCommandParameterService slashCommandParameterService;
@Autowired
private MeetupManagementServiceBean meetupManagementServiceBean;
@Autowired
private MeetupServiceBean meetupServiceBean;
@Autowired
private InteractionService interactionService;
private static final String MEETUP_ID_PARAMETER = "meetupId";
private static final String NOTIFICATION_MESSAGE_PARAMETER = "notificationMessage";
private static final String NOTIFY_MEETUP_PARTICIPANTS_COMMAND = "notifyMeetupParticipants";
private static final String NOTIFY_MEETUP_PARTICIPANTS_RESPONSE = "notifyMeetupParticipants_response";
@Override
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
List<Object> parameters = commandContext.getParameters().getParameters();
Long meetupId = (Long) parameters.get(0);
Meetup meetup = meetupManagementServiceBean.getMeetup(meetupId, commandContext.getGuild().getIdLong());
if(!meetup.getOrganizer().getUserReference().getId().equals(commandContext.getAuthor().getIdLong())) {
throw new NotMeetupOrganizerException();
}
String notificationMessage = (String) parameters.get(1);
return meetupServiceBean.notifyMeetupParticipants(meetup, notificationMessage)
.thenApply(unused -> CommandResult.fromSuccess());
}
@Override
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
Long meetupId = slashCommandParameterService.getCommandOption(MEETUP_ID_PARAMETER, event, Integer.class).longValue();
Meetup meetup = meetupManagementServiceBean.getMeetup(meetupId, event.getGuild().getIdLong());
if(!meetup.getOrganizer().getUserReference().getId().equals(event.getMember().getIdLong())) {
throw new NotMeetupOrganizerException();
}
String notificationMessage = slashCommandParameterService.getCommandOption(NOTIFICATION_MESSAGE_PARAMETER, event, String.class);
return meetupServiceBean.notifyMeetupParticipants(meetup, notificationMessage)
.thenCompose(unused -> interactionService.replyEmbed(NOTIFY_MEETUP_PARTICIPANTS_RESPONSE, event))
.thenApply(unused -> CommandResult.fromSuccess());
}
@Override
public CommandConfiguration getConfiguration() {
Parameter meetupIdParameter = Parameter
.builder()
.templated(true)
.name(MEETUP_ID_PARAMETER)
.type(Long.class)
.build();
Parameter notificationMessage = Parameter
.builder()
.templated(true)
.name(NOTIFICATION_MESSAGE_PARAMETER)
.type(String.class)
.remainder(true)
.build();
List<Parameter> parameters = Arrays.asList(meetupIdParameter, notificationMessage);
HelpInfo helpInfo = HelpInfo
.builder()
.templated(true)
.build();
SlashCommandConfig slashCommandConfig = SlashCommandConfig
.builder()
.enabled(true)
.rootCommandName(MeetupSlashCommandNames.MEETUP)
.commandName("notify")
.build();
return CommandConfiguration.builder()
.name(NOTIFY_MEETUP_PARTICIPANTS_COMMAND)
.module(UtilityModuleDefinition.UTILITY)
.templated(true)
.slashCommandConfig(slashCommandConfig)
.async(true)
.supportsEmbedException(true)
.causesReaction(true)
.parameters(parameters)
.help(helpInfo)
.build();
}
@Override
public FeatureDefinition getFeature() {
return MeetupFeatureDefinition.MEETUP;
}
}

View File

@@ -2,4 +2,5 @@ package dev.sheldan.sissi.module.meetup.config;
public class MeetupSlashCommandNames {
public static final String MEETUP = "meetup";
public static final String MEETUP_PUBLIC = "meetupPublic";
}

View File

@@ -0,0 +1,15 @@
package dev.sheldan.sissi.module.meetup.exception;
import dev.sheldan.abstracto.core.exception.AbstractoTemplatableException;
public class NotMeetupOrganizerException extends AbstractoTemplatableException {
@Override
public String getTemplateName() {
return "meetup_not_organizer_exception";
}
@Override
public Object getTemplateModel() {
return new Object();
}
}

View File

@@ -0,0 +1,78 @@
package dev.sheldan.sissi.module.meetup.listener;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.config.ListenerPriority;
import dev.sheldan.abstracto.core.listener.ButtonClickedListenerResult;
import dev.sheldan.abstracto.core.listener.async.jda.ButtonClickedListener;
import dev.sheldan.abstracto.core.models.listener.ButtonClickedListenerModel;
import dev.sheldan.abstracto.core.service.MessageService;
import dev.sheldan.abstracto.core.service.management.ComponentPayloadManagementService;
import dev.sheldan.sissi.module.meetup.config.MeetupFeatureDefinition;
import dev.sheldan.sissi.module.meetup.model.database.Meetup;
import dev.sheldan.sissi.module.meetup.model.payload.MeetupChangeTimeConfirmationPayload;
import dev.sheldan.sissi.module.meetup.service.MeetupServiceBean;
import dev.sheldan.sissi.module.meetup.service.management.MeetupManagementServiceBean;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.time.Instant;
@Component
@Slf4j
public class MeetupChangeTimeConfirmationListener implements ButtonClickedListener {
@Autowired
private MeetupManagementServiceBean meetupManagementServiceBean;
@Autowired
private MessageService messageService;
@Autowired
private ComponentPayloadManagementService componentPayloadManagementService;
@Autowired
private MeetupServiceBean meetupServiceBean;
@Override
public ButtonClickedListenerResult execute(ButtonClickedListenerModel model) {
MeetupChangeTimeConfirmationPayload payload = (MeetupChangeTimeConfirmationPayload) model.getDeserializedPayload();
if(model.getEvent().getUser().getIdLong() != payload.getOrganizerUserId()) {
return ButtonClickedListenerResult.IGNORED;
}
if(model.getEvent().getComponentId().equals(payload.getConfirmationId())) {
Meetup meetup = meetupManagementServiceBean.getMeetup(payload.getMeetupId(), payload.getGuildId());
meetupServiceBean.changeMeetupTimeAndNotifyParticipants(meetup, Instant.ofEpochSecond(payload.getNewTime()));
messageService.deleteMessage(model.getEvent().getMessage());
cleanupConfirmationMessagePayloads(payload);
} else if(model.getEvent().getComponentId().equals(payload.getCancelId())) {
messageService.deleteMessage(model.getEvent().getMessage());
cleanupConfirmationMessagePayloads(payload);
return ButtonClickedListenerResult.ACKNOWLEDGED;
} else {
return ButtonClickedListenerResult.IGNORED;
}
return ButtonClickedListenerResult.IGNORED;
}
private void cleanupConfirmationMessagePayloads(MeetupChangeTimeConfirmationPayload payload) {
componentPayloadManagementService.deletePayload(payload.getCancelId());
componentPayloadManagementService.deletePayload(payload.getConfirmationId());
}
@Override
public Boolean handlesEvent(ButtonClickedListenerModel model) {
return model.getOrigin().equals(MeetupServiceBean.MEETUP_CHANGE_TIME_CONFIRMATION_BUTTON) &&
model.getEvent().isFromGuild();
}
@Override
public FeatureDefinition getFeature() {
return MeetupFeatureDefinition.MEETUP;
}
@Override
public Integer getPriority() {
return ListenerPriority.LOWEST;
}
}

View File

@@ -6,6 +6,7 @@ import dev.sheldan.abstracto.core.listener.ButtonClickedListenerResult;
import dev.sheldan.abstracto.core.listener.async.jda.ButtonClickedListener;
import dev.sheldan.abstracto.core.models.database.AChannel;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.models.database.ComponentPayload;
import dev.sheldan.abstracto.core.models.listener.ButtonClickedListenerModel;
import dev.sheldan.abstracto.core.service.ChannelService;
import dev.sheldan.abstracto.core.service.ComponentPayloadService;
@@ -24,6 +25,7 @@ import dev.sheldan.sissi.module.meetup.model.payload.MeetupDecisionPayload;
import dev.sheldan.sissi.module.meetup.model.payload.MeetupConfirmationPayload;
import dev.sheldan.sissi.module.meetup.model.template.MeetupMessageModel;
import dev.sheldan.sissi.module.meetup.service.MeetupServiceBean;
import dev.sheldan.sissi.module.meetup.service.management.MeetupComponentManagementServiceBean;
import dev.sheldan.sissi.module.meetup.service.management.MeetupManagementServiceBean;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.Message;
@@ -71,6 +73,9 @@ public class MeetupConfirmationListener implements ButtonClickedListener {
@Autowired
private ComponentPayloadManagementService componentPayloadManagementService;
@Autowired
private MeetupComponentManagementServiceBean meetupComponentManagementServiceBean;
@Override
public ButtonClickedListenerResult execute(ButtonClickedListenerModel model) {
MeetupConfirmationPayload payload = (MeetupConfirmationPayload) model.getDeserializedPayload();
@@ -83,22 +88,22 @@ public class MeetupConfirmationListener implements ButtonClickedListener {
} else if(model.getEvent().getComponentId().equals(payload.getCancelId())){
meetup.setState(MeetupState.CANCELLED);
messageService.deleteMessage(model.getEvent().getMessage());
cleanupConfirmationMessage(payload);
cleanupConfirmationMessagePayloads(payload);
meetupManagementServiceBean.deleteMeetup(meetup);
return ButtonClickedListenerResult.ACKNOWLEDGED;
} else {
return ButtonClickedListenerResult.IGNORED;
}
cleanupConfirmationMessage(payload);
cleanupConfirmationMessagePayloads(payload);
String yesButtonId = componentService.generateComponentId();
String noButtonId = componentService.generateComponentId();
String maybeButtonId = componentService.generateComponentId();
String cancelButtonId = componentService.generateComponentId();
String noTimeButtonId = componentService.generateComponentId();
MeetupMessageModel messageModel = meetupServiceBean.getMeetupMessageModel(meetup);
messageModel.setYesId(yesButtonId);
messageModel.setNoId(noButtonId);
messageModel.setMaybeId(maybeButtonId);
messageModel.setCancelId(cancelButtonId);
messageModel.setNoTimeId(noTimeButtonId);
messageModel.setCancelled(false);
Long meetupId = payload.getMeetupId();
Long serverId = payload.getGuildId();
@@ -108,7 +113,7 @@ public class MeetupConfirmationListener implements ButtonClickedListener {
messageService.deleteMessage(model.getEvent().getMessage());
Message meetupMessage = messageFutures.get(0).join();
messageService.pinMessage(meetupMessage);
self.persistPayloads(meetupId, serverId, yesButtonId, noButtonId, maybeButtonId, cancelButtonId, meetupMessage);
self.persistPayloads(meetupId, serverId, yesButtonId, noButtonId, maybeButtonId, noTimeButtonId, meetupMessage);
}).exceptionally(throwable -> {
log.error("Failed to send meetup message for meetup {}.", meetupId, throwable);
return null;
@@ -116,30 +121,36 @@ public class MeetupConfirmationListener implements ButtonClickedListener {
return ButtonClickedListenerResult.ACKNOWLEDGED;
}
private void cleanupConfirmationMessage(MeetupConfirmationPayload payload) {
private void cleanupConfirmationMessagePayloads(MeetupConfirmationPayload payload) {
componentPayloadManagementService.deletePayload(payload.getCancelId());
componentPayloadManagementService.deletePayload(payload.getConfirmationId());
}
@Transactional
public void persistPayloads(Long meetupId, Long serverId, String yesButtonId, String noButtonId, String maybeButtonId, String cancelButtonId, Message meetupMessage) {
public void persistPayloads(Long meetupId, Long serverId, String yesButtonId, String noButtonId, String maybeButtonId, String noTimeButtonId, Message meetupMessage) {
MeetupDecisionPayload decisionPayload = MeetupDecisionPayload
.builder()
.meetupId(meetupId)
.guildId(serverId)
.componentPayloads(Arrays.asList(yesButtonId, noButtonId, maybeButtonId))
.componentPayloads(Arrays.asList(yesButtonId, noButtonId, maybeButtonId, noTimeButtonId))
.build();
AServer server = serverManagementService.loadServer(serverId);
decisionPayload.setMeetupDecision(MeetupDecision.YES);
componentPayloadService.createButtonPayload(yesButtonId, decisionPayload, MEETUP_DECISION_BUTTON, server);
ComponentPayload yesPayload = componentPayloadService.createButtonPayload(yesButtonId, decisionPayload, MEETUP_DECISION_BUTTON, server);
decisionPayload.setMeetupDecision(MeetupDecision.NO);
componentPayloadService.createButtonPayload(noButtonId, decisionPayload, MEETUP_DECISION_BUTTON, server);
ComponentPayload noPayload = componentPayloadService.createButtonPayload(noButtonId, decisionPayload, MEETUP_DECISION_BUTTON, server);
decisionPayload.setMeetupDecision(MeetupDecision.MAYBE);
componentPayloadService.createButtonPayload(maybeButtonId, decisionPayload, MEETUP_DECISION_BUTTON, server);
decisionPayload.setMeetupDecision(MeetupDecision.CANCEL);
componentPayloadService.createButtonPayload(cancelButtonId, decisionPayload, MEETUP_DECISION_BUTTON, server);
ComponentPayload maybePayload = componentPayloadService.createButtonPayload(maybeButtonId, decisionPayload, MEETUP_DECISION_BUTTON, server);
decisionPayload.setMeetupDecision(MeetupDecision.NO_TIME);
ComponentPayload noTimePayload = componentPayloadService.createButtonPayload(noTimeButtonId, decisionPayload, MEETUP_DECISION_BUTTON, server);
Meetup meetup = meetupManagementServiceBean.getMeetup(meetupId, serverId);
// storing the button IDs, so we can remove them independently
meetupComponentManagementServiceBean.createComponent(meetup, yesButtonId, yesPayload);
meetupComponentManagementServiceBean.createComponent(meetup, noButtonId, noPayload);
meetupComponentManagementServiceBean.createComponent(meetup, maybeButtonId, maybePayload);
meetupComponentManagementServiceBean.createComponent(meetup, noTimeButtonId, noTimePayload);
meetupServiceBean.scheduleReminders(meetup);
meetup.setMessageId(meetupMessage.getIdLong());
AChannel channel = channelManagementService.loadChannel(meetupMessage.getChannel());

View File

@@ -13,7 +13,7 @@ import dev.sheldan.abstracto.core.templating.model.MessageToSend;
import dev.sheldan.sissi.module.meetup.config.MeetupFeatureDefinition;
import dev.sheldan.sissi.module.meetup.model.database.Meetup;
import dev.sheldan.sissi.module.meetup.model.database.MeetupDecision;
import dev.sheldan.sissi.module.meetup.model.database.MeetupParticipator;
import dev.sheldan.sissi.module.meetup.model.database.MeetupParticipant;
import dev.sheldan.sissi.module.meetup.model.payload.MeetupDecisionPayload;
import dev.sheldan.sissi.module.meetup.model.template.MeetupMessageModel;
import dev.sheldan.sissi.module.meetup.service.MeetupServiceBean;
@@ -49,13 +49,9 @@ public class MeetupDecisionListener implements ButtonClickedListener {
public ButtonClickedListenerResult execute(ButtonClickedListenerModel model) {
MeetupDecisionPayload payload = (MeetupDecisionPayload) model.getDeserializedPayload();
Meetup meetup = meetupManagementServiceBean.getMeetup(payload.getMeetupId(), payload.getGuildId());
if(payload.getMeetupDecision().equals(MeetupDecision.CANCEL) && model.getEvent().getUser().getIdLong() == meetup.getOrganizer().getUserReference().getId()) {
meetupServiceBean.cancelMeetup(meetup, payload.getComponentPayloads());
return ButtonClickedListenerResult.ACKNOWLEDGED;
}
AUserInAServer userInAServer = userInServerManagementService.loadOrCreateUser(model.getEvent().getMember());
Optional<MeetupParticipator> participationOptional = meetupParticipatorManagementServiceBean.getParticipation(meetup, userInAServer);
Optional<MeetupParticipant> participationOptional = meetupParticipatorManagementServiceBean.getParticipation(meetup, userInAServer);
if(participationOptional.isPresent()) {
participationOptional.get().setDecision(payload.getMeetupDecision());
} else {
@@ -64,12 +60,12 @@ public class MeetupDecisionListener implements ButtonClickedListener {
MeetupMessageModel meetupMessageModel = meetupServiceBean.getMeetupMessageModel(meetup);
addParticipationToModel(meetupMessageModel, userInAServer, payload.getMeetupDecision());
MessageToSend messageToSend = meetupServiceBean.getMeetupMessage(meetupMessageModel);
channelService.editEmbedMessageInAChannel(messageToSend.getEmbeds().get(0), model.getEvent().getChannel(), meetup.getMessageId()).thenAccept(message -> {
log.info("Updated message of meetup {} in channel {} in server {}.", meetup.getId().getId(), meetup.getMeetupChannel().getId(), meetup.getServer().getId());
}).exceptionally(throwable -> {
log.info("Failed to update message of meetup {} in channel {} in server {}.", meetup.getId().getId(), meetup.getMeetupChannel().getId(), meetup.getServer().getId(), throwable);
return null;
});
channelService.editEmbedMessageInAChannel(messageToSend.getEmbeds().get(0), model.getEvent().getChannel(), meetup.getMessageId())
.thenAccept(message -> log.info("Updated message of meetup {} in channel {} in server {}.", meetup.getId().getId(), meetup.getMeetupChannel().getId(), meetup.getServer().getId()))
.exceptionally(throwable -> {
log.info("Failed to update message of meetup {} in channel {} in server {}.", meetup.getId().getId(), meetup.getMeetupChannel().getId(), meetup.getServer().getId(), throwable);
return null;
});
return ButtonClickedListenerResult.ACKNOWLEDGED;
}
@@ -80,7 +76,8 @@ public class MeetupDecisionListener implements ButtonClickedListener {
addIfMissing(model.getParticipants(), aUserInAServer);
} else if(decision.equals(MeetupDecision.MAYBE)) {
addIfMissing(model.getMaybeParticipants(), aUserInAServer);
}
} else if(decision.equals(MeetupDecision.NO_TIME))
addIfMissing(model.getNoTimeParticipants(), aUserInAServer);
}
private void addIfMissing(List<MemberDisplay> list, AUserInAServer aUserInAServer) {

View File

@@ -0,0 +1,21 @@
package dev.sheldan.sissi.module.meetup.model.command;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import java.time.Instant;
@Getter
@Setter
@Builder
public class MeetupChangeTimeConfirmationModel {
private Instant meetupTime;
private String topic;
private Long userId;
private String description;
private Long meetupId;
private Long guildId;
private String confirmationId;
private String cancelId;
}

View File

@@ -49,7 +49,15 @@ public class Meetup {
cascade = {CascadeType.PERSIST, CascadeType.MERGE},
mappedBy = "meetup")
@Builder.Default
private List<MeetupParticipator> participants = new ArrayList<>();
private List<MeetupParticipant> participants = new ArrayList<>();
@OneToMany(
fetch = FetchType.LAZY,
orphanRemoval = true,
cascade = {CascadeType.PERSIST, CascadeType.MERGE},
mappedBy = "meetup")
@Builder.Default
private List<MeetupComponent> meetupComponents = new ArrayList<>();
@Getter
@Enumerated(EnumType.STRING)

View File

@@ -0,0 +1,40 @@
package dev.sheldan.sissi.module.meetup.model.database;
import dev.sheldan.abstracto.core.models.database.ComponentPayload;
import dev.sheldan.sissi.module.meetup.model.database.embed.MeetupComponentId;
import lombok.*;
import javax.persistence.*;
import java.time.Instant;
@Builder
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "meetup_component")
@Getter
@Setter
@EqualsAndHashCode
public class MeetupComponent {
@EmbeddedId
@Getter
private MeetupComponentId id;
@ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, fetch = FetchType.LAZY)
@MapsId("componentId")
@JoinColumn(name = "component_id", nullable = false)
private ComponentPayload payload;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumns(
{
@JoinColumn(updatable = false, insertable = false, name = "meetup_id", referencedColumnName = "id"),
@JoinColumn(updatable = false, insertable = false, name = "server_id", referencedColumnName = "server_id")
})
private Meetup meetup;
@Column(name = "created")
private Instant created;
}

View File

@@ -1,5 +1,5 @@
package dev.sheldan.sissi.module.meetup.model.database;
public enum MeetupDecision {
YES, NO, MAYBE, CANCEL
YES, NO, MAYBE, NO_TIME
}

View File

@@ -15,14 +15,14 @@ import java.time.Instant;
@Getter
@Setter
@EqualsAndHashCode
public class MeetupParticipator {
public class MeetupParticipant {
@EmbeddedId
@Getter
private MeetupParticipationId id;
@ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, fetch = FetchType.LAZY)
@MapsId("voterId")
@MapsId("participatorId")
@JoinColumn(name = "meetup_participator_user_in_server_id", nullable = false)
private AUserInAServer participator;

View File

@@ -0,0 +1,25 @@
package dev.sheldan.sissi.module.meetup.model.database.embed;
import lombok.*;
import javax.persistence.Column;
import javax.persistence.Embeddable;
import java.io.Serializable;
@Embeddable
@Getter
@Setter
@Builder
@EqualsAndHashCode
@NoArgsConstructor
@AllArgsConstructor
public class MeetupComponentId implements Serializable {
@Column(name = "component_id")
private String componentId;
@Column(name = "meetup_id")
private Long meetupId;
@Column(name = "server_id")
private Long serverId;
}

View File

@@ -0,0 +1,18 @@
package dev.sheldan.sissi.module.meetup.model.payload;
import dev.sheldan.abstracto.core.models.template.button.ButtonPayload;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
@Builder
@Getter
@Setter
public class MeetupChangeTimeConfirmationPayload implements ButtonPayload {
private Long organizerUserId;
private Long meetupId;
private Long newTime;
private Long guildId;
private String confirmationId;
private String cancelId;
}

View File

@@ -16,12 +16,14 @@ public class MeetupMessageModel {
private String description;
private Instant meetupTime;
private MemberDisplay organizer;
private Long meetupId;
private String yesId;
private String noId;
private String maybeId;
private String cancelId;
private String noTimeId;
private Boolean cancelled;
private List<MemberDisplay> participants;
private List<MemberDisplay> maybeParticipants;
private List<MemberDisplay> noTimeParticipants;
private List<MemberDisplay> declinedParticipants;
}

View File

@@ -0,0 +1,14 @@
package dev.sheldan.sissi.module.meetup.model.template;
import dev.sheldan.abstracto.core.models.template.display.MemberDisplay;
import lombok.Builder;
import lombok.Getter;
import java.util.List;
@Builder
@Getter
public class MeetupNotificationModel {
private List<MemberDisplay> participants;
private String notificationMessage;
}

View File

@@ -0,0 +1,17 @@
package dev.sheldan.sissi.module.meetup.model.template;
import dev.sheldan.abstracto.core.models.ServerChannelMessage;
import lombok.Builder;
import lombok.Getter;
import java.time.Instant;
@Builder
@Getter
public class MeetupTimeChangedNotificationModel {
private String meetupTopic;
private String meetupDescription;
private Instant oldDate;
private Instant newDate;
private ServerChannelMessage meetupMessage;
}

View File

@@ -0,0 +1,10 @@
package dev.sheldan.sissi.module.meetup.repository;
import dev.sheldan.sissi.module.meetup.model.database.MeetupComponent;
import dev.sheldan.sissi.module.meetup.model.database.embed.MeetupComponentId;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface MeetupComponentRepository extends JpaRepository<MeetupComponent, MeetupComponentId> {
}

View File

@@ -1,10 +1,10 @@
package dev.sheldan.sissi.module.meetup.repository;
import dev.sheldan.sissi.module.meetup.model.database.MeetupParticipator;
import dev.sheldan.sissi.module.meetup.model.database.MeetupParticipant;
import dev.sheldan.sissi.module.meetup.model.database.embed.MeetupParticipationId;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface MeetupParticipatorRepository extends JpaRepository<MeetupParticipator, MeetupParticipationId> {
public interface MeetupParticipatorRepository extends JpaRepository<MeetupParticipant, MeetupParticipationId> {
}

View File

@@ -2,6 +2,7 @@ package dev.sheldan.sissi.module.meetup.repository;
import dev.sheldan.abstracto.core.models.ServerSpecificId;
import dev.sheldan.sissi.module.meetup.model.database.Meetup;
import dev.sheldan.sissi.module.meetup.model.database.MeetupState;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@@ -12,4 +13,6 @@ import java.util.List;
public interface MeetupRepository extends JpaRepository<Meetup, ServerSpecificId> {
List<Meetup> findByMeetupTimeLessThan(Instant date);
List<Meetup> findByMeetupTimeGreaterThan(Instant date);
List<Meetup> findByMeetupTimeGreaterThanAndState(Instant date, MeetupState state);
List<Meetup> findByState(MeetupState state);
}

View File

@@ -1,5 +1,6 @@
package dev.sheldan.sissi.module.meetup.service;
import dev.sheldan.abstracto.core.models.ServerChannelMessage;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.models.template.display.MemberDisplay;
import dev.sheldan.abstracto.core.service.*;
@@ -7,27 +8,33 @@ import dev.sheldan.abstracto.core.service.management.ComponentPayloadManagementS
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.FutureUtils;
import dev.sheldan.abstracto.scheduling.model.JobParameters;
import dev.sheldan.abstracto.scheduling.service.SchedulerService;
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;
import dev.sheldan.sissi.module.meetup.model.database.MeetupDecision;
import dev.sheldan.sissi.module.meetup.model.database.MeetupParticipator;
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.MeetupMessageModel;
import dev.sheldan.sissi.module.meetup.model.template.MeetupNotificationModel;
import dev.sheldan.sissi.module.meetup.model.template.MeetupTimeChangedNotificationModel;
import dev.sheldan.sissi.module.meetup.service.management.MeetupComponentManagementServiceBean;
import dev.sheldan.sissi.module.meetup.service.management.MeetupManagementServiceBean;
import dev.sheldan.sissi.module.meetup.service.management.MeetupParticipatorManagementServiceBean;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.GuildMessageChannel;
import net.dv8tion.jda.api.entities.MessageChannel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
@@ -36,9 +43,11 @@ import java.util.stream.Collectors;
public class MeetupServiceBean {
public static final String MEETUP_CONFIRMATION_BUTTON = "MEETUP_CONFIRMATION_BUTTON";
public static final String MEETUP_CHANGE_TIME_CONFIRMATION_BUTTON = "MEETUP_CHANGE_TIME_CONFIRMATION_BUTTON";
public static final String MEETUP_DECISION_BUTTON = "MEETUP_DECISION_BUTTON";
private static final String MEETUP_DISPLAY_TEMPLATE = "meetup_display";
private static final String MEETUP_CANCELLATION_TEMPLATE = "meetup_cancel_notification";
private static final String MEETUP_CHANGE_TIME_NOTIFICATION_TEMPLATE = "changeMeetupTime_notification";
private static final String MEETUP_REMINDER_TEMPLATE = "meetup_reminder_notification";
private static final String MEETUP_LATE_REMINDER_CONFIG_KEY = "meetupLateReminderSeconds";
private static final String MEETUP_EARLY_REMINDER_CONFIG_KEY = "meetupEarlyReminderSeconds";
@@ -77,6 +86,12 @@ public class MeetupServiceBean {
@Autowired
private SchedulerService schedulerService;
@Autowired
private MeetupParticipatorManagementServiceBean meetupParticipatorManagementServiceBean;
@Autowired
private MeetupComponentManagementServiceBean meetupComponentManagementServiceBean;
public void storeMeetupConfirmation(MeetupConfirmationModel model) {
AServer server = serverManagementService.loadServer(model.getGuildId());
MeetupConfirmationPayload confirmationPayload = MeetupConfirmationPayload
@@ -91,35 +106,56 @@ public class MeetupServiceBean {
componentPayloadService.createButtonPayload(model.getCancelId(), confirmationPayload, MEETUP_CONFIRMATION_BUTTON, server);
}
public void storeMeetupChangeTimeConfirmation(MeetupChangeTimeConfirmationModel model) {
AServer server = serverManagementService.loadServer(model.getGuildId());
MeetupChangeTimeConfirmationPayload confirmationPayload = MeetupChangeTimeConfirmationPayload
.builder()
.newTime(model.getMeetupTime().getEpochSecond())
.confirmationId(model.getConfirmationId())
.meetupId(model.getMeetupId())
.organizerUserId(model.getUserId())
.cancelId(model.getCancelId())
.guildId(model.getGuildId())
.build();
componentPayloadService.createButtonPayload(model.getConfirmationId(), confirmationPayload, MEETUP_CHANGE_TIME_CONFIRMATION_BUTTON, server);
componentPayloadService.createButtonPayload(model.getCancelId(), confirmationPayload, MEETUP_CHANGE_TIME_CONFIRMATION_BUTTON, server);
}
public MeetupMessageModel getMeetupMessageModel(Meetup meetup) {
List<MeetupParticipator> allParticipants = meetup.getParticipants();
List<MeetupParticipator> participating = allParticipants
List<MeetupParticipant> allParticipants = meetup.getParticipants();
List<MeetupParticipant> participating = allParticipants
.stream()
.filter(meetupParticipator -> meetupParticipator.getDecision().equals(MeetupDecision.YES))
.collect(Collectors.toList());
List<MeetupParticipator> maybe = allParticipants
List<MeetupParticipant> maybe = allParticipants
.stream()
.filter(meetupParticipator -> meetupParticipator.getDecision().equals(MeetupDecision.MAYBE))
.collect(Collectors.toList());
List<MeetupParticipator> notParticipating = allParticipants
List<MeetupParticipant> notParticipating = allParticipants
.stream()
.filter(meetupParticipator -> meetupParticipator.getDecision().equals(MeetupDecision.NO))
.collect(Collectors.toList());
List<MeetupParticipant> notTimeParticipating = allParticipants
.stream()
.filter(meetupParticipator -> meetupParticipator.getDecision().equals(MeetupDecision.NO_TIME))
.collect(Collectors.toList());
return MeetupMessageModel
.builder()
.description(meetup.getDescription())
.topic(meetup.getTopic())
.meetupTime(meetup.getMeetupTime())
.meetupId(meetup.getId().getId())
.participants(getMemberDisplays(participating))
.declinedParticipants(getMemberDisplays(notParticipating))
.noTimeParticipants(getMemberDisplays(notTimeParticipating))
.maybeParticipants(getMemberDisplays(maybe))
.cancelled(meetup.getState().equals(MeetupState.CANCELLED))
.organizer(MemberDisplay.fromAUserInAServer(meetup.getOrganizer()))
.build();
}
private List<MemberDisplay> getMemberDisplays(List<MeetupParticipator> participants) {
private List<MemberDisplay> getMemberDisplays(List<MeetupParticipant> participants) {
return participants
.stream()
.map(meetupParticipator -> MemberDisplay.fromAUserInAServer(meetupParticipator.getParticipator()))
@@ -130,11 +166,16 @@ public class MeetupServiceBean {
return templateService.renderEmbedTemplate(MEETUP_DISPLAY_TEMPLATE, model);
}
public CompletableFuture<Void> cancelMeetup(Meetup meetup, List<String> componentPayloads) {
public CompletableFuture<Void> cancelMeetup(Meetup meetup) {
Long serverId = meetup.getServer().getId();
Long meetupId = meetup.getId().getId();
GuildMessageChannel channel = channelService.getMessageChannelFromServer(serverId, meetup.getMeetupChannel().getId());
MeetupMessageModel model = getMeetupMessageModel(meetup);
List<String> componentPayloads = meetup
.getMeetupComponents()
.stream()
.map(meetupComponent -> meetupComponent.getId().getComponentId())
.collect(Collectors.toList());
model.setCancelled(true);
MessageToSend meetupMessage = getMeetupMessage(model);
return messageService.editMessageInChannel(channel, meetupMessage, meetup.getMessageId())
@@ -147,18 +188,29 @@ public class MeetupServiceBean {
Meetup meetup = meetupManagementServiceBean.getMeetup(meetupId, serverId);
MeetupMessageModel model = getMeetupMessageModel(meetup);
MessageToSend messageToSend = templateService.renderEmbedTemplate(MEETUP_CANCELLATION_TEMPLATE, model);
meetup.getParticipants().forEach(meetupParticipator -> {
Long userId = meetupParticipator.getParticipator().getUserReference().getId();
userService.retrieveUserForId(userId)
.thenCompose(user -> messageService.sendMessageToSendToUser(user, messageToSend))
.thenAccept(message -> log.info("Notified user {} about cancellation of meetup {} in server {}.", userId, meetupId, serverId));
});
meetup
.getParticipants()
.stream()
.filter(meetupParticipator ->
meetupParticipator.getDecision().equals(MeetupDecision.MAYBE) ||
meetupParticipator.getDecision().equals(MeetupDecision.YES))
.forEach(meetupParticipator -> {
Long userId = meetupParticipator.getParticipator().getUserReference().getId();
userService.retrieveUserForId(userId)
.thenCompose(user -> messageService.sendMessageToSendToUser(user, messageToSend))
.thenAccept(message -> log.info("Notified user {} about cancellation of meetup {} in server {}.", userId, meetupId, serverId))
.exceptionally(throwable -> {
log.warn("Failed to notify user {} about cancellation of meetup {} in server {}.", userId, meetupId, serverId);
return null;
});
});
}
@Transactional
public void cleanupMeetup(Long meetupId, Long serverId, List<String> componentPayloads) {
Meetup meetup = meetupManagementServiceBean.getMeetup(meetupId, serverId);
meetup.setState(MeetupState.CANCELLED);
meetupComponentManagementServiceBean.deleteAllComponents(meetup);
log.info("Cleanup meetup {} in server {}.", meetup, serverId);
if(meetup.getEarlyReminderJobTriggerKey() != null) {
schedulerService.stopTrigger(meetup.getEarlyReminderJobTriggerKey());
@@ -197,6 +249,25 @@ public class MeetupServiceBean {
}
}
public CompletableFuture<Void> notifyMeetupParticipants(Meetup meetup, String message) {
List<MeetupDecision> decisionsToBeNotified = Arrays.asList(MeetupDecision.MAYBE, MeetupDecision.YES);
List<MemberDisplay> participants = meetup
.getParticipants()
.stream()
.filter(meetupParticipator -> decisionsToBeNotified.contains(meetupParticipator.getDecision()))
.map(meetupParticipator -> MemberDisplay.fromAUserInAServer(meetupParticipator.getParticipator()))
.collect(Collectors.toList());
MeetupNotificationModel model = MeetupNotificationModel
.builder()
.notificationMessage(message)
.participants(participants)
.build();
MessageChannel channel = channelService.getMessageChannelFromServer(meetup.getServer().getId(), meetup.getMeetupChannel().getId());
MessageToSend messageToSend = templateService.renderEmbedTemplate("notifyMeetupParticipants_notification_message", model, meetup.getServer().getId());
return FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, channel));
}
@Transactional
public void remindParticipants(Long meetupId, Long serverId) {
Meetup meetup = meetupManagementServiceBean.getMeetup(meetupId, serverId);
@@ -209,21 +280,100 @@ public class MeetupServiceBean {
meetupParticipator.getDecision().equals(MeetupDecision.MAYBE) ||
meetupParticipator.getDecision().equals(MeetupDecision.YES))
.forEach(meetupParticipator -> {
Long userId = meetupParticipator.getParticipator().getUserReference().getId();
userService.retrieveUserForId(userId)
.thenCompose(user -> messageService.sendMessageToSendToUser(user, messageToSend))
.thenAccept(message -> log.info("Notified user {} about incoming meetup {} in server {}.", userId, meetupId, serverId));
});
Long userId = meetupParticipator.getParticipator().getUserReference().getId();
userService.retrieveUserForId(userId)
.thenCompose(user -> messageService.sendMessageToSendToUser(user, messageToSend))
.thenAccept(message -> log.info("Notified user {} about incoming meetup {} in server {}.", userId, meetupId, serverId));
});
}
@Transactional
public void cleanupMeetups() {
Instant time = Instant.now().minus(1, ChronoUnit.DAYS);
List<Meetup> oldMeetups = meetupManagementServiceBean.getMeetupsOlderThan(time)
.stream()
.filter(meetup -> meetup.getMessageId() != null)
.collect(Collectors.toList());
oldMeetups.forEach(meetup -> messageService.deleteMessageInChannelInServer(meetup.getServer().getId(), meetup.getMeetupChannel().getId(), meetup.getMessageId()));
List<Meetup> oldMeetups = meetupManagementServiceBean.getMeetupsOlderThan(time);
deleteMeetups(oldMeetups);
List<Meetup> cancelledMeetups = meetupManagementServiceBean.findCancelledMeetups();
deleteMeetups(cancelledMeetups);
}
private void deleteMeetups(List<Meetup> oldMeetups) {
oldMeetups.forEach(meetup -> {
if(meetup.getMessageId() != null) {
messageService.deleteMessageInChannelInServer(meetup.getServer().getId(), meetup.getMeetupChannel().getId(), meetup.getMessageId());
}
meetupComponentManagementServiceBean.deleteAllComponents(meetup);
});
meetupManagementServiceBean.deleteMeetups(oldMeetups);
}
public CompletableFuture<Void> changeMeetupTimeAndNotifyParticipants(Meetup meetup, Instant newTime) {
List<MeetupDecision> decisions = Arrays.asList(MeetupDecision.MAYBE, MeetupDecision.NO_TIME, MeetupDecision.YES);
List<MeetupParticipant> participants = meetup
.getParticipants()
.stream()
.filter(meetupParticipator -> decisions.contains(meetupParticipator.getDecision()))
.collect(Collectors.toList());
List<Long> userIdsToNotify = participants
.stream()
.map(meetupParticipator -> meetupParticipator.getParticipator().getUserReference().getId())
.collect(Collectors.toList());
Long serverId = meetup.getServer().getId();
ServerChannelMessage meetupMessage = ServerChannelMessage
.builder()
.serverId(serverId)
.channelId(meetup.getMeetupChannel().getId())
.messageId(meetup.getMessageId())
.build();
MeetupTimeChangedNotificationModel notificationModel = MeetupTimeChangedNotificationModel
.builder()
.meetupDescription(meetup.getDescription())
.meetupTopic(meetup.getTopic())
.meetupMessage(meetupMessage)
.newDate(newTime)
.oldDate(meetup.getMeetupTime())
.build();
if(meetup.getEarlyReminderJobTriggerKey() != null) {
schedulerService.stopTrigger(meetup.getEarlyReminderJobTriggerKey());
}
if(meetup.getLateReminderJobTriggerKey() != null) {
schedulerService.stopTrigger(meetup.getLateReminderJobTriggerKey());
}
// set the new time here, so that we can use it in schedule
meetup.setMeetupTime(newTime);
scheduleReminders(meetup);
MessageToSend messageToSend = templateService.renderEmbedTemplate(MEETUP_CHANGE_TIME_NOTIFICATION_TEMPLATE, notificationModel, serverId);
Long meetupId = meetup.getId().getId();
userIdsToNotify.forEach(userId -> {
userService.retrieveUserForId(userId).thenCompose(user -> messageService.sendMessageToSendToUser(user, messageToSend)
.exceptionally(throwable -> {
log.warn("Failed to notify user {} about changed time of meetup {} in server {}.", userId, meetupId, serverId);
return null;
}));
});
meetupParticipatorManagementServiceBean.deleteParticipants(participants);
List<Long> userInServerIds = participants
.stream()
.map(meetupParticipant -> meetupParticipant.getParticipator().getUserInServerId())
.collect(Collectors.toList());
meetup
.getParticipants().removeIf(meetupParticipant -> userInServerIds.contains(meetupParticipant.getParticipator().getUserInServerId()));
MeetupMessageModel meetupMessageModel = getMeetupMessageModel(meetup);
meetupMessageModel.setParticipants(new ArrayList<>());
meetupMessageModel.setMaybeParticipants(new ArrayList<>());
meetupMessageModel.setNoTimeParticipants(new ArrayList<>());
MessageToSend updatedMeetupMessage = getMeetupMessage(meetupMessageModel);
GuildMessageChannel meetupChannel = channelService.getMessageChannelFromServer(serverId, meetup.getMeetupChannel().getId());
return channelService.editEmbedMessageInAChannel(updatedMeetupMessage.getEmbeds().get(0), meetupChannel, meetup.getMessageId())
.thenAccept(message -> log.info("Updated message of meetup {} in channel {} in server {}.", meetupId, meetup.getMeetupChannel().getId(), serverId))
.exceptionally(throwable -> {
log.info("Failed to update message of meetup {} in channel {} in server {}.", meetupId, meetup.getMeetupChannel().getId(), serverId, throwable);
return null;
});
}
}

View File

@@ -0,0 +1,40 @@
package dev.sheldan.sissi.module.meetup.service.management;
import dev.sheldan.abstracto.core.models.database.ComponentPayload;
import dev.sheldan.sissi.module.meetup.model.database.Meetup;
import dev.sheldan.sissi.module.meetup.model.database.MeetupComponent;
import dev.sheldan.sissi.module.meetup.model.database.embed.MeetupComponentId;
import dev.sheldan.sissi.module.meetup.repository.MeetupComponentRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class MeetupComponentManagementServiceBean {
@Autowired
private MeetupComponentRepository meetupComponentRepository;
public MeetupComponent createComponent(Meetup meetup, String componentId, ComponentPayload payload) {
MeetupComponentId id = MeetupComponentId
.builder()
.meetupId(meetup.getId().getId())
.serverId(meetup.getServer().getId())
.componentId(componentId)
.build();
MeetupComponent component = MeetupComponent
.builder()
.id(id)
.payload(payload)
.meetup(meetup)
.build();
return meetupComponentRepository.save(component);
}
public void deleteComponent(MeetupComponent meetupComponent) {
meetupComponentRepository.delete(meetupComponent);
}
public void deleteAllComponents(Meetup meetup) {
meetupComponentRepository.deleteAll(meetup.getMeetupComponents());
}
}

View File

@@ -58,10 +58,18 @@ public class MeetupManagementServiceBean {
return meetupRepository.findAll();
}
public List<Meetup> findCancelledMeetups() {
return meetupRepository.findByState(MeetupState.CANCELLED);
}
public List<Meetup> getFutureMeetups() {
return meetupRepository.findByMeetupTimeGreaterThan(Instant.now());
}
public List<Meetup> getIncomingMeetups() {
return meetupRepository.findByMeetupTimeGreaterThanAndState(Instant.now(), MeetupState.CONFIRMED);
}
public void deleteMeetups(List<Meetup> meetups) {
meetupRepository.deleteAll(meetups);
}

View File

@@ -3,21 +3,24 @@ package dev.sheldan.sissi.module.meetup.service.management;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.sissi.module.meetup.model.database.Meetup;
import dev.sheldan.sissi.module.meetup.model.database.MeetupDecision;
import dev.sheldan.sissi.module.meetup.model.database.MeetupParticipator;
import dev.sheldan.sissi.module.meetup.model.database.MeetupParticipant;
import dev.sheldan.sissi.module.meetup.model.database.embed.MeetupParticipationId;
import dev.sheldan.sissi.module.meetup.repository.MeetupParticipatorRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Optional;
@Component
@Slf4j
public class MeetupParticipatorManagementServiceBean {
@Autowired
private MeetupParticipatorRepository repository;
public Optional<MeetupParticipator> getParticipation(Meetup meetup, AUserInAServer aUserInAServer) {
public Optional<MeetupParticipant> getParticipation(Meetup meetup, AUserInAServer aUserInAServer) {
MeetupParticipationId id = MeetupParticipationId
.builder()
.meetupId(meetup.getId().getId())
@@ -27,14 +30,20 @@ public class MeetupParticipatorManagementServiceBean {
return repository.findById(id);
}
public MeetupParticipator createParticipation(Meetup meetup, AUserInAServer aUserInAServer, MeetupDecision meetupDecision) {
public void deleteParticipants(List<MeetupParticipant> participants) {
log.info("Deleting {} participants", participants.size());
repository.deleteAll(participants);
participants.forEach(meetupParticipant -> meetupParticipant.setMeetup(null));
}
public MeetupParticipant createParticipation(Meetup meetup, AUserInAServer aUserInAServer, MeetupDecision meetupDecision) {
MeetupParticipationId id = MeetupParticipationId
.builder()
.meetupId(meetup.getId().getId())
.serverId(meetup.getServer().getId())
.participatorId(aUserInAServer.getUserInServerId())
.build();
MeetupParticipator participator = MeetupParticipator
MeetupParticipant participator = MeetupParticipant
.builder()
.id(id)
.meetup(meetup)

View File

@@ -0,0 +1,11 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
<include file="seedData/data.xml" relativeToChangelogFile="true"/>
<include file="tables/tables.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -0,0 +1,30 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
<property name="utilityModule" value="(SELECT id FROM module WHERE name = 'utility')"/>
<property name="meetupFeature" value="(SELECT id FROM feature WHERE key = 'meetup')"/>
<changeSet author="Sheldan" id="meetup-commands">
<insert tableName="command">
<column name="name" value="cancelMeetup"/>
<column name="module_id" valueComputed="${utilityModule}"/>
<column name="feature_id" valueComputed="${meetupFeature}"/>
</insert>
<insert tableName="command">
<column name="name" value="changeMeetupTime"/>
<column name="module_id" valueComputed="${utilityModule}"/>
<column name="feature_id" valueComputed="${meetupFeature}"/>
</insert>
<insert tableName="command">
<column name="name" value="notifyMeetupParticipants"/>
<column name="module_id" valueComputed="${utilityModule}"/>
<column name="feature_id" valueComputed="${meetupFeature}"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

@@ -0,0 +1,10 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
<include file="command.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -0,0 +1,37 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
<changeSet author="Sheldan" id="meetup_component-table">
<createTable tableName="meetup_component">
<column name="component_id" type="VARCHAR(100)">
<constraints nullable="false"/>
</column>
<column name="meetup_id" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="server_id" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE">
<constraints nullable="false"/>
</column>
</createTable>
<addPrimaryKey columnNames="component_id, meetup_id, server_id" tableName="meetup_component" constraintName="pk_meetup_component" validate="true"/>
<addForeignKeyConstraint baseColumnNames="meetup_id, server_id" baseTableName="meetup_component" constraintName="fk_meetup_component_meetup"
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION"
referencedColumnNames="id, server_id" referencedTableName="meetup" validate="true"/>
<addForeignKeyConstraint baseColumnNames="component_id" baseTableName="meetup_component" constraintName="fk_meetup_component_component"
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION"
referencedColumnNames="id" referencedTableName="component_payload" validate="false"/>
<sql>
DROP TRIGGER IF EXISTS meetup_component_insert_trigger ON meetup_component;
CREATE TRIGGER meetup_component_insert_trigger BEFORE INSERT ON meetup_component FOR EACH ROW EXECUTE PROCEDURE insert_trigger_procedure();
</sql>
</changeSet>
</databaseChangeLog>

View File

@@ -0,0 +1,16 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
<changeSet author="Sheldan" id="meetup_participator-table">
<sql>
ALTER TABLE meetup_participator DROP CONSTRAINT check_meetup_participator_decision;
ALTER TABLE meetup_participator ADD CONSTRAINT check_meetup_participator_decision CHECK (decision IN ('YES','NO', 'MAYBE', 'NO_TIME'));
</sql>
</changeSet>
</databaseChangeLog>

View File

@@ -0,0 +1,11 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
<include file="meetup_participator.xml" relativeToChangelogFile="true"/>
<include file="meetup_component.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -7,4 +7,5 @@
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
<include file="1.1.0/collection.xml" relativeToChangelogFile="true"/>
<include file="1.2.0/collection.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.sissi.application</groupId>
<artifactId>application</artifactId>
<version>1.1.0.RC1</version>
<version>1.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.sissi.application</groupId>
<artifactId>sissi-modules</artifactId>
<version>1.1.0.RC1</version>
<version>1.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.sissi</groupId>
<artifactId>deployment</artifactId>
<version>1.1.0.RC1</version>
<version>1.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -30,4 +30,4 @@ PGADMIN_DEFAULT_EMAIL=sheldan@sheldan.dev
PGADMIN_DEFAULT_PASSWORD=admin
TOKEN=<INSERT TOKEN>
YOUTUBE_API_KEY=<INSERT KEY>
SISSI_VERSION=1.1.0.RC1
SISSI_VERSION=1.2.0

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.sissi</groupId>
<artifactId>deployment</artifactId>
<version>1.1.0.RC1</version>
<version>1.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.sissi</groupId>
<artifactId>sissi</artifactId>
<version>1.1.0.RC1</version>
<version>1.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -13,7 +13,7 @@
<groupId>dev.sheldan.sissi</groupId>
<artifactId>sissi</artifactId>
<name>Sissi</name>
<version>1.1.0.RC1</version>
<version>1.2.0</version>
<properties>
<maven.compiler.target>1.8</maven.compiler.target>
@@ -57,7 +57,7 @@
<scm>
<url>https://maven.pkg.github.com/Sheldan/Sissi</url>
<developerConnection>scm:git:git@github.com:Sheldan/Sissi.git</developerConnection>
<tag>sissi-1.1.0.RC1</tag>
<tag>sissi-1.2.0</tag>
</scm>
</project>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.sissi</groupId>
<artifactId>sissi</artifactId>
<version>1.1.0.RC1</version>
<version>1.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>module-templates</artifactId>
<groupId>dev.sheldan.sissi.templates</groupId>
<version>1.1.0.RC1</version>
<version>1.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -0,0 +1,6 @@
{
"additionalMessage": "<@safe_include "cancelMeetup_response_text"/>",
"messageConfig": {
"ephemeral": true
}
}

View File

@@ -2,7 +2,7 @@
{
"embeds": [
{
<#include "abstracto_color">,
<#include "abstracto_color">,
<#assign time><@format_instant_date_time instant=meetupTime/></#assign>
<#assign topicText>${topic?json_string}</#assign>
"description": "<#include "meetup_cancel_notification_description">"

View File

@@ -0,0 +1,25 @@
<#include "format_instant">
{
"embeds": [
{
<#include "abstracto_color">,
"title": {
"title": "${topic?json_string}"
},
"description": "<@format_instant_date_time instant=meetupTime/>
${description?json_string}"
}
],
"buttons": [
{
"label": "<@safe_include "createMeetup_confirm_button_label"/>",
"id": "${confirmationId}",
"buttonStyle": "success"
},
{
"label": "<@safe_include "createMeetup_cancel_button_label"/>",
"id": "${cancelId}",
"buttonStyle": "danger"
}
]
}

View File

@@ -0,0 +1,13 @@
<#include "format_instant">
{
"embeds": [
{
<#include "abstracto_color">,
<#assign topicText=meetupTopic>
<#assign oldTime><@format_instant_date_time instant=oldDate/></#assign>
<#assign newTime><@format_instant_date_time instant=newDate/></#assign>
<#assign messageLink=meetupMessage.jumpUrl>
"description": "<@safe_include "changeMeetupTime_notification_text"/>"
}
]
}

View File

@@ -0,0 +1,5 @@
{
<#assign userMentions><#list participants as user>${user.memberMention}<#sep>, </#list></#assign>
"additionalMessage": "${userMentions?json_string}
${notificationMessage}"
}

View File

@@ -0,0 +1,6 @@
{
"additionalMessage": "<@safe_include "notifyMeetupParticipants_response_text"/>",
"messageConfig": {
"ephemeral": true
}
}

View File

@@ -0,0 +1 @@
<#include "meetup_not_organizer_exception_message">

View File

@@ -6,15 +6,18 @@
{
<#include "abstracto_color">,
"title": {
"title": "${topic?json_string}"
"title": "${topic?json_string} - <@safe_include "meetup_message_id_display"/>"
},
<#assign time><@format_instant_date_time instant=meetupTime/></#assign>
<#assign timeRelative><@format_instant_relative instant=meetupTime/></#assign>
<#assign organizerText>${organizer.memberMention}</#assign>
<#assign meetupId=meetupId/>
<#assign descriptionText>${description?json_string}</#assign>
<#assign participantsText><#list participants as member>${member.memberMention}<#else><#include "meetup_message_no_member"></#list></#assign>
<#assign maybeParticipantsText><#list maybeParticipants as member>${member.memberMention}<#else><#include "meetup_message_no_member"></#list></#assign>
<#assign declinedParticipantsText><#list declinedParticipants as member>${member.memberMention}<#else><#include "meetup_message_no_member"></#list></#assign>
"description": "<#if cancelled>~~</#if><#include "meetup_display_description"><#if cancelled>~~</#if>"
<#assign participantsText> (${participants?size}) <#list participants as member>${member.memberMention}<#sep>, </#sep><#else><#include "meetup_message_no_member"></#list></#assign>
<#assign maybeParticipantsText> (${maybeParticipants?size}) <#list maybeParticipants as member>${member.memberMention}<#sep>, </#sep><#else><#include "meetup_message_no_member"></#list></#assign>
<#assign noTimeParticipantsText> (${noTimeParticipants?size}) <#list noTimeParticipants as member>${member.memberMention}<#sep>, </#sep><#else><#include "meetup_message_no_member"></#list></#assign>
<#assign declinedParticipantsText> (${declinedParticipants?size}) <#list declinedParticipants as member>${member.memberMention}<#sep>, </#sep><#else><#include "meetup_message_no_member"></#list></#assign>
"description": "<#if cancelled>~~</#if><@safe_include "meetup_display_description"/><#if cancelled>~~</#if>"
}
],
<#if yesId?has_content && noId?has_content && maybeId?has_content && !cancelled>
@@ -30,13 +33,13 @@
"buttonStyle": "secondary"
},
{
"label": "<@safe_include "meetup_message_no_button_label"/>",
"id": "${noId}",
"label": "<@safe_include "meetup_message_no_time_button_label"/>",
"id": "${noTimeId}",
"buttonStyle": "danger"
},
{
"label": "<@safe_include "meetup_message_cancel_button_label"/>",
"id": "${cancelId}",
"label": "<@safe_include "meetup_message_no_button_label"/>",
"id": "${noId}",
"buttonStyle": "danger"
}
],

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.sissi.templates</groupId>
<artifactId>sissi-templates</artifactId>
<version>1.1.0.RC1</version>
<version>1.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.sissi.templates</groupId>
<artifactId>module-templates</artifactId>
<version>1.1.0.RC1</version>
<version>1.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.sissi.templates</groupId>
<artifactId>templates</artifactId>
<version>1.1.0.RC1</version>
<version>1.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.sissi.templates.translations</groupId>
<artifactId>module-translations</artifactId>
<version>1.1.0.RC1</version>
<version>1.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -0,0 +1,3 @@
This command is used to cancel a meetup.
This includes notifying all current participants, who either said yes or maybe, that the meetup has been cancelled and updating the message to reflect this.
Cancelled meetups are deleted after one to two days completely.

View File

@@ -0,0 +1,2 @@
Meetup with topic ${topicText} has been moved from ${oldTime} to ${newTime}.
Your response has been removed, please click [here](${messageLink}) to respond again.

View File

@@ -0,0 +1,3 @@
This command is used to change the time of a meetup.
This includes notifying all current participants, who either said yes, maybe or no time, that the time of the meetup has changed.
All previous responses are deleted (except no) and the message is updated accordingly.

View File

@@ -0,0 +1,2 @@
This command is used to notify all participants of a meetup.
This means every participant will get mentioned and the message will be sent.

View File

@@ -1,6 +1,11 @@
Time: ${time} ${timeRelative}
<#if descriptionText?hasContent>Description: ${descriptionText}</#if>
Organized by: ${organizerText}
Participants: ${participantsText}
Maybe: ${maybeParticipantsText}
Declined: ${declinedParticipantsText}
Declined: ${declinedParticipantsText}
No time: ${noTimeParticipantsText}

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.sissi.templates.translations</groupId>
<artifactId>sissi-translations</artifactId>
<version>1.1.0.RC1</version>
<version>1.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.sissi.templates.translations</groupId>
<artifactId>module-translations</artifactId>
<version>1.1.0.RC1</version>
<version>1.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.sissi.templates</groupId>
<artifactId>templates</artifactId>
<version>1.1.0.RC1</version>
<version>1.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>