mirror of
https://github.com/Sheldan/Sissi.git
synced 2026-01-26 19:21:43 +00:00
[SIS-3] adding meetup implementation
This commit is contained in:
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@@ -34,5 +34,5 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
REGISTRY_PREFIX: docker.pkg.github.com/sheldan/sissi/
|
REGISTRY_PREFIX: docker.pkg.github.com/sheldan/sissi/
|
||||||
VERSION: ${{ env.version }}
|
VERSION: ${{ env.version }}
|
||||||
ABSTRACTO_VERSION: 1.3.13
|
ABSTRACTO_VERSION: 1.4.0.RC2
|
||||||
ABSTRACTO_REGISTRY_PREFIX: docker.pkg.github.com/sheldan/abstracto/
|
ABSTRACTO_REGISTRY_PREFIX: docker.pkg.github.com/sheldan/abstracto/
|
||||||
@@ -81,6 +81,12 @@
|
|||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>dev.sheldan.sissi.application.module</groupId>
|
||||||
|
<artifactId>meetup</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
45
application/sissi-modules/meetup/pom.xml
Normal file
45
application/sissi-modules/meetup/pom.xml
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<groupId>dev.sheldan.sissi.application</groupId>
|
||||||
|
<artifactId>sissi-modules</artifactId>
|
||||||
|
<version>1.1.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>dev.sheldan.sissi.application.module</groupId>
|
||||||
|
<artifactId>meetup</artifactId>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-assembly-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<descriptors>
|
||||||
|
<descriptor>src/main/assembly/liquibase.xml</descriptor>
|
||||||
|
</descriptors>
|
||||||
|
</configuration>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>make-assembly</id>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>single</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>dev.sheldan.abstracto.scheduling</groupId>
|
||||||
|
<artifactId>scheduling-int</artifactId>
|
||||||
|
<version>${abstracto.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.1.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.1.0 http://maven.apache.org/xsd/assembly-2.1.0.xsd">
|
||||||
|
<id>liquibase</id>
|
||||||
|
<formats>
|
||||||
|
<format>zip</format>
|
||||||
|
</formats>
|
||||||
|
<includeBaseDirectory>false</includeBaseDirectory>
|
||||||
|
<fileSets>
|
||||||
|
<fileSet>
|
||||||
|
<outputDirectory>.</outputDirectory>
|
||||||
|
<directory>${project.basedir}/src/main/resources/migrations</directory>
|
||||||
|
<includes>
|
||||||
|
<include>**/*</include>
|
||||||
|
</includes>
|
||||||
|
</fileSet>
|
||||||
|
</fileSets>
|
||||||
|
</assembly>
|
||||||
@@ -0,0 +1,199 @@
|
|||||||
|
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.models.database.AChannel;
|
||||||
|
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||||
|
import dev.sheldan.abstracto.core.models.template.display.MemberDisplay;
|
||||||
|
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||||
|
import dev.sheldan.abstracto.core.service.ComponentService;
|
||||||
|
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
|
||||||
|
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||||
|
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.model.command.MeetupConfirmationModel;
|
||||||
|
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.entities.Message;
|
||||||
|
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 CreateMeetup extends AbstractConditionableCommand {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private TemplateService templateService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ChannelService channelService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ComponentService componentService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MeetupServiceBean meetupServiceBean;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MeetupManagementServiceBean meetupManagementServiceBean;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UserInServerManagementService userInServerManagementService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ChannelManagementService channelManagementService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private InteractionService interactionService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SlashCommandParameterService slashCommandParameterService;
|
||||||
|
|
||||||
|
private static final String CREATE_MEETUP_COMMAND = "createMeetup";
|
||||||
|
private static final String MEETUP_TIME_PARAMETER = "meetupTime";
|
||||||
|
private static final String TOPIC_PARAMETER = "topic";
|
||||||
|
private static final String DESCRIPTION_PARAMETER = "description";
|
||||||
|
private static final String CONFIRMATION_TEMPLATE = "createMeetup_confirmation";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
|
||||||
|
List<Object> parameters = commandContext.getParameters().getParameters();
|
||||||
|
Instant meetupTime = (Instant) parameters.get(0);
|
||||||
|
String meetupTopic = (String) parameters.get(1);
|
||||||
|
String description;
|
||||||
|
if(parameters.size() > 2) {
|
||||||
|
description = (String) parameters.get(2);
|
||||||
|
} else {
|
||||||
|
description = "";
|
||||||
|
}
|
||||||
|
AUserInAServer organizer = userInServerManagementService.loadOrCreateUser(commandContext.getAuthor());
|
||||||
|
AChannel meetupChannel = channelManagementService.loadChannel(commandContext.getChannel().getIdLong());
|
||||||
|
Meetup meetup = meetupManagementServiceBean.createMeetup(meetupTime, meetupTopic, description, organizer, meetupChannel);
|
||||||
|
String confirmationId = componentService.generateComponentId();
|
||||||
|
String cancelId = componentService.generateComponentId();
|
||||||
|
MeetupConfirmationModel model = MeetupConfirmationModel
|
||||||
|
.builder()
|
||||||
|
.meetupTime(meetupTime)
|
||||||
|
.guildId(commandContext.getGuild().getIdLong())
|
||||||
|
.description(description)
|
||||||
|
.topic(meetupTopic)
|
||||||
|
.confirmationId(confirmationId)
|
||||||
|
.cancelId(cancelId)
|
||||||
|
.meetupId(meetup.getId().getId())
|
||||||
|
.organizer(MemberDisplay.fromMember(commandContext.getAuthor()))
|
||||||
|
.build();
|
||||||
|
MessageToSend messageToSend = templateService.renderEmbedTemplate(CONFIRMATION_TEMPLATE, model, commandContext.getGuild().getIdLong());
|
||||||
|
List<CompletableFuture<Message>> messageFutures = channelService.sendMessageToSendToChannel(messageToSend, commandContext.getChannel());
|
||||||
|
return FutureUtils.toSingleFutureGeneric(messageFutures)
|
||||||
|
.thenAccept(unused -> meetupServiceBean.storeMeetupConfirmation(model))
|
||||||
|
.thenApply(unused -> CommandResult.fromIgnored());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
||||||
|
Integer time = slashCommandParameterService.getCommandOption(MEETUP_TIME_PARAMETER, event, Long.class, Integer.class);
|
||||||
|
String topic = slashCommandParameterService.getCommandOption(TOPIC_PARAMETER, event, String.class);
|
||||||
|
String description;
|
||||||
|
if(slashCommandParameterService.hasCommandOption(DESCRIPTION_PARAMETER, event)) {
|
||||||
|
description = slashCommandParameterService.getCommandOption(DESCRIPTION_PARAMETER, event, String.class);
|
||||||
|
} else {
|
||||||
|
description = "";
|
||||||
|
}
|
||||||
|
Instant meetupTime = Instant.ofEpochSecond(time);
|
||||||
|
AUserInAServer organizer = userInServerManagementService.loadOrCreateUser(event.getMember());
|
||||||
|
AChannel meetupChannel = channelManagementService.loadChannel(event.getChannel().getIdLong());
|
||||||
|
Meetup meetup = meetupManagementServiceBean.createMeetup(meetupTime, topic, description, organizer, meetupChannel);
|
||||||
|
String confirmationId = componentService.generateComponentId();
|
||||||
|
String cancelId = componentService.generateComponentId();
|
||||||
|
MeetupConfirmationModel model = MeetupConfirmationModel
|
||||||
|
.builder()
|
||||||
|
.meetupTime(meetupTime)
|
||||||
|
.guildId(event.getGuild().getIdLong())
|
||||||
|
.description(description)
|
||||||
|
.topic(topic)
|
||||||
|
.confirmationId(confirmationId)
|
||||||
|
.cancelId(cancelId)
|
||||||
|
.meetupId(meetup.getId().getId())
|
||||||
|
.organizer(MemberDisplay.fromMember(event.getMember()))
|
||||||
|
.build();
|
||||||
|
MessageToSend messageToSend = templateService.renderEmbedTemplate(CONFIRMATION_TEMPLATE, model, event.getGuild().getIdLong());
|
||||||
|
return interactionService.replyMessageToSend(messageToSend, event)
|
||||||
|
.thenAccept(interactionHook -> meetupServiceBean.storeMeetupConfirmation(model))
|
||||||
|
.thenApply(unused -> CommandResult.fromSuccess());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommandConfiguration getConfiguration() {
|
||||||
|
|
||||||
|
Parameter timeParameter = Parameter
|
||||||
|
.builder()
|
||||||
|
.templated(true)
|
||||||
|
.name(MEETUP_TIME_PARAMETER)
|
||||||
|
.type(Instant.class)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Parameter topicParameter = Parameter
|
||||||
|
.builder()
|
||||||
|
.templated(true)
|
||||||
|
.name(TOPIC_PARAMETER)
|
||||||
|
.type(String.class)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Parameter descriptionParameter = Parameter
|
||||||
|
.builder()
|
||||||
|
.templated(true)
|
||||||
|
.name(DESCRIPTION_PARAMETER)
|
||||||
|
.remainder(true)
|
||||||
|
.optional(true)
|
||||||
|
.type(String.class)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
List<Parameter> parameters = Arrays.asList(timeParameter, topicParameter, descriptionParameter);
|
||||||
|
HelpInfo helpInfo = HelpInfo
|
||||||
|
.builder()
|
||||||
|
.templated(true)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
SlashCommandConfig slashCommandConfig = SlashCommandConfig
|
||||||
|
.builder()
|
||||||
|
.enabled(true)
|
||||||
|
.rootCommandName(MeetupSlashCommandNames.MEETUP)
|
||||||
|
.commandName("create")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
return CommandConfiguration.builder()
|
||||||
|
.name(CREATE_MEETUP_COMMAND)
|
||||||
|
.module(UtilityModuleDefinition.UTILITY)
|
||||||
|
.templated(true)
|
||||||
|
.slashCommandConfig(slashCommandConfig)
|
||||||
|
.async(true)
|
||||||
|
.supportsEmbedException(true)
|
||||||
|
.causesReaction(false)
|
||||||
|
.parameters(parameters)
|
||||||
|
.help(helpInfo)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FeatureDefinition getFeature() {
|
||||||
|
return MeetupFeatureDefinition.MEETUP;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
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.config.FeatureDefinition;
|
||||||
|
import dev.sheldan.abstracto.core.interaction.InteractionService;
|
||||||
|
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||||
|
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.model.command.MeetupListItemModel;
|
||||||
|
import dev.sheldan.sissi.module.meetup.model.command.MeetupListModel;
|
||||||
|
import dev.sheldan.sissi.module.meetup.model.database.Meetup;
|
||||||
|
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.ArrayList;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class ListMeetups extends AbstractConditionableCommand {
|
||||||
|
|
||||||
|
private static final String LIST_MEETUPS_RESPONSE_TEMPLATE = "listMeetups_response";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MeetupManagementServiceBean meetupManagementServiceBean;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private TemplateService templateService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ChannelService channelService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private InteractionService interactionService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
|
||||||
|
MessageToSend messageToSend = getMessageToSend(commandContext.getGuild().getIdLong());
|
||||||
|
return FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, commandContext.getChannel()))
|
||||||
|
.thenApply(unused -> CommandResult.fromIgnored());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
||||||
|
return interactionService.replyMessageToSend(getMessageToSend(event.getGuild().getIdLong()), event)
|
||||||
|
.thenApply(interactionHook -> CommandResult.fromSuccess());
|
||||||
|
}
|
||||||
|
|
||||||
|
private MessageToSend getMessageToSend(Long serverId) {
|
||||||
|
List<Meetup> meetups = meetupManagementServiceBean.getFutureMeetups();
|
||||||
|
List<MeetupListItemModel> listItems = meetups
|
||||||
|
.stream()
|
||||||
|
.map(MeetupListItemModel::fromMeetup)
|
||||||
|
.sorted(Comparator.comparing(MeetupListItemModel::getMeetupTime))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
MeetupListModel model = MeetupListModel
|
||||||
|
.builder()
|
||||||
|
.meetups(listItems)
|
||||||
|
.build();
|
||||||
|
return templateService.renderEmbedTemplate(LIST_MEETUPS_RESPONSE_TEMPLATE, model, serverId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommandConfiguration getConfiguration() {
|
||||||
|
|
||||||
|
List<Parameter> parameters = new ArrayList<>();
|
||||||
|
HelpInfo helpInfo = HelpInfo
|
||||||
|
.builder()
|
||||||
|
.templated(true)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
SlashCommandConfig slashCommandConfig = SlashCommandConfig
|
||||||
|
.builder()
|
||||||
|
.enabled(true)
|
||||||
|
.rootCommandName(MeetupSlashCommandNames.MEETUP)
|
||||||
|
.commandName("list")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
return CommandConfiguration.builder()
|
||||||
|
.name("listMeetups")
|
||||||
|
.module(UtilityModuleDefinition.UTILITY)
|
||||||
|
.templated(true)
|
||||||
|
.slashCommandConfig(slashCommandConfig)
|
||||||
|
.async(true)
|
||||||
|
.supportsEmbedException(true)
|
||||||
|
.causesReaction(false)
|
||||||
|
.parameters(parameters)
|
||||||
|
.help(helpInfo)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FeatureDefinition getFeature() {
|
||||||
|
return MeetupFeatureDefinition.MEETUP;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package dev.sheldan.sissi.module.meetup.config;
|
||||||
|
|
||||||
|
import dev.sheldan.abstracto.core.config.FeatureConfig;
|
||||||
|
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class MeetupFeatureConfig implements FeatureConfig {
|
||||||
|
@Override
|
||||||
|
public FeatureDefinition getFeature() {
|
||||||
|
return MeetupFeatureDefinition.MEETUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package dev.sheldan.sissi.module.meetup.config;
|
||||||
|
|
||||||
|
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public enum MeetupFeatureDefinition implements FeatureDefinition {
|
||||||
|
MEETUP("meetup");
|
||||||
|
|
||||||
|
private String key;
|
||||||
|
|
||||||
|
MeetupFeatureDefinition(String key) {
|
||||||
|
this.key = key;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package dev.sheldan.sissi.module.meetup.config;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.annotation.PropertySource;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@PropertySource("classpath:meetup.properties")
|
||||||
|
public class MeetupProperties {
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package dev.sheldan.sissi.module.meetup.config;
|
||||||
|
|
||||||
|
public class MeetupSlashCommandNames {
|
||||||
|
public static final String MEETUP = "meetup";
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package dev.sheldan.sissi.module.meetup.exception;
|
||||||
|
|
||||||
|
import dev.sheldan.abstracto.core.exception.AbstractoTemplatableException;
|
||||||
|
|
||||||
|
public class MeetupNotFoundException extends AbstractoTemplatableException {
|
||||||
|
@Override
|
||||||
|
public String getTemplateName() {
|
||||||
|
return "meetup_not_found_exception";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getTemplateModel() {
|
||||||
|
return new Object();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package dev.sheldan.sissi.module.meetup.exception;
|
||||||
|
|
||||||
|
import dev.sheldan.abstracto.core.exception.AbstractoTemplatableException;
|
||||||
|
|
||||||
|
public class MeetupPastTimeException extends AbstractoTemplatableException {
|
||||||
|
@Override
|
||||||
|
public String getTemplateName() {
|
||||||
|
return "meetup_in_past_exception";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getTemplateModel() {
|
||||||
|
return new Object();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package dev.sheldan.sissi.module.meetup.job;
|
||||||
|
|
||||||
|
import dev.sheldan.sissi.module.meetup.service.MeetupServiceBean;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.quartz.DisallowConcurrentExecution;
|
||||||
|
import org.quartz.JobExecutionContext;
|
||||||
|
import org.quartz.JobExecutionException;
|
||||||
|
import org.quartz.PersistJobDataAfterExecution;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.scheduling.quartz.QuartzJobBean;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@DisallowConcurrentExecution
|
||||||
|
@Component
|
||||||
|
@PersistJobDataAfterExecution
|
||||||
|
public class MeetupCleanupJob extends QuartzJobBean {
|
||||||
|
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MeetupServiceBean meetupServiceBean;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
|
||||||
|
try {
|
||||||
|
log.info("Executing cleanup job for meetups.");
|
||||||
|
meetupServiceBean.cleanupMeetups();
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Meetup cleanup job failed.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package dev.sheldan.sissi.module.meetup.job;
|
||||||
|
|
||||||
|
import dev.sheldan.sissi.module.meetup.service.MeetupServiceBean;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.quartz.DisallowConcurrentExecution;
|
||||||
|
import org.quartz.JobExecutionContext;
|
||||||
|
import org.quartz.JobExecutionException;
|
||||||
|
import org.quartz.PersistJobDataAfterExecution;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.scheduling.quartz.QuartzJobBean;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@DisallowConcurrentExecution
|
||||||
|
@Component
|
||||||
|
@PersistJobDataAfterExecution
|
||||||
|
public class MeetupReminderJob extends QuartzJobBean {
|
||||||
|
|
||||||
|
private Long meetupId;
|
||||||
|
private Long serverId;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MeetupServiceBean meetupServiceBean;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
|
||||||
|
try {
|
||||||
|
log.info("Executing reminder job for meetup {} in server {}.", meetupId, serverId);
|
||||||
|
meetupServiceBean.remindParticipants(meetupId, serverId);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Meetup reminder job failed.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getMeetupId() {
|
||||||
|
return meetupId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMeetupId(Long meetupId) {
|
||||||
|
this.meetupId = meetupId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getServerId() {
|
||||||
|
return serverId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setServerId(Long serverId) {
|
||||||
|
this.serverId = serverId;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,165 @@
|
|||||||
|
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.database.AChannel;
|
||||||
|
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||||
|
import dev.sheldan.abstracto.core.models.listener.ButtonClickedListenerModel;
|
||||||
|
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||||
|
import dev.sheldan.abstracto.core.service.ComponentPayloadService;
|
||||||
|
import dev.sheldan.abstracto.core.service.ComponentService;
|
||||||
|
import dev.sheldan.abstracto.core.service.MessageService;
|
||||||
|
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
|
||||||
|
import dev.sheldan.abstracto.core.service.management.ComponentPayloadManagementService;
|
||||||
|
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
||||||
|
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||||
|
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||||
|
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.MeetupState;
|
||||||
|
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.MeetupManagementServiceBean;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import net.dv8tion.jda.api.entities.Message;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
import static dev.sheldan.sissi.module.meetup.service.MeetupServiceBean.MEETUP_DECISION_BUTTON;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@Slf4j
|
||||||
|
public class MeetupConfirmationListener implements ButtonClickedListener {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MeetupManagementServiceBean meetupManagementServiceBean;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MeetupServiceBean meetupServiceBean;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ComponentService componentService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ComponentPayloadService componentPayloadService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ServerManagementService serverManagementService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ChannelService channelService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ChannelManagementService channelManagementService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MeetupConfirmationListener self;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MessageService messageService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ComponentPayloadManagementService componentPayloadManagementService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ButtonClickedListenerResult execute(ButtonClickedListenerModel model) {
|
||||||
|
MeetupConfirmationPayload payload = (MeetupConfirmationPayload) model.getDeserializedPayload();
|
||||||
|
if(model.getEvent().getUser().getIdLong() != payload.getOrganizerUserId()) {
|
||||||
|
return ButtonClickedListenerResult.IGNORED;
|
||||||
|
}
|
||||||
|
Meetup meetup = meetupManagementServiceBean.getMeetup(payload.getMeetupId(), payload.getGuildId());
|
||||||
|
if(model.getEvent().getComponentId().equals(payload.getConfirmationId())) {
|
||||||
|
meetup.setState(MeetupState.CONFIRMED);
|
||||||
|
} else if(model.getEvent().getComponentId().equals(payload.getCancelId())){
|
||||||
|
meetup.setState(MeetupState.CANCELLED);
|
||||||
|
messageService.deleteMessage(model.getEvent().getMessage());
|
||||||
|
cleanupConfirmationMessage(payload);
|
||||||
|
meetupManagementServiceBean.deleteMeetup(meetup);
|
||||||
|
return ButtonClickedListenerResult.ACKNOWLEDGED;
|
||||||
|
} else {
|
||||||
|
return ButtonClickedListenerResult.IGNORED;
|
||||||
|
}
|
||||||
|
cleanupConfirmationMessage(payload);
|
||||||
|
String yesButtonId = componentService.generateComponentId();
|
||||||
|
String noButtonId = componentService.generateComponentId();
|
||||||
|
String maybeButtonId = componentService.generateComponentId();
|
||||||
|
String cancelButtonId = componentService.generateComponentId();
|
||||||
|
MeetupMessageModel messageModel = meetupServiceBean.getMeetupMessageModel(meetup);
|
||||||
|
messageModel.setYesId(yesButtonId);
|
||||||
|
messageModel.setNoId(noButtonId);
|
||||||
|
messageModel.setMaybeId(maybeButtonId);
|
||||||
|
messageModel.setCancelId(cancelButtonId);
|
||||||
|
messageModel.setCancelled(false);
|
||||||
|
Long meetupId = payload.getMeetupId();
|
||||||
|
Long serverId = payload.getGuildId();
|
||||||
|
MessageToSend messageToSend = meetupServiceBean.getMeetupMessage(messageModel);
|
||||||
|
List<CompletableFuture<Message>> messageFutures = channelService.sendMessageToSendToChannel(messageToSend, model.getEvent().getMessageChannel());
|
||||||
|
FutureUtils.toSingleFutureGeneric(messageFutures).thenAccept(unused -> {
|
||||||
|
messageService.deleteMessage(model.getEvent().getMessage());
|
||||||
|
Message meetupMessage = messageFutures.get(0).join();
|
||||||
|
messageService.pinMessage(meetupMessage);
|
||||||
|
self.persistPayloads(meetupId, serverId, yesButtonId, noButtonId, maybeButtonId, cancelButtonId, meetupMessage);
|
||||||
|
}).exceptionally(throwable -> {
|
||||||
|
log.error("Failed to send meetup message for meetup {}.", meetupId, throwable);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
return ButtonClickedListenerResult.ACKNOWLEDGED;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cleanupConfirmationMessage(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) {
|
||||||
|
MeetupDecisionPayload decisionPayload = MeetupDecisionPayload
|
||||||
|
.builder()
|
||||||
|
.meetupId(meetupId)
|
||||||
|
.guildId(serverId)
|
||||||
|
.componentPayloads(Arrays.asList(yesButtonId, noButtonId, maybeButtonId))
|
||||||
|
.build();
|
||||||
|
AServer server = serverManagementService.loadServer(serverId);
|
||||||
|
|
||||||
|
decisionPayload.setMeetupDecision(MeetupDecision.YES);
|
||||||
|
componentPayloadService.createButtonPayload(yesButtonId, decisionPayload, MEETUP_DECISION_BUTTON, server);
|
||||||
|
decisionPayload.setMeetupDecision(MeetupDecision.NO);
|
||||||
|
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);
|
||||||
|
Meetup meetup = meetupManagementServiceBean.getMeetup(meetupId, serverId);
|
||||||
|
meetupServiceBean.scheduleReminders(meetup);
|
||||||
|
meetup.setMessageId(meetupMessage.getIdLong());
|
||||||
|
AChannel channel = channelManagementService.loadChannel(meetupMessage.getChannel());
|
||||||
|
meetup.setMeetupChannel(channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean handlesEvent(ButtonClickedListenerModel model) {
|
||||||
|
return model.getOrigin().equals(MeetupServiceBean.MEETUP_CONFIRMATION_BUTTON) &&
|
||||||
|
model.getEvent().isFromGuild();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FeatureDefinition getFeature() {
|
||||||
|
return MeetupFeatureDefinition.MEETUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer getPriority() {
|
||||||
|
return ListenerPriority.LOWEST;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
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.database.AUserInAServer;
|
||||||
|
import dev.sheldan.abstracto.core.models.listener.ButtonClickedListenerModel;
|
||||||
|
import dev.sheldan.abstracto.core.models.template.display.MemberDisplay;
|
||||||
|
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||||
|
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||||
|
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.payload.MeetupDecisionPayload;
|
||||||
|
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.MeetupManagementServiceBean;
|
||||||
|
import dev.sheldan.sissi.module.meetup.service.management.MeetupParticipatorManagementServiceBean;
|
||||||
|
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 MeetupDecisionListener implements ButtonClickedListener {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MeetupParticipatorManagementServiceBean meetupParticipatorManagementServiceBean;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MeetupManagementServiceBean meetupManagementServiceBean;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UserInServerManagementService userInServerManagementService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MeetupServiceBean meetupServiceBean;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ChannelService channelService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
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);
|
||||||
|
if(participationOptional.isPresent()) {
|
||||||
|
participationOptional.get().setDecision(payload.getMeetupDecision());
|
||||||
|
} else {
|
||||||
|
meetupParticipatorManagementServiceBean.createParticipation(meetup, userInAServer, payload.getMeetupDecision());
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
});
|
||||||
|
return ButtonClickedListenerResult.ACKNOWLEDGED;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addParticipationToModel(MeetupMessageModel model, AUserInAServer aUserInAServer, MeetupDecision decision) {
|
||||||
|
if(decision.equals(MeetupDecision.NO)) {
|
||||||
|
addIfMissing(model.getDeclinedParticipants(), aUserInAServer);
|
||||||
|
} else if(decision.equals(MeetupDecision.YES)) {
|
||||||
|
addIfMissing(model.getParticipants(), aUserInAServer);
|
||||||
|
} else if(decision.equals(MeetupDecision.MAYBE)) {
|
||||||
|
addIfMissing(model.getMaybeParticipants(), aUserInAServer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addIfMissing(List<MemberDisplay> list, AUserInAServer aUserInAServer) {
|
||||||
|
if(list.stream().noneMatch(memberDisplay -> memberDisplay.getUserId().equals(aUserInAServer.getUserReference().getId()))) {
|
||||||
|
list.add(MemberDisplay.fromAUserInAServer(aUserInAServer));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean handlesEvent(ButtonClickedListenerModel model) {
|
||||||
|
return model.getOrigin().equals(MeetupServiceBean.MEETUP_DECISION_BUTTON) && model.getEvent().isFromGuild();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FeatureDefinition getFeature() {
|
||||||
|
return MeetupFeatureDefinition.MEETUP;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer getPriority() {
|
||||||
|
return ListenerPriority.MEDIUM;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package dev.sheldan.sissi.module.meetup.model.command;
|
||||||
|
|
||||||
|
import dev.sheldan.abstracto.core.models.template.display.MemberDisplay;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Builder
|
||||||
|
public class MeetupConfirmationModel {
|
||||||
|
private MemberDisplay organizer;
|
||||||
|
private Instant meetupTime;
|
||||||
|
private Long meetupId;
|
||||||
|
private String topic;
|
||||||
|
private String description;
|
||||||
|
private Long guildId;
|
||||||
|
private String confirmationId;
|
||||||
|
private String cancelId;
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package dev.sheldan.sissi.module.meetup.model.command;
|
||||||
|
|
||||||
|
import dev.sheldan.abstracto.core.models.ServerChannelMessage;
|
||||||
|
import dev.sheldan.sissi.module.meetup.model.database.Meetup;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Builder
|
||||||
|
public class MeetupListItemModel {
|
||||||
|
private String topic;
|
||||||
|
private Instant meetupTime;
|
||||||
|
private ServerChannelMessage meetupMessage;
|
||||||
|
|
||||||
|
public static MeetupListItemModel fromMeetup(Meetup meetup) {
|
||||||
|
ServerChannelMessage message = ServerChannelMessage
|
||||||
|
.builder()
|
||||||
|
.serverId(meetup.getServer().getId())
|
||||||
|
.channelId(meetup.getMeetupChannel().getId())
|
||||||
|
.messageId(meetup.getMessageId())
|
||||||
|
.build();
|
||||||
|
return MeetupListItemModel
|
||||||
|
.builder()
|
||||||
|
.topic(meetup.getTopic())
|
||||||
|
.meetupTime(meetup.getMeetupTime())
|
||||||
|
.meetupMessage(message)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package dev.sheldan.sissi.module.meetup.model.command;
|
||||||
|
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Builder
|
||||||
|
public class MeetupListModel {
|
||||||
|
private List<MeetupListItemModel> meetups;
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
package dev.sheldan.sissi.module.meetup.model.database;
|
||||||
|
|
||||||
|
import dev.sheldan.abstracto.core.models.ServerSpecificId;
|
||||||
|
import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||||
|
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||||
|
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||||
|
import lombok.*;
|
||||||
|
|
||||||
|
import javax.persistence.*;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Builder
|
||||||
|
@Entity
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Table(name = "meetup")
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@EqualsAndHashCode
|
||||||
|
public class Meetup {
|
||||||
|
|
||||||
|
@EmbeddedId
|
||||||
|
@Getter
|
||||||
|
@Id
|
||||||
|
private ServerSpecificId id;
|
||||||
|
|
||||||
|
@ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, fetch = FetchType.LAZY)
|
||||||
|
@MapsId("serverId")
|
||||||
|
@JoinColumn(name = "server_id", referencedColumnName = "id", nullable = false)
|
||||||
|
private AServer server;
|
||||||
|
|
||||||
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
|
@JoinColumn(name = "organizer_user_in_server_id", nullable = false)
|
||||||
|
private AUserInAServer organizer;
|
||||||
|
|
||||||
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
|
@JoinColumn(name = "meetup_channel_id", nullable = false)
|
||||||
|
private AChannel meetupChannel;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Column(name = "message_id")
|
||||||
|
private Long messageId;
|
||||||
|
|
||||||
|
@OneToMany(
|
||||||
|
fetch = FetchType.LAZY,
|
||||||
|
orphanRemoval = true,
|
||||||
|
cascade = {CascadeType.PERSIST, CascadeType.MERGE},
|
||||||
|
mappedBy = "meetup")
|
||||||
|
@Builder.Default
|
||||||
|
private List<MeetupParticipator> participants = new ArrayList<>();
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
@Column(name = "state", nullable = false)
|
||||||
|
private MeetupState state;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Column(name = "topic", nullable = false)
|
||||||
|
private String topic;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Column(name = "description")
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
@Column(name = "meetup_time", nullable = false)
|
||||||
|
private Instant meetupTime;
|
||||||
|
|
||||||
|
@Column(name = "created")
|
||||||
|
private Instant created;
|
||||||
|
|
||||||
|
@Column(name = "updated")
|
||||||
|
private Instant updated;
|
||||||
|
|
||||||
|
@Column(name = "early_reminder_job_trigger_key")
|
||||||
|
private String earlyReminderJobTriggerKey;
|
||||||
|
|
||||||
|
@Column(name = "late_reminder_job_trigger_key")
|
||||||
|
private String lateReminderJobTriggerKey;
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package dev.sheldan.sissi.module.meetup.model.database;
|
||||||
|
|
||||||
|
public enum MeetupDecision {
|
||||||
|
YES, NO, MAYBE, CANCEL
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package dev.sheldan.sissi.module.meetup.model.database;
|
||||||
|
|
||||||
|
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||||
|
import dev.sheldan.sissi.module.meetup.model.database.embed.MeetupParticipationId;
|
||||||
|
import lombok.*;
|
||||||
|
|
||||||
|
import javax.persistence.*;
|
||||||
|
import java.time.Instant;
|
||||||
|
|
||||||
|
@Builder
|
||||||
|
@Entity
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Table(name = "meetup_participator")
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@EqualsAndHashCode
|
||||||
|
public class MeetupParticipator {
|
||||||
|
|
||||||
|
@EmbeddedId
|
||||||
|
@Getter
|
||||||
|
private MeetupParticipationId id;
|
||||||
|
|
||||||
|
@ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, fetch = FetchType.LAZY)
|
||||||
|
@MapsId("voterId")
|
||||||
|
@JoinColumn(name = "meetup_participator_user_in_server_id", nullable = false)
|
||||||
|
private AUserInAServer participator;
|
||||||
|
|
||||||
|
@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;
|
||||||
|
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
@Column(name = "decision", nullable = false)
|
||||||
|
private MeetupDecision decision;
|
||||||
|
|
||||||
|
@Column(name = "created")
|
||||||
|
private Instant created;
|
||||||
|
|
||||||
|
@Column(name = "updated")
|
||||||
|
private Instant updated;
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package dev.sheldan.sissi.module.meetup.model.database;
|
||||||
|
|
||||||
|
public enum MeetupState {
|
||||||
|
NEW, CONFIRMED, CANCELLED, DONE
|
||||||
|
}
|
||||||
@@ -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 MeetupParticipationId implements Serializable {
|
||||||
|
@Column(name = "meetup_participator_user_in_server_id")
|
||||||
|
private Long participatorId;
|
||||||
|
|
||||||
|
@Column(name = "meetup_id")
|
||||||
|
private Long meetupId;
|
||||||
|
|
||||||
|
@Column(name = "server_id")
|
||||||
|
private Long serverId;
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
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 MeetupConfirmationPayload implements ButtonPayload {
|
||||||
|
private Long organizerUserId;
|
||||||
|
private Long meetupId;
|
||||||
|
private Long guildId;
|
||||||
|
private String confirmationId;
|
||||||
|
private String cancelId;
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package dev.sheldan.sissi.module.meetup.model.payload;
|
||||||
|
|
||||||
|
import dev.sheldan.abstracto.core.models.template.button.ButtonPayload;
|
||||||
|
import dev.sheldan.sissi.module.meetup.model.database.MeetupDecision;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Builder
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class MeetupDecisionPayload implements ButtonPayload {
|
||||||
|
private Long meetupId;
|
||||||
|
private Long guildId;
|
||||||
|
private MeetupDecision meetupDecision;
|
||||||
|
private List<String> componentPayloads;
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package dev.sheldan.sissi.module.meetup.model.template;
|
||||||
|
|
||||||
|
import dev.sheldan.abstracto.core.models.template.display.MemberDisplay;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Builder
|
||||||
|
@Setter
|
||||||
|
public class MeetupMessageModel {
|
||||||
|
private String topic;
|
||||||
|
private String description;
|
||||||
|
private Instant meetupTime;
|
||||||
|
private MemberDisplay organizer;
|
||||||
|
private String yesId;
|
||||||
|
private String noId;
|
||||||
|
private String maybeId;
|
||||||
|
private String cancelId;
|
||||||
|
private Boolean cancelled;
|
||||||
|
private List<MemberDisplay> participants;
|
||||||
|
private List<MemberDisplay> maybeParticipants;
|
||||||
|
private List<MemberDisplay> declinedParticipants;
|
||||||
|
}
|
||||||
@@ -0,0 +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.embed.MeetupParticipationId;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public interface MeetupParticipatorRepository extends JpaRepository<MeetupParticipator, MeetupParticipationId> {
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package dev.sheldan.sissi.module.meetup.repository;
|
||||||
|
|
||||||
|
import dev.sheldan.abstracto.core.models.ServerSpecificId;
|
||||||
|
import dev.sheldan.sissi.module.meetup.model.database.Meetup;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public interface MeetupRepository extends JpaRepository<Meetup, ServerSpecificId> {
|
||||||
|
List<Meetup> findByMeetupTimeLessThan(Instant date);
|
||||||
|
List<Meetup> findByMeetupTimeGreaterThan(Instant date);
|
||||||
|
}
|
||||||
@@ -0,0 +1,229 @@
|
|||||||
|
package dev.sheldan.sissi.module.meetup.service;
|
||||||
|
|
||||||
|
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||||
|
import dev.sheldan.abstracto.core.models.template.display.MemberDisplay;
|
||||||
|
import dev.sheldan.abstracto.core.service.*;
|
||||||
|
import dev.sheldan.abstracto.core.service.management.ComponentPayloadManagementService;
|
||||||
|
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.scheduling.model.JobParameters;
|
||||||
|
import dev.sheldan.abstracto.scheduling.service.SchedulerService;
|
||||||
|
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.MeetupState;
|
||||||
|
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.management.MeetupManagementServiceBean;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import net.dv8tion.jda.api.entities.GuildMessageChannel;
|
||||||
|
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.concurrent.CompletableFuture;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@Slf4j
|
||||||
|
public class MeetupServiceBean {
|
||||||
|
|
||||||
|
public static final String MEETUP_CONFIRMATION_BUTTON = "MEETUP_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_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";
|
||||||
|
public static final String MEETUP_REMINDER_JOB_NAME = "meetupReminderJob";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private TemplateService templateService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ComponentPayloadService componentPayloadService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ServerManagementService serverManagementService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MessageService messageService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ComponentPayloadManagementService componentPayloadManagementService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MeetupManagementServiceBean meetupManagementServiceBean;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MeetupServiceBean self;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ChannelService channelService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UserService userService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ConfigService configService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SchedulerService schedulerService;
|
||||||
|
|
||||||
|
public void storeMeetupConfirmation(MeetupConfirmationModel model) {
|
||||||
|
AServer server = serverManagementService.loadServer(model.getGuildId());
|
||||||
|
MeetupConfirmationPayload confirmationPayload = MeetupConfirmationPayload
|
||||||
|
.builder()
|
||||||
|
.confirmationId(model.getConfirmationId())
|
||||||
|
.meetupId(model.getMeetupId())
|
||||||
|
.cancelId(model.getCancelId())
|
||||||
|
.organizerUserId(model.getOrganizer().getUserId())
|
||||||
|
.guildId(model.getGuildId())
|
||||||
|
.build();
|
||||||
|
componentPayloadService.createButtonPayload(model.getConfirmationId(), confirmationPayload, MEETUP_CONFIRMATION_BUTTON, server);
|
||||||
|
componentPayloadService.createButtonPayload(model.getCancelId(), confirmationPayload, MEETUP_CONFIRMATION_BUTTON, server);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public MeetupMessageModel getMeetupMessageModel(Meetup meetup) {
|
||||||
|
List<MeetupParticipator> allParticipants = meetup.getParticipants();
|
||||||
|
List<MeetupParticipator> participating = allParticipants
|
||||||
|
.stream()
|
||||||
|
.filter(meetupParticipator -> meetupParticipator.getDecision().equals(MeetupDecision.YES))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
List<MeetupParticipator> maybe = allParticipants
|
||||||
|
.stream()
|
||||||
|
.filter(meetupParticipator -> meetupParticipator.getDecision().equals(MeetupDecision.MAYBE))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
List<MeetupParticipator> notParticipating = allParticipants
|
||||||
|
.stream()
|
||||||
|
.filter(meetupParticipator -> meetupParticipator.getDecision().equals(MeetupDecision.NO))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
return MeetupMessageModel
|
||||||
|
.builder()
|
||||||
|
.description(meetup.getDescription())
|
||||||
|
.topic(meetup.getTopic())
|
||||||
|
.meetupTime(meetup.getMeetupTime())
|
||||||
|
.participants(getMemberDisplays(participating))
|
||||||
|
.declinedParticipants(getMemberDisplays(notParticipating))
|
||||||
|
.maybeParticipants(getMemberDisplays(maybe))
|
||||||
|
.cancelled(meetup.getState().equals(MeetupState.CANCELLED))
|
||||||
|
.organizer(MemberDisplay.fromAUserInAServer(meetup.getOrganizer()))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<MemberDisplay> getMemberDisplays(List<MeetupParticipator> participants) {
|
||||||
|
return participants
|
||||||
|
.stream()
|
||||||
|
.map(meetupParticipator -> MemberDisplay.fromAUserInAServer(meetupParticipator.getParticipator()))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public MessageToSend getMeetupMessage(MeetupMessageModel model) {
|
||||||
|
return templateService.renderEmbedTemplate(MEETUP_DISPLAY_TEMPLATE, model);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CompletableFuture<Void> cancelMeetup(Meetup meetup, List<String> componentPayloads) {
|
||||||
|
Long serverId = meetup.getServer().getId();
|
||||||
|
Long meetupId = meetup.getId().getId();
|
||||||
|
GuildMessageChannel channel = channelService.getMessageChannelFromServer(serverId, meetup.getMeetupChannel().getId());
|
||||||
|
MeetupMessageModel model = getMeetupMessageModel(meetup);
|
||||||
|
model.setCancelled(true);
|
||||||
|
MessageToSend meetupMessage = getMeetupMessage(model);
|
||||||
|
return messageService.editMessageInChannel(channel, meetupMessage, meetup.getMessageId())
|
||||||
|
.thenAccept(unused -> self.notifyParticipants(meetupId, serverId))
|
||||||
|
.thenAccept(unused -> self.cleanupMeetup(meetupId, serverId, componentPayloads));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void notifyParticipants(Long meetupId, Long serverId) {
|
||||||
|
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));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void cleanupMeetup(Long meetupId, Long serverId, List<String> componentPayloads) {
|
||||||
|
Meetup meetup = meetupManagementServiceBean.getMeetup(meetupId, serverId);
|
||||||
|
meetup.setState(MeetupState.CANCELLED);
|
||||||
|
log.info("Cleanup meetup {} in server {}.", meetup, serverId);
|
||||||
|
if(meetup.getEarlyReminderJobTriggerKey() != null) {
|
||||||
|
schedulerService.stopTrigger(meetup.getEarlyReminderJobTriggerKey());
|
||||||
|
}
|
||||||
|
if(meetup.getLateReminderJobTriggerKey() != null) {
|
||||||
|
schedulerService.stopTrigger(meetup.getLateReminderJobTriggerKey());
|
||||||
|
}
|
||||||
|
componentPayloads.forEach(s -> componentPayloadManagementService.deletePayload(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void scheduleReminders(Meetup meetup) {
|
||||||
|
Long serverId = meetup.getServer().getId();
|
||||||
|
Long meetupId = meetup.getId().getId();
|
||||||
|
Long earlyReminderSeconds = configService.getLongValueOrConfigDefault(MEETUP_EARLY_REMINDER_CONFIG_KEY, serverId);
|
||||||
|
Long lateReminderSeconds = configService.getLongValueOrConfigDefault(MEETUP_LATE_REMINDER_CONFIG_KEY, serverId);
|
||||||
|
|
||||||
|
HashMap<Object, Object> parameters = new HashMap<>();
|
||||||
|
parameters.put("meetupId", meetupId.toString());
|
||||||
|
parameters.put("serverId", serverId.toString());
|
||||||
|
JobParameters jobParameters = JobParameters
|
||||||
|
.builder()
|
||||||
|
.parameters(parameters)
|
||||||
|
.build();
|
||||||
|
Instant meetupDate = meetup.getMeetupTime();
|
||||||
|
Instant earlyDate = meetupDate.minus(earlyReminderSeconds, ChronoUnit.SECONDS);
|
||||||
|
if(earlyDate.isAfter(Instant.now())) {
|
||||||
|
log.info("Scheduling early reminder job for meetup {} in server {} at {}.", meetupId, serverId, earlyDate);
|
||||||
|
String earlyTriggerKey = schedulerService.executeJobWithParametersOnce(MEETUP_REMINDER_JOB_NAME, "meetup", jobParameters, Date.from(earlyDate));
|
||||||
|
meetup.setEarlyReminderJobTriggerKey(earlyTriggerKey);
|
||||||
|
}
|
||||||
|
Instant lateDate = meetupDate.minus(lateReminderSeconds, ChronoUnit.SECONDS);
|
||||||
|
if(lateDate.isAfter(Instant.now())) {
|
||||||
|
log.info("Scheduling late reminder job for meetup {} in server {} at {}.", meetupId, serverId, lateDate);
|
||||||
|
String lateTriggerKey = schedulerService.executeJobWithParametersOnce(MEETUP_REMINDER_JOB_NAME, "meetup", jobParameters, Date.from(lateDate));
|
||||||
|
meetup.setLateReminderJobTriggerKey(lateTriggerKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void remindParticipants(Long meetupId, Long serverId) {
|
||||||
|
Meetup meetup = meetupManagementServiceBean.getMeetup(meetupId, serverId);
|
||||||
|
MeetupMessageModel model = getMeetupMessageModel(meetup);
|
||||||
|
MessageToSend messageToSend = templateService.renderEmbedTemplate(MEETUP_REMINDER_TEMPLATE, model);
|
||||||
|
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 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()));
|
||||||
|
meetupManagementServiceBean.deleteMeetups(oldMeetups);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
package dev.sheldan.sissi.module.meetup.service.management;
|
||||||
|
|
||||||
|
import dev.sheldan.abstracto.core.models.ServerSpecificId;
|
||||||
|
import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||||
|
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||||
|
import dev.sheldan.abstracto.core.service.CounterService;
|
||||||
|
import dev.sheldan.sissi.module.meetup.exception.MeetupNotFoundException;
|
||||||
|
import dev.sheldan.sissi.module.meetup.exception.MeetupPastTimeException;
|
||||||
|
import dev.sheldan.sissi.module.meetup.model.database.Meetup;
|
||||||
|
import dev.sheldan.sissi.module.meetup.model.database.MeetupState;
|
||||||
|
import dev.sheldan.sissi.module.meetup.repository.MeetupRepository;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class MeetupManagementServiceBean {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MeetupRepository meetupRepository;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private CounterService counterService;
|
||||||
|
|
||||||
|
public static final String MEETUP_COUNTER_KEY = "meetup";
|
||||||
|
|
||||||
|
public Meetup createMeetup(Instant timeStamp, String topic, String description, AUserInAServer organizer, AChannel meetupChannel) {
|
||||||
|
if(timeStamp.isBefore(Instant.now())) {
|
||||||
|
throw new MeetupPastTimeException();
|
||||||
|
}
|
||||||
|
Long meetupId = counterService.getNextCounterValue(organizer.getServerReference(), MEETUP_COUNTER_KEY);
|
||||||
|
Meetup meetup = Meetup
|
||||||
|
.builder()
|
||||||
|
.meetupTime(timeStamp)
|
||||||
|
.description(description)
|
||||||
|
.topic(topic)
|
||||||
|
.organizer(organizer)
|
||||||
|
.server(organizer.getServerReference())
|
||||||
|
.meetupChannel(meetupChannel)
|
||||||
|
.state(MeetupState.NEW)
|
||||||
|
.id(new ServerSpecificId(organizer.getServerReference().getId(), meetupId))
|
||||||
|
.build();
|
||||||
|
return meetupRepository.save(meetup);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Meetup getMeetup(Long meetupId, Long serverId) {
|
||||||
|
return meetupRepository.findById(new ServerSpecificId(serverId, meetupId))
|
||||||
|
.orElseThrow(MeetupNotFoundException::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Meetup> getMeetupsOlderThan(Instant instant) {
|
||||||
|
return meetupRepository.findByMeetupTimeLessThan(instant);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Meetup> getMeetups() {
|
||||||
|
return meetupRepository.findAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Meetup> getFutureMeetups() {
|
||||||
|
return meetupRepository.findByMeetupTimeGreaterThan(Instant.now());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deleteMeetups(List<Meetup> meetups) {
|
||||||
|
meetupRepository.deleteAll(meetups);
|
||||||
|
}
|
||||||
|
public void deleteMeetup(Meetup meetup) {
|
||||||
|
meetupRepository.delete(meetup);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
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.embed.MeetupParticipationId;
|
||||||
|
import dev.sheldan.sissi.module.meetup.repository.MeetupParticipatorRepository;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class MeetupParticipatorManagementServiceBean {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MeetupParticipatorRepository repository;
|
||||||
|
|
||||||
|
public Optional<MeetupParticipator> getParticipation(Meetup meetup, AUserInAServer aUserInAServer) {
|
||||||
|
MeetupParticipationId id = MeetupParticipationId
|
||||||
|
.builder()
|
||||||
|
.meetupId(meetup.getId().getId())
|
||||||
|
.serverId(meetup.getServer().getId())
|
||||||
|
.participatorId(aUserInAServer.getUserInServerId())
|
||||||
|
.build();
|
||||||
|
return repository.findById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MeetupParticipator 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
|
||||||
|
.builder()
|
||||||
|
.id(id)
|
||||||
|
.meetup(meetup)
|
||||||
|
.participator(aUserInAServer)
|
||||||
|
.decision(meetupDecision)
|
||||||
|
.build();
|
||||||
|
return repository.save(participator);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
abstracto.featureFlags.meetup.featureName=meetup
|
||||||
|
abstracto.featureFlags.meetup.enabled=false
|
||||||
|
|
||||||
|
abstracto.systemConfigs.meetupEarlyReminderSeconds.name=meetupEarlyReminderSeconds
|
||||||
|
abstracto.systemConfigs.meetupEarlyReminderSeconds.longValue=604800
|
||||||
|
|
||||||
|
abstracto.systemConfigs.meetupLateReminderSeconds.name=meetupLateReminderSeconds
|
||||||
|
abstracto.systemConfigs.meetupLateReminderSeconds.longValue=86400
|
||||||
@@ -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="tables/tables.xml" relativeToChangelogFile="true"/>
|
||||||
|
<include file="seedData/data.xml" relativeToChangelogFile="true"/>
|
||||||
|
</databaseChangeLog>
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
<?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="createMeetup"/>
|
||||||
|
<column name="module_id" valueComputed="${utilityModule}"/>
|
||||||
|
<column name="feature_id" valueComputed="${meetupFeature}"/>
|
||||||
|
</insert>
|
||||||
|
<insert tableName="command">
|
||||||
|
<column name="name" value="listMeetups"/>
|
||||||
|
<column name="module_id" valueComputed="${utilityModule}"/>
|
||||||
|
<column name="feature_id" valueComputed="${meetupFeature}"/>
|
||||||
|
</insert>
|
||||||
|
</changeSet>
|
||||||
|
|
||||||
|
</databaseChangeLog>
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
<?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="feature.xml" relativeToChangelogFile="true"/>
|
||||||
|
<include file="command.xml" relativeToChangelogFile="true"/>
|
||||||
|
<include file="reminder_job.xml" relativeToChangelogFile="true"/>
|
||||||
|
<include file="meetup_cleanup_job.xml" relativeToChangelogFile="true"/>
|
||||||
|
</databaseChangeLog>
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
<?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_feature-insertion">
|
||||||
|
<insert tableName="feature">
|
||||||
|
<column name="key" value="meetup"/>
|
||||||
|
</insert>
|
||||||
|
</changeSet>
|
||||||
|
</databaseChangeLog>
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
<?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-cleanup-job-insert">
|
||||||
|
<insert tableName="scheduler_job">
|
||||||
|
<column name="name" value="meetupCleanupJob"/>
|
||||||
|
<column name="group_name" value="meetup"/>
|
||||||
|
<column name="clazz" value="dev.sheldan.sissi.module.meetup.job.MeetupCleanupJob"/>
|
||||||
|
<column name="active" value="true"/>
|
||||||
|
<column name="cron_expression" value="0 0 0 * * ?"/>
|
||||||
|
<column name="recovery" value="false"/>
|
||||||
|
</insert>
|
||||||
|
</changeSet>
|
||||||
|
</databaseChangeLog>
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
<?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-reminder-job-insert">
|
||||||
|
<insert tableName="scheduler_job">
|
||||||
|
<column name="name" value="meetupReminderJob"/>
|
||||||
|
<column name="group_name" value="meetup"/>
|
||||||
|
<column name="clazz" value="dev.sheldan.sissi.module.meetup.job.MeetupReminderJob"/>
|
||||||
|
<column name="active" value="true"/>
|
||||||
|
<column name="recovery" value="false"/>
|
||||||
|
</insert>
|
||||||
|
</changeSet>
|
||||||
|
</databaseChangeLog>
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
<?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-table">
|
||||||
|
<createTable tableName="meetup">
|
||||||
|
<column name="id" type="BIGINT">
|
||||||
|
<constraints nullable="false"/>
|
||||||
|
</column>
|
||||||
|
<column name="organizer_user_in_server_id" type="BIGINT">
|
||||||
|
<constraints nullable="false"/>
|
||||||
|
</column>
|
||||||
|
<column name="meetup_channel_id" type="BIGINT">
|
||||||
|
<constraints nullable="false"/>
|
||||||
|
</column>
|
||||||
|
<column name="server_id" type="BIGINT">
|
||||||
|
<constraints nullable="false"/>
|
||||||
|
</column>
|
||||||
|
<column name="message_id" type="BIGINT">
|
||||||
|
<constraints nullable="true"/>
|
||||||
|
</column>
|
||||||
|
<column name="topic" type="VARCHAR(256)">
|
||||||
|
<constraints nullable="false"/>
|
||||||
|
</column>
|
||||||
|
<column name="state" type="VARCHAR(256)">
|
||||||
|
<constraints nullable="false"/>
|
||||||
|
</column>
|
||||||
|
<column name="description" type="VARCHAR(2048)">
|
||||||
|
<constraints nullable="true"/>
|
||||||
|
</column>
|
||||||
|
<column name="meetup_time" type="TIMESTAMP WITHOUT TIME ZONE">
|
||||||
|
<constraints nullable="false"/>
|
||||||
|
</column>
|
||||||
|
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE"/>
|
||||||
|
<column name="updated" type="TIMESTAMP WITHOUT TIME ZONE"/>
|
||||||
|
<column name="early_reminder_job_trigger_key" type="VARCHAR(255)"/>
|
||||||
|
<column name="late_reminder_job_trigger_key" type="VARCHAR(255)"/>
|
||||||
|
</createTable>
|
||||||
|
<addPrimaryKey columnNames="server_id, id" tableName="meetup" constraintName="pk_meetup" validate="true"/>
|
||||||
|
<addForeignKeyConstraint baseColumnNames="meetup_channel_id" baseTableName="meetup" constraintName="fk_meetup_channel"
|
||||||
|
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION"
|
||||||
|
referencedColumnNames="id" referencedTableName="channel" validate="true"/>
|
||||||
|
<addForeignKeyConstraint baseColumnNames="organizer_user_in_server_id" baseTableName="meetup" constraintName="fk_meetup_organizer"
|
||||||
|
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION"
|
||||||
|
referencedColumnNames="user_in_server_id" referencedTableName="user_in_server" validate="true"/>
|
||||||
|
<addForeignKeyConstraint baseColumnNames="server_id" baseTableName="meetup" constraintName="fk_meetup_server"
|
||||||
|
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION"
|
||||||
|
referencedColumnNames="id" referencedTableName="server" validate="true"/>
|
||||||
|
<sql>
|
||||||
|
DROP TRIGGER IF EXISTS meetup_update_trigger ON meetup;
|
||||||
|
CREATE TRIGGER meetup_update_trigger BEFORE UPDATE ON meetup FOR EACH ROW EXECUTE PROCEDURE update_trigger_procedure();
|
||||||
|
</sql>
|
||||||
|
<sql>
|
||||||
|
DROP TRIGGER IF EXISTS meetup_insert_trigger ON meetup;
|
||||||
|
CREATE TRIGGER meetup_insert_trigger BEFORE INSERT ON meetup FOR EACH ROW EXECUTE PROCEDURE insert_trigger_procedure();
|
||||||
|
</sql>
|
||||||
|
<sql>
|
||||||
|
ALTER TABLE meetup ADD CONSTRAINT check_meetup_state CHECK (state IN ('NEW', 'CONFIRMED', 'CANCELLED', 'DONE'));
|
||||||
|
</sql>
|
||||||
|
</changeSet>
|
||||||
|
|
||||||
|
</databaseChangeLog>
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
<?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">
|
||||||
|
<createTable tableName="meetup_participator">
|
||||||
|
<column name="meetup_participator_user_in_server_id" type="BIGINT">
|
||||||
|
<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="decision" type="VARCHAR(255)">
|
||||||
|
<constraints nullable="false"/>
|
||||||
|
</column>
|
||||||
|
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE">
|
||||||
|
<constraints nullable="false"/>
|
||||||
|
</column>
|
||||||
|
<column name="updated" type="TIMESTAMP WITHOUT TIME ZONE"/>
|
||||||
|
</createTable>
|
||||||
|
<addPrimaryKey columnNames="meetup_participator_user_in_server_id, meetup_id, server_id" tableName="meetup_participator" constraintName="pk_meetup_participator" validate="false"/>
|
||||||
|
<addForeignKeyConstraint baseColumnNames="meetup_id, server_id" baseTableName="meetup_participator" constraintName="fk_meetup_participator_meetup"
|
||||||
|
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION"
|
||||||
|
referencedColumnNames="id, server_id" referencedTableName="meetup" validate="false"/>
|
||||||
|
<addForeignKeyConstraint baseColumnNames="meetup_participator_user_in_server_id" baseTableName="meetup_participator" constraintName="fk_meetup_participator_participator"
|
||||||
|
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION"
|
||||||
|
referencedColumnNames="user_in_server_id" referencedTableName="user_in_server" validate="false"/>
|
||||||
|
<sql>
|
||||||
|
DROP TRIGGER IF EXISTS meetup_participator_update_trigger ON meetup_participator;
|
||||||
|
CREATE TRIGGER meetup_participator_update_trigger BEFORE UPDATE ON meetup_participator FOR EACH ROW EXECUTE PROCEDURE update_trigger_procedure();
|
||||||
|
</sql>
|
||||||
|
<sql>
|
||||||
|
DROP TRIGGER IF EXISTS meetup_participator_insert_trigger ON meetup_participator;
|
||||||
|
CREATE TRIGGER meetup_participator_insert_trigger BEFORE INSERT ON meetup_participator FOR EACH ROW EXECUTE PROCEDURE insert_trigger_procedure();
|
||||||
|
</sql>
|
||||||
|
<sql>
|
||||||
|
ALTER TABLE meetup_participator ADD CONSTRAINT check_meetup_participator_decision CHECK (decision IN ('YES','NO', 'MAYBE'));
|
||||||
|
</sql>
|
||||||
|
</changeSet>
|
||||||
|
|
||||||
|
</databaseChangeLog>
|
||||||
@@ -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.xml" relativeToChangelogFile="true"/>
|
||||||
|
<include file="meetup_participator.xml" relativeToChangelogFile="true"/>
|
||||||
|
</databaseChangeLog>
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -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="1.1.0/collection.xml" relativeToChangelogFile="true"/>
|
||||||
|
</databaseChangeLog>
|
||||||
@@ -12,6 +12,7 @@
|
|||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
<modules>
|
<modules>
|
||||||
<module>quotes</module>
|
<module>quotes</module>
|
||||||
|
<module>meetup</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package dev.sheldan.sissi.module.quotes.command;
|
package dev.sheldan.sissi.module.quotes.commands;
|
||||||
|
|
||||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package dev.sheldan.sissi.module.quotes.command;
|
package dev.sheldan.sissi.module.quotes.commands;
|
||||||
|
|
||||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package dev.sheldan.sissi.module.quotes.command;
|
package dev.sheldan.sissi.module.quotes.commands;
|
||||||
|
|
||||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package dev.sheldan.sissi.module.quotes.command;
|
package dev.sheldan.sissi.module.quotes.commands;
|
||||||
|
|
||||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package dev.sheldan.sissi.module.quotes.command;
|
package dev.sheldan.sissi.module.quotes.commands;
|
||||||
|
|
||||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||||
@@ -30,4 +30,4 @@ PGADMIN_DEFAULT_EMAIL=sheldan@sheldan.dev
|
|||||||
PGADMIN_DEFAULT_PASSWORD=admin
|
PGADMIN_DEFAULT_PASSWORD=admin
|
||||||
TOKEN=<INSERT TOKEN>
|
TOKEN=<INSERT TOKEN>
|
||||||
YOUTUBE_API_KEY=<INSERT KEY>
|
YOUTUBE_API_KEY=<INSERT KEY>
|
||||||
SISSI_VERSION=1.0.2
|
SISSI_VERSION=1.1.0.RC1
|
||||||
@@ -62,6 +62,7 @@
|
|||||||
<outputDirectory>${file.basedir}/deployment/template-artifacts/</outputDirectory>
|
<outputDirectory>${file.basedir}/deployment/template-artifacts/</outputDirectory>
|
||||||
<destFileName>link-embed.zip</destFileName>
|
<destFileName>link-embed.zip</destFileName>
|
||||||
</artifactItem>
|
</artifactItem>
|
||||||
|
|
||||||
<artifactItem>
|
<artifactItem>
|
||||||
<groupId>dev.sheldan.abstracto-templates.templates</groupId>
|
<groupId>dev.sheldan.abstracto-templates.templates</groupId>
|
||||||
<artifactId>starboard</artifactId>
|
<artifactId>starboard</artifactId>
|
||||||
@@ -82,6 +83,16 @@
|
|||||||
<destFileName>quotes.zip</destFileName>
|
<destFileName>quotes.zip</destFileName>
|
||||||
</artifactItem>
|
</artifactItem>
|
||||||
|
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>dev.sheldan.sissi.templates</groupId>
|
||||||
|
<artifactId>meetup-templates</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<type>zip</type>
|
||||||
|
<overWrite>true</overWrite>
|
||||||
|
<outputDirectory>${file.basedir}/deployment/template-artifacts/</outputDirectory>
|
||||||
|
<destFileName>meetup.zip</destFileName>
|
||||||
|
</artifactItem>
|
||||||
|
|
||||||
<!-- translation artefacts -->
|
<!-- translation artefacts -->
|
||||||
|
|
||||||
<artifactItem>
|
<artifactItem>
|
||||||
@@ -124,6 +135,16 @@
|
|||||||
<destFileName>quotes.zip</destFileName>
|
<destFileName>quotes.zip</destFileName>
|
||||||
</artifactItem>
|
</artifactItem>
|
||||||
|
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>dev.sheldan.sissi.templates.translations</groupId>
|
||||||
|
<artifactId>meetup-translations</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<type>zip</type>
|
||||||
|
<overWrite>true</overWrite>
|
||||||
|
<outputDirectory>${file.basedir}/deployment/translation-artifacts/</outputDirectory>
|
||||||
|
<destFileName>meetup.zip</destFileName>
|
||||||
|
</artifactItem>
|
||||||
|
|
||||||
<!-- custom -->
|
<!-- custom -->
|
||||||
|
|
||||||
<!-- liquibase artifacts -->
|
<!-- liquibase artifacts -->
|
||||||
@@ -184,6 +205,17 @@
|
|||||||
<destFileName>quotes.zip</destFileName>
|
<destFileName>quotes.zip</destFileName>
|
||||||
</artifactItem>
|
</artifactItem>
|
||||||
|
|
||||||
|
<artifactItem>
|
||||||
|
<groupId>dev.sheldan.sissi.application.module</groupId>
|
||||||
|
<artifactId>meetup</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<classifier>liquibase</classifier>
|
||||||
|
<type>zip</type>
|
||||||
|
<overWrite>true</overWrite>
|
||||||
|
<outputDirectory>${file.basedir}/deployment/liquibase-artifacts/</outputDirectory>
|
||||||
|
<destFileName>meetup.zip</destFileName>
|
||||||
|
</artifactItem>
|
||||||
|
|
||||||
<!-- customizations -->
|
<!-- customizations -->
|
||||||
|
|
||||||
<!-- overrides -->
|
<!-- overrides -->
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
{
|
{
|
||||||
"template_artifacts": ["core","starboard", "link-embed", "quotes"],
|
"template_artifacts": ["core","starboard", "link-embed", "quotes", "meetup"],
|
||||||
"translation_artifacts": ["core", "starboard", "link-embed", "quotes"],
|
"translation_artifacts": ["core", "starboard", "link-embed", "quotes", "meetup"],
|
||||||
"liquibase_artifacts": [
|
"liquibase_artifacts": [
|
||||||
{ "zip": "scheduling", "file": "scheduling-changeLog.xml" },
|
{ "zip": "scheduling", "file": "scheduling-changeLog.xml" },
|
||||||
{ "zip": "core", "file": "core-changeLog.xml" },
|
{ "zip": "core", "file": "core-changeLog.xml" },
|
||||||
{ "zip": "link-embed", "file": "link-embed-changeLog.xml"},
|
{ "zip": "link-embed", "file": "link-embed-changeLog.xml"},
|
||||||
{ "zip": "starboard", "file": "starboard-changeLog.xml"},
|
{ "zip": "starboard", "file": "starboard-changeLog.xml"},
|
||||||
{ "zip": "quotes", "file": "quotes-changeLog.xml"}
|
{ "zip": "quotes", "file": "quotes-changeLog.xml"},
|
||||||
|
{ "zip": "meetup", "file": "meetup-changeLog.xml"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
4
pom.xml
4
pom.xml
@@ -20,8 +20,8 @@
|
|||||||
<maven.compiler.source>1.8</maven.compiler.source>
|
<maven.compiler.source>1.8</maven.compiler.source>
|
||||||
<!-- edit in release.yml as well -->
|
<!-- edit in release.yml as well -->
|
||||||
<!-- when releasing a new bot version, update the .env as well-->
|
<!-- when releasing a new bot version, update the .env as well-->
|
||||||
<abstracto.version>1.4.0-SNAPSHOT</abstracto.version>
|
<abstracto.version>1.4.0.RC2</abstracto.version>
|
||||||
<abstracto.templates.version>1.4.0-SNAPSHOT</abstracto.templates.version>
|
<abstracto.templates.version>1.4.0.RC1</abstracto.templates.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<artifactId>module-templates</artifactId>
|
||||||
|
<groupId>dev.sheldan.sissi.templates</groupId>
|
||||||
|
<version>1.1.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>meetup-templates</artifactId>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-assembly-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>single</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<finalName>meetup-templates-${project.version}</finalName>
|
||||||
|
<appendAssemblyId>false</appendAssemblyId>
|
||||||
|
<descriptors>
|
||||||
|
<descriptor>src/main/assembly/assembly.xml</descriptor>
|
||||||
|
</descriptors>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
|
||||||
|
<id>zip</id>
|
||||||
|
<includeBaseDirectory>false</includeBaseDirectory>
|
||||||
|
<formats>
|
||||||
|
<format>zip</format>
|
||||||
|
</formats>
|
||||||
|
<fileSets>
|
||||||
|
<fileSet>
|
||||||
|
<outputDirectory>.</outputDirectory>
|
||||||
|
<directory>${project.basedir}/src/main/resources</directory>
|
||||||
|
</fileSet>
|
||||||
|
</fileSets>
|
||||||
|
</assembly>
|
||||||
@@ -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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<#include "format_instant">
|
||||||
|
{
|
||||||
|
"embeds": [
|
||||||
|
{
|
||||||
|
<#include "abstracto_color">,
|
||||||
|
"description": "<#list meetups as meetup><#assign meetup=meetup><#assign topic=meetup.topic><#assign time><@format_instant_date_time instant=meetup.meetupTime/></#assign><#assign timeRelative><@format_instant_relative instant=meetup.meetupTime/></#assign><#assign link=meetup.meetupMessage.jumpUrl><#include "meetup_list_meetup_display">
|
||||||
|
<#else><#include "meetup_list_no_meetups"></#list>"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
<#include "meetup_in_past_exception_message">
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
<#include "meetup_not_found_exception_message">
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
<#include "format_instant">
|
||||||
|
{
|
||||||
|
"embeds": [
|
||||||
|
{
|
||||||
|
<#include "abstracto_color">,
|
||||||
|
<#assign time><@format_instant_date_time instant=meetupTime/></#assign>
|
||||||
|
<#assign topicText>${topic?json_string}</#assign>
|
||||||
|
"description": "<#include "meetup_cancel_notification_description">"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
<#include "format_instant">
|
||||||
|
{
|
||||||
|
<#assign roleMention="<@&371419588619141121>"/>
|
||||||
|
"additionalMessage": "${roleMention?json_string}",
|
||||||
|
"embeds": [
|
||||||
|
{
|
||||||
|
<#include "abstracto_color">,
|
||||||
|
"title": {
|
||||||
|
"title": "${topic?json_string}"
|
||||||
|
},
|
||||||
|
<#assign time><@format_instant_date_time instant=meetupTime/></#assign>
|
||||||
|
<#assign timeRelative><@format_instant_relative instant=meetupTime/></#assign>
|
||||||
|
<#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>"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
<#if yesId?has_content && noId?has_content && maybeId?has_content && !cancelled>
|
||||||
|
"buttons": [
|
||||||
|
{
|
||||||
|
"label": "<@safe_include "meetup_message_yes_button_label"/>",
|
||||||
|
"id": "${yesId}",
|
||||||
|
"buttonStyle": "success"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "<@safe_include "meetup_message_maybe_button_label"/>",
|
||||||
|
"id": "${maybeId}",
|
||||||
|
"buttonStyle": "secondary"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "<@safe_include "meetup_message_no_button_label"/>",
|
||||||
|
"id": "${noId}",
|
||||||
|
"buttonStyle": "danger"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "<@safe_include "meetup_message_cancel_button_label"/>",
|
||||||
|
"id": "${cancelId}",
|
||||||
|
"buttonStyle": "danger"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
</#if>
|
||||||
|
"messageConfig": {
|
||||||
|
"allowsRoleMention": true
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
<#include "format_instant">
|
||||||
|
{
|
||||||
|
"embeds": [
|
||||||
|
{
|
||||||
|
<#include "abstracto_color">,
|
||||||
|
<#assign time><@format_instant_date_time instant=meetupTime/></#assign>
|
||||||
|
<#assign topicText>${topic?json_string}</#assign>
|
||||||
|
"description": "<#include "meetup_reminder_notification_description">"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -11,6 +11,7 @@
|
|||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
<modules>
|
<modules>
|
||||||
<module>quotes-templates</module>
|
<module>quotes-templates</module>
|
||||||
|
<module>meetup-templates</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<groupId>dev.sheldan.sissi.templates.translations</groupId>
|
||||||
|
<artifactId>module-translations</artifactId>
|
||||||
|
<version>1.1.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>meetup-translations</artifactId>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-assembly-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>single</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<finalName>meetup-translations-${project.version}</finalName>
|
||||||
|
<appendAssemblyId>false</appendAssemblyId>
|
||||||
|
<descriptors>
|
||||||
|
<descriptor>src/main/assembly/assembly.xml</descriptor>
|
||||||
|
</descriptors>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
|
||||||
|
<id>zip</id>
|
||||||
|
<includeBaseDirectory>false</includeBaseDirectory>
|
||||||
|
<formats>
|
||||||
|
<format>zip</format>
|
||||||
|
</formats>
|
||||||
|
<fileSets>
|
||||||
|
<fileSet>
|
||||||
|
<outputDirectory>.</outputDirectory>
|
||||||
|
<directory>${project.basedir}/src/main/resources</directory>
|
||||||
|
</fileSet>
|
||||||
|
</fileSets>
|
||||||
|
</assembly>
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Cancel
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
OK
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Creates a meetup
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
Command used to schedule a meetup.
|
||||||
|
This creates a message which people can register (yes/no/maybe) themselves for a meetup.
|
||||||
|
People will receive a notification at certain time periods before the meetup.
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
What the meetup should be.
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Time of the meetup (https://www.unixtimestamp.com/)
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Short description of the meetup
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Lists all future meetups
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
This command can be used to list all future meetups and get information about them.
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
Time: ${time} ${timeRelative}
|
||||||
|
Link: [here](${link})
|
||||||
|
Meetup Topic: `${topic}`
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
No meetups found.
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Meetup
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Meetup is in the past. Not possible.
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Meetup not found.
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Meetup with topic ${topicText} at ${time} has been cancelled.
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
Time: ${time} ${timeRelative}
|
||||||
|
<#if descriptionText?hasContent>Description: ${descriptionText}</#if>
|
||||||
|
|
||||||
|
Participants: ${participantsText}
|
||||||
|
Maybe: ${maybeParticipantsText}
|
||||||
|
Declined: ${declinedParticipantsText}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Cancel
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Maybe
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
No
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Nobody.
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Yes
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Meetup with topic ${topicText} is at ${time}.
|
||||||
@@ -11,6 +11,7 @@
|
|||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
<modules>
|
<modules>
|
||||||
<module>quote-translations</module>
|
<module>quote-translations</module>
|
||||||
|
<module>meetup-translations</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user