Compare commits

...

34 Commits

Author SHA1 Message Date
Sheldan
f2522d5a47 [maven-release-plugin] prepare for next development iteration 2024-01-24 08:26:15 +01:00
Sheldan
61450a6a00 [maven-release-plugin] prepare release v1.5.22 2024-01-24 08:26:11 +01:00
Sheldan
05ea4d7dd3 [AB-xxx] prepare for release 2024-01-24 08:20:07 +01:00
Sheldan
71c18f8348 [AB-xxx] adding amongusText image generation 2024-01-24 08:18:36 +01:00
Sheldan
6030904d21 [AB-xxx] fixing not considering allowed mentions for interactions 2023-12-29 15:32:39 +01:00
Sheldan
2fd636a39e [maven-release-plugin] prepare for next development iteration 2023-12-29 00:21:06 +01:00
Sheldan
a94b9293f7 [maven-release-plugin] prepare release v1.5.21 2023-12-29 00:21:02 +01:00
Sheldan
3c4edf5671 [AB-xxx] fixing check in case no wikipedia article was found 2023-12-29 00:19:29 +01:00
Sheldan
f02f1eac4c [maven-release-plugin] prepare for next development iteration 2023-12-28 22:30:45 +01:00
Sheldan
373ed4cde5 [maven-release-plugin] prepare release v1.5.20 2023-12-28 22:30:41 +01:00
Sheldan
5eb9a0e674 [AB-xxx] preparing for release 2023-12-28 22:29:14 +01:00
Sheldan
d4f07bd719 [AB-xxx] adding wikipedia and dictionary features 2023-12-28 22:27:33 +01:00
Sheldan
8924b75530 [AB-xxx] adding check in case the modmail thread has been closed, this is needed because in thread mode one could potentially still execute commands
removing some message command implementations
refactoring the way modmail threads are loaded
2023-12-28 10:57:07 +01:00
Sheldan
25bdc98944 [maven-release-plugin] prepare for next development iteration 2023-12-26 21:04:49 +01:00
Sheldan
062581fce5 [maven-release-plugin] prepare release v1.5.19 2023-12-26 21:04:45 +01:00
Sheldan
be41551529 [AB-xxx] preparing for release 2023-12-26 21:03:11 +01:00
Sheldan
af8206c529 [AB-xxx] adding bonk image generation command
fixing offline streamer handling not being able to handle streamer without current sessions
2023-12-26 15:42:02 +01:00
Sheldan
8efedf6f6f [AB-xxx] renaming pat sprite png 2023-12-25 23:44:43 +01:00
Sheldan
80aff40054 [AB-xxx] adding pat gif generator command 2023-12-25 23:43:34 +01:00
Sheldan
c71f5f004d [AB-xxx] changing displayed user for already existing user in modmail to be the target user 2023-12-25 12:58:47 +01:00
Sheldan
350a634f50 [maven-release-plugin] prepare for next development iteration 2023-12-25 01:07:26 +01:00
Sheldan
f5de74c1e4 [maven-release-plugin] prepare release v1.5.18 2023-12-25 01:07:21 +01:00
Sheldan
6e3809bfd9 [AB-xxx] prepare for release 2023-12-25 01:06:02 +01:00
Sheldan
8e6339a99b [AB-109] fixing streamers not being marked online if the post target is disabled 2023-12-25 01:00:54 +01:00
Sheldan
befef1f61d [AB-xxx] refactoring modmail to offer a feature mode to use threads instead of channels
adding various utilities for thread channels in core
fixing enable feature not showing validation messages
restructuring feature mode collection to be a startup listener, because postconstruct might not have the appropriate values available, and therefore not initialize the map correctly
2023-12-24 23:25:03 +01:00
Sheldan
1f0bc493d9 [maven-release-plugin] prepare for next development iteration 2023-12-23 23:18:06 +01:00
Sheldan
48fa7a99dc [maven-release-plugin] prepare release v1.5.17 2023-12-23 23:18:02 +01:00
Sheldan
d12497753d [AB-xxx] preparing for release 2023-12-23 23:16:39 +01:00
Sheldan
20a6e29f1b [AB-xxx] fixing custom command alternative to filter when it should be executed more accurately 2023-12-23 23:16:01 +01:00
Sheldan
d2231b0934 [maven-release-plugin] prepare for next development iteration 2023-12-23 21:09:36 +01:00
Sheldan
0464afb7db [maven-release-plugin] prepare release v1.5.16 2023-12-23 21:09:32 +01:00
Sheldan
c473ca74d4 [AB-xxx] prepare for release 2023-12-23 21:08:20 +01:00
Sheldan
a70ac5aa94 [AB-xxx] fixing path for env file loading 2023-12-23 21:05:59 +01:00
Sheldan
d10faf4d3d [maven-release-plugin] prepare for next development iteration 2023-12-23 20:45:33 +01:00
252 changed files with 2227 additions and 275 deletions

2
.env
View File

@@ -1,2 +1,2 @@
REGISTRY_PREFIX=harbor.sheldan.dev/abstracto/ REGISTRY_PREFIX=harbor.sheldan.dev/abstracto/
VERSION=1.5.15 VERSION=1.5.22

View File

@@ -47,7 +47,7 @@ jobs:
id: dotenv id: dotenv
uses: falti/dotenv-action@v1.0.4 uses: falti/dotenv-action@v1.0.4
with: with:
path: ./deployment/installer/.env path: .env
- name: Push container - name: Push container
run: docker-compose build && docker-compose push run: docker-compose build && docker-compose push
env: env:

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<artifactId>anti-raid</artifactId> <artifactId>anti-raid</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<artifactId>anti-raid</artifactId> <artifactId>anti-raid</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<artifactId>abstracto-modules</artifactId> <artifactId>abstracto-modules</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>assignable-roles</artifactId> <artifactId>assignable-roles</artifactId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>assignable-roles</artifactId> <artifactId>assignable-roles</artifactId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<artifactId>assignable-roles-int</artifactId> <artifactId>assignable-roles-int</artifactId>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>abstracto-modules</artifactId> <artifactId>abstracto-modules</artifactId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>custom-command</artifactId> <artifactId>custom-command</artifactId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -45,8 +45,16 @@ public class CustomCommandAlternative implements CommandAlternative {
private CustomCommandFeatureConfig customCommandFeatureConfig; private CustomCommandFeatureConfig customCommandFeatureConfig;
@Override @Override
public boolean shouldExecute(UnParsedCommandParameter parameter, Guild guild) { public boolean shouldExecute(UnParsedCommandParameter parameter, Guild guild, Message message) {
return featureFlagService.isFeatureEnabled(customCommandFeatureConfig, guild.getIdLong()); boolean featureEnabled = featureFlagService.isFeatureEnabled(customCommandFeatureConfig, guild.getIdLong());
if(featureEnabled) {
String contentStripped = message.getContentRaw();
List<String> parameters = Arrays.asList(contentStripped.split(" "));
String commandName = commandRegistry.getCommandName(parameters.get(0), message.getGuild().getIdLong());
Optional<CustomCommand> customCommandOptional = customCommandManagementService.getCustomCommandByName(commandName, message.getGuild().getIdLong());
return customCommandOptional.isPresent();
}
return false;
} }
@Override @Override

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>custom-command</artifactId> <artifactId>custom-command</artifactId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<artifactId>abstracto-modules</artifactId> <artifactId>abstracto-modules</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>dynamic-activity</artifactId> <artifactId>dynamic-activity</artifactId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<artifactId>dynamic-activity</artifactId> <artifactId>dynamic-activity</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<artifactId>abstracto-modules</artifactId> <artifactId>abstracto-modules</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<artifactId>entertainment</artifactId> <artifactId>entertainment</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<artifactId>entertainment</artifactId> <artifactId>entertainment</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<artifactId>abstracto-modules</artifactId> <artifactId>abstracto-modules</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>experience-tracking</artifactId> <artifactId>experience-tracking</artifactId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>experience-tracking</artifactId> <artifactId>experience-tracking</artifactId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>abstracto-modules</artifactId> <artifactId>abstracto-modules</artifactId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>giveaway</artifactId> <artifactId>giveaway</artifactId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<artifactId>giveaway-impl</artifactId> <artifactId>giveaway-impl</artifactId>

View File

@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>giveaway</artifactId> <artifactId>giveaway</artifactId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<artifactId>giveaway-int</artifactId> <artifactId>giveaway-int</artifactId>

View File

@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>abstracto-modules</artifactId> <artifactId>abstracto-modules</artifactId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<artifactId>giveaway</artifactId> <artifactId>giveaway</artifactId>

View File

@@ -4,7 +4,7 @@
<parent> <parent>
<artifactId>image-generation</artifactId> <artifactId>image-generation</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<artifactId>image-generation-impl</artifactId> <artifactId>image-generation-impl</artifactId>

View File

@@ -0,0 +1,133 @@
package dev.sheldan.abstracto.imagegeneration.command;
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.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.interaction.slash.SlashCommandConfig;
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
import dev.sheldan.abstracto.core.service.ChannelService;
import dev.sheldan.abstracto.core.templating.model.AttachedFile;
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
import dev.sheldan.abstracto.core.templating.service.TemplateService;
import dev.sheldan.abstracto.core.utils.FileService;
import dev.sheldan.abstracto.core.utils.FutureUtils;
import dev.sheldan.abstracto.imagegeneration.config.ImageGenerationFeatureDefinition;
import dev.sheldan.abstracto.imagegeneration.config.ImageGenerationSlashCommandNames;
import dev.sheldan.abstracto.imagegeneration.service.ImageGenerationService;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@Component
public class AmongusText extends AbstractConditionableCommand {
public static final String TEXT_PARAMETER_KEY = "text";
@Autowired
private ImageGenerationService imageGenerationService;
@Autowired
private TemplateService templateService;
@Autowired
private ChannelService channelService;
@Autowired
private FileService fileService;
@Autowired
private InteractionService interactionService;
@Autowired
private SlashCommandParameterService slashCommandParameterService;
private static final String AMONGUS_TEXT_EMBED_TEMPLATE_KEY = "amongusText_response";
@Override
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
String text = (String) commandContext.getParameters().getParameters().get(0);
File amongusTextImage = imageGenerationService.getAmongusTextImage(text);
MessageToSend messageToSend = templateService.renderEmbedTemplate(AMONGUS_TEXT_EMBED_TEMPLATE_KEY, new Object());
// template support does not support binary files
AttachedFile file = AttachedFile
.builder()
.file(amongusTextImage)
.fileName("amongus.png")
.build();
messageToSend.getAttachedFiles().add(file);
return FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, commandContext.getChannel()))
.thenAccept(unused -> fileService.safeDeleteIgnoreException(messageToSend.getAttachedFiles().get(0).getFile()))
.thenApply(unused -> CommandResult.fromIgnored());
}
@Override
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
event.deferReply().queue();
String text = slashCommandParameterService.getCommandOption(TEXT_PARAMETER_KEY, event, String.class);
File amongusTextImage = imageGenerationService.getAmongusTextImage(text);
MessageToSend messageToSend = templateService.renderEmbedTemplate(AMONGUS_TEXT_EMBED_TEMPLATE_KEY, new Object());
// template support does not support binary files
AttachedFile file = AttachedFile
.builder()
.file(amongusTextImage)
.fileName("amongus.png")
.build();
messageToSend.getAttachedFiles().add(file);
return FutureUtils.toSingleFutureGeneric(interactionService.sendMessageToInteraction(messageToSend, event.getHook()))
.thenAccept(unused -> fileService.safeDeleteIgnoreException(messageToSend.getAttachedFiles().get(0).getFile()))
.thenApply(unused -> CommandResult.fromIgnored());
}
@Override
public CommandConfiguration getConfiguration() {
List<Parameter> parameters = new ArrayList<>();
Parameter memberParameter = Parameter
.builder()
.name(TEXT_PARAMETER_KEY)
.type(String.class)
.remainder(true)
.templated(true)
.build();
parameters.add(memberParameter);
HelpInfo helpInfo = HelpInfo
.builder()
.templated(true)
.build();
SlashCommandConfig slashCommandConfig = SlashCommandConfig
.builder()
.enabled(true)
.rootCommandName(ImageGenerationSlashCommandNames.IMAGE_GENERATION)
.groupName("memes")
.commandName("amongustext")
.build();
return CommandConfiguration.builder()
.name("amongusText")
.module(UtilityModuleDefinition.UTILITY)
.templated(true)
.supportsEmbedException(true)
.async(true)
.slashCommandConfig(slashCommandConfig)
.parameters(parameters)
.help(helpInfo)
.build();
}
@Override
public FeatureDefinition getFeature() {
return ImageGenerationFeatureDefinition.IMAGE_GENERATION;
}
}

View File

@@ -0,0 +1,147 @@
package dev.sheldan.abstracto.imagegeneration.command;
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.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.interaction.slash.SlashCommandConfig;
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
import dev.sheldan.abstracto.core.service.ChannelService;
import dev.sheldan.abstracto.core.templating.model.AttachedFile;
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
import dev.sheldan.abstracto.core.templating.service.TemplateService;
import dev.sheldan.abstracto.core.utils.FileService;
import dev.sheldan.abstracto.core.utils.FutureUtils;
import dev.sheldan.abstracto.imagegeneration.config.ImageGenerationFeatureDefinition;
import dev.sheldan.abstracto.imagegeneration.config.ImageGenerationSlashCommandNames;
import dev.sheldan.abstracto.imagegeneration.service.ImageGenerationService;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@Component
public class Bonk extends AbstractConditionableCommand {
public static final String MEMBER_PARAMETER_KEY = "member";
@Autowired
private ImageGenerationService imageGenerationService;
@Autowired
private TemplateService templateService;
@Autowired
private ChannelService channelService;
@Autowired
private FileService fileService;
@Autowired
private InteractionService interactionService;
@Autowired
private SlashCommandParameterService slashCommandParameterService;
private static final String BONK_EMBED_TEMPLATE_KEY = "bonk_response";
@Value("${abstracto.feature.imagegeneration.bonk.imagesize}")
private Integer imageSize;
@Override
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
Member member;
List<Object> parameters = commandContext.getParameters().getParameters();
if(parameters.isEmpty()) {
member = commandContext.getAuthor();
} else {
member = (Member) parameters.get(0);
}
File bonkGifFile = imageGenerationService.getBonkGif(member.getEffectiveAvatar().getUrl(imageSize));
MessageToSend messageToSend = templateService.renderEmbedTemplate(BONK_EMBED_TEMPLATE_KEY, new Object());
// template support does not support binary files
AttachedFile file = AttachedFile
.builder()
.file(bonkGifFile)
.fileName("bonk.gif")
.build();
messageToSend.getAttachedFiles().add(file);
return FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, commandContext.getChannel()))
.thenAccept(unused -> fileService.safeDeleteIgnoreException(messageToSend.getAttachedFiles().get(0).getFile()))
.thenApply(unused -> CommandResult.fromIgnored());
}
@Override
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
event.deferReply().queue();
Member targetMember;
if(slashCommandParameterService.hasCommandOption(MEMBER_PARAMETER_KEY, event)) {
targetMember = slashCommandParameterService.getCommandOption(MEMBER_PARAMETER_KEY, event, Member.class);
} else {
targetMember = event.getMember();
}
File bonkGifFile = imageGenerationService.getBonkGif(targetMember.getEffectiveAvatar().getUrl(imageSize));
MessageToSend messageToSend = templateService.renderEmbedTemplate(BONK_EMBED_TEMPLATE_KEY, new Object());
// template support does not support binary files
AttachedFile file = AttachedFile
.builder()
.file(bonkGifFile)
.fileName("bonk.gif")
.build();
messageToSend.getAttachedFiles().add(file);
return FutureUtils.toSingleFutureGeneric(interactionService.sendMessageToInteraction(messageToSend, event.getHook()))
.thenAccept(unused -> fileService.safeDeleteIgnoreException(messageToSend.getAttachedFiles().get(0).getFile()))
.thenApply(unused -> CommandResult.fromIgnored());
}
@Override
public CommandConfiguration getConfiguration() {
List<Parameter> parameters = new ArrayList<>();
Parameter memberParameter = Parameter
.builder()
.name(MEMBER_PARAMETER_KEY)
.type(Member.class)
.templated(true)
.optional(true)
.build();
parameters.add(memberParameter);
HelpInfo helpInfo = HelpInfo
.builder()
.templated(true)
.build();
SlashCommandConfig slashCommandConfig = SlashCommandConfig
.builder()
.enabled(true)
.rootCommandName(ImageGenerationSlashCommandNames.IMAGE_GENERATION)
.groupName("memes")
.commandName("bonk")
.build();
return CommandConfiguration.builder()
.name("bonk")
.module(UtilityModuleDefinition.UTILITY)
.templated(true)
.supportsEmbedException(true)
.async(true)
.slashCommandConfig(slashCommandConfig)
.parameters(parameters)
.help(helpInfo)
.build();
}
@Override
public FeatureDefinition getFeature() {
return ImageGenerationFeatureDefinition.IMAGE_GENERATION;
}
}

View File

@@ -0,0 +1,147 @@
package dev.sheldan.abstracto.imagegeneration.command;
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.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.interaction.slash.SlashCommandConfig;
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
import dev.sheldan.abstracto.core.service.ChannelService;
import dev.sheldan.abstracto.core.templating.model.AttachedFile;
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
import dev.sheldan.abstracto.core.templating.service.TemplateService;
import dev.sheldan.abstracto.core.utils.FileService;
import dev.sheldan.abstracto.core.utils.FutureUtils;
import dev.sheldan.abstracto.imagegeneration.config.ImageGenerationFeatureDefinition;
import dev.sheldan.abstracto.imagegeneration.config.ImageGenerationSlashCommandNames;
import dev.sheldan.abstracto.imagegeneration.service.ImageGenerationService;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@Component
public class Pat extends AbstractConditionableCommand {
public static final String MEMBER_PARAMETER_KEY = "member";
@Autowired
private ImageGenerationService imageGenerationService;
@Autowired
private TemplateService templateService;
@Autowired
private ChannelService channelService;
@Autowired
private FileService fileService;
@Autowired
private InteractionService interactionService;
@Autowired
private SlashCommandParameterService slashCommandParameterService;
private static final String PAT_EMBED_TEMPLATE_KEY = "pat_response";
@Value("${abstracto.feature.imagegeneration.pat.imagesize}")
private Integer imageSize;
@Override
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
Member member;
List<Object> parameters = commandContext.getParameters().getParameters();
if(parameters.isEmpty()) {
member = commandContext.getAuthor();
} else {
member = (Member) parameters.get(0);
}
File patGifFile = imageGenerationService.getPatGif(member.getEffectiveAvatar().getUrl(imageSize));
MessageToSend messageToSend = templateService.renderEmbedTemplate(PAT_EMBED_TEMPLATE_KEY, new Object());
// template support does not support binary files
AttachedFile file = AttachedFile
.builder()
.file(patGifFile)
.fileName("pat.gif")
.build();
messageToSend.getAttachedFiles().add(file);
return FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, commandContext.getChannel()))
.thenAccept(unused -> fileService.safeDeleteIgnoreException(messageToSend.getAttachedFiles().get(0).getFile()))
.thenApply(unused -> CommandResult.fromIgnored());
}
@Override
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
event.deferReply().queue();
Member targetMember;
if(slashCommandParameterService.hasCommandOption(MEMBER_PARAMETER_KEY, event)) {
targetMember = slashCommandParameterService.getCommandOption(MEMBER_PARAMETER_KEY, event, Member.class);
} else {
targetMember = event.getMember();
}
File patGifFile = imageGenerationService.getPatGif(targetMember.getEffectiveAvatar().getUrl(imageSize));
MessageToSend messageToSend = templateService.renderEmbedTemplate(PAT_EMBED_TEMPLATE_KEY, new Object());
// template support does not support binary files
AttachedFile file = AttachedFile
.builder()
.file(patGifFile)
.fileName("pat.gif")
.build();
messageToSend.getAttachedFiles().add(file);
return FutureUtils.toSingleFutureGeneric(interactionService.sendMessageToInteraction(messageToSend, event.getHook()))
.thenAccept(unused -> fileService.safeDeleteIgnoreException(messageToSend.getAttachedFiles().get(0).getFile()))
.thenApply(unused -> CommandResult.fromIgnored());
}
@Override
public CommandConfiguration getConfiguration() {
List<Parameter> parameters = new ArrayList<>();
Parameter memberParameter = Parameter
.builder()
.name(MEMBER_PARAMETER_KEY)
.type(Member.class)
.templated(true)
.optional(true)
.build();
parameters.add(memberParameter);
HelpInfo helpInfo = HelpInfo
.builder()
.templated(true)
.build();
SlashCommandConfig slashCommandConfig = SlashCommandConfig
.builder()
.enabled(true)
.rootCommandName(ImageGenerationSlashCommandNames.IMAGE_GENERATION)
.groupName("memes")
.commandName("pat")
.build();
return CommandConfiguration.builder()
.name("pat")
.module(UtilityModuleDefinition.UTILITY)
.templated(true)
.supportsEmbedException(true)
.async(true)
.slashCommandConfig(slashCommandConfig)
.parameters(parameters)
.help(helpInfo)
.build();
}
@Override
public FeatureDefinition getFeature() {
return ImageGenerationFeatureDefinition.IMAGE_GENERATION;
}
}

View File

@@ -73,7 +73,7 @@ public class Triggered extends AbstractConditionableCommand {
AttachedFile file = AttachedFile AttachedFile file = AttachedFile
.builder() .builder()
.file(triggeredGifFile) .file(triggeredGifFile)
.fileName("avatar.gif") .fileName("triggered.gif")
.build(); .build();
messageToSend.getAttachedFiles().add(file); messageToSend.getAttachedFiles().add(file);
return FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, commandContext.getChannel())) return FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, commandContext.getChannel()))
@@ -96,7 +96,7 @@ public class Triggered extends AbstractConditionableCommand {
AttachedFile file = AttachedFile AttachedFile file = AttachedFile
.builder() .builder()
.file(triggeredGifFile) .file(triggeredGifFile)
.fileName("avatar.gif") .fileName("triggered.gif")
.build(); .build();
messageToSend.getAttachedFiles().add(file); messageToSend.getAttachedFiles().add(file);
return FutureUtils.toSingleFutureGeneric(interactionService.sendMessageToInteraction(messageToSend, event.getHook())) return FutureUtils.toSingleFutureGeneric(interactionService.sendMessageToInteraction(messageToSend, event.getHook()))

View File

@@ -1,7 +1,9 @@
package dev.sheldan.abstracto.imagegeneration.service; package dev.sheldan.abstracto.imagegeneration.service;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException; import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import dev.sheldan.abstracto.core.exception.RequestException;
import dev.sheldan.abstracto.core.service.HttpService; import dev.sheldan.abstracto.core.service.HttpService;
import dev.sheldan.abstracto.imagegeneration.exception.AmongusTextRequestException;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@@ -16,6 +18,14 @@ public class ImageGenerationServiceBean implements ImageGenerationService {
@Value("${abstracto.feature.imagegeneration.triggered.url}") @Value("${abstracto.feature.imagegeneration.triggered.url}")
private String triggeredUrl; private String triggeredUrl;
@Value("${abstracto.feature.imagegeneration.pat.url}")
private String patUrl;
@Value("${abstracto.feature.imagegeneration.bonk.url}")
private String bonkUrl;
@Value("${abstracto.feature.imagegeneration.amongusText.url}")
private String amongusTextUrl;
@Autowired @Autowired
private HttpService httpService; private HttpService httpService;
@@ -29,4 +39,33 @@ public class ImageGenerationServiceBean implements ImageGenerationService {
} }
} }
@Override
public File getPatGif(String imageUrl) {
try {
return httpService.downloadFileToTempFile(patUrl.replace("{1}", imageUrl));
} catch (IOException e) {
throw new AbstractoRunTimeException(String.format("Failed to download pat gif for url %s with error %s", imageUrl, e.getMessage()));
}
}
@Override
public File getBonkGif(String imageUrl) {
try {
return httpService.downloadFileToTempFile(bonkUrl.replace("{1}", imageUrl));
} catch (IOException e) {
throw new AbstractoRunTimeException(String.format("Failed to download bonk gif for url %s with error %s", imageUrl, e.getMessage()));
}
}
@Override
public File getAmongusTextImage(String text) {
try {
return httpService.downloadFileToTempFile(amongusTextUrl.replace("{1}", text));
} catch (IOException e) {
throw new AbstractoRunTimeException(String.format("Failed to download amongus text with error %s", text, e.getMessage()));
} catch (RequestException exception) {
throw new AmongusTextRequestException(text, exception.getErrorMessage());
}
}
} }

View File

@@ -2,4 +2,12 @@ abstracto.featureFlags.imageGeneration.featureName=imageGeneration
abstracto.featureFlags.imageGeneration.enabled=false abstracto.featureFlags.imageGeneration.enabled=false
abstracto.feature.imagegeneration.triggered.url=http://${PRIVATE_REST_API_HOST}:${PRIVATE_REST_API_PORT}/memes/triggered/file.gif?url={1} abstracto.feature.imagegeneration.triggered.url=http://${PRIVATE_REST_API_HOST}:${PRIVATE_REST_API_PORT}/memes/triggered/file.gif?url={1}
abstracto.feature.imagegeneration.triggered.imagesize=128 abstracto.feature.imagegeneration.triggered.imagesize=128
abstracto.feature.imagegeneration.pat.url=http://${PRIVATE_REST_API_HOST}:${PRIVATE_REST_API_PORT}/memes/pat/file.gif?url={1}
abstracto.feature.imagegeneration.pat.imagesize=128
abstracto.feature.imagegeneration.bonk.url=http://${PRIVATE_REST_API_HOST}:${PRIVATE_REST_API_PORT}/memes/bonk/file.gif?url={1}
abstracto.feature.imagegeneration.bonk.imagesize=128
abstracto.feature.imagegeneration.amongusText.url=http://${PRIVATE_REST_API_HOST}:${PRIVATE_REST_API_PORT}/memes/amogus/text?text={1}

View File

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

View File

@@ -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="imageGenerationFeature" value="(SELECT id FROM feature WHERE key = 'imageGeneration')"/>
<changeSet author="Sheldan" id="pat_bonk-commands">
<insert tableName="command">
<column name="name" value="pat"/>
<column name="module_id" valueComputed="${utilityModule}"/>
<column name="feature_id" valueComputed="${imageGenerationFeature}"/>
</insert>
<insert tableName="command">
<column name="name" value="bonk"/>
<column name="module_id" valueComputed="${utilityModule}"/>
<column name="feature_id" valueComputed="${imageGenerationFeature}"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

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

View File

@@ -0,0 +1,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="seedData/data.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -0,0 +1,20 @@
<?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="imageGenerationFeature" value="(SELECT id FROM feature WHERE key = 'imageGeneration')"/>
<changeSet author="Sheldan" id="amongusText-commands">
<insert tableName="command">
<column name="name" value="amongusText"/>
<column name="module_id" valueComputed="${utilityModule}"/>
<column name="feature_id" valueComputed="${imageGenerationFeature}"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

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

View File

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

View File

@@ -4,7 +4,7 @@
<parent> <parent>
<artifactId>image-generation</artifactId> <artifactId>image-generation</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<artifactId>image-generation-int</artifactId> <artifactId>image-generation-int</artifactId>

View File

@@ -0,0 +1,26 @@
package dev.sheldan.abstracto.imagegeneration.exception;
import dev.sheldan.abstracto.core.exception.AbstractoTemplatableException;
import dev.sheldan.abstracto.imagegeneration.model.exception.AmongusTextRequestExceptionModel;
public class AmongusTextRequestException extends AbstractoTemplatableException {
private final AmongusTextRequestExceptionModel model;
public AmongusTextRequestException(String inputText, String errorMessage) {
this.model = AmongusTextRequestExceptionModel
.builder()
.inputText(inputText)
.errorMessage(errorMessage)
.build();
}
@Override
public String getTemplateName() {
return "amongusText_exception";
}
@Override
public Object getTemplateModel() {
return model;
}
}

View File

@@ -0,0 +1,13 @@
package dev.sheldan.abstracto.imagegeneration.model.exception;
import lombok.Builder;
import lombok.Getter;
import java.io.Serializable;
@Getter
@Builder
public class AmongusTextRequestExceptionModel implements Serializable {
private String inputText;
private String errorMessage;
}

View File

@@ -4,4 +4,7 @@ import java.io.File;
public interface ImageGenerationService { public interface ImageGenerationService {
File getTriggeredGif(String imageUrl); File getTriggeredGif(String imageUrl);
File getPatGif(String imageUrl);
File getBonkGif(String imageUrl);
File getAmongusTextImage(String text);
} }

View File

@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>abstracto-modules</artifactId> <artifactId>abstracto-modules</artifactId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<artifactId>image-generation</artifactId> <artifactId>image-generation</artifactId>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<artifactId>invite-filter</artifactId> <artifactId>invite-filter</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<artifactId>invite-filter</artifactId> <artifactId>invite-filter</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<artifactId>abstracto-modules</artifactId> <artifactId>abstracto-modules</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<artifactId>link-embed</artifactId> <artifactId>link-embed</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<artifactId>link-embed</artifactId> <artifactId>link-embed</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<artifactId>abstracto-modules</artifactId> <artifactId>abstracto-modules</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<artifactId>logging</artifactId> <artifactId>logging</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<artifactId>logging</artifactId> <artifactId>logging</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<artifactId>abstracto-modules</artifactId> <artifactId>abstracto-modules</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>moderation</artifactId> <artifactId>moderation</artifactId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>moderation</artifactId> <artifactId>moderation</artifactId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>abstracto-modules</artifactId> <artifactId>abstracto-modules</artifactId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>modmail</artifactId> <artifactId>modmail</artifactId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -8,12 +8,12 @@ import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.CommandContext; import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult; import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureDefinition; import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.models.database.AChannel;
import dev.sheldan.abstracto.core.service.MemberService; import dev.sheldan.abstracto.core.service.MemberService;
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
import dev.sheldan.abstracto.modmail.condition.ModMailContextCondition; import dev.sheldan.abstracto.modmail.condition.ModMailContextCondition;
import dev.sheldan.abstracto.modmail.config.ModMailFeatureDefinition; import dev.sheldan.abstracto.modmail.config.ModMailFeatureDefinition;
import dev.sheldan.abstracto.modmail.exception.ModMailThreadClosedException;
import dev.sheldan.abstracto.modmail.model.database.ModMailThread; import dev.sheldan.abstracto.modmail.model.database.ModMailThread;
import dev.sheldan.abstracto.modmail.model.database.ModMailThreadState;
import dev.sheldan.abstracto.modmail.service.ModMailThreadService; import dev.sheldan.abstracto.modmail.service.ModMailThreadService;
import dev.sheldan.abstracto.modmail.service.management.ModMailThreadManagementService; import dev.sheldan.abstracto.modmail.service.management.ModMailThreadManagementService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@@ -42,18 +42,17 @@ public class AnonReply extends AbstractConditionableCommand {
@Autowired @Autowired
private MemberService memberService; private MemberService memberService;
@Autowired
private ChannelManagementService channelManagementService;
@Override @Override
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) { public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
List<Object> parameters = commandContext.getParameters().getParameters(); List<Object> parameters = commandContext.getParameters().getParameters();
// text is optional, for example if only an attachment is sent // text is optional, for example if only an attachment is sent
String text = parameters.size() == 1 ? (String) parameters.get(0) : ""; String text = parameters.size() == 1 ? (String) parameters.get(0) : "";
AChannel channel = channelManagementService.loadChannel(commandContext.getChannel()); ModMailThread modMailThread = modMailThreadManagementService.getByChannelId(commandContext.getChannel().getIdLong());
ModMailThread thread = modMailThreadManagementService.getByChannel(channel); if(ModMailThreadState.CLOSED.equals(modMailThread.getState()) || ModMailThreadState.CLOSING.equals(modMailThread.getState())) {
Long threadId = thread.getId(); throw new ModMailThreadClosedException();
return memberService.getMemberInServerAsync(thread.getUser()).thenCompose(member -> }
Long threadId = modMailThread.getId();
return memberService.getMemberInServerAsync(modMailThread.getUser()).thenCompose(member ->
modMailThreadService.loadExecutingMemberAndRelay(threadId, text, commandContext.getMessage(), true, member) modMailThreadService.loadExecutingMemberAndRelay(threadId, text, commandContext.getMessage(), true, member)
).thenApply(aVoid -> CommandResult.fromSuccess()); ).thenApply(aVoid -> CommandResult.fromSuccess());
} }

View File

@@ -11,13 +11,13 @@ import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService; import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
import dev.sheldan.abstracto.core.config.FeatureDefinition; import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.interaction.InteractionService; import dev.sheldan.abstracto.core.interaction.InteractionService;
import dev.sheldan.abstracto.core.models.database.AChannel;
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
import dev.sheldan.abstracto.modmail.condition.ModMailContextCondition; import dev.sheldan.abstracto.modmail.condition.ModMailContextCondition;
import dev.sheldan.abstracto.modmail.config.ModMailFeatureDefinition; import dev.sheldan.abstracto.modmail.config.ModMailFeatureDefinition;
import dev.sheldan.abstracto.modmail.config.ModMailSlashCommandNames; import dev.sheldan.abstracto.modmail.config.ModMailSlashCommandNames;
import dev.sheldan.abstracto.modmail.exception.ModMailThreadClosedException;
import dev.sheldan.abstracto.modmail.model.ClosingContext; import dev.sheldan.abstracto.modmail.model.ClosingContext;
import dev.sheldan.abstracto.modmail.model.database.ModMailThread; import dev.sheldan.abstracto.modmail.model.database.ModMailThread;
import dev.sheldan.abstracto.modmail.model.database.ModMailThreadState;
import dev.sheldan.abstracto.modmail.service.ModMailThreadService; import dev.sheldan.abstracto.modmail.service.ModMailThreadService;
import dev.sheldan.abstracto.modmail.service.management.ModMailThreadManagementService; import dev.sheldan.abstracto.modmail.service.management.ModMailThreadManagementService;
import dev.sheldan.abstracto.core.templating.service.TemplateService; import dev.sheldan.abstracto.core.templating.service.TemplateService;
@@ -59,9 +59,6 @@ public class Close extends AbstractConditionableCommand {
@Autowired @Autowired
private TemplateService templateService; private TemplateService templateService;
@Autowired
private ChannelManagementService channelManagementService;
@Autowired @Autowired
private InteractionService interactionService; private InteractionService interactionService;
@@ -76,8 +73,10 @@ public class Close extends AbstractConditionableCommand {
List<Object> parameters = commandContext.getParameters().getParameters(); List<Object> parameters = commandContext.getParameters().getParameters();
// the default value of the note is configurable via template // the default value of the note is configurable via template
String note = parameters.size() == 1 ? (String) parameters.get(0) : templateService.renderTemplate(MODMAIL_CLOSE_DEFAULT_NOTE_TEMPLATE_KEY, new Object()); String note = parameters.size() == 1 ? (String) parameters.get(0) : templateService.renderTemplate(MODMAIL_CLOSE_DEFAULT_NOTE_TEMPLATE_KEY, new Object());
AChannel channel = channelManagementService.loadChannel(commandContext.getChannel()); ModMailThread modMailThread = modMailThreadManagementService.getByChannelId(commandContext.getChannel().getIdLong());
ModMailThread thread = modMailThreadManagementService.getByChannel(channel); if(ModMailThreadState.CLOSED.equals(modMailThread.getState()) || ModMailThreadState.CLOSING.equals(modMailThread.getState())) {
throw new ModMailThreadClosedException();
}
ClosingContext context = ClosingContext ClosingContext context = ClosingContext
.builder() .builder()
.closingMember(commandContext.getAuthor()) .closingMember(commandContext.getAuthor())
@@ -86,7 +85,7 @@ public class Close extends AbstractConditionableCommand {
.log(true) .log(true)
.note(note) .note(note)
.build(); .build();
return modMailThreadService.closeModMailThread(thread, context, commandContext.getUndoActions()) return modMailThreadService.closeModMailThread(modMailThread, context, commandContext.getUndoActions())
.thenApply(aVoid -> CommandResult.fromIgnored()); .thenApply(aVoid -> CommandResult.fromIgnored());
} }
@@ -125,9 +124,11 @@ public class Close extends AbstractConditionableCommand {
@Transactional @Transactional
public CompletableFuture<Void> closeThread(ClosingContext closingContext) { public CompletableFuture<Void> closeThread(ClosingContext closingContext) {
AChannel channel = channelManagementService.loadChannel(closingContext.getChannel()); ModMailThread modMailThread = modMailThreadManagementService.getByChannelId(closingContext.getChannel().getIdLong());
ModMailThread thread = modMailThreadManagementService.getByChannel(channel); if(ModMailThreadState.CLOSED.equals(modMailThread.getState()) || ModMailThreadState.CLOSING.equals(modMailThread.getState())) {
return modMailThreadService.closeModMailThread(thread, closingContext, new ArrayList<>()); throw new ModMailThreadClosedException();
}
return modMailThreadService.closeModMailThread(modMailThread, closingContext, new ArrayList<>());
} }
@Override @Override

View File

@@ -8,12 +8,12 @@ import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.CommandContext; import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult; import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureDefinition; import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.models.database.AChannel;
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
import dev.sheldan.abstracto.modmail.condition.ModMailContextCondition; import dev.sheldan.abstracto.modmail.condition.ModMailContextCondition;
import dev.sheldan.abstracto.modmail.config.ModMailFeatureDefinition; import dev.sheldan.abstracto.modmail.config.ModMailFeatureDefinition;
import dev.sheldan.abstracto.modmail.exception.ModMailThreadClosedException;
import dev.sheldan.abstracto.modmail.model.ClosingContext; import dev.sheldan.abstracto.modmail.model.ClosingContext;
import dev.sheldan.abstracto.modmail.model.database.ModMailThread; import dev.sheldan.abstracto.modmail.model.database.ModMailThread;
import dev.sheldan.abstracto.modmail.model.database.ModMailThreadState;
import dev.sheldan.abstracto.modmail.service.ModMailThreadService; import dev.sheldan.abstracto.modmail.service.ModMailThreadService;
import dev.sheldan.abstracto.modmail.service.management.ModMailThreadManagementService; import dev.sheldan.abstracto.modmail.service.management.ModMailThreadManagementService;
import dev.sheldan.abstracto.core.templating.service.TemplateService; import dev.sheldan.abstracto.core.templating.service.TemplateService;
@@ -43,16 +43,15 @@ public class CloseSilently extends AbstractConditionableCommand {
@Autowired @Autowired
private TemplateService templateService; private TemplateService templateService;
@Autowired
private ChannelManagementService channelManagementService;
@Override @Override
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) { public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
List<Object> parameters = commandContext.getParameters().getParameters(); List<Object> parameters = commandContext.getParameters().getParameters();
// default note text is configurable via template, because the note is optional // default note text is configurable via template, because the note is optional
String note = parameters.size() == 1 ? (String) parameters.get(0) : templateService.renderTemplate("modmail_close_default_note", new Object()); String note = parameters.size() == 1 ? (String) parameters.get(0) : templateService.renderTemplate("modmail_close_default_note", new Object());
AChannel channel = channelManagementService.loadChannel(commandContext.getChannel()); ModMailThread modMailThread = modMailThreadManagementService.getByChannelId(commandContext.getChannel().getIdLong());
ModMailThread thread = modMailThreadManagementService.getByChannel(channel); if(ModMailThreadState.CLOSED.equals(modMailThread.getState()) || ModMailThreadState.CLOSING.equals(modMailThread.getState())) {
throw new ModMailThreadClosedException();
}
ClosingContext context = ClosingContext ClosingContext context = ClosingContext
.builder() .builder()
.closingMember(commandContext.getAuthor()) .closingMember(commandContext.getAuthor())
@@ -60,7 +59,7 @@ public class CloseSilently extends AbstractConditionableCommand {
.log(true) .log(true)
.note(note) .note(note)
.build(); .build();
return modMailThreadService.closeModMailThread(thread, context, commandContext.getUndoActions()) return modMailThreadService.closeModMailThread(modMailThread, context, commandContext.getUndoActions())
.thenApply(aVoid -> CommandResult.fromIgnored()); .thenApply(aVoid -> CommandResult.fromIgnored());
} }

View File

@@ -82,7 +82,7 @@ public class Contact extends AbstractConditionableCommand {
ModMailThreadExistsModel model = ModMailThreadExistsModel ModMailThreadExistsModel model = ModMailThreadExistsModel
.builder() .builder()
.existingModMailThread(existingThread) .existingModMailThread(existingThread)
.executingMemberDisplay(MemberNameDisplay.fromMember(commandContext.getAuthor())) .executingMemberDisplay(MemberNameDisplay.fromMember(targetUser))
.build(); .build();
List<CompletableFuture<Message>> futures = channelService.sendEmbedTemplateInTextChannelList(MODMAIL_THREAD_ALREADY_EXISTS_TEMPLATE, model, commandContext.getChannel()); List<CompletableFuture<Message>> futures = channelService.sendEmbedTemplateInTextChannelList(MODMAIL_THREAD_ALREADY_EXISTS_TEMPLATE, model, commandContext.getChannel());
return FutureUtils.toSingleFutureGeneric(futures).thenApply(aVoid -> CommandResult.fromIgnored()); return FutureUtils.toSingleFutureGeneric(futures).thenApply(aVoid -> CommandResult.fromIgnored());

View File

@@ -8,12 +8,12 @@ import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.CommandContext; import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult; import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureDefinition; import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.models.database.AChannel;
import dev.sheldan.abstracto.core.service.MemberService; import dev.sheldan.abstracto.core.service.MemberService;
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
import dev.sheldan.abstracto.modmail.condition.ModMailContextCondition; import dev.sheldan.abstracto.modmail.condition.ModMailContextCondition;
import dev.sheldan.abstracto.modmail.config.ModMailFeatureDefinition; import dev.sheldan.abstracto.modmail.config.ModMailFeatureDefinition;
import dev.sheldan.abstracto.modmail.exception.ModMailThreadClosedException;
import dev.sheldan.abstracto.modmail.model.database.ModMailThread; import dev.sheldan.abstracto.modmail.model.database.ModMailThread;
import dev.sheldan.abstracto.modmail.model.database.ModMailThreadState;
import dev.sheldan.abstracto.modmail.service.ModMailThreadService; import dev.sheldan.abstracto.modmail.service.ModMailThreadService;
import dev.sheldan.abstracto.modmail.service.management.ModMailThreadManagementService; import dev.sheldan.abstracto.modmail.service.management.ModMailThreadManagementService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@@ -41,17 +41,16 @@ public class Reply extends AbstractConditionableCommand {
@Autowired @Autowired
private MemberService memberService; private MemberService memberService;
@Autowired
private ChannelManagementService channelManagementService;
@Override @Override
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) { public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
List<Object> parameters = commandContext.getParameters().getParameters(); List<Object> parameters = commandContext.getParameters().getParameters();
String text = parameters.size() == 1 ? (String) parameters.get(0) : ""; String text = parameters.size() == 1 ? (String) parameters.get(0) : "";
AChannel channel = channelManagementService.loadChannel(commandContext.getChannel()); ModMailThread modMailThread = modMailThreadManagementService.getByChannelId(commandContext.getChannel().getIdLong());
ModMailThread thread = modMailThreadManagementService.getByChannel(channel); if(ModMailThreadState.CLOSED.equals(modMailThread.getState()) || ModMailThreadState.CLOSING.equals(modMailThread.getState())) {
Long threadId = thread.getId(); throw new ModMailThreadClosedException();
return memberService.getMemberInServerAsync(thread.getUser()).thenCompose(member -> }
Long threadId = modMailThread.getId();
return memberService.getMemberInServerAsync(modMailThread.getUser()).thenCompose(member ->
modMailThreadService.loadExecutingMemberAndRelay(threadId, text, commandContext.getMessage(), false, member) modMailThreadService.loadExecutingMemberAndRelay(threadId, text, commandContext.getMessage(), false, member)
).thenApply(aVoid -> CommandResult.fromSuccess()); ).thenApply(aVoid -> CommandResult.fromSuccess());
} }

View File

@@ -5,7 +5,6 @@ import dev.sheldan.abstracto.core.command.condition.CommandCondition;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration; import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo; import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig; import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult; import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureDefinition; import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.interaction.InteractionService; import dev.sheldan.abstracto.core.interaction.InteractionService;
@@ -13,7 +12,9 @@ import dev.sheldan.abstracto.core.service.management.UserInServerManagementServi
import dev.sheldan.abstracto.modmail.condition.ModMailContextCondition; import dev.sheldan.abstracto.modmail.condition.ModMailContextCondition;
import dev.sheldan.abstracto.modmail.config.ModMailFeatureDefinition; import dev.sheldan.abstracto.modmail.config.ModMailFeatureDefinition;
import dev.sheldan.abstracto.modmail.config.ModMailSlashCommandNames; import dev.sheldan.abstracto.modmail.config.ModMailSlashCommandNames;
import dev.sheldan.abstracto.modmail.exception.ModMailThreadClosedException;
import dev.sheldan.abstracto.modmail.model.database.ModMailThread; import dev.sheldan.abstracto.modmail.model.database.ModMailThread;
import dev.sheldan.abstracto.modmail.model.database.ModMailThreadState;
import dev.sheldan.abstracto.modmail.service.ModMailSubscriptionService; import dev.sheldan.abstracto.modmail.service.ModMailSubscriptionService;
import dev.sheldan.abstracto.modmail.service.management.ModMailThreadManagementService; import dev.sheldan.abstracto.modmail.service.management.ModMailThreadManagementService;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
@@ -49,16 +50,12 @@ public class Subscribe extends AbstractConditionableCommand {
@Autowired @Autowired
private InteractionService interactionService; private InteractionService interactionService;
@Override
public CommandResult execute(CommandContext commandContext) {
ModMailThread modMailThread = modMailThreadManagementService.getByChannelId(commandContext.getChannel().getIdLong());
modMailSubscriptionService.subscribeToThread(userInServerManagementService.loadOrCreateUser(commandContext.getAuthor()), modMailThread);
return CommandResult.fromSuccess();
}
@Override @Override
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) { public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
ModMailThread modMailThread = modMailThreadManagementService.getByChannelId(event.getChannel().getIdLong()); ModMailThread modMailThread = modMailThreadManagementService.getByChannelId(event.getChannel().getIdLong());
if(ModMailThreadState.CLOSED.equals(modMailThread.getState()) || ModMailThreadState.CLOSING.equals(modMailThread.getState())) {
throw new ModMailThreadClosedException();
}
modMailSubscriptionService.subscribeToThread(userInServerManagementService.loadOrCreateUser(event.getMember()), modMailThread); modMailSubscriptionService.subscribeToThread(userInServerManagementService.loadOrCreateUser(event.getMember()), modMailThread);
return interactionService.replyEmbed(SUBSCRIBE_RESPONSE, event) return interactionService.replyEmbed(SUBSCRIBE_RESPONSE, event)
.thenApply(interactionHook -> CommandResult.fromSuccess()); .thenApply(interactionHook -> CommandResult.fromSuccess());
@@ -83,6 +80,7 @@ public class Subscribe extends AbstractConditionableCommand {
.slashCommandConfig(slashCommandConfig) .slashCommandConfig(slashCommandConfig)
.module(ModMailModuleDefinition.MODMAIL) .module(ModMailModuleDefinition.MODMAIL)
.help(helpInfo) .help(helpInfo)
.slashCommandOnly(true)
.supportsEmbedException(true) .supportsEmbedException(true)
.templated(true) .templated(true)
.causesReaction(true) .causesReaction(true)

View File

@@ -5,7 +5,6 @@ import dev.sheldan.abstracto.core.command.condition.CommandCondition;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration; import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo; import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig; import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult; import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureDefinition; import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.interaction.InteractionService; import dev.sheldan.abstracto.core.interaction.InteractionService;
@@ -14,7 +13,9 @@ import dev.sheldan.abstracto.core.service.management.UserInServerManagementServi
import dev.sheldan.abstracto.modmail.condition.ModMailContextCondition; import dev.sheldan.abstracto.modmail.condition.ModMailContextCondition;
import dev.sheldan.abstracto.modmail.config.ModMailFeatureDefinition; import dev.sheldan.abstracto.modmail.config.ModMailFeatureDefinition;
import dev.sheldan.abstracto.modmail.config.ModMailSlashCommandNames; import dev.sheldan.abstracto.modmail.config.ModMailSlashCommandNames;
import dev.sheldan.abstracto.modmail.exception.ModMailThreadClosedException;
import dev.sheldan.abstracto.modmail.model.database.ModMailThread; import dev.sheldan.abstracto.modmail.model.database.ModMailThread;
import dev.sheldan.abstracto.modmail.model.database.ModMailThreadState;
import dev.sheldan.abstracto.modmail.service.ModMailSubscriptionService; import dev.sheldan.abstracto.modmail.service.ModMailSubscriptionService;
import dev.sheldan.abstracto.modmail.service.management.ModMailThreadManagementService; import dev.sheldan.abstracto.modmail.service.management.ModMailThreadManagementService;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent; import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
@@ -50,17 +51,12 @@ public class UnSubscribe extends AbstractConditionableCommand {
@Autowired @Autowired
private InteractionService interactionService; private InteractionService interactionService;
@Override
public CommandResult execute(CommandContext commandContext) {
ModMailThread modMailThread = modMailThreadManagementService.getByChannelId(commandContext.getChannel().getIdLong());
AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(commandContext.getAuthor());
modMailSubscriptionService.unsubscribeFromThread(aUserInAServer, modMailThread);
return CommandResult.fromSuccess();
}
@Override @Override
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) { public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
ModMailThread modMailThread = modMailThreadManagementService.getByChannelId(event.getChannel().getIdLong()); ModMailThread modMailThread = modMailThreadManagementService.getByChannelId(event.getChannel().getIdLong());
if(ModMailThreadState.CLOSED.equals(modMailThread.getState()) || ModMailThreadState.CLOSING.equals(modMailThread.getState())) {
throw new ModMailThreadClosedException();
}
AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(event.getMember()); AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(event.getMember());
modMailSubscriptionService.unsubscribeFromThread(aUserInAServer, modMailThread); modMailSubscriptionService.unsubscribeFromThread(aUserInAServer, modMailThread);
return interactionService.replyEmbed(UN_SUBSCRIBE_RESPONSE, event) return interactionService.replyEmbed(UN_SUBSCRIBE_RESPONSE, event)
@@ -86,6 +82,7 @@ public class UnSubscribe extends AbstractConditionableCommand {
.slashCommandConfig(slashCommandConfig) .slashCommandConfig(slashCommandConfig)
.module(ModMailModuleDefinition.MODMAIL) .module(ModMailModuleDefinition.MODMAIL)
.help(helpInfo) .help(helpInfo)
.slashCommandOnly(true)
.supportsEmbedException(true) .supportsEmbedException(true)
.templated(true) .templated(true)
.causesReaction(true) .causesReaction(true)

View File

@@ -40,6 +40,7 @@ import dev.sheldan.abstracto.core.templating.service.TemplateService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.*; import net.dv8tion.jda.api.entities.*;
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
import net.dv8tion.jda.api.entities.channel.concrete.ThreadChannel;
import net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel; import net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel;
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel; import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.exceptions.InsufficientPermissionException; import net.dv8tion.jda.api.exceptions.InsufficientPermissionException;
@@ -56,14 +57,12 @@ import java.util.concurrent.CompletableFuture;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static dev.sheldan.abstracto.modmail.config.ModMailFeatureConfig.MOD_MAIL_CLOSING_TEXT_SYSTEM_CONFIG_KEY;
@Component @Component
@Slf4j @Slf4j
public class ModMailThreadServiceBean implements ModMailThreadService { public class ModMailThreadServiceBean implements ModMailThreadService {
/**
* The config key to use for the closing text
*/
public static final String MODMAIL_CLOSING_MESSAGE_TEXT = "modMailClosingText";
/** /**
* The config key to use for the ID of the category to create {@link GuildMessageChannel} in * The config key to use for the ID of the category to create {@link GuildMessageChannel} in
*/ */
@@ -190,11 +189,9 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
@Override @Override
public CompletableFuture<MessageChannel> createModMailThreadForUser(Member member, Message initialMessage, boolean userInitiated, List<UndoActionInstance> undoActions) { public CompletableFuture<MessageChannel> createModMailThreadForUser(Member member, Message initialMessage, boolean userInitiated, List<UndoActionInstance> undoActions) {
Long serverId = member.getGuild().getIdLong(); Long serverId = member.getGuild().getIdLong();
Long categoryId = configService.getLongValue(MODMAIL_CATEGORY, serverId); User user = member.getUser();
AServer server = serverManagementService.loadServer(member.getGuild().getIdLong()); AServer server = serverManagementService.loadServer(member.getGuild().getIdLong());
metricService.incrementCounter(MODMAIL_THREAD_CREATED_COUNTER); metricService.incrementCounter(MODMAIL_THREAD_CREATED_COUNTER);
User user = member.getUser();
log.info("Creating modmail channel for user {} in category {} on server {}.", user.getId(), categoryId, serverId);
ModMailChannelNameModel model = ModMailChannelNameModel ModMailChannelNameModel model = ModMailChannelNameModel
.builder() .builder()
.serverId(serverId) .serverId(serverId)
@@ -204,12 +201,36 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
.currentDate(Instant.now()) .currentDate(Instant.now())
.build(); .build();
String channelName = templateService.renderTemplate(TEXT_CHANNEL_NAME_TEMPLATE_KEY, model, serverId); String channelName = templateService.renderTemplate(TEXT_CHANNEL_NAME_TEMPLATE_KEY, model, serverId);
CompletableFuture<TextChannel> textChannelFuture = channelService.createTextChannel(channelName, server, categoryId); if (featureModeService.featureModeActive(ModMailFeatureDefinition.MOD_MAIL, serverId, ModMailMode.THREAD_CONTAINER)) {
return textChannelFuture.thenCompose(channel -> { MessageToSend notificationMessageToSend = getModmailNotificationMessageToSend(member, null, serverId, false);
undoActions.add(UndoActionInstance.getChannelDeleteAction(serverId, channel.getIdLong())); Optional<GuildMessageChannel> modmailContainerOptional = postTargetService.getPostTargetChannel(ModMailPostTargets.MOD_MAIL_CONTAINER, serverId);
return self.performModMailThreadSetup(member, initialMessage, channel, userInitiated, undoActions) if(modmailContainerOptional.isEmpty()) {
.thenCompose(unused -> CompletableFuture.completedFuture(channel)); throw new AbstractoRunTimeException("Modmail thread container not setup.");
}); }
GuildMessageChannel modmailContainer = modmailContainerOptional.get();
Optional<TextChannel> textChannelOptional = channelService.getTextChannelFromServerOptional(serverId, modmailContainer.getIdLong());
if(textChannelOptional.isEmpty()) {
throw new AbstractoRunTimeException("Modmail thread container text channel not found.");
}
TextChannel textChannel = textChannelOptional.get();
List<CompletableFuture<Message>> notificationMessage = channelService.sendMessageToSendToChannel(notificationMessageToSend, modmailContainer);
return FutureUtils.toSingleFutureGeneric(notificationMessage)
.thenCompose(unused -> channelService.createThreadWithStarterMessage(textChannel, channelName, notificationMessage.get(0).join().getIdLong()))
.thenCompose(threadChannel -> {
undoActions.add(UndoActionInstance.getChannelDeleteAction(serverId, threadChannel.getIdLong()));
return self.performModMailThreadSetup(member, initialMessage, threadChannel, userInitiated, undoActions)
.thenCompose(unused -> CompletableFuture.completedFuture(threadChannel));
});
} else {
Long categoryId = configService.getLongValue(MODMAIL_CATEGORY, serverId);
log.info("Creating modmail channel for user {} in category {} on server {}.", user.getId(), categoryId, serverId);
CompletableFuture<TextChannel> textChannelFuture = channelService.createTextChannel(channelName, server, categoryId);
return textChannelFuture.thenCompose(channel -> {
undoActions.add(UndoActionInstance.getChannelDeleteAction(serverId, channel.getIdLong()));
return self.performModMailThreadSetup(member, initialMessage, channel, userInitiated, undoActions)
.thenCompose(unused -> CompletableFuture.completedFuture(channel));
});
}
} }
@Transactional @Transactional
@@ -239,12 +260,12 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
* @param member The {@link Member} for which a {@link ModMailThread} is being created * @param member The {@link Member} for which a {@link ModMailThread} is being created
* @param initialMessage The {@link Message} which was sent by the user to open a thread, this is null, if the thread was opened via a command * @param initialMessage The {@link Message} which was sent by the user to open a thread, this is null, if the thread was opened via a command
* @param channel The created {@link TextChannel} in which the mod mail thread is dealt with * @param channel The created {@link TextChannel} in which the mod mail thread is dealt with
* @param userInitiated Whether or not the thread was initiated by a member * @param userInitiated Whether the thread was initiated by a member
* @param undoActions The list of actions to undo, in case an exception occurs * @param undoActions The list of actions to undo, in case an exception occurs
* @return A {@link CompletableFuture future} which completes when the setup is done * @return A {@link CompletableFuture future} which completes when the setup is done
*/ */
@Transactional @Transactional
public CompletableFuture<Void> performModMailThreadSetup(Member member, Message initialMessage, TextChannel channel, boolean userInitiated, List<UndoActionInstance> undoActions) { public CompletableFuture<Void> performModMailThreadSetup(Member member, Message initialMessage, GuildMessageChannel channel, boolean userInitiated, List<UndoActionInstance> undoActions) {
log.info("Performing modmail thread setup for channel {} for user {} in server {}. It was initiated by a user: {}.", channel.getIdLong(), member.getId(), channel.getGuild().getId(), userInitiated); log.info("Performing modmail thread setup for channel {} for user {} in server {}. It was initiated by a user: {}.", channel.getIdLong(), member.getId(), channel.getGuild().getId(), userInitiated);
CompletableFuture<Void> headerFuture = sendModMailHeader(channel, member); CompletableFuture<Void> headerFuture = sendModMailHeader(channel, member);
CompletableFuture<Message> userReplyMessage; CompletableFuture<Message> userReplyMessage;
@@ -268,7 +289,7 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
} }
@Transactional @Transactional
public void setupModMailThreadInDB(Message initialMessage, TextChannel channel, Member member, Message sendMessage) { public void setupModMailThreadInDB(Message initialMessage, GuildMessageChannel channel, Member member, Message sendMessage) {
log.info("Persisting info about modmail thread {} in database.", channel.getIdLong()); log.info("Persisting info about modmail thread {} in database.", channel.getIdLong());
AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(member); AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(member);
ModMailThread thread = createThreadObject(channel, aUserInAServer); ModMailThread thread = createThreadObject(channel, aUserInAServer);
@@ -281,15 +302,25 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
/** /**
* Sends the message containing the pings to notify the staff members to handle the opened {@link ModMailThread} * Sends the message containing the pings to notify the staff members to handle the opened {@link ModMailThread}
* @param member The {@link FullUserInServer} which opened the thread * @param member The {@link FullUserInServer} which opened the thread
* @param channel The created {@link TextChannel} in which the mod mail thread is dealt with * @param channel The created {@link GuildMessageChannel} in which the mod mail thread is dealt with
* @return A {@link CompletableFuture future} which complets when the notification has been sent * @return A {@link CompletableFuture future} which completes when the notification has been sent
*/ */
@Transactional @Transactional
public CompletableFuture<Void> sendModMailNotification(Member member, TextChannel channel) { public CompletableFuture<Void> sendModMailNotification(Member member, GuildMessageChannel channel) {
Long serverId = member.getGuild().getIdLong(); Long serverId = member.getGuild().getIdLong();
MessageToSend messageToSend = getModmailNotificationMessageToSend(member, channel, serverId, true);
return FutureUtils.toSingleFutureGeneric(postTargetService.sendEmbedInPostTarget(messageToSend, ModMailPostTargets.MOD_MAIL_PING, serverId));
}
private MessageToSend getModmailNotificationMessageToSend(Member member, GuildMessageChannel channel, Long serverId, boolean pingRole) {
log.info("Sending modmail notification for new modmail thread about user {} in server {}.", member.getId(), serverId); log.info("Sending modmail notification for new modmail thread about user {} in server {}.", member.getId(), serverId);
AServer server = serverManagementService.loadServer(serverId); AServer server = serverManagementService.loadServer(serverId);
List<ModMailRole> rolesToPing = modMailRoleManagementService.getRolesForServer(server); List<ModMailRole> rolesToPing;
if(pingRole) {
rolesToPing = modMailRoleManagementService.getRolesForServer(server);
} else {
rolesToPing = new ArrayList<>();
}
log.debug("Pinging {} roles to notify about modmail thread about user {} in server {}.", rolesToPing.size(), member.getId(), serverId); log.debug("Pinging {} roles to notify about modmail thread about user {} in server {}.", rolesToPing.size(), member.getId(), serverId);
ModMailNotificationModel modMailNotificationModel = ModMailNotificationModel ModMailNotificationModel modMailNotificationModel = ModMailNotificationModel
.builder() .builder()
@@ -297,29 +328,31 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
.roles(rolesToPing) .roles(rolesToPing)
.channel(channel) .channel(channel)
.build(); .build();
MessageToSend messageToSend = templateService.renderEmbedTemplate("modmail_notification_message", modMailNotificationModel, channel.getGuild().getIdLong()); return templateService.renderEmbedTemplate("modmail_notification_message", modMailNotificationModel, serverId);
return FutureUtils.toSingleFutureGeneric(postTargetService.sendEmbedInPostTarget(messageToSend, ModMailPostTargets.MOD_MAIL_PING, serverId));
} }
/** /**
* Creates the instance of the {@link ModMailThread} in the database. * Creates the instance of the {@link ModMailThread} in the database.
* @param channel The {@link TextChannel} in which the {@link ModMailThread} is being done * @param channel The {@link GuildMessageChannel} in which the {@link ModMailThread} is being done
* @param user The {@link AUserInAServer} which the thread is about * @param user The {@link AUserInAServer} which the thread is about
* @return The created instance of {@link ModMailThread} * @return The created instance of {@link ModMailThread}
*/ */
public ModMailThread createThreadObject(TextChannel channel, AUserInAServer user) { public ModMailThread createThreadObject(GuildMessageChannel channel, AUserInAServer user) {
log.info("Creating database objects related to modmail thread in channel {} and about user {} in server {}.", channel.getIdLong(), user.getUserReference().getId(), channel.getGuild().getId()); log.info("Creating database objects related to modmail thread in channel {} and about user {} in server {}.", channel.getIdLong(), user.getUserReference().getId(), channel.getGuild().getId());
AChannel channel2 = channelManagementService.createChannel(channel.getIdLong(), AChannelType.TEXT, user.getServerReference()); boolean useThreads = featureModeService.featureModeActive(ModMailFeatureDefinition.MOD_MAIL, channel.getGuild().getIdLong(), ModMailMode.THREAD_CONTAINER);
log.info("Creating mod mail thread in channel {} with db channel {}", channel.getIdLong(), channel2.getId()); AChannel aChannel = channelManagementService.createChannel(channel.getIdLong(), useThreads ? AChannelType.PUBLIC_THREAD : AChannelType.TEXT, user.getServerReference());
return modMailThreadManagementService.createModMailThread(user, channel2); log.info("Creating mod mail thread in channel {} with db channel {}", channel.getIdLong(), aChannel.getId());
return modMailThreadManagementService.createModMailThread(user, aChannel);
} }
@Override @Override
public void setModMailCategoryTo(Guild guild, Long categoryId) { public void setModMailCategoryTo(Guild guild, Long categoryId) {
log.info("Trying to set modmail category to {} in guild {}.", categoryId, guild.getId()); log.info("Trying to set modmail category to {} in guild {}.", categoryId, guild.getId());
FeatureValidationResult result = FeatureValidationResult.builder().build(); FeatureValidationResult result = FeatureValidationResult
.builder()
.build();
modMailFeatureValidator.validateModMailCategory(result, guild, categoryId); modMailFeatureValidator.validateModMailCategory(result, guild, categoryId);
if(result.getValidationResult()) { if(!result.getValidationResult()) {
throw new ModMailCategoryIdException(categoryId); throw new ModMailCategoryIdException(categoryId);
} }
configService.setLongValue(MODMAIL_CATEGORY, guild.getIdLong(), categoryId); configService.setLongValue(MODMAIL_CATEGORY, guild.getIdLong(), categoryId);
@@ -416,10 +449,10 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
/** /**
* Method used to send the header of a newly created mod mail thread. This message contains information about * Method used to send the header of a newly created mod mail thread. This message contains information about
* the user which the thread is about * the user which the thread is about
* @param channel The {@link TextChannel} in which the mod mail thread is present in * @param channel The {@link GuildMessageChannel} in which the mod mail thread is present in
* @param member The {@link Member} which the {@link ModMailThread} is about * @param member The {@link Member} which the {@link ModMailThread} is about
*/ */
private CompletableFuture<Void> sendModMailHeader(TextChannel channel, Member member) { private CompletableFuture<Void> sendModMailHeader(GuildMessageChannel channel, Member member) {
log.debug("Sending modmail thread header for tread in channel {} on server {}.", channel.getIdLong(), channel.getGuild().getId()); log.debug("Sending modmail thread header for tread in channel {} on server {}.", channel.getIdLong(), channel.getGuild().getId());
AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(member); AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(member);
ModMailThread latestThread = modMailThreadManagementService.getLatestModMailThread(aUserInAServer); ModMailThread latestThread = modMailThreadManagementService.getLatestModMailThread(aUserInAServer);
@@ -472,8 +505,8 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
* @param modMailThreadId The id of the modmail thread to which the received {@link Message} is a reply to, can be null, if it is null, its the initial message * @param modMailThreadId The id of the modmail thread to which the received {@link Message} is a reply to, can be null, if it is null, its the initial message
* @param messageFromUser The received message from the user * @param messageFromUser The received message from the user
* @param member The {@link Member} instance from the user the thread is about. It is used as author * @param member The {@link Member} instance from the user the thread is about. It is used as author
* @param modMailThreadExists Whether or not the modmail thread already exists and is persisted. * @param modMailThreadExists Whether the modmail thread already exists and is persisted.
* @return A {@link CompletableFuture} which resolves when the post processing of the message is completed (adding read notification, and storing messageIDs) * @return A {@link CompletableFuture} which resolves when the postprocessing of the message is completed (adding read notification, and storing messageIDs)
*/ */
public CompletableFuture<Message> sendUserReply(GuildMessageChannel messageChannel, Long modMailThreadId, Message messageFromUser, Member member, boolean modMailThreadExists) { public CompletableFuture<Message> sendUserReply(GuildMessageChannel messageChannel, Long modMailThreadId, Message messageFromUser, Member member, boolean modMailThreadExists) {
List<CompletableFuture<Member>> subscriberMemberFutures = new ArrayList<>(); List<CompletableFuture<Member>> subscriberMemberFutures = new ArrayList<>();
@@ -548,7 +581,7 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
} }
/** /**
* This message handles the post processing of the messages received by the user. This includes: saving the messageIDs * This message handles the postprocessing of the messages received by the user. This includes: saving the messageIDs
* in the database, updating the state of the {@link ModMailThread} and adding the read reaction to the user message * in the database, updating the state of the {@link ModMailThread} and adding the read reaction to the user message
* @param textChannel The channel in which the message * @param textChannel The channel in which the message
* @param messageInModMailThread The actual {@link Message} instance which was sent to the mod mail thread * @param messageInModMailThread The actual {@link Message} instance which was sent to the mod mail thread
@@ -640,22 +673,31 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
List<ModMailMessage> modMailMessages = modMailThread.getMessages(); List<ModMailMessage> modMailMessages = modMailThread.getMessages();
Long userId = modMailThread.getUser().getUserReference().getId(); Long userId = modMailThread.getUser().getUserReference().getId();
Long serverId = modMailThread.getServer().getId(); Long serverId = modMailThread.getServer().getId();
if(closingConfig.getLog()) { if (featureModeService.featureModeActive(ModMailFeatureDefinition.MOD_MAIL, serverId, ModMailMode.THREAD_CONTAINER)) {
if(!modMailMessages.isEmpty()) { ThreadChannel threadChannel = channelService.getThreadChannel(modMailThread.getChannel().getId());
return modMailMessageService.loadModMailMessages(modMailMessages) log.info("Archiving thread {} for modmail thread closing.", modMailThread.getChannel().getId());
.thenAccept(loadedModmailThreadMessages -> self.logMessagesToModMailLog(closingConfig, modMailThreadId, undoActions, loadedModmailThreadMessages, serverId, userId)); return loadUserAndSendClosingHeader(modMailThread, closingConfig)
} else { .thenCompose(unused -> channelService.archiveThreadChannel(threadChannel))
log.info("Modmail thread {} in server {} has no messages. Only logging header.", modMailThreadId, serverId); .thenCompose(unused -> memberService.getMemberInServerAsync(serverId, userId))
return loadUserAndSendClosingHeader(modMailThread, closingConfig) .thenAccept(member -> self.afterSuccessfulLog(modMailThreadId, closingConfig.getNotifyUser(), member, undoActions));
.thenAccept(unused -> memberService.getMemberInServerAsync(modMailThread.getUser()).thenCompose(member ->
self.afterSuccessfulLog(modMailThreadId, closingConfig.getNotifyUser(), member, undoActions)
));
}
} else { } else {
log.debug("Not logging modmail thread {}.", modMailThreadId); if(closingConfig.getLog()) {
return memberService.getMemberInServerAsync(modMailThread.getUser()).thenCompose(member -> if(!modMailMessages.isEmpty()) {
self.afterSuccessfulLog(modMailThreadId, closingConfig.getNotifyUser(), member, undoActions) return modMailMessageService.loadModMailMessages(modMailMessages)
); .thenAccept(loadedModmailThreadMessages -> self.logMessagesToModMailLog(closingConfig, modMailThreadId, undoActions, loadedModmailThreadMessages, serverId, userId));
} else {
log.info("Modmail thread {} in server {} has no messages. Only logging header.", modMailThreadId, serverId);
return loadUserAndSendClosingHeader(modMailThread, closingConfig)
.thenAccept(unused -> memberService.getMemberInServerAsync(modMailThread.getUser()).thenCompose(member ->
self.afterSuccessfulLog(modMailThreadId, closingConfig.getNotifyUser(), member, undoActions)
));
}
} else {
log.debug("Not logging modmail thread {}.", modMailThreadId);
return memberService.getMemberInServerAsync(modMailThread.getUser()).thenCompose(member ->
self.afterSuccessfulLog(modMailThreadId, closingConfig.getNotifyUser(), member, undoActions)
);
}
} }
} }
@@ -711,7 +753,7 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
* This message is executed after the thread has been logged and notifies the user about the closed {@link ModMailThread} * This message is executed after the thread has been logged and notifies the user about the closed {@link ModMailThread}
* which a configurable closing text. This method then calls the method to delete the channel. * which a configurable closing text. This method then calls the method to delete the channel.
* @param modMailThreadId The ID of the {@link ModMailThread} which is being closed. * @param modMailThreadId The ID of the {@link ModMailThread} which is being closed.
* @param notifyUser Whether or not the user should be notified * @param notifyUser Whether the user should be notified
* @param undoActions The list of {@link UndoActionInstance} to execute in case of exceptions * @param undoActions The list of {@link UndoActionInstance} to execute in case of exceptions
* @param modMailThreaduser The {@link Member member} for which the {@link ModMailThread thread} was for * @param modMailThreaduser The {@link Member member} for which the {@link ModMailThread thread} was for
* @throws ModMailThreadNotFoundException in case the {@link ModMailThread} is not found by the ID * @throws ModMailThreadNotFoundException in case the {@link ModMailThread} is not found by the ID
@@ -727,7 +769,7 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
ModMailThread modMailThread = modMailThreadOpt.get(); ModMailThread modMailThread = modMailThreadOpt.get();
HashMap<String, String> closingMessage = new HashMap<>(); HashMap<String, String> closingMessage = new HashMap<>();
String defaultValue = templateService.renderSimpleTemplate("modmail_closing_user_message_description"); String defaultValue = templateService.renderSimpleTemplate("modmail_closing_user_message_description");
closingMessage.put("closingMessage", configService.getStringValue(MODMAIL_CLOSING_MESSAGE_TEXT, modMailThread.getServer().getId(), defaultValue)); closingMessage.put("closingMessage", configService.getStringValue(MOD_MAIL_CLOSING_TEXT_SYSTEM_CONFIG_KEY, modMailThread.getServer().getId(), defaultValue));
return messageService.sendEmbedToUser(modMailThreaduser.getUser(), "modmail_closing_user_message", closingMessage).thenAccept(message -> return messageService.sendEmbedToUser(modMailThreaduser.getUser(), "modmail_closing_user_message", closingMessage).thenAccept(message ->
self.deleteChannelAndClose(modMailThreadId, undoActions) self.deleteChannelAndClose(modMailThreadId, undoActions)
).exceptionally(throwable -> { ).exceptionally(throwable -> {
@@ -758,11 +800,17 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
ModMailThread modMailThread = modMailThreadOpt.get(); ModMailThread modMailThread = modMailThreadOpt.get();
String failureMessage = "Failed to delete text channel containing mod mail thread {}"; String failureMessage = "Failed to delete text channel containing mod mail thread {}";
try { try {
log.debug("Deleting channel {} which contained the modmail thread {}.", modMailThread.getChannel().getId(), modMailThreadId); if (featureModeService.featureModeActive(ModMailFeatureDefinition.MOD_MAIL, modMailThread.getServer().getId(), ModMailMode.THREAD_CONTAINER)) {
return channelService.deleteTextChannel(modMailThread.getChannel()).thenAccept(avoid -> {
undoActions.clear(); undoActions.clear();
self.closeModMailThreadInDb(modMailThreadId); self.closeModMailThreadInDb(modMailThreadId);
}); return CompletableFuture.completedFuture(null);
} else {
log.debug("Deleting channel {} which contained the modmail thread {}.", modMailThread.getChannel().getId(), modMailThreadId);
return channelService.deleteTextChannel(modMailThread.getChannel()).thenAccept(avoid -> {
undoActions.clear();
self.closeModMailThreadInDb(modMailThreadId);
});
}
} catch (InsufficientPermissionException ex) { } catch (InsufficientPermissionException ex) {
log.error(failureMessage, modMailThreadId, ex); log.error(failureMessage, modMailThreadId, ex);
String message = "Failed To delete mod mail thread channel because no permissions."; String message = "Failed To delete mod mail thread channel because no permissions.";
@@ -864,16 +912,22 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
.serverId(modMailThread.getServer().getId()) .serverId(modMailThread.getServer().getId())
.userId(modMailThread.getUser().getUserReference().getId()) .userId(modMailThread.getUser().getUserReference().getId())
.build(); .build();
Long modmailThreadId = modMailThread.getId();
return userService.retrieveUserForId(modMailThread.getUser().getUserReference().getId()).thenApply(user -> { return userService.retrieveUserForId(modMailThread.getUser().getUserReference().getId()).thenApply(user -> {
headerModel.setUser(user); headerModel.setUser(user);
return self.sendClosingHeader(headerModel).get(0); return self.sendClosingHeader(headerModel, modmailThreadId).get(0);
}).thenCompose(Function.identity()); }).thenCompose(Function.identity());
} }
@Transactional @Transactional
public List<CompletableFuture<Message>> sendClosingHeader(ModMailClosingHeaderModel model) { public List<CompletableFuture<Message>> sendClosingHeader(ModMailClosingHeaderModel model, Long modmailThreadId) {
MessageToSend messageToSend = templateService.renderEmbedTemplate("modmail_close_header", model, model.getServerId()); MessageToSend messageToSend = templateService.renderEmbedTemplate("modmail_close_header", model, model.getServerId());
return postTargetService.sendEmbedInPostTarget(messageToSend, ModMailPostTargets.MOD_MAIL_LOG, model.getServerId()); if (featureModeService.featureModeActive(ModMailFeatureDefinition.MOD_MAIL, model.getServerId(), ModMailMode.THREAD_CONTAINER)) {
ModMailThread modMailThread = modMailThreadManagementService.getById(modmailThreadId);
return channelService.sendMessageEmbedToSendToAChannel(messageToSend, modMailThread.getChannel());
} else {
return postTargetService.sendEmbedInPostTarget(messageToSend, ModMailPostTargets.MOD_MAIL_LOG, model.getServerId());
}
} }
/** /**
@@ -899,7 +953,7 @@ public class ModMailThreadServiceBean implements ModMailThreadService {
* sends this to the appropriate logging {@link PostTarget} * sends this to the appropriate logging {@link PostTarget}
* @param modMailThreadId The ID of {@link ModMailThread} to which the loaded messages belong to * @param modMailThreadId The ID of {@link ModMailThread} to which the loaded messages belong to
* @param loadedMessages The list of {@link ModMailLoggedMessageModel} which can be rendered * @param loadedMessages The list of {@link ModMailLoggedMessageModel} which can be rendered
* @return A list of {@link CompletableFuture} which represent each of the messages being send to the {@link PostTarget} * @return A list of {@link CompletableFuture} which represent each of the messages being sent to the {@link PostTarget}
*/ */
public List<CompletableFuture<Message>> sendMessagesToPostTarget(Long modMailThreadId, List<ModMailLoggedMessageModel> loadedMessages, Message updateMessage) { public List<CompletableFuture<Message>> sendMessagesToPostTarget(Long modMailThreadId, List<ModMailLoggedMessageModel> loadedMessages, Message updateMessage) {
List<CompletableFuture<Message>> messageFutures = new ArrayList<>(); List<CompletableFuture<Message>> messageFutures = new ArrayList<>();

View File

@@ -3,21 +3,25 @@ package dev.sheldan.abstracto.modmail.validator;
import dev.sheldan.abstracto.core.config.FeatureConfig; import dev.sheldan.abstracto.core.config.FeatureConfig;
import dev.sheldan.abstracto.core.models.FeatureValidationResult; import dev.sheldan.abstracto.core.models.FeatureValidationResult;
import dev.sheldan.abstracto.core.models.database.AServer; import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.service.ConfigService; import dev.sheldan.abstracto.core.service.*;
import dev.sheldan.abstracto.core.service.FeatureValidatorService; import dev.sheldan.abstracto.modmail.config.ModMailFeatureDefinition;
import dev.sheldan.abstracto.core.service.GuildService; import dev.sheldan.abstracto.modmail.config.ModMailMode;
import dev.sheldan.abstracto.modmail.config.ModMailPostTargets;
import dev.sheldan.abstracto.modmail.model.template.ModMailCategoryValidationErrorModel; import dev.sheldan.abstracto.modmail.model.template.ModMailCategoryValidationErrorModel;
import dev.sheldan.abstracto.modmail.model.template.ModMailThreadContainerValidationErrorModel;
import dev.sheldan.abstracto.modmail.service.ModMailThreadServiceBean; import dev.sheldan.abstracto.modmail.service.ModMailThreadServiceBean;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.channel.attribute.IThreadContainer;
import net.dv8tion.jda.api.entities.channel.concrete.Category; import net.dv8tion.jda.api.entities.channel.concrete.Category;
import net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.util.Optional; import java.util.Optional;
/** /**
* This component is used to validate whether or not the mod mail feature has a mod mail category configured, which points to * This component is used to validate whether the mod mail feature has a mod mail category configured, which points to
* a category on the server it is configured for. This and other {@link dev.sheldan.abstracto.core.service.FeatureValidator} * a category on the server it is configured for. This and other {@link dev.sheldan.abstracto.core.service.FeatureValidator}
* are used to fully validate the mod mail feature. * are used to fully validate the mod mail feature.
*/ */
@@ -34,8 +38,16 @@ public class ModMailFeatureValidatorBean implements ModMailFeatureValidator {
@Autowired @Autowired
private FeatureValidatorService featureValidatorService; private FeatureValidatorService featureValidatorService;
@Autowired
private FeatureModeService featureModeService;
@Autowired
private PostTargetService postTargetService;
/** /**
* Checks if the mod mail category contains a value and whether or not this valid also points to a {@link Category} * Checks if the mod mail category contains a value and whether this valid also points to a {@link Category}.
* Additionally, if the thread container feature mode is already enabled. This will check if the current posttarget
* for threads can hold threads.
* @param featureConfig The instance of {@link FeatureConfig} of mod mail * @param featureConfig The instance of {@link FeatureConfig} of mod mail
* @param server The {@link AServer} to check the config for * @param server The {@link AServer} to check the config for
* @param validationResult The current {@link FeatureValidationResult} used to accumulate the wrong values * @param validationResult The current {@link FeatureValidationResult} used to accumulate the wrong values
@@ -52,6 +64,29 @@ public class ModMailFeatureValidatorBean implements ModMailFeatureValidator {
Long modMailCategory = configService.getLongValue(ModMailThreadServiceBean.MODMAIL_CATEGORY, server.getId()); Long modMailCategory = configService.getLongValue(ModMailThreadServiceBean.MODMAIL_CATEGORY, server.getId());
validateModMailCategory(validationResult, guild, modMailCategory); validateModMailCategory(validationResult, guild, modMailCategory);
} }
if (featureModeService.featureModeActive(ModMailFeatureDefinition.MOD_MAIL, server.getId(), ModMailMode.THREAD_CONTAINER)) {
Optional<GuildMessageChannel> modmailContainerOptional = postTargetService.getPostTargetChannel(ModMailPostTargets.MOD_MAIL_CONTAINER, server.getId());
if(modmailContainerOptional.isEmpty()) {
ModMailThreadContainerValidationErrorModel newError = ModMailThreadContainerValidationErrorModel
.builder()
.currentChannelId(null)
.build();
validationResult.getValidationErrorModels().add(newError);
validationResult.setValidationResult(false);
} else {
GuildMessageChannel threadContainer = modmailContainerOptional.get();
if(!(threadContainer instanceof IThreadContainer)) {
validationResult.setValidationResult(false);
ModMailThreadContainerValidationErrorModel newError = ModMailThreadContainerValidationErrorModel
.builder()
.currentChannelId(threadContainer.getIdLong())
.build();
validationResult.getValidationErrorModels().add(newError);
} else {
validationResult.setValidationResult(true);
}
}
}
} }
} }
@@ -70,6 +105,8 @@ public class ModMailFeatureValidatorBean implements ModMailFeatureValidator {
.currentCategoryId(modMailCategory) .currentCategoryId(modMailCategory)
.build(); .build();
validationResult.getValidationErrorModels().add(newError); validationResult.getValidationErrorModels().add(newError);
} else {
validationResult.setValidationResult(true);
} }
} }
} }

View File

@@ -9,11 +9,16 @@ abstracto.featureFlags.modmail.enabled=false
abstracto.postTargets.modmailLog.name=modmailLog abstracto.postTargets.modmailLog.name=modmailLog
abstracto.postTargets.modmailPing.name=modmailPing abstracto.postTargets.modmailPing.name=modmailPing
abstracto.postTargets.modmailContainer.name=modmailContainer
abstracto.featureModes.log.featureName=modmail abstracto.featureModes.log.featureName=modmail
abstracto.featureModes.log.mode=log abstracto.featureModes.log.mode=log
abstracto.featureModes.log.enabled=true abstracto.featureModes.log.enabled=true
abstracto.featureModes.threadContainer.featureName=modmail
abstracto.featureModes.threadContainer.mode=threadContainer
abstracto.featureModes.threadContainer.enabled=false
abstracto.featureModes.threadMessage.featureName=modmail abstracto.featureModes.threadMessage.featureName=modmail
abstracto.featureModes.threadMessage.mode=threadMessage abstracto.featureModes.threadMessage.mode=threadMessage
abstracto.featureModes.threadMessage.enabled=true abstracto.featureModes.threadMessage.enabled=true

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>modmail</artifactId> <artifactId>modmail</artifactId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -20,6 +20,7 @@ import java.util.List;
@Component @Component
public class ModMailFeatureConfig implements FeatureConfig { public class ModMailFeatureConfig implements FeatureConfig {
public static final String MOD_MAIL_CLOSING_TEXT_SYSTEM_CONFIG_KEY = "modMailClosingText";
@Autowired @Autowired
private ModMailFeatureValidator modMailFeatureValidator; private ModMailFeatureValidator modMailFeatureValidator;
@@ -33,7 +34,7 @@ public class ModMailFeatureConfig implements FeatureConfig {
@Override @Override
public List<PostTargetEnum> getRequiredPostTargets() { public List<PostTargetEnum> getRequiredPostTargets() {
return Arrays.asList(ModMailPostTargets.MOD_MAIL_PING, ModMailPostTargets.MOD_MAIL_LOG); return Arrays.asList(ModMailPostTargets.MOD_MAIL_PING, ModMailPostTargets.MOD_MAIL_LOG, ModMailPostTargets.MOD_MAIL_CONTAINER);
} }
@Override @Override
@@ -48,12 +49,12 @@ public class ModMailFeatureConfig implements FeatureConfig {
@Override @Override
public List<FeatureMode> getAvailableModes() { public List<FeatureMode> getAvailableModes() {
return Arrays.asList(ModMailMode.LOGGING, ModMailMode.SEPARATE_MESSAGE); return Arrays.asList(ModMailMode.LOGGING, ModMailMode.SEPARATE_MESSAGE, ModMailMode.THREAD_CONTAINER);
} }
@Override @Override
public List<String> getRequiredSystemConfigKeys() { public List<String> getRequiredSystemConfigKeys() {
return Arrays.asList("modMailClosingText"); return Arrays.asList(MOD_MAIL_CLOSING_TEXT_SYSTEM_CONFIG_KEY);
} }
@Override @Override

View File

@@ -9,7 +9,7 @@ import lombok.Getter;
*/ */
@Getter @Getter
public enum ModMailMode implements FeatureMode { public enum ModMailMode implements FeatureMode {
LOGGING("log"), SEPARATE_MESSAGE("threadMessage"); LOGGING("log"), SEPARATE_MESSAGE("threadMessage"), THREAD_CONTAINER("threadContainer");
private final String key; private final String key;

View File

@@ -12,7 +12,11 @@ public enum ModMailPostTargets implements PostTargetEnum {
/** /**
* The channel to be used to log the contents of closed mod mail threads * The channel to be used to log the contents of closed mod mail threads
*/ */
MOD_MAIL_LOG("modmailLog"); MOD_MAIL_LOG("modmailLog"),
/**
* The thread used as a container for the modmail threads
*/
MOD_MAIL_CONTAINER("modmailContainer");
private String key; private String key;

View File

@@ -0,0 +1,22 @@
package dev.sheldan.abstracto.modmail.exception;
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
import dev.sheldan.abstracto.core.templating.Templatable;
public class ModMailThreadClosedException extends AbstractoRunTimeException implements Templatable {
public ModMailThreadClosedException() {
super("Mod mail thread closed");
}
@Override
public String getTemplateName() {
return "modmail_thread_closed_exception";
}
@Override
public Object getTemplateModel() {
return new Object();
}
}

View File

@@ -41,4 +41,5 @@ public class ModMailClosingHeaderModel {
private Boolean silently; private Boolean silently;
private User user; private User user;
private Long serverId; private Long serverId;
private Long modmailThreadId;
} }

View File

@@ -8,7 +8,7 @@ import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import lombok.experimental.SuperBuilder; import lombok.experimental.SuperBuilder;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; import net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel;
import java.util.List; import java.util.List;
@@ -33,7 +33,7 @@ public class ModMailNotificationModel extends ServerContext {
*/ */
private List<ModMailRole> roles; private List<ModMailRole> roles;
/** /**
* The {@link TextChannel} in which the mod mail thread is handled * The {@link GuildMessageChannel} in which the mod mail thread is handled
*/ */
private TextChannel channel; private GuildMessageChannel channel;
} }

View File

@@ -0,0 +1,23 @@
package dev.sheldan.abstracto.modmail.model.template;
import dev.sheldan.abstracto.core.models.ValidationErrorModel;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Builder
public class ModMailThreadContainerValidationErrorModel implements ValidationErrorModel {
private Long currentChannelId;
@Override
public String getTemplateName() {
return "feature_setup_modmail_thread_container_not_setup";
}
@Override
public Object getTemplateModel() {
return new Object();
}
}

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>abstracto-modules</artifactId> <artifactId>abstracto-modules</artifactId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>dev.sheldan.abstracto</groupId> <groupId>dev.sheldan.abstracto</groupId>
<artifactId>abstracto-application</artifactId> <artifactId>abstracto-application</artifactId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<artifactId>abstracto-modules</artifactId> <artifactId>abstracto-modules</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<artifactId>profanity-filter</artifactId> <artifactId>profanity-filter</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>profanity-filter</artifactId> <artifactId>profanity-filter</artifactId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<artifactId>abstracto-modules</artifactId> <artifactId>abstracto-modules</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<artifactId>remind</artifactId> <artifactId>remind</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<artifactId>remind</artifactId> <artifactId>remind</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<artifactId>abstracto-modules</artifactId> <artifactId>abstracto-modules</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<artifactId>repost-detection</artifactId> <artifactId>repost-detection</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<artifactId>repost-detection</artifactId> <artifactId>repost-detection</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<artifactId>abstracto-modules</artifactId> <artifactId>abstracto-modules</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<artifactId>starboard</artifactId> <artifactId>starboard</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<artifactId>starboard</artifactId> <artifactId>starboard</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>abstracto-modules</artifactId> <artifactId>abstracto-modules</artifactId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>statistic</artifactId> <artifactId>statistic</artifactId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>statistic</artifactId> <artifactId>statistic</artifactId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<artifactId>abstracto-modules</artifactId> <artifactId>abstracto-modules</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<artifactId>suggestion</artifactId> <artifactId>suggestion</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<artifactId>suggestion</artifactId> <artifactId>suggestion</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<artifactId>abstracto-modules</artifactId> <artifactId>abstracto-modules</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<artifactId>twitch</artifactId> <artifactId>twitch</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -314,7 +314,8 @@ public class StreamerServiceBean implements StreamerService {
} }
log.info("Streamer {} went offline.", streamerId); log.info("Streamer {} went offline.", streamerId);
if (deleteFlagValues.computeIfAbsent(streamer.getServer().getId(), if (deleteFlagValues.computeIfAbsent(streamer.getServer().getId(),
aLong -> featureModeService.featureModeActive(TwitchFeatureDefinition.TWITCH, aLong, TwitchFeatureMode.DELETE_NOTIFICATION))) { aLong -> featureModeService.featureModeActive(TwitchFeatureDefinition.TWITCH, aLong, TwitchFeatureMode.DELETE_NOTIFICATION))
&& streamer.getCurrentSession() != null) {
Long channelId = streamer.getCurrentSession().getChannel().getId(); Long channelId = streamer.getCurrentSession().getChannel().getId();
Long messageId = streamer.getCurrentSession().getId(); Long messageId = streamer.getCurrentSession().getId();
messageService.deleteMessageInChannelInServer(streamer.getServer().getId(), channelId, messageId).thenAccept(unused -> { messageService.deleteMessageInChannelInServer(streamer.getServer().getId(), channelId, messageId).thenAccept(unused -> {
@@ -400,23 +401,37 @@ public class StreamerServiceBean implements StreamerService {
} }
streamer.setCurrentGameId(stream.getGameId()); streamer.setCurrentGameId(stream.getGameId());
} }
return; } else if(currentSession == null &&
} !postTargetService.postTargetUsableInServer(TwitchPostTarget.TWITCH_LIVE_NOTIFICATION, server.getId())) {
CompletableFutureList<Message> messages = notifyAboutOnlineStream(stream, streamer, streamerUser); // this is the case in which the streamer is online, and we should in theory notify about the online status
messages.getMainFuture() // _but_ the difference is that there is no current session on going - as the sessions in our database are
.thenAccept(unused -> { // bound to actual notifications sent, and this is the case in which the post target has been disabled.
Message message = messages.getFutures().get(0).join(); // In this case we only update current game if necessary
if(message != null) { // this only really serves as a shortcut to not evaluate and create a full MessageToSend object
// just to not actually send it
if(streamer.getCurrentGameId() == null || !streamer.getCurrentGameId().equals(stream.getGameId())) {
log.info("Game for streamer {} has changed - updating game.", streamerId);
streamer.setCurrentGameId(stream.getGameId());
}
streamer.setOnline(true);
streamerManagementService.saveStreamer(streamer);
} else {
CompletableFutureList<Message> messages = notifyAboutOnlineStream(stream, streamer, streamerUser);
messages.getMainFuture()
.thenAccept(unused -> {
Message message = messages.getFutures().get(0).join();
try { try {
self.storeStreamNotificationMessage(message, streamerId, stream); if(message != null) {
self.storeStreamNotificationMessage(message, streamerId, stream);
}
} catch (Exception exception) { } catch (Exception exception) {
log.error("Failed to store stream notification message of streamer {}.", streamerId, exception); log.error("Failed to update streamer {} in database.", streamerId, exception);
} }
} }).exceptionally(throwable -> {
}).exceptionally(throwable -> { log.error("Failed to notify about online stream of streamer {}.", streamerId, throwable);
log.error("Failed to notify about online stream of streamer {}.", streamerId, throwable); return null;
return null; });
}); }
} }
@Transactional @Transactional

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>twitch</artifactId> <artifactId>twitch</artifactId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>abstracto-modules</artifactId> <artifactId>abstracto-modules</artifactId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent> <parent>
<groupId>dev.sheldan.abstracto.modules</groupId> <groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>utility</artifactId> <artifactId>utility</artifactId>
<version>1.5.15</version> <version>1.5.23-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

Some files were not shown because too many files have changed in this diff Show More