Compare commits

...

14 Commits

Author SHA1 Message Date
Sheldan
aea3572fb5 [maven-release-plugin] prepare release abstracto-application-1.2.8 2021-04-11 00:12:01 +02:00
Sheldan
b578b0eb6d [AB-xxx] fixing reminders test 2021-04-10 23:57:12 +02:00
Sheldan
7a9aa32332 [AB-xxx] adding reminder display to reminders command to add a link to the existing reminder 2021-04-10 23:39:36 +02:00
Sheldan
8fea80328d [AB-59] adding command received handler test and fixed some scenarios 2021-04-10 22:29:11 +02:00
Sheldan
446a830514 [AB-xxx] adding alternative interface for creating reminders
fixing reminder IDs not being strings for the quartz job
fixing number handling for very large durations
2021-04-10 00:30:58 +02:00
Sheldan
15d2eb8bd9 [AB-229] exposing gateway ping for metrics 2021-04-08 00:37:49 +02:00
Sheldan
e2c86b98b6 [AB-222] adding uptime command
changed necessary intents
2021-04-08 00:07:31 +02:00
Sheldan
400181a280 [AB-225] adding parameter handler for messages
reworking parameter handling in command received handler
adding string parameter handler to explicitly parse strings
2021-04-07 23:16:25 +02:00
Sheldan
c56a037d28 [AB-226] adding caching of referenced messages (only one element on the chain) 2021-04-06 23:38:45 +02:00
Sheldan
dd97503238 [AB-172] updating to JDA 4.2.1_254 and removing deprecated code from guava 2021-04-06 21:11:36 +02:00
Sheldan
e7b1fbe9d1 [AB-209] adding cleanup job for old embedded messages, this job deletes the entries from the database and removes reactions
reducing thread count for listener executor and scheduling
fixing channel deletion listener not being part of a transaction
2021-04-06 20:23:26 +02:00
Sheldan
61d16d5985 [AB-224] fixing not properly ignoring ignored starboard posts leading to re-creation of them 2021-04-06 03:43:24 +02:00
Sheldan
1d3a85ff01 [AB-221] fixing creation of template for deleted users 2021-04-05 14:24:09 +02:00
Sheldan
09c7daf3e0 [maven-release-plugin] prepare for next development iteration 2021-04-05 01:48:20 +02:00
158 changed files with 1743 additions and 245 deletions

View File

@@ -14,7 +14,7 @@ An example implementation of this bot can be seen [here](https://github.com/Shel
## Technologies ## Technologies
* [JDA](https://github.com/DV8FromTheWorld/JDA/) The Discord API Wrapper in the version 4.1.1_167 * [JDA](https://github.com/DV8FromTheWorld/JDA/) The Discord API Wrapper in the version 4.2.1_254
* [Spring boot](https://github.com/spring-projects/spring-boot) is used as a framework to create standalone application in Java with Java EE methods. (including Dependency injection and more) * [Spring boot](https://github.com/spring-projects/spring-boot) is used as a framework to create standalone application in Java with Java EE methods. (including Dependency injection and more)
* [Hibernate](https://github.com/hibernate/hibernate-orm) is used as a reference implementation of JPA. * [Hibernate](https://github.com/hibernate/hibernate-orm) is used as a reference implementation of JPA.
* [Freemarker](https://github.com/apache/freemarker) is used as a templating engine. This is used to provide internationalization for user facing text and enable dynamic embed configuration. * [Freemarker](https://github.com/apache/freemarker) is used as a templating engine. This is used to provide internationalization for user facing text and enable dynamic embed configuration.

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.2.7</version> <version>1.2.8</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.2.7</version> <version>1.2.8</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.2.7</version> <version>1.2.8</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.2.7</version> <version>1.2.8</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -43,7 +43,7 @@ public class LoveCalc extends AbstractConditionableCommand {
model.setFirstPart(firstPart); model.setFirstPart(firstPart);
model.setSecondPart(secondPart); model.setSecondPart(secondPart);
return FutureUtils.toSingleFutureGeneric(channelService.sendEmbedTemplateInTextChannelList(LOVE_CALC_RESPONSE_TEMPLATE_KEY, model, commandContext.getChannel())) return FutureUtils.toSingleFutureGeneric(channelService.sendEmbedTemplateInTextChannelList(LOVE_CALC_RESPONSE_TEMPLATE_KEY, model, commandContext.getChannel()))
.thenApply(unused -> CommandResult.fromIgnored()); .thenApply(unused -> CommandResult.fromSuccess());
} }
@Override @Override
@@ -58,7 +58,6 @@ public class LoveCalc extends AbstractConditionableCommand {
.module(EntertainmentModuleDefinition.ENTERTAINMENT) .module(EntertainmentModuleDefinition.ENTERTAINMENT)
.templated(true) .templated(true)
.supportsEmbedException(true) .supportsEmbedException(true)
.causesReaction(true)
.parameters(parameters) .parameters(parameters)
.help(helpInfo) .help(helpInfo)
.build(); .build();

View File

@@ -0,0 +1,81 @@
package dev.sheldan.abstracto.entertainment.command;
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.command.execution.ContextConverter;
import dev.sheldan.abstracto.core.command.handler.parameter.CombinedParameter;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.service.ChannelService;
import dev.sheldan.abstracto.core.utils.FutureUtils;
import dev.sheldan.abstracto.entertainment.config.EntertainmentFeatureDefinition;
import dev.sheldan.abstracto.entertainment.config.EntertainmentModuleDefinition;
import dev.sheldan.abstracto.entertainment.model.MockResponseModel;
import dev.sheldan.abstracto.entertainment.service.EntertainmentService;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import static dev.sheldan.abstracto.core.command.config.Parameter.ADDITIONAL_TYPES_KEY;
@Component
public class Mock extends AbstractConditionableCommand {
public static final String MOCK_RESPONSE_TEMPLATE_KEY = "mock_response";
@Autowired
private EntertainmentService entertainmentService;
@Autowired
private ChannelService channelService;
@Override
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
Object givenParameter = commandContext.getParameters().getParameters().get(0);
String messageText;
Member mockedMember = null;
if(givenParameter instanceof Message) {
Message originalMessage = (Message) givenParameter;
messageText = originalMessage.getContentRaw();
mockedMember = originalMessage.getMember();
} else {
messageText = givenParameter.toString();
}
String mockingText = entertainmentService.createMockText(messageText, commandContext.getAuthor(), mockedMember);
MockResponseModel model = (MockResponseModel) ContextConverter.slimFromCommandContext(commandContext, MockResponseModel.class);
model.setOriginalText(messageText);
model.setMockingText(mockingText);
return FutureUtils.toSingleFutureGeneric(channelService.sendEmbedTemplateInTextChannelList(MOCK_RESPONSE_TEMPLATE_KEY, model, commandContext.getChannel()))
.thenApply(unused -> CommandResult.fromSuccess());
}
@Override
public CommandConfiguration getConfiguration() {
List<Parameter> parameters = new ArrayList<>();
Map<String, Object> parameterAlternatives = new HashMap<>();
parameterAlternatives.put(ADDITIONAL_TYPES_KEY, Arrays.asList(Message.class, String.class));
parameters.add(Parameter.builder().name("message").type(CombinedParameter.class).remainder(true)
.additionalInfo(parameterAlternatives).templated(true).build());
HelpInfo helpInfo = HelpInfo.builder().templated(true).build();
return CommandConfiguration.builder()
.name("mock")
.module(EntertainmentModuleDefinition.ENTERTAINMENT)
.templated(true)
.async(true)
.supportsEmbedException(true)
.parameters(parameters)
.help(helpInfo)
.build();
}
@Override
public FeatureDefinition getFeature() {
return EntertainmentFeatureDefinition.ENTERTAINMENT;
}
}

View File

@@ -54,4 +54,19 @@ public class EntertainmentServiceBean implements EntertainmentService {
public String takeChoice(List<String> choices, Member memberExecuting) { public String takeChoice(List<String> choices, Member memberExecuting) {
return choices.get(secureRandom.nextInt(choices.size())); return choices.get(secureRandom.nextInt(choices.size()));
} }
@Override
public String createMockText(String text, Member memberExecuting, Member mockedUser) {
char[] textChars = text.toLowerCase().toCharArray();
StringBuilder sb = new StringBuilder();
for (int i = 0, textCharsLength = textChars.length; i < textCharsLength; i++) {
char character = textChars[i];
if(i % 2 == 0) {
sb.append(Character.toUpperCase(character));
} else {
sb.append(character);
}
}
return sb.toString();
}
} }

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-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../dbchangelog-3.8.xsd" >
<include file="entertainment-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-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
<property name="entertainmentModule" value="(SELECT id FROM module WHERE name = 'entertainment')"/>
<property name="entertainmentFeature" value="(SELECT id FROM feature WHERE key = 'entertainment')"/>
<changeSet author="Sheldan" id="mock-command">
<insert tableName="command">
<column name="name" value="mock"/>
<column name="module_id" valueComputed="${entertainmentModule}"/>
<column name="feature_id" valueComputed="${entertainmentFeature}"/>
</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-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
<include file="command.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

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

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.2.7</version> <version>1.2.8</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -0,0 +1,14 @@
package dev.sheldan.abstracto.entertainment.model;
import dev.sheldan.abstracto.core.models.context.SlimUserInitiatedServerContext;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.SuperBuilder;
@Getter
@Setter
@SuperBuilder
public class MockResponseModel extends SlimUserInitiatedServerContext {
private String originalText;
private String mockingText;
}

View File

@@ -10,4 +10,5 @@ public interface EntertainmentService {
Integer calculateRollResult(Integer low, Integer high); Integer calculateRollResult(Integer low, Integer high);
boolean executeRoulette(Member memberExecuting); boolean executeRoulette(Member memberExecuting);
String takeChoice(List<String> choices, Member memberExecuting); String takeChoice(List<String> choices, Member memberExecuting);
String createMockText(String text, Member memberExecuting, Member mockedUser);
} }

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.2.7</version> <version>1.2.8</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.2.7</version> <version>1.2.8</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.2.7</version> <version>1.2.8</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.2.7</version> <version>1.2.8</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.2.7</version> <version>1.2.8</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@@ -38,6 +38,12 @@
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </dependency>
<dependency>
<groupId>dev.sheldan.abstracto.scheduling</groupId>
<artifactId>scheduling-int</artifactId>
<version>${project.version}</version>
</dependency>
<dependency> <dependency>
<groupId>dev.sheldan.abstracto.core</groupId> <groupId>dev.sheldan.abstracto.core</groupId>
<artifactId>metrics-int</artifactId> <artifactId>metrics-int</artifactId>

View File

@@ -0,0 +1,31 @@
package dev.sheldan.abstracto.linkembed.job;
import dev.sheldan.abstracto.linkembed.service.MessageEmbedService;
import lombok.extern.slf4j.Slf4j;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.PersistJobDataAfterExecution;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.stereotype.Component;
@Slf4j
@DisallowConcurrentExecution
@Component
@PersistJobDataAfterExecution
public class LinkEmbedCleanupJob extends QuartzJobBean {
@Autowired
private MessageEmbedService messageEmbedService;
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
try {
log.info("Executing link embed clean up job.");
messageEmbedService.cleanUpOldMessageEmbeds();
} catch (Exception exception) {
log.error("Link embed cleanup job failed.", exception);
}
}
}

View File

@@ -4,7 +4,12 @@ package dev.sheldan.abstracto.linkembed.repository;
import dev.sheldan.abstracto.linkembed.model.database.EmbeddedMessage; import dev.sheldan.abstracto.linkembed.model.database.EmbeddedMessage;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import java.time.Instant;
import java.util.List;
public interface EmbeddedMessageRepository extends JpaRepository<EmbeddedMessage, Long> { public interface EmbeddedMessageRepository extends JpaRepository<EmbeddedMessage, Long> {
EmbeddedMessage findByEmbeddingMessageId(Long messageId); EmbeddedMessage findByEmbeddingMessageId(Long messageId);
List<EmbeddedMessage> findByCreatedLessThan(Instant date);
void deleteByEmbeddingMessageIdIn(List<Long> embeddedMessageId);
} }

View File

@@ -1,5 +1,6 @@
package dev.sheldan.abstracto.linkembed.service; package dev.sheldan.abstracto.linkembed.service;
import dev.sheldan.abstracto.core.models.ServerChannelMessage;
import dev.sheldan.abstracto.core.models.cache.CachedMessage; import dev.sheldan.abstracto.core.models.cache.CachedMessage;
import dev.sheldan.abstracto.core.models.database.AUserInAServer; import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.models.template.listener.MessageEmbeddedModel; import dev.sheldan.abstracto.core.models.template.listener.MessageEmbeddedModel;
@@ -9,22 +10,31 @@ import dev.sheldan.abstracto.core.service.management.ServerManagementService;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService; import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
import dev.sheldan.abstracto.core.templating.model.MessageToSend; import dev.sheldan.abstracto.core.templating.model.MessageToSend;
import dev.sheldan.abstracto.core.templating.service.TemplateService; import dev.sheldan.abstracto.core.templating.service.TemplateService;
import dev.sheldan.abstracto.core.utils.CompletableFutureList;
import dev.sheldan.abstracto.core.utils.FutureUtils;
import dev.sheldan.abstracto.linkembed.model.MessageEmbedLink; import dev.sheldan.abstracto.linkembed.model.MessageEmbedLink;
import dev.sheldan.abstracto.linkembed.model.database.EmbeddedMessage;
import dev.sheldan.abstracto.linkembed.service.management.MessageEmbedPostManagementService; import dev.sheldan.abstracto.linkembed.service.management.MessageEmbedPostManagementService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.TextChannel; import net.dv8tion.jda.api.entities.TextChannel;
import net.dv8tion.jda.api.entities.User; import net.dv8tion.jda.api.entities.User;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.stream.Collectors;
@Component @Component
@Slf4j @Slf4j
@@ -68,6 +78,15 @@ public class MessageEmbedServiceBean implements MessageEmbedService {
@Autowired @Autowired
private ReactionService reactionService; private ReactionService reactionService;
@Autowired
private MessageService messageService;
@Autowired
private EmoteService emoteService;
@Value("${abstracto.feature.linkEmbed.removalDays}")
private Long embedRemovalDays;
@Override @Override
public List<MessageEmbedLink> getLinksInMessage(String message) { public List<MessageEmbedLink> getLinksInMessage(String message) {
List<MessageEmbedLink> links = new ArrayList<>(); List<MessageEmbedLink> links = new ArrayList<>();
@@ -97,7 +116,6 @@ public class MessageEmbedServiceBean implements MessageEmbedService {
linksToEmbed.forEach(messageEmbedLink -> linksToEmbed.forEach(messageEmbedLink ->
messageCache.getMessageFromCache(messageEmbedLink.getServerId(), messageEmbedLink.getChannelId(), messageEmbedLink.getMessageId()) messageCache.getMessageFromCache(messageEmbedLink.getServerId(), messageEmbedLink.getChannelId(), messageEmbedLink.getMessageId())
.thenAccept(cachedMessage -> self.embedLink(cachedMessage, target, userEmbeddingUserInServerId, embeddingMessage) .thenAccept(cachedMessage -> self.embedLink(cachedMessage, target, userEmbeddingUserInServerId, embeddingMessage)
).exceptionally(throwable -> { ).exceptionally(throwable -> {
log.error("Message embedding from cache failed for message {}.", messageEmbedLink.getMessageId(), throwable); log.error("Message embedding from cache failed for message {}.", messageEmbedLink.getMessageId(), throwable);
return null; return null;
@@ -113,6 +131,60 @@ public class MessageEmbedServiceBean implements MessageEmbedService {
); );
} }
@Override
public CompletableFuture<Void> cleanUpOldMessageEmbeds() {
Instant oldestDate = Instant.now().truncatedTo(ChronoUnit.DAYS).minus(embedRemovalDays, ChronoUnit.DAYS);
List<EmbeddedMessage> embeddedMessages = messageEmbedPostManagementService.getEmbeddedMessagesOlderThan(oldestDate);
if(embeddedMessages.isEmpty()) {
log.info("No embedded messages to clean up.");
return CompletableFuture.completedFuture(null);
}
log.info("Cleaning up {} embedded embeddedMessages", embeddedMessages.size());
List<ServerChannelMessage> serverChannelMessages = embeddedMessages.stream().map(embeddedMessage ->
ServerChannelMessage
.builder()
.serverId(embeddedMessage.getEmbeddedServer().getId())
.channelId(embeddedMessage.getEmbeddedChannel().getId())
.messageId(embeddedMessage.getEmbeddingMessageId())
.build()
)
.collect(Collectors.toList());
List<Long> embeddedMessagesHandled = embeddedMessages
.stream()
.map(EmbeddedMessage::getEmbeddingMessageId)
.collect(Collectors.toList());
List<CompletableFuture<Message>> messageFutures = messageService.retrieveMessages(serverChannelMessages);
CompletableFutureList<Message> future = new CompletableFutureList<>(messageFutures);
return future.getMainFuture()
.handle((unused, throwable) -> self.removeReactions(future.getObjects()))
.thenCompose(Function.identity())
// deleting the messages from db regardless of exceptions, at most the reaction remains
.whenComplete((unused, throwable) -> self.deleteEmbeddedMessages(embeddedMessagesHandled))
.exceptionally(throwable -> {
log.error("Failed to clean up embedded messages.", throwable);
return null;
});
}
@Transactional
public CompletableFuture<Void> removeReactions(List<Message> allMessages) {
List<CompletableFuture<Void>> removalFutures = new ArrayList<>();
Map<Long, List<Message>> groupedPerServer = allMessages
.stream()
.collect(Collectors.groupingBy(message -> message.getGuild().getIdLong()));
groupedPerServer.forEach((serverId, serverMessages) -> {
// we assume the emote remained the same
CompletableFutureList<Void> removalFuture = reactionService.removeReactionFromMessagesWithFutureWithFutureList(serverMessages, REMOVAL_EMOTE);
removalFutures.add(removalFuture.getMainFuture());
});
return FutureUtils.toSingleFutureGeneric(removalFutures);
}
@Transactional
public void deleteEmbeddedMessages(List<Long> embeddedMessagesToDelete) {
messageEmbedPostManagementService.deleteEmbeddedMessagesViaId(embeddedMessagesToDelete);
}
@Transactional @Transactional
public CompletableFuture<Void> sendEmbeddingMessage(CachedMessage cachedMessage, TextChannel target, Long userEmbeddingUserInServerId, MessageEmbeddedModel messageEmbeddedModel) { public CompletableFuture<Void> sendEmbeddingMessage(CachedMessage cachedMessage, TextChannel target, Long userEmbeddingUserInServerId, MessageEmbeddedModel messageEmbeddedModel) {
MessageToSend embed = templateService.renderEmbedTemplate(MESSAGE_EMBED_TEMPLATE, messageEmbeddedModel, target.getGuild().getIdLong()); MessageToSend embed = templateService.renderEmbedTemplate(MESSAGE_EMBED_TEMPLATE, messageEmbeddedModel, target.getGuild().getIdLong());
@@ -139,8 +211,7 @@ public class MessageEmbedServiceBean implements MessageEmbedService {
self.loadMessageEmbedModel(message, embeddedMessage, authorUser) self.loadMessageEmbedModel(message, embeddedMessage, authorUser)
).exceptionally(throwable -> { ).exceptionally(throwable -> {
log.warn("Failed to retrieve author for user {}.", embeddedMessage.getAuthor().getAuthorId(), throwable); log.warn("Failed to retrieve author for user {}.", embeddedMessage.getAuthor().getAuthorId(), throwable);
self.loadMessageEmbedModel(message, embeddedMessage, null); return self.loadMessageEmbedModel(message, embeddedMessage, null);
return null;
}); });
} }

View File

@@ -16,6 +16,8 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.time.Instant;
import java.util.List;
import java.util.Optional; import java.util.Optional;
@Component @Component
@@ -76,4 +78,15 @@ public class MessageEmbedPostManagementServiceBean implements MessageEmbedPostMa
embeddedMessageRepository.delete(embeddedMessage); embeddedMessageRepository.delete(embeddedMessage);
} }
@Override
public List<EmbeddedMessage> getEmbeddedMessagesOlderThan(Instant date) {
return embeddedMessageRepository.findByCreatedLessThan(date);
}
@Override
public void deleteEmbeddedMessagesViaId(List<Long> embeddingMessageId) {
log.info("Deleting {} embedded messages from db.", embeddingMessageId.size());
embeddedMessageRepository.deleteByEmbeddingMessageIdIn(embeddingMessageId);
}
} }

View File

@@ -1,2 +1,5 @@
abstracto.featureFlags.linkEmbeds.featureName=linkEmbeds abstracto.featureFlags.linkEmbeds.featureName=linkEmbeds
abstracto.featureFlags.linkEmbeds.enabled=false abstracto.featureFlags.linkEmbeds.enabled=false
abstracto.feature.linkEmbed.removalDays=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-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../dbchangelog-3.8.xsd" >
<include file="link-embed-seedData/data.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-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
<include file="linkEmbedCleanupJob.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -0,0 +1,19 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext ../../dbchangelog-3.8.xsd
http://www.liquibase.org/xml/ns/pro ../../dbchangelog-3.8.xsd" >
<changeSet author="Sheldan" id="linkEmbed-cleanup-insert">
<insert tableName="scheduler_job">
<column name="name" value="linkEmbedCleanupJob"/>
<column name="group_name" value="linkEmbed"/>
<column name="clazz" value="dev.sheldan.abstracto.linkembed.job.LinkEmbedCleanupJob"/>
<column name="active" value="true"/>
<column name="cron_expression" value="0 0 0 * * ?"/>
<column name="recovery" value="false"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

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

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.2.7</version> <version>1.2.8</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -12,4 +12,5 @@ public interface MessageEmbedService {
List<MessageEmbedLink> getLinksInMessage(String message); List<MessageEmbedLink> getLinksInMessage(String message);
void embedLinks(List<MessageEmbedLink> linksToEmbed, TextChannel target, Long userEmbeddingUserInServerId, Message embeddingMessage); void embedLinks(List<MessageEmbedLink> linksToEmbed, TextChannel target, Long userEmbeddingUserInServerId, Message embeddingMessage);
CompletableFuture<Void> embedLink(CachedMessage cachedMessage, TextChannel target, Long userEmbeddingUserInServerId, Message embeddingMessage); CompletableFuture<Void> embedLink(CachedMessage cachedMessage, TextChannel target, Long userEmbeddingUserInServerId, Message embeddingMessage);
CompletableFuture<Void> cleanUpOldMessageEmbeds();
} }

View File

@@ -5,10 +5,14 @@ import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.linkembed.model.database.EmbeddedMessage; import dev.sheldan.abstracto.linkembed.model.database.EmbeddedMessage;
import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.entities.Message;
import java.time.Instant;
import java.util.List;
import java.util.Optional; import java.util.Optional;
public interface MessageEmbedPostManagementService { public interface MessageEmbedPostManagementService {
void createMessageEmbed(CachedMessage embeddedMessage, Message messageContainingEmbed, AUserInAServer cause); void createMessageEmbed(CachedMessage embeddedMessage, Message messageContainingEmbed, AUserInAServer cause);
Optional<EmbeddedMessage> findEmbeddedPostByMessageId(Long messageId); Optional<EmbeddedMessage> findEmbeddedPostByMessageId(Long messageId);
void deleteEmbeddedMessage(EmbeddedMessage embeddedMessage); void deleteEmbeddedMessage(EmbeddedMessage embeddedMessage);
List<EmbeddedMessage> getEmbeddedMessagesOlderThan(Instant date);
void deleteEmbeddedMessagesViaId(List<Long> embeddingMessageId);
} }

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.2.7</version> <version>1.2.8</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.2.7</version> <version>1.2.8</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.2.7</version> <version>1.2.8</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.2.7</version> <version>1.2.8</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.2.7</version> <version>1.2.8</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.2.7</version> <version>1.2.8</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.2.7</version> <version>1.2.8</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.2.7</version> <version>1.2.8</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.2.7</version> <version>1.2.8</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.2.7</version> <version>1.2.8</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -8,12 +8,14 @@ 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.command.execution.ContextConverter; import dev.sheldan.abstracto.core.command.execution.ContextConverter;
import dev.sheldan.abstracto.core.config.FeatureDefinition; import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.models.ServerChannelMessage;
import dev.sheldan.abstracto.core.models.database.AUserInAServer; import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.service.ChannelService; import dev.sheldan.abstracto.core.service.ChannelService;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService; import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
import dev.sheldan.abstracto.core.utils.FutureUtils; import dev.sheldan.abstracto.core.utils.FutureUtils;
import dev.sheldan.abstracto.remind.config.RemindFeatureDefinition; import dev.sheldan.abstracto.remind.config.RemindFeatureDefinition;
import dev.sheldan.abstracto.remind.model.database.Reminder; import dev.sheldan.abstracto.remind.model.database.Reminder;
import dev.sheldan.abstracto.remind.model.template.commands.ReminderDisplay;
import dev.sheldan.abstracto.remind.model.template.commands.RemindersModel; import dev.sheldan.abstracto.remind.model.template.commands.RemindersModel;
import dev.sheldan.abstracto.remind.service.management.ReminderManagementService; import dev.sheldan.abstracto.remind.service.management.ReminderManagementService;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -42,7 +44,20 @@ public class Reminders extends AbstractConditionableCommand {
AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(commandContext.getAuthor()); AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(commandContext.getAuthor());
List<Reminder> activeReminders = reminderManagementService.getActiveRemindersForUser(aUserInAServer); List<Reminder> activeReminders = reminderManagementService.getActiveRemindersForUser(aUserInAServer);
RemindersModel model = (RemindersModel) ContextConverter.fromCommandContext(commandContext, RemindersModel.class); RemindersModel model = (RemindersModel) ContextConverter.fromCommandContext(commandContext, RemindersModel.class);
model.setReminders(activeReminders); activeReminders.forEach(reminder -> {
ServerChannelMessage originMessage = ServerChannelMessage
.builder()
.messageId(reminder.getMessageId())
.channelId(reminder.getChannel().getId())
.serverId(commandContext.getGuild().getIdLong())
.build();
ReminderDisplay display = ReminderDisplay
.builder()
.reminder(reminder)
.message(originMessage)
.build();
model.getReminders().add(display);
});
log.info("Showing {} reminders for user {} in server {}.", activeReminders.size(), commandContext.getAuthor().getId(), commandContext.getGuild().getId()); log.info("Showing {} reminders for user {} in server {}.", activeReminders.size(), commandContext.getAuthor().getId(), commandContext.getGuild().getId());
return FutureUtils.toSingleFutureGeneric(channelService.sendEmbedTemplateInTextChannelList(REMINDERS_RESPONSE_TEMPLATE, model, commandContext.getChannel())) return FutureUtils.toSingleFutureGeneric(channelService.sendEmbedTemplateInTextChannelList(REMINDERS_RESPONSE_TEMPLATE, model, commandContext.getChannel()))
.thenApply(aVoid -> CommandResult.fromIgnored()); .thenApply(aVoid -> CommandResult.fromIgnored());

View File

@@ -27,7 +27,7 @@ public class ReminderJob extends QuartzJobBean {
log.info("Executing reminder job for reminder {}", reminderId); log.info("Executing reminder job for reminder {}", reminderId);
reminderService.executeReminder(reminderId); reminderService.executeReminder(reminderId);
} catch (Exception e) { } catch (Exception e) {
log.error("Reminder job failed to execute.", e); log.error("Reminder job failed.", e);
} }
} }

View File

@@ -72,7 +72,12 @@ public class RemindServiceBean implements ReminderService {
@Override @Override
public Reminder createReminderInForUser(AUserInAServer user, String remindText, Duration remindIn, Message message) { public Reminder createReminderInForUser(AUserInAServer user, String remindText, Duration remindIn, Message message) {
AChannel channel = channelManagementService.loadChannel(message.getChannel().getIdLong()); return createReminderInForUser(user, remindText, remindIn, message.getChannel().getIdLong(), message.getIdLong());
}
@Override
public Reminder createReminderInForUser(AUserInAServer user, String remindText, Duration remindIn, Long channelId, Long messageId) {
AChannel channel = channelManagementService.loadChannel(channelId);
AServerAChannelAUser aServerAChannelAUser = AServerAChannelAUser AServerAChannelAUser aServerAChannelAUser = AServerAChannelAUser
.builder() .builder()
.user(user.getUserReference()) .user(user.getUserReference())
@@ -80,8 +85,8 @@ public class RemindServiceBean implements ReminderService {
.guild(user.getServerReference()) .guild(user.getServerReference())
.channel(channel) .channel(channel)
.build(); .build();
Instant remindAt = Instant.now().plusNanos(remindIn.toNanos()); Instant remindAt = Instant.now().plusMillis(remindIn.toMillis());
Reminder reminder = reminderManagementService.createReminder(aServerAChannelAUser, remindText, remindAt, message.getIdLong()); Reminder reminder = reminderManagementService.createReminder(aServerAChannelAUser, remindText, remindAt, messageId);
log.info("Creating reminder for user {} in guild {} due at {}.", log.info("Creating reminder for user {} in guild {} due at {}.",
user.getUserReference().getId(), user.getServerReference().getId(), remindAt); user.getUserReference().getId(), user.getServerReference().getId(), remindAt);
@@ -96,7 +101,7 @@ public class RemindServiceBean implements ReminderService {
}, remindIn.toNanos(), TimeUnit.NANOSECONDS); }, remindIn.toNanos(), TimeUnit.NANOSECONDS);
} else { } else {
HashMap<Object, Object> parameters = new HashMap<>(); HashMap<Object, Object> parameters = new HashMap<>();
parameters.put("reminderId", reminder.getId()); parameters.put("reminderId", reminder.getId().toString());
JobParameters jobParameters = JobParameters.builder().parameters(parameters).build(); JobParameters jobParameters = JobParameters.builder().parameters(parameters).build();
String triggerKey = schedulerService.executeJobWithParametersOnce("reminderJob", "utility", jobParameters, Date.from(reminder.getTargetDate())); String triggerKey = schedulerService.executeJobWithParametersOnce("reminderJob", "utility", jobParameters, Date.from(reminder.getTargetDate()));
log.info("Starting scheduled job with trigger {} to execute reminder. {}", triggerKey, reminder.getId()); log.info("Starting scheduled job with trigger {} to execute reminder. {}", triggerKey, reminder.getId());

View File

@@ -2,6 +2,8 @@ package dev.sheldan.abstracto.remind.command;
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.models.database.AChannel;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.models.database.AUserInAServer; import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.service.ChannelService; import dev.sheldan.abstracto.core.service.ChannelService;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService; import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
@@ -37,6 +39,9 @@ public class RemindersTest {
@Mock @Mock
private UserInServerManagementService userInServerManagementService; private UserInServerManagementService userInServerManagementService;
@Mock
private AChannel channel;
@Captor @Captor
private ArgumentCaptor<RemindersModel> modelCaptor; private ArgumentCaptor<RemindersModel> modelCaptor;
@@ -44,7 +49,9 @@ public class RemindersTest {
public void testExecuteCommand() { public void testExecuteCommand() {
CommandContext context = CommandTestUtilities.getNoParameters(); CommandContext context = CommandTestUtilities.getNoParameters();
Reminder reminder = Mockito.mock(Reminder.class); Reminder reminder = Mockito.mock(Reminder.class);
when(reminder.getChannel()).thenReturn(channel);
Reminder secondReminder = Mockito.mock(Reminder.class); Reminder secondReminder = Mockito.mock(Reminder.class);
when(secondReminder.getChannel()).thenReturn(channel);
List<Reminder> reminders = Arrays.asList(reminder, secondReminder); List<Reminder> reminders = Arrays.asList(reminder, secondReminder);
AUserInAServer user = Mockito.mock(AUserInAServer.class); AUserInAServer user = Mockito.mock(AUserInAServer.class);
when(userInServerManagementService.loadOrCreateUser(context.getAuthor())).thenReturn(user); when(userInServerManagementService.loadOrCreateUser(context.getAuthor())).thenReturn(user);
@@ -52,8 +59,8 @@ public class RemindersTest {
CompletableFuture<CommandResult> result = testUnit.executeAsync(context); CompletableFuture<CommandResult> result = testUnit.executeAsync(context);
verify(channelService, times(1)).sendEmbedTemplateInTextChannelList(eq(Reminders.REMINDERS_RESPONSE_TEMPLATE), modelCaptor.capture(), eq(context.getChannel())); verify(channelService, times(1)).sendEmbedTemplateInTextChannelList(eq(Reminders.REMINDERS_RESPONSE_TEMPLATE), modelCaptor.capture(), eq(context.getChannel()));
RemindersModel usedModel = modelCaptor.getValue(); RemindersModel usedModel = modelCaptor.getValue();
Assert.assertEquals(reminder, usedModel.getReminders().get(0)); Assert.assertEquals(reminder, usedModel.getReminders().get(0).getReminder());
Assert.assertEquals(secondReminder, usedModel.getReminders().get(1)); Assert.assertEquals(secondReminder, usedModel.getReminders().get(1).getReminder());
Assert.assertEquals(reminders.size(), usedModel.getReminders().size()); Assert.assertEquals(reminders.size(), usedModel.getReminders().size());
CommandTestUtilities.checkSuccessfulCompletionAsync(result); CommandTestUtilities.checkSuccessfulCompletionAsync(result);
} }

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.2.7</version> <version>1.2.8</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -0,0 +1,15 @@
package dev.sheldan.abstracto.remind.model.template.commands;
import dev.sheldan.abstracto.core.models.ServerChannelMessage;
import dev.sheldan.abstracto.remind.model.database.Reminder;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@Builder
public class ReminderDisplay {
private Reminder reminder;
private ServerChannelMessage message;
}

View File

@@ -1,16 +1,18 @@
package dev.sheldan.abstracto.remind.model.template.commands; package dev.sheldan.abstracto.remind.model.template.commands;
import dev.sheldan.abstracto.core.models.context.UserInitiatedServerContext; import dev.sheldan.abstracto.core.models.context.UserInitiatedServerContext;
import dev.sheldan.abstracto.remind.model.database.Reminder; import lombok.Builder;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import lombok.experimental.SuperBuilder; import lombok.experimental.SuperBuilder;
import java.util.ArrayList;
import java.util.List; import java.util.List;
@Getter @Getter
@Setter @Setter
@SuperBuilder @SuperBuilder
public class RemindersModel extends UserInitiatedServerContext { public class RemindersModel extends UserInitiatedServerContext {
private List<Reminder> reminders; @Builder.Default
private List<ReminderDisplay> reminders = new ArrayList<>();
} }

View File

@@ -8,6 +8,7 @@ import java.time.Duration;
public interface ReminderService { public interface ReminderService {
Reminder createReminderInForUser(AUserInAServer user, String remindText, Duration remindIn, Message message); Reminder createReminderInForUser(AUserInAServer user, String remindText, Duration remindIn, Message message);
Reminder createReminderInForUser(AUserInAServer user, String remindText, Duration remindIn, Long channelId, Long messageId);
void executeReminder(Long reminderId); void executeReminder(Long reminderId);
void unRemind(Long reminderId, AUserInAServer userInAServer); void unRemind(Long reminderId, AUserInAServer userInAServer);
} }

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.2.7</version> <version>1.2.8</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.2.7</version> <version>1.2.8</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.2.7</version> <version>1.2.8</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.2.7</version> <version>1.2.8</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.2.7</version> <version>1.2.8</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -70,6 +70,11 @@ public abstract class StarboardListener {
protected void handleStarboardPostChange(CachedMessage message, CachedReactions reaction, ServerUser userReacting, boolean adding) { protected void handleStarboardPostChange(CachedMessage message, CachedReactions reaction, ServerUser userReacting, boolean adding) {
Optional<StarboardPost> starboardPostOptional = starboardPostManagementService.findByMessageId(message.getMessageId()); Optional<StarboardPost> starboardPostOptional = starboardPostManagementService.findByMessageId(message.getMessageId());
boolean starboardPostExists = starboardPostOptional.isPresent();
if(starboardPostExists && starboardPostOptional.get().isIgnored()) {
log.info("Starboard post {} for message {} in server {} is ignored. Doing nothing.", starboardPostOptional.get().getId(), message.getMessageId(), message.getServerId());
return;
}
if(reaction != null) { if(reaction != null) {
AUserInAServer author = userInServerManagementService.loadOrCreateUser(message.getServerId(), message.getAuthor().getAuthorId()); AUserInAServer author = userInServerManagementService.loadOrCreateUser(message.getServerId(), message.getAuthor().getAuthorId());
List<AUserInAServer> userExceptAuthor = getUsersExcept(reaction.getUsers(), author); List<AUserInAServer> userExceptAuthor = getUsersExcept(reaction.getUsers(), author);
@@ -78,7 +83,7 @@ public abstract class StarboardListener {
if (userExceptAuthor.size() >= starMinimum) { if (userExceptAuthor.size() >= starMinimum) {
log.info("Post reached starboard minimum. Message {} in channel {} in server {} will be starred/updated.", log.info("Post reached starboard minimum. Message {} in channel {} in server {} will be starred/updated.",
message.getMessageId(), message.getChannelId(), message.getServerId()); message.getMessageId(), message.getChannelId(), message.getServerId());
if(starboardPostOptional.isPresent()) { if(starboardPostExists) {
updateStarboardPost(message, userAddingReaction, adding, starboardPostOptional.get(), userExceptAuthor); updateStarboardPost(message, userAddingReaction, adding, starboardPostOptional.get(), userExceptAuthor);
} else { } else {
metricService.incrementCounter(STARBOARD_STARS_THRESHOLD_REACHED); metricService.incrementCounter(STARBOARD_STARS_THRESHOLD_REACHED);
@@ -89,14 +94,14 @@ public abstract class StarboardListener {
}); });
} }
} else { } else {
if(starboardPostOptional.isPresent()) { if(starboardPostExists) {
metricService.incrementCounter(STARBOARD_STARS_THRESHOLD_FELL); metricService.incrementCounter(STARBOARD_STARS_THRESHOLD_FELL);
log.info("Removing starboard post for message {} in channel {} in server {}. It fell under the threshold {}", message.getMessageId(), message.getChannelId(), message.getServerId(), starMinimum); log.info("Removing starboard post for message {} in channel {} in server {}. It fell under the threshold {}", message.getMessageId(), message.getChannelId(), message.getServerId(), starMinimum);
starboardPostOptional.ifPresent(starboardPost -> completelyRemoveStarboardPost(starboardPost, userReacting)); starboardPostOptional.ifPresent(starboardPost -> completelyRemoveStarboardPost(starboardPost, userReacting));
} }
} }
} else { } else {
if(starboardPostOptional.isPresent()) { if(starboardPostExists) {
log.info("Removing starboard post for message {} in channel {} in server {}", message.getMessageId(), message.getChannelId(), message.getServerId()); log.info("Removing starboard post for message {} in channel {} in server {}", message.getMessageId(), message.getChannelId(), message.getServerId());
starboardPostOptional.ifPresent(starboardPost -> completelyRemoveStarboardPost(starboardPost, userReacting)); starboardPostOptional.ifPresent(starboardPost -> completelyRemoveStarboardPost(starboardPost, userReacting));
} }

View File

@@ -165,6 +165,18 @@ public class StarAddedListenerTest {
verify(starboardPostReactorManagementService, times(1)).addReactor(post, userInServerActing); verify(starboardPostReactorManagementService, times(1)).addReactor(post, userInServerActing);
} }
@Test
public void testAddingEmoteToExistingIgnoredPost() {
Long requiredStars = 1L;
setupActingAndAuthor();
when(post.isIgnored()).thenReturn(true);
executeAddingTest(requiredStars, post);
verify(metricService, times(1)).incrementCounter(any());
verify(starboardService, times(0)).updateStarboardPost(eq(post), any(CachedMessage.class), anyList());
verify(starboardPostReactorManagementService, times(0)).addReactor(post, userInServerActing);
}
private void setupActingAndAuthor() { private void setupActingAndAuthor() {
when(userInServerActing.getUserReference()).thenReturn(userActing); when(userInServerActing.getUserReference()).thenReturn(userActing);
when(userActing.getId()).thenReturn(USER_ACTING_ID); when(userActing.getId()).thenReturn(USER_ACTING_ID);

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.2.7</version> <version>1.2.8</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.2.7</version> <version>1.2.8</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.2.7</version> <version>1.2.8</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -1,9 +1,12 @@
package dev.sheldan.abstracto.statistic.emote.command.parameter.handler; package dev.sheldan.abstracto.statistic.emote.command.parameter.handler;
import dev.sheldan.abstracto.core.command.Command;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece; import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
import dev.sheldan.abstracto.core.command.handler.CommandParameterHandler; import dev.sheldan.abstracto.core.command.handler.CommandParameterHandler;
import dev.sheldan.abstracto.core.command.handler.CommandParameterIterators; import dev.sheldan.abstracto.core.command.handler.CommandParameterIterators;
import dev.sheldan.abstracto.core.command.handler.provided.EmoteParameterHandler; import dev.sheldan.abstracto.core.command.handler.provided.EmoteParameterHandler;
import dev.sheldan.abstracto.core.command.service.CommandService;
import dev.sheldan.abstracto.statistic.emote.model.database.TrackedEmote; import dev.sheldan.abstracto.statistic.emote.model.database.TrackedEmote;
import dev.sheldan.abstracto.statistic.emote.service.TrackedEmoteService; import dev.sheldan.abstracto.statistic.emote.service.TrackedEmoteService;
import net.dv8tion.jda.api.entities.Emote; import net.dv8tion.jda.api.entities.Emote;
@@ -24,6 +27,9 @@ public class TrackedEmoteParameterHandler implements CommandParameterHandler {
@Autowired @Autowired
private TrackedEmoteService trackedEmoteService; private TrackedEmoteService trackedEmoteService;
@Autowired
private CommandService commandService;
/** /**
* This {@link CommandParameterHandler} only handles {@link TrackedEmote} * This {@link CommandParameterHandler} only handles {@link TrackedEmote}
* @param clazz The desired {@link Class} of a parameter * @param clazz The desired {@link Class} of a parameter
@@ -42,14 +48,17 @@ public class TrackedEmoteParameterHandler implements CommandParameterHandler {
* @param input The {@link String} input at the current position * @param input The {@link String} input at the current position
* @param iterators The {@link CommandParameterIterators} containing all available iterators to directly retrieve JDA related * @param iterators The {@link CommandParameterIterators} containing all available iterators to directly retrieve JDA related
* entities from * entities from
* @param clazz The {@link Class} which this type should handle * @param param The {@link Class} which this type should handle
* @param context The {@link Message} which caused the command to be executed * @param context The {@link Message} which caused the command to be executed
* @param command
* @return A faked {@link TrackedEmote} based on the given input or from {@link CommandParameterIterators} directly. This {@link TrackedEmote} * @return A faked {@link TrackedEmote} based on the given input or from {@link CommandParameterIterators} directly. This {@link TrackedEmote}
* does not need to actually exist. * does not need to actually exist.
*/ */
@Override @Override
public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Class clazz, Message context) { public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Parameter param, Message context, Command command) {
Emote emote = (Emote) emoteParameterHandler.handle(input, iterators, Emote.class, context); Parameter cloned = commandService.cloneParameter(param);
cloned.setType(Emote.class);
Emote emote = (Emote) emoteParameterHandler.handle(input, iterators, cloned, context, command);
if(emote != null) { if(emote != null) {
return trackedEmoteService.getFakeTrackedEmote(emote, context.getGuild()); return trackedEmoteService.getFakeTrackedEmote(emote, context.getGuild());
} else { } else {

View File

@@ -1,9 +1,12 @@
package dev.sheldan.abstracto.statistic.emote.command.parameter.handler; package dev.sheldan.abstracto.statistic.emote.command.parameter.handler;
import dev.sheldan.abstracto.core.command.Command;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece; import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
import dev.sheldan.abstracto.core.command.handler.CommandParameterHandler; import dev.sheldan.abstracto.core.command.handler.CommandParameterHandler;
import dev.sheldan.abstracto.core.command.handler.CommandParameterIterators; import dev.sheldan.abstracto.core.command.handler.CommandParameterIterators;
import dev.sheldan.abstracto.core.command.handler.provided.EmoteParameterHandler; import dev.sheldan.abstracto.core.command.handler.provided.EmoteParameterHandler;
import dev.sheldan.abstracto.core.command.service.CommandService;
import dev.sheldan.abstracto.statistic.emote.command.parameter.TrackEmoteParameter; import dev.sheldan.abstracto.statistic.emote.command.parameter.TrackEmoteParameter;
import dev.sheldan.abstracto.statistic.emote.model.database.TrackedEmote; import dev.sheldan.abstracto.statistic.emote.model.database.TrackedEmote;
import dev.sheldan.abstracto.statistic.emote.service.TrackedEmoteService; import dev.sheldan.abstracto.statistic.emote.service.TrackedEmoteService;
@@ -28,6 +31,9 @@ public class TrackedEmoteParameterParameterHandler implements CommandParameterHa
@Autowired @Autowired
private TrackedEmoteService trackedEmoteService; private TrackedEmoteService trackedEmoteService;
@Autowired
private CommandService commandService;
/** /**
* This {@link CommandParameterHandler} only handles {@link TrackEmoteParameter} * This {@link CommandParameterHandler} only handles {@link TrackEmoteParameter}
* @param clazz The desired {@link Class} of a parameter * @param clazz The desired {@link Class} of a parameter
@@ -45,15 +51,18 @@ public class TrackedEmoteParameterParameterHandler implements CommandParameterHa
* @param input The {@link String} input at the current position * @param input The {@link String} input at the current position
* @param iterators The {@link CommandParameterIterators} containing all available iterators to directly retrieve JDA related * @param iterators The {@link CommandParameterIterators} containing all available iterators to directly retrieve JDA related
* entities from * entities from
* @param clazz The {@link Class} which this type should handle * @param param The {@link Class} which this type should handle
* @param context The {@link Message} which caused the command to be executed * @param context The {@link Message} which caused the command to be executed
* @param command
* @return An instance of {@link TrackEmoteParameter} which contains the available instances. This is an {@link Emote} in case it was * @return An instance of {@link TrackEmoteParameter} which contains the available instances. This is an {@link Emote} in case it was
* used directly. In every successful case, it will contain a faked {@link TrackedEmote}. * used directly. In every successful case, it will contain a faked {@link TrackedEmote}.
*/ */
@Override @Override
public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Class clazz, Message context) { public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Parameter param, Message context, Command command) {
TrackEmoteParameter parameter = TrackEmoteParameter.builder().build(); TrackEmoteParameter parameter = TrackEmoteParameter.builder().build();
Emote emote = (Emote) emoteParameterHandler.handle(input, iterators, Emote.class, context); Parameter cloned = commandService.cloneParameter(param);
cloned.setType(Emote.class);
Emote emote = (Emote) emoteParameterHandler.handle(input, iterators, cloned, context, command);
if(emote != null) { if(emote != null) {
parameter.setEmote(emote); parameter.setEmote(emote);
parameter.setTrackedEmote(trackedEmoteService.getFakeTrackedEmote(emote, context.getGuild())); parameter.setTrackedEmote(trackedEmoteService.getFakeTrackedEmote(emote, context.getGuild()));

View File

@@ -1,8 +1,11 @@
package dev.sheldan.abstracto.statistic.emote.command.handler; package dev.sheldan.abstracto.statistic.emote.command.handler;
import dev.sheldan.abstracto.core.command.Command;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece; import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
import dev.sheldan.abstracto.core.command.handler.CommandParameterIterators; import dev.sheldan.abstracto.core.command.handler.CommandParameterIterators;
import dev.sheldan.abstracto.core.command.handler.provided.EmoteParameterHandler; import dev.sheldan.abstracto.core.command.handler.provided.EmoteParameterHandler;
import dev.sheldan.abstracto.core.command.service.CommandService;
import dev.sheldan.abstracto.statistic.emote.command.parameter.handler.TrackedEmoteParameterHandler; import dev.sheldan.abstracto.statistic.emote.command.parameter.handler.TrackedEmoteParameterHandler;
import dev.sheldan.abstracto.statistic.emote.model.database.TrackedEmote; import dev.sheldan.abstracto.statistic.emote.model.database.TrackedEmote;
import dev.sheldan.abstracto.statistic.emote.service.TrackedEmoteService; import dev.sheldan.abstracto.statistic.emote.service.TrackedEmoteService;
@@ -31,6 +34,9 @@ public class TrackedEmoteParameterHandlerTest {
@Mock @Mock
private TrackedEmoteService trackedEmoteService; private TrackedEmoteService trackedEmoteService;
@Mock
private CommandService commandService;
@Mock @Mock
private Message contextMessage; private Message contextMessage;
@@ -40,6 +46,15 @@ public class TrackedEmoteParameterHandlerTest {
@Mock @Mock
private Guild guild; private Guild guild;
@Mock
private Parameter parameter;
@Mock
private Parameter parameter2;
@Mock
private Command command;
@Mock @Mock
private TrackedEmote trackedEmote; private TrackedEmote trackedEmote;
@@ -60,9 +75,10 @@ public class TrackedEmoteParameterHandlerTest {
when(contextMessage.getGuild()).thenReturn(guild); when(contextMessage.getGuild()).thenReturn(guild);
Emote emote = Mockito.mock(Emote.class); Emote emote = Mockito.mock(Emote.class);
UnparsedCommandParameterPiece input = Mockito.mock(UnparsedCommandParameterPiece.class); UnparsedCommandParameterPiece input = Mockito.mock(UnparsedCommandParameterPiece.class);
when(emoteParameterHandler.handle(input, iterators, Emote.class, contextMessage)).thenReturn(emote); when(commandService.cloneParameter(parameter)).thenReturn(parameter2);
when(emoteParameterHandler.handle(input, iterators, parameter2, contextMessage, command)).thenReturn(emote);
when(trackedEmoteService.getFakeTrackedEmote(emote, guild)).thenReturn(trackedEmote); when(trackedEmoteService.getFakeTrackedEmote(emote, guild)).thenReturn(trackedEmote);
TrackedEmote parsedEmote = (TrackedEmote) testUnit.handle(input, iterators, TrackedEmote.class, contextMessage); TrackedEmote parsedEmote = (TrackedEmote) testUnit.handle(input, iterators, parameter, contextMessage, command);
Assert.assertEquals(trackedEmote, parsedEmote); Assert.assertEquals(trackedEmote, parsedEmote);
} }
@@ -72,9 +88,10 @@ public class TrackedEmoteParameterHandlerTest {
when(contextMessage.getGuild()).thenReturn(guild); when(contextMessage.getGuild()).thenReturn(guild);
UnparsedCommandParameterPiece input = Mockito.mock(UnparsedCommandParameterPiece.class); UnparsedCommandParameterPiece input = Mockito.mock(UnparsedCommandParameterPiece.class);
when(input.getValue()).thenReturn(emoteId.toString()); when(input.getValue()).thenReturn(emoteId.toString());
when(commandService.cloneParameter(parameter)).thenReturn(parameter2);
when(trackedEmoteService.getFakeTrackedEmote(emoteId, guild)).thenReturn(trackedEmote); when(trackedEmoteService.getFakeTrackedEmote(emoteId, guild)).thenReturn(trackedEmote);
when(emoteParameterHandler.handle(input, iterators, Emote.class, contextMessage)).thenReturn(null); when(emoteParameterHandler.handle(input, iterators, parameter2, contextMessage, command)).thenReturn(null);
TrackedEmote parsedEmote = (TrackedEmote) testUnit.handle(input, iterators, TrackedEmote.class, contextMessage); TrackedEmote parsedEmote = (TrackedEmote) testUnit.handle(input, iterators, parameter, contextMessage, command);
verify(trackedEmoteService, times(0)).getFakeTrackedEmote(any(Emote.class), eq(guild)); verify(trackedEmoteService, times(0)).getFakeTrackedEmote(any(Emote.class), eq(guild));
Assert.assertEquals(trackedEmote, parsedEmote); Assert.assertEquals(trackedEmote, parsedEmote);
} }
@@ -83,7 +100,8 @@ public class TrackedEmoteParameterHandlerTest {
public void testWithIllegalInput() { public void testWithIllegalInput() {
UnparsedCommandParameterPiece input = Mockito.mock(UnparsedCommandParameterPiece.class); UnparsedCommandParameterPiece input = Mockito.mock(UnparsedCommandParameterPiece.class);
when(input.getValue()).thenReturn(WRONG_FORMATTED_INPUT); when(input.getValue()).thenReturn(WRONG_FORMATTED_INPUT);
when(emoteParameterHandler.handle(input, iterators, Emote.class, contextMessage)).thenReturn(null); when(commandService.cloneParameter(parameter)).thenReturn(parameter2);
testUnit.handle(input, iterators, TrackedEmote.class, contextMessage); when(emoteParameterHandler.handle(input, iterators, parameter2, contextMessage, command)).thenReturn(null);
testUnit.handle(input, iterators, parameter, contextMessage, command);
} }
} }

View File

@@ -1,8 +1,11 @@
package dev.sheldan.abstracto.statistic.emote.command.handler; package dev.sheldan.abstracto.statistic.emote.command.handler;
import dev.sheldan.abstracto.core.command.Command;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece; import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
import dev.sheldan.abstracto.core.command.handler.CommandParameterIterators; import dev.sheldan.abstracto.core.command.handler.CommandParameterIterators;
import dev.sheldan.abstracto.core.command.handler.provided.EmoteParameterHandler; import dev.sheldan.abstracto.core.command.handler.provided.EmoteParameterHandler;
import dev.sheldan.abstracto.core.command.service.CommandService;
import dev.sheldan.abstracto.statistic.emote.command.parameter.TrackEmoteParameter; import dev.sheldan.abstracto.statistic.emote.command.parameter.TrackEmoteParameter;
import dev.sheldan.abstracto.statistic.emote.command.parameter.handler.TrackedEmoteParameterParameterHandler; import dev.sheldan.abstracto.statistic.emote.command.parameter.handler.TrackedEmoteParameterParameterHandler;
import dev.sheldan.abstracto.statistic.emote.model.database.TrackedEmote; import dev.sheldan.abstracto.statistic.emote.model.database.TrackedEmote;
@@ -34,6 +37,9 @@ public class TrackedEmoteParameterParameterHandlerTest {
@Mock @Mock
private TrackedEmoteService trackedEmoteService; private TrackedEmoteService trackedEmoteService;
@Mock
private CommandService commandService;
@Mock @Mock
private Message contextMessage; private Message contextMessage;
@@ -46,6 +52,15 @@ public class TrackedEmoteParameterParameterHandlerTest {
@Mock @Mock
private TrackedEmote trackedEmote; private TrackedEmote trackedEmote;
@Mock
private Parameter parameter;
@Mock
private Parameter parameter2;
@Mock
private Command command;
private static final String WRONG_FORMATTED_INPUT = "input"; private static final String WRONG_FORMATTED_INPUT = "input";
@Test @Test
@@ -63,9 +78,10 @@ public class TrackedEmoteParameterParameterHandlerTest {
when(contextMessage.getGuild()).thenReturn(guild); when(contextMessage.getGuild()).thenReturn(guild);
Emote emote = Mockito.mock(Emote.class); Emote emote = Mockito.mock(Emote.class);
UnparsedCommandParameterPiece input = Mockito.mock(UnparsedCommandParameterPiece.class); UnparsedCommandParameterPiece input = Mockito.mock(UnparsedCommandParameterPiece.class);
when(emoteParameterHandler.handle(input, iterators, Emote.class, contextMessage)).thenReturn(emote); when(commandService.cloneParameter(parameter)).thenReturn(parameter2);
when(emoteParameterHandler.handle(input, iterators, parameter2, contextMessage, command)).thenReturn(emote);
when(trackedEmoteService.getFakeTrackedEmote(emote, guild)).thenReturn(trackedEmote); when(trackedEmoteService.getFakeTrackedEmote(emote, guild)).thenReturn(trackedEmote);
TrackEmoteParameter parsedEmote = (TrackEmoteParameter) testUnit.handle(input, iterators, TrackedEmote.class, contextMessage); TrackEmoteParameter parsedEmote = (TrackEmoteParameter) testUnit.handle(input, iterators, parameter, contextMessage, command);
Assert.assertEquals(trackedEmote, parsedEmote.getTrackedEmote()); Assert.assertEquals(trackedEmote, parsedEmote.getTrackedEmote());
Assert.assertEquals(emote, parsedEmote.getEmote()); Assert.assertEquals(emote, parsedEmote.getEmote());
} }
@@ -77,8 +93,9 @@ public class TrackedEmoteParameterParameterHandlerTest {
UnparsedCommandParameterPiece input = Mockito.mock(UnparsedCommandParameterPiece.class); UnparsedCommandParameterPiece input = Mockito.mock(UnparsedCommandParameterPiece.class);
when(input.getValue()).thenReturn(emoteId.toString()); when(input.getValue()).thenReturn(emoteId.toString());
when(trackedEmoteService.getFakeTrackedEmote(emoteId, guild)).thenReturn(trackedEmote); when(trackedEmoteService.getFakeTrackedEmote(emoteId, guild)).thenReturn(trackedEmote);
when(emoteParameterHandler.handle(input, iterators, Emote.class, contextMessage)).thenReturn(null); when(commandService.cloneParameter(parameter)).thenReturn(parameter2);
TrackEmoteParameter parsedEmote = (TrackEmoteParameter) testUnit.handle(input, iterators, TrackedEmote.class, contextMessage); when(emoteParameterHandler.handle(input, iterators, parameter2, contextMessage, command)).thenReturn(null);
TrackEmoteParameter parsedEmote = (TrackEmoteParameter) testUnit.handle(input, iterators, parameter, contextMessage, command);
verify(trackedEmoteService, times(0)).getFakeTrackedEmote(any(Emote.class), eq(guild)); verify(trackedEmoteService, times(0)).getFakeTrackedEmote(any(Emote.class), eq(guild));
Assert.assertEquals(trackedEmote, parsedEmote.getTrackedEmote()); Assert.assertEquals(trackedEmote, parsedEmote.getTrackedEmote());
} }
@@ -87,8 +104,9 @@ public class TrackedEmoteParameterParameterHandlerTest {
public void testWithIllegalInput() { public void testWithIllegalInput() {
UnparsedCommandParameterPiece input = Mockito.mock(UnparsedCommandParameterPiece.class); UnparsedCommandParameterPiece input = Mockito.mock(UnparsedCommandParameterPiece.class);
when(input.getValue()).thenReturn(WRONG_FORMATTED_INPUT); when(input.getValue()).thenReturn(WRONG_FORMATTED_INPUT);
when(emoteParameterHandler.handle(input, iterators, Emote.class, contextMessage)).thenReturn(null); when(commandService.cloneParameter(parameter)).thenReturn(parameter2);
testUnit.handle(input, iterators, TrackedEmote.class, contextMessage); when(emoteParameterHandler.handle(input, iterators, parameter2, contextMessage, command)).thenReturn(null);
testUnit.handle(input, iterators, parameter, contextMessage, command);
} }
} }

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.2.7</version> <version>1.2.8</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.2.7</version> <version>1.2.8</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.2.7</version> <version>1.2.8</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.2.7</version> <version>1.2.8</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.2.7</version> <version>1.2.8</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.2.7</version> <version>1.2.8</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.2.7</version> <version>1.2.8</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.2.7</version> <version>1.2.8</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>webservices</artifactId> <artifactId>webservices</artifactId>
<version>1.2.7</version> <version>1.2.8</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>webservices</artifactId> <artifactId>webservices</artifactId>
<version>1.2.7</version> <version>1.2.8</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.2.7</version> <version>1.2.8</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.core</groupId> <groupId>dev.sheldan.abstracto.core</groupId>
<artifactId>core</artifactId> <artifactId>core</artifactId>
<version>1.2.7</version> <version>1.2.8</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging> <packaging>jar</packaging>

View File

@@ -4,6 +4,7 @@ import dev.sheldan.abstracto.core.command.condition.ConditionResult;
import dev.sheldan.abstracto.core.command.config.Parameter; import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.config.ParameterValidator; import dev.sheldan.abstracto.core.command.config.ParameterValidator;
import dev.sheldan.abstracto.core.command.config.Parameters; import dev.sheldan.abstracto.core.command.config.Parameters;
import dev.sheldan.abstracto.core.command.config.ParseResult;
import dev.sheldan.abstracto.core.command.exception.CommandParameterValidationException; import dev.sheldan.abstracto.core.command.exception.CommandParameterValidationException;
import dev.sheldan.abstracto.core.command.exception.IncorrectParameterException; import dev.sheldan.abstracto.core.command.exception.IncorrectParameterException;
import dev.sheldan.abstracto.core.command.execution.CommandContext; import dev.sheldan.abstracto.core.command.execution.CommandContext;
@@ -207,7 +208,7 @@ public class CommandReceivedHandler extends ListenerAdapter {
// we iterate only over the actually found parameters, that way we dont have to consider the optional parameters // we iterate only over the actually found parameters, that way we dont have to consider the optional parameters
// the parameters are going from left to right anyway // the parameters are going from left to right anyway
for (int i = 0; i < parameters.getParameters().size(); i++) { for (int i = 0; i < parameters.getParameters().size(); i++) {
Parameter parameter = parameterList.get(i); Parameter parameter = parameterList.get(Math.min(i, parameterList.size() - 1));
for (ParameterValidator parameterValidator : parameter.getValidators()) { for (ParameterValidator parameterValidator : parameter.getValidators()) {
boolean validate = parameterValidator.validate(parameters.getParameters().get(i)); boolean validate = parameterValidator.validate(parameters.getParameters().get(i));
if(!validate) { if(!validate) {
@@ -243,37 +244,36 @@ public class CommandReceivedHandler extends ListenerAdapter {
} }
public CompletableFuture<Parameters> getParsedParameters(UnParsedCommandParameter unParsedCommandParameter, Command command, Message message){ public CompletableFuture<Parameters> getParsedParameters(UnParsedCommandParameter unParsedCommandParameter, Command command, Message message){
List<Object> parsedParameters = new ArrayList<>(); List<ParseResult> parsedParameters = new ArrayList<>();
if(command.getConfiguration().getParameters() == null || command.getConfiguration().getParameters().isEmpty()) { List<Parameter> parameters = command.getConfiguration().getParameters();
return CompletableFuture.completedFuture(Parameters.builder().parameters(parsedParameters).build()); if(parameters == null || parameters.isEmpty()) {
return CompletableFuture.completedFuture(Parameters.builder().parameters(new ArrayList<>()).build());
} }
log.debug("Parsing parameters for command {} based on message {}.", command.getConfiguration().getName(), message.getId()); log.debug("Parsing parameters for command {} based on message {}.", command.getConfiguration().getName(), message.getId());
Iterator<TextChannel> channelIterator = message.getMentionedChannels().iterator(); Iterator<TextChannel> channelIterator = message.getMentionedChannels().iterator();
Iterator<Emote> emoteIterator = message.getEmotesBag().iterator(); Iterator<Emote> emoteIterator = message.getEmotesBag().iterator();
Iterator<Member> memberIterator = message.getMentionedMembers().iterator(); Iterator<Member> memberIterator = message.getMentionedMembers().iterator();
Iterator<Role> roleIterator = message.getMentionedRolesBag().iterator(); Iterator<Role> roleIterator = message.getMentionedRolesBag().iterator();
Parameter param = command.getConfiguration().getParameters().get(0); Parameter param = parameters.get(0);
CommandParameterIterators iterators = new CommandParameterIterators(channelIterator, emoteIterator, memberIterator, roleIterator); CommandParameterIterators iterators = new CommandParameterIterators(channelIterator, emoteIterator, memberIterator, roleIterator);
boolean reminderActive = false;
List<CompletableFuture> futures = new ArrayList<>(); List<CompletableFuture> futures = new ArrayList<>();
for (int i = 0; i < unParsedCommandParameter.getParameters().size(); i++) { for (int i = 0; i < unParsedCommandParameter.getParameters().size(); i++) {
if(i < command.getConfiguration().getParameters().size() && !param.isRemainder()) { if(i < parameters.size() && !param.isRemainder()) {
param = command.getConfiguration().getParameters().get(i); param = parameters.get(i);
} else { } else {
reminderActive = true; param = parameters.get(parameters.size() - 1);
} }
UnparsedCommandParameterPiece value = unParsedCommandParameter.getParameters().get(i); UnparsedCommandParameterPiece value = unParsedCommandParameter.getParameters().get(i);
boolean handlerMatched = false;
for (CommandParameterHandler handler : parameterHandlers) { for (CommandParameterHandler handler : parameterHandlers) {
try { try {
if (handler.handles(param.getType())) { if (handler.handles(param.getType())) {
handlerMatched = true;
if (handler.async()) { if (handler.async()) {
CompletableFuture future = handler.handleAsync(value, iterators, param.getType(), message); CompletableFuture future = handler.handleAsync(value, iterators, param, message, command);
futures.add(future); futures.add(future);
parsedParameters.add(future); parsedParameters.add(ParseResult.builder().parameter(param).result(future).build());
} else { } else {
parsedParameters.add(handler.handle(value, iterators, param.getType(), message)); Object result = handler.handle(value, iterators, param, message, command);
parsedParameters.add(ParseResult.builder().parameter(param).result(result).build());
} }
break; break;
} }
@@ -285,44 +285,30 @@ public class CommandReceivedHandler extends ListenerAdapter {
throw new IncorrectParameterException(command, param.getName()); throw new IncorrectParameterException(command, param.getName());
} }
} }
if(!handlerMatched) {
Object valueAsString = value.getValue().toString();
if(!reminderActive) {
parsedParameters.add(valueAsString);
} else {
if(!param.isListParam()) {
if(parsedParameters.isEmpty()) {
parsedParameters.add(valueAsString);
} else {
int lastIndex = parsedParameters.size() - 1;
parsedParameters.set(lastIndex, parsedParameters.get(lastIndex) + " " + valueAsString);
}
} else {
if(parsedParameters.isEmpty()) {
ArrayList<Object> list = new ArrayList<>();
list.add(valueAsString);
parsedParameters.add(list);
} else {
int lastIndex = parsedParameters.size() - 1;
((List)parsedParameters.get(lastIndex)).add(valueAsString);
}
}
}
}
} }
if(!futures.isEmpty()) { if(!futures.isEmpty()) {
CompletableFuture<Parameters> multipleFuturesFuture = new CompletableFuture<>(); CompletableFuture<Parameters> multipleFuturesFuture = new CompletableFuture<>();
CompletableFuture<Void> combinedFuture = FutureUtils.toSingleFuture(futures); CompletableFuture<Void> combinedFuture = FutureUtils.toSingleFuture(futures);
combinedFuture.thenAccept(aVoid -> { combinedFuture.thenAccept(aVoid -> {
List<Object> usableParameters = parsedParameters.stream().map(o -> { List<Object> allParamResults = parsedParameters.stream().map(o -> {
if(o instanceof CompletableFuture) { if(o.getResult() instanceof CompletableFuture) {
return ((CompletableFuture) o).join(); return ((CompletableFuture) o.getResult()).join();
} else { } else {
return o; return o.getResult();
} }
}).collect(Collectors.toList()); }).collect(Collectors.toList());
multipleFuturesFuture.complete(Parameters.builder().parameters(usableParameters).build()); List<ParseResult> parseResults = new ArrayList<>();
for (int i = 0; i < allParamResults.size(); i++) {
ParseResult parseResult = ParseResult
.builder()
.result(allParamResults.get(i))
// all parameters beyond the most possible ones are attributed to be from the last parameter
.parameter(parameters.get(Math.min(i, parameters.size() - 1)))
.build();
parseResults.add(parseResult);
}
multipleFuturesFuture.complete(Parameters.builder().parameters(extractParametersFromParsed(parseResults)).build());
}); });
combinedFuture.exceptionally(throwable -> { combinedFuture.exceptionally(throwable -> {
@@ -331,11 +317,38 @@ public class CommandReceivedHandler extends ListenerAdapter {
}); });
return multipleFuturesFuture; return multipleFuturesFuture;
} else { } else {
Parameters parameters = Parameters.builder().parameters(parsedParameters).build(); Parameters resultParameters = Parameters.builder().parameters(extractParametersFromParsed(parsedParameters)).build();
return CompletableFuture.completedFuture(parameters); return CompletableFuture.completedFuture(resultParameters);
} }
} }
private List<Object> extractParametersFromParsed(List<ParseResult> results) {
List<Object> usableParameters = new ArrayList<>();
results.forEach(parseResult -> {
if(parseResult.getParameter().isRemainder() && !parseResult.getParameter().isListParam() && parseResult.getResult() instanceof String) {
if(usableParameters.isEmpty() || !(usableParameters.get(usableParameters.size() -1) instanceof String)) {
usableParameters.add(parseResult.getResult());
} else {
int lastIndex = usableParameters.size() - 1;
usableParameters.set(lastIndex, usableParameters.get(lastIndex).toString() + " " + parseResult.getResult().toString());
}
} else if(parseResult.getParameter().isListParam()) {
if(usableParameters.isEmpty()) {
ArrayList<Object> list = new ArrayList<>();
list.add(parseResult.getResult().toString());
usableParameters.add(list);
} else {
int lastIndex = usableParameters.size() - 1;
((List)usableParameters.get(lastIndex)).add(parseResult.getResult());
}
}
else {
usableParameters.add(parseResult.getResult());
}
});
return usableParameters;
}
@PostConstruct @PostConstruct
public void postConstruct() { public void postConstruct() {
metricService.registerCounter(COMMANDS_PROCESSED_COUNTER, "Commands processed"); metricService.registerCounter(COMMANDS_PROCESSED_COUNTER, "Commands processed");

View File

@@ -1,6 +1,8 @@
package dev.sheldan.abstracto.core.command.handler; package dev.sheldan.abstracto.core.command.handler;
import dev.sheldan.abstracto.core.command.Command;
import dev.sheldan.abstracto.core.command.CommandConstants; import dev.sheldan.abstracto.core.command.CommandConstants;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece; import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
import dev.sheldan.abstracto.core.command.handler.provided.AChannelParameterHandler; import dev.sheldan.abstracto.core.command.handler.provided.AChannelParameterHandler;
import dev.sheldan.abstracto.core.command.handler.provided.TextChannelParameterHandler; import dev.sheldan.abstracto.core.command.handler.provided.TextChannelParameterHandler;
@@ -30,8 +32,8 @@ public class AChannelParameterHandlerImpl implements AChannelParameterHandler {
} }
@Override @Override
public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Class clazz, Message context) { public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Parameter param, Message context, Command command) {
TextChannel textChannel = (TextChannel) textChannelParameterHandler.handle(input, iterators, clazz, context); TextChannel textChannel = (TextChannel) textChannelParameterHandler.handle(input, iterators, param, context, command);
if(textChannel == null) { if(textChannel == null) {
Long channelId = Long.parseLong((String) input.getValue()); Long channelId = Long.parseLong((String) input.getValue());
AChannel actualInstance = channelManagementService.loadChannel(channelId); AChannel actualInstance = channelManagementService.loadChannel(channelId);

View File

@@ -1,9 +1,12 @@
package dev.sheldan.abstracto.core.command.handler; package dev.sheldan.abstracto.core.command.handler;
import dev.sheldan.abstracto.core.command.Command;
import dev.sheldan.abstracto.core.command.CommandConstants; import dev.sheldan.abstracto.core.command.CommandConstants;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece; import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
import dev.sheldan.abstracto.core.command.handler.provided.AEmoteParameterHandler; import dev.sheldan.abstracto.core.command.handler.provided.AEmoteParameterHandler;
import dev.sheldan.abstracto.core.command.handler.provided.EmoteParameterHandler; import dev.sheldan.abstracto.core.command.handler.provided.EmoteParameterHandler;
import dev.sheldan.abstracto.core.command.service.CommandService;
import dev.sheldan.abstracto.core.models.database.AEmote; import dev.sheldan.abstracto.core.models.database.AEmote;
import dev.sheldan.abstracto.core.service.EmoteService; import dev.sheldan.abstracto.core.service.EmoteService;
import net.dv8tion.jda.api.entities.Emote; import net.dv8tion.jda.api.entities.Emote;
@@ -20,14 +23,19 @@ public class AEmoteParameterHandlerImpl implements AEmoteParameterHandler {
@Autowired @Autowired
private EmoteService emoteService; private EmoteService emoteService;
@Autowired
private CommandService commandService;
@Override @Override
public boolean handles(Class clazz) { public boolean handles(Class clazz) {
return clazz.equals(AEmote.class); return clazz.equals(AEmote.class);
} }
@Override @Override
public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Class clazz, Message context) { public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Parameter param, Message context, Command command) {
Emote emote = (Emote) emoteParameterHandler.handle(input, iterators, Emote.class, context); Parameter cloned = commandService.cloneParameter(param);
cloned.setType(Emote.class);
Emote emote = (Emote) emoteParameterHandler.handle(input, iterators, cloned, context, command);
if(emote != null) { if(emote != null) {
return emoteService.getFakeEmoteFromEmote(emote); return emoteService.getFakeEmoteFromEmote(emote);
} else { } else {

View File

@@ -1,9 +1,12 @@
package dev.sheldan.abstracto.core.command.handler; package dev.sheldan.abstracto.core.command.handler;
import dev.sheldan.abstracto.core.command.Command;
import dev.sheldan.abstracto.core.command.CommandConstants; import dev.sheldan.abstracto.core.command.CommandConstants;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece; import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
import dev.sheldan.abstracto.core.command.handler.provided.ARoleParameterHandler; import dev.sheldan.abstracto.core.command.handler.provided.ARoleParameterHandler;
import dev.sheldan.abstracto.core.command.handler.provided.RoleParameterHandler; import dev.sheldan.abstracto.core.command.handler.provided.RoleParameterHandler;
import dev.sheldan.abstracto.core.command.service.CommandService;
import dev.sheldan.abstracto.core.models.database.ARole; import dev.sheldan.abstracto.core.models.database.ARole;
import dev.sheldan.abstracto.core.service.RoleService; import dev.sheldan.abstracto.core.service.RoleService;
import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.entities.Message;
@@ -20,14 +23,19 @@ public class ARoleParameterHandlerImpl implements ARoleParameterHandler {
@Autowired @Autowired
private RoleService roleService; private RoleService roleService;
@Autowired
private CommandService commandService;
@Override @Override
public boolean handles(Class clazz) { public boolean handles(Class clazz) {
return clazz.equals(ARole.class); return clazz.equals(ARole.class);
} }
@Override @Override
public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Class clazz, Message context) { public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Parameter param, Message context, Command command) {
Role role = (Role) roleParameterHandler.handle(input, iterators, Role.class, context); Parameter cloned = commandService.cloneParameter(param);
cloned.setType(Role.class);
Role role = (Role) roleParameterHandler.handle(input, iterators, cloned, context, command);
return roleService.getFakeRoleFromRole(role); return roleService.getFakeRoleFromRole(role);
} }

View File

@@ -1,9 +1,12 @@
package dev.sheldan.abstracto.core.command.handler; package dev.sheldan.abstracto.core.command.handler;
import dev.sheldan.abstracto.core.command.Command;
import dev.sheldan.abstracto.core.command.CommandConstants; import dev.sheldan.abstracto.core.command.CommandConstants;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece; import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
import dev.sheldan.abstracto.core.command.handler.provided.AUserInAServerParameterHandler; import dev.sheldan.abstracto.core.command.handler.provided.AUserInAServerParameterHandler;
import dev.sheldan.abstracto.core.command.handler.provided.MemberParameterHandler; import dev.sheldan.abstracto.core.command.handler.provided.MemberParameterHandler;
import dev.sheldan.abstracto.core.command.service.CommandService;
import dev.sheldan.abstracto.core.exception.UserInServerNotFoundException; import dev.sheldan.abstracto.core.exception.UserInServerNotFoundException;
import dev.sheldan.abstracto.core.models.database.AUserInAServer; import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService; import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
@@ -23,10 +26,15 @@ public class AUserInAServerParameterHandlerImpl implements AUserInAServerParamet
@Autowired @Autowired
private UserInServerManagementService userInServerManagementService; private UserInServerManagementService userInServerManagementService;
@Autowired
private CommandService commandService;
@Override @Override
public CompletableFuture handleAsync(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Class clazz, Message context) { public CompletableFuture handleAsync(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Parameter param, Message context, Command command) {
CompletableFuture<AUserInAServer> future = new CompletableFuture<>(); CompletableFuture<AUserInAServer> future = new CompletableFuture<>();
memberParameterHandler.handleAsync(input, iterators, Member.class, context).whenComplete((o, throwable) -> { Parameter cloned = commandService.cloneParameter(param);
cloned.setType(Member.class);
memberParameterHandler.handleAsync(input, iterators, cloned, context, command).whenComplete((o, throwable) -> {
try { try {
AUserInAServer actualInstance; AUserInAServer actualInstance;
if (throwable == null) { if (throwable == null) {

View File

@@ -1,6 +1,8 @@
package dev.sheldan.abstracto.core.command.handler; package dev.sheldan.abstracto.core.command.handler;
import dev.sheldan.abstracto.core.command.Command;
import dev.sheldan.abstracto.core.command.CommandConstants; import dev.sheldan.abstracto.core.command.CommandConstants;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece; import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
import dev.sheldan.abstracto.core.command.handler.provided.BooleanParameterHandler; import dev.sheldan.abstracto.core.command.handler.provided.BooleanParameterHandler;
import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.entities.Message;
@@ -14,7 +16,7 @@ public class BooleanParameterHandlerImpl implements BooleanParameterHandler {
} }
@Override @Override
public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Class clazz, Message context) { public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Parameter param, Message context, Command command) {
return Boolean.valueOf((String) input.getValue()); return Boolean.valueOf((String) input.getValue());
} }

View File

@@ -1,6 +1,8 @@
package dev.sheldan.abstracto.core.command.handler; package dev.sheldan.abstracto.core.command.handler;
import dev.sheldan.abstracto.core.command.Command;
import dev.sheldan.abstracto.core.command.CommandConstants; import dev.sheldan.abstracto.core.command.CommandConstants;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.exception.ChannelGroupNotFoundException; import dev.sheldan.abstracto.core.command.exception.ChannelGroupNotFoundException;
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece; import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
import dev.sheldan.abstracto.core.command.handler.provided.ChannelGroupParameterHandler; import dev.sheldan.abstracto.core.command.handler.provided.ChannelGroupParameterHandler;
@@ -23,7 +25,7 @@ public class ChannelGroupParameterHandlerImpl implements ChannelGroupParameterHa
private ServerManagementService serverManagementService; private ServerManagementService serverManagementService;
@Override @Override
public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Class clazz, Message context) { public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Parameter param, Message context, Command command) {
AServer server = serverManagementService.loadServer(context.getGuild().getIdLong()); AServer server = serverManagementService.loadServer(context.getGuild().getIdLong());
String inputString = (String) input.getValue(); String inputString = (String) input.getValue();
AChannelGroup actualInstance = channelGroupManagementService.findByNameAndServerOptional(inputString, server) AChannelGroup actualInstance = channelGroupManagementService.findByNameAndServerOptional(inputString, server)

View File

@@ -1,6 +1,8 @@
package dev.sheldan.abstracto.core.command.handler; package dev.sheldan.abstracto.core.command.handler;
import dev.sheldan.abstracto.core.command.Command;
import dev.sheldan.abstracto.core.command.CommandConstants; import dev.sheldan.abstracto.core.command.CommandConstants;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece; import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
import dev.sheldan.abstracto.core.command.handler.provided.ChannelGroupTypeParameterHandler; import dev.sheldan.abstracto.core.command.handler.provided.ChannelGroupTypeParameterHandler;
import dev.sheldan.abstracto.core.models.database.ChannelGroupType; import dev.sheldan.abstracto.core.models.database.ChannelGroupType;
@@ -25,7 +27,7 @@ public class ChannelGroupTypeParameterHandlerImpl implements ChannelGroupTypePar
} }
@Override @Override
public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Class clazz, Message context) { public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Parameter param, Message context, Command command) {
ChannelGroupType actualGroupType = channelGroupTypeManagementService.findChannelGroupTypeByKey((String) input.getValue()); ChannelGroupType actualGroupType = channelGroupTypeManagementService.findChannelGroupTypeByKey((String) input.getValue());
return ChannelGroupType return ChannelGroupType
.builder() .builder()

View File

@@ -0,0 +1,86 @@
package dev.sheldan.abstracto.core.command.handler;
import dev.sheldan.abstracto.core.command.Command;
import dev.sheldan.abstracto.core.command.CommandConstants;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.exception.IncorrectParameterException;
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
import dev.sheldan.abstracto.core.command.handler.parameter.CombinedParameter;
import dev.sheldan.abstracto.core.command.handler.provided.CombinedParametersHandler;
import dev.sheldan.abstracto.core.metric.service.MetricService;
import dev.sheldan.abstracto.core.utils.FutureUtils;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.Message;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@Component
@Slf4j
public class CombinedParameterHandlerImpl implements CombinedParametersHandler {
@Autowired
@Lazy
private List<CommandParameterHandler> parameterHandlers;
@Autowired
private MetricService metricService;
@Override
public boolean async() {
return true;
}
@Override
public CompletableFuture<Object> handleAsync(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Parameter param, Message context, Command command) {
List<CompletableFuture<Object>> futures = new ArrayList<>();
CompletableFuture<Object> returningFuture = new CompletableFuture<>();
List<Object> possibleTypes = (List) param.getAdditionalInfo().get(Parameter.ADDITIONAL_TYPES_KEY);
for (Object concreteParameter: possibleTypes) {
for (CommandParameterHandler handler : parameterHandlers) {
try {
if (handler.handles((Class) concreteParameter)) {
if (handler.async()) {
futures.add(handler.handleAsync(input, iterators, param, context, command));
} else {
Object result = handler.handle(input, iterators, param, context, command);
futures.add(CompletableFuture.completedFuture(result));
}
}
} catch (Exception e) {
CompletableFuture<Object> exceptionFuture = new CompletableFuture<>();
futures.add(exceptionFuture);
exceptionFuture.completeExceptionally(e);
}
}
}
FutureUtils.toSingleFutureGeneric(futures).whenComplete((unused, throwable) -> {
for (CompletableFuture<Object> future: futures) {
if(!future.isCompletedExceptionally()) {
Object value = future.join();
if(value != null) {
returningFuture.complete(value);
return;
}
}
}
returningFuture.completeExceptionally(new IncorrectParameterException(command, param.getName()));
});
return returningFuture;
}
@Override
public boolean handles(Class clazz) {
return clazz.equals(CombinedParameter.class);
}
@Override
public Integer getPriority() {
return CommandConstants.CORE_HANDLER_PRIORITY;
}
}

View File

@@ -1,6 +1,8 @@
package dev.sheldan.abstracto.core.command.handler; package dev.sheldan.abstracto.core.command.handler;
import dev.sheldan.abstracto.core.command.Command;
import dev.sheldan.abstracto.core.command.CommandConstants; import dev.sheldan.abstracto.core.command.CommandConstants;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.CommandParameterKey; import dev.sheldan.abstracto.core.command.execution.CommandParameterKey;
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece; import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
import dev.sheldan.abstracto.core.command.handler.provided.CommandKeyParameterHandler; import dev.sheldan.abstracto.core.command.handler.provided.CommandKeyParameterHandler;
@@ -16,8 +18,8 @@ public class CommandKeyParameterHandlerImpl implements CommandKeyParameterHandle
} }
@Override @Override
public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Class clazz, Message context) { public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Parameter param, Message context, Command command) {
return CommandParameterKey.getEnumFromKey(clazz, (String) input.getValue()); return CommandParameterKey.getEnumFromKey(param.getType(), (String) input.getValue());
} }
@Override @Override

View File

@@ -1,6 +1,8 @@
package dev.sheldan.abstracto.core.command.handler; package dev.sheldan.abstracto.core.command.handler;
import dev.sheldan.abstracto.core.command.Command;
import dev.sheldan.abstracto.core.command.CommandConstants; import dev.sheldan.abstracto.core.command.CommandConstants;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece; import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
import dev.sheldan.abstracto.core.command.handler.provided.DoubleParameterHandler; import dev.sheldan.abstracto.core.command.handler.provided.DoubleParameterHandler;
import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.entities.Message;
@@ -14,7 +16,7 @@ public class DoubleParameterHandlerImpl implements DoubleParameterHandler {
} }
@Override @Override
public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Class clazz, Message context) { public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Parameter param, Message context, Command command) {
return Double.parseDouble((String) input.getValue()); return Double.parseDouble((String) input.getValue());
} }

View File

@@ -1,6 +1,8 @@
package dev.sheldan.abstracto.core.command.handler; package dev.sheldan.abstracto.core.command.handler;
import dev.sheldan.abstracto.core.command.Command;
import dev.sheldan.abstracto.core.command.CommandConstants; import dev.sheldan.abstracto.core.command.CommandConstants;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece; import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
import dev.sheldan.abstracto.core.command.handler.provided.DurationParameterHandler; import dev.sheldan.abstracto.core.command.handler.provided.DurationParameterHandler;
import dev.sheldan.abstracto.core.utils.ParseUtils; import dev.sheldan.abstracto.core.utils.ParseUtils;
@@ -17,7 +19,7 @@ public class DurationParameterHandlerImpl implements DurationParameterHandler {
} }
@Override @Override
public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Class clazz, Message context) { public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Parameter param, Message context, Command command) {
return ParseUtils.parseDuration((String) input.getValue()); return ParseUtils.parseDuration((String) input.getValue());
} }

View File

@@ -1,6 +1,8 @@
package dev.sheldan.abstracto.core.command.handler; package dev.sheldan.abstracto.core.command.handler;
import dev.sheldan.abstracto.core.command.Command;
import dev.sheldan.abstracto.core.command.CommandConstants; import dev.sheldan.abstracto.core.command.CommandConstants;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece; import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
import dev.sheldan.abstracto.core.command.handler.provided.EmoteParameterHandler; import dev.sheldan.abstracto.core.command.handler.provided.EmoteParameterHandler;
import net.dv8tion.jda.api.entities.Emote; import net.dv8tion.jda.api.entities.Emote;
@@ -19,7 +21,7 @@ public class EmoteParameterHandlerImpl implements EmoteParameterHandler {
} }
@Override @Override
public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Class clazz, Message context) { public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Parameter param, Message context, Command command) {
String inputString = (String) input.getValue(); String inputString = (String) input.getValue();
Matcher matcher = Message.MentionType.EMOTE.getPattern().matcher(inputString); Matcher matcher = Message.MentionType.EMOTE.getPattern().matcher(inputString);
if(matcher.matches()) { if(matcher.matches()) {

View File

@@ -1,6 +1,8 @@
package dev.sheldan.abstracto.core.command.handler; package dev.sheldan.abstracto.core.command.handler;
import dev.sheldan.abstracto.core.command.Command;
import dev.sheldan.abstracto.core.command.CommandConstants; import dev.sheldan.abstracto.core.command.CommandConstants;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.exception.NoAttachmentFoundException; import dev.sheldan.abstracto.core.command.exception.NoAttachmentFoundException;
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece; import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
import dev.sheldan.abstracto.core.command.handler.provided.FileParameterHandler; import dev.sheldan.abstracto.core.command.handler.provided.FileParameterHandler;
@@ -25,7 +27,7 @@ public class FileParameterHandlerImpl implements FileParameterHandler {
} }
@Override @Override
public CompletableFuture<Object> handleAsync(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Class clazz, Message context) { public CompletableFuture<Object> handleAsync(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Parameter param, Message context, Command command) {
if(context.getAttachments().isEmpty()) { if(context.getAttachments().isEmpty()) {
throw new NoAttachmentFoundException(); throw new NoAttachmentFoundException();
} }

View File

@@ -1,9 +1,12 @@
package dev.sheldan.abstracto.core.command.handler; package dev.sheldan.abstracto.core.command.handler;
import dev.sheldan.abstracto.core.command.Command;
import dev.sheldan.abstracto.core.command.CommandConstants; import dev.sheldan.abstracto.core.command.CommandConstants;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece; import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
import dev.sheldan.abstracto.core.command.handler.provided.EmoteParameterHandler; import dev.sheldan.abstracto.core.command.handler.provided.EmoteParameterHandler;
import dev.sheldan.abstracto.core.command.handler.provided.FullEmoteParameterHandler; import dev.sheldan.abstracto.core.command.handler.provided.FullEmoteParameterHandler;
import dev.sheldan.abstracto.core.command.service.CommandService;
import dev.sheldan.abstracto.core.models.FullEmote; import dev.sheldan.abstracto.core.models.FullEmote;
import dev.sheldan.abstracto.core.models.database.AEmote; import dev.sheldan.abstracto.core.models.database.AEmote;
import dev.sheldan.abstracto.core.service.EmoteService; import dev.sheldan.abstracto.core.service.EmoteService;
@@ -21,14 +24,19 @@ public class FullEmoteParameterHandlerImpl implements FullEmoteParameterHandler
@Autowired @Autowired
private EmoteService emoteService; private EmoteService emoteService;
@Autowired
private CommandService commandService;
@Override @Override
public boolean handles(Class clazz) { public boolean handles(Class clazz) {
return clazz.equals(FullEmote.class); return clazz.equals(FullEmote.class);
} }
@Override @Override
public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Class clazz, Message context) { public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Parameter param, Message context, Command command) {
Emote emote = (Emote) emoteParameterHandler.handle(input, iterators, Emote.class, context); Parameter cloned = commandService.cloneParameter(param);
cloned.setType(Emote.class);
Emote emote = (Emote) emoteParameterHandler.handle(input, iterators, cloned, context, command);
AEmote aEmote; AEmote aEmote;
if(emote != null) { if(emote != null) {
aEmote = emoteService.getFakeEmoteFromEmote(emote); aEmote = emoteService.getFakeEmoteFromEmote(emote);

View File

@@ -1,9 +1,12 @@
package dev.sheldan.abstracto.core.command.handler; package dev.sheldan.abstracto.core.command.handler;
import dev.sheldan.abstracto.core.command.Command;
import dev.sheldan.abstracto.core.command.CommandConstants; import dev.sheldan.abstracto.core.command.CommandConstants;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece; import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
import dev.sheldan.abstracto.core.command.handler.provided.FullRoleParameterHandler; import dev.sheldan.abstracto.core.command.handler.provided.FullRoleParameterHandler;
import dev.sheldan.abstracto.core.command.handler.provided.RoleParameterHandler; import dev.sheldan.abstracto.core.command.handler.provided.RoleParameterHandler;
import dev.sheldan.abstracto.core.command.service.CommandService;
import dev.sheldan.abstracto.core.models.FullRole; import dev.sheldan.abstracto.core.models.FullRole;
import dev.sheldan.abstracto.core.models.database.ARole; import dev.sheldan.abstracto.core.models.database.ARole;
import dev.sheldan.abstracto.core.service.RoleService; import dev.sheldan.abstracto.core.service.RoleService;
@@ -21,14 +24,20 @@ public class FullRoleParameterHandlerImpl implements FullRoleParameterHandler {
@Autowired @Autowired
private RoleService roleService; private RoleService roleService;
@Autowired
private CommandService commandService;
@Override @Override
public boolean handles(Class clazz) { public boolean handles(Class clazz) {
return clazz.equals(FullRole.class); return clazz.equals(FullRole.class);
} }
@Override @Override
public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Class clazz, Message context) { public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Parameter param, Message context, Command command) {
Role role = (Role) roleParameterHandler.handle(input, iterators, Role.class, context); Parameter cloned = commandService.cloneParameter(param);
cloned.setType(Role.class);
Role role = (Role) roleParameterHandler.handle(input, iterators, cloned, context, command);
ARole aRole = roleService.getFakeRoleFromRole(role); ARole aRole = roleService.getFakeRoleFromRole(role);
return FullRole.builder().role(aRole).serverRole(role).build(); return FullRole.builder().role(aRole).serverRole(role).build();
} }

View File

@@ -1,6 +1,8 @@
package dev.sheldan.abstracto.core.command.handler; package dev.sheldan.abstracto.core.command.handler;
import dev.sheldan.abstracto.core.command.Command;
import dev.sheldan.abstracto.core.command.CommandConstants; import dev.sheldan.abstracto.core.command.CommandConstants;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece; import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
import dev.sheldan.abstracto.core.command.handler.provided.IntegerParameterHandler; import dev.sheldan.abstracto.core.command.handler.provided.IntegerParameterHandler;
import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.entities.Message;
@@ -15,7 +17,7 @@ public class IntegerParameterHandlerImpl implements IntegerParameterHandler {
} }
@Override @Override
public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Class clazz, Message context) { public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Parameter param, Message context, Command command) {
return Integer.parseInt((String) input.getValue()); return Integer.parseInt((String) input.getValue());
} }

View File

@@ -1,6 +1,8 @@
package dev.sheldan.abstracto.core.command.handler; package dev.sheldan.abstracto.core.command.handler;
import dev.sheldan.abstracto.core.command.Command;
import dev.sheldan.abstracto.core.command.CommandConstants; import dev.sheldan.abstracto.core.command.CommandConstants;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece; import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
import dev.sheldan.abstracto.core.command.handler.provided.LongParameterHandler; import dev.sheldan.abstracto.core.command.handler.provided.LongParameterHandler;
import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.entities.Message;
@@ -15,7 +17,7 @@ public class LongParameterHandlerImpl implements LongParameterHandler {
} }
@Override @Override
public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Class clazz, Message context) { public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Parameter param, Message context, Command command) {
return Long.parseLong((String) input.getValue()); return Long.parseLong((String) input.getValue());
} }

View File

@@ -1,6 +1,8 @@
package dev.sheldan.abstracto.core.command.handler; package dev.sheldan.abstracto.core.command.handler;
import dev.sheldan.abstracto.core.command.Command;
import dev.sheldan.abstracto.core.command.CommandConstants; import dev.sheldan.abstracto.core.command.CommandConstants;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.exception.AbstractoTemplatedException; import dev.sheldan.abstracto.core.command.exception.AbstractoTemplatedException;
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece; import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
import dev.sheldan.abstracto.core.command.handler.provided.MemberParameterHandler; import dev.sheldan.abstracto.core.command.handler.provided.MemberParameterHandler;
@@ -26,7 +28,7 @@ public class MemberParameterHandlerImpl implements MemberParameterHandler {
} }
@Override @Override
public CompletableFuture<Object> handleAsync(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Class clazz, Message context) { public CompletableFuture<Object> handleAsync(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Parameter param, Message context, Command command) {
String inputString = (String) input.getValue(); String inputString = (String) input.getValue();
Matcher matcher = Message.MentionType.USER.getPattern().matcher(inputString); Matcher matcher = Message.MentionType.USER.getPattern().matcher(inputString);
if(matcher.matches()) { if(matcher.matches()) {

View File

@@ -0,0 +1,28 @@
package dev.sheldan.abstracto.core.command.handler;
import dev.sheldan.abstracto.core.command.Command;
import dev.sheldan.abstracto.core.command.CommandConstants;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
import dev.sheldan.abstracto.core.command.handler.provided.MessageParameterHandler;
import net.dv8tion.jda.api.entities.Message;
import org.springframework.stereotype.Component;
@Component
public class MessageParameterHandlerImpl implements MessageParameterHandler {
@Override
public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Parameter param, Message context, Command command) {
return context.getReferencedMessage();
}
@Override
public boolean handles(Class clazz) {
return clazz.equals(Message.class);
}
@Override
public Integer getPriority() {
return CommandConstants.CORE_HANDLER_PRIORITY;
}
}

View File

@@ -1,6 +1,8 @@
package dev.sheldan.abstracto.core.command.handler; package dev.sheldan.abstracto.core.command.handler;
import dev.sheldan.abstracto.core.command.Command;
import dev.sheldan.abstracto.core.command.CommandConstants; import dev.sheldan.abstracto.core.command.CommandConstants;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.exception.AbstractoTemplatedException; import dev.sheldan.abstracto.core.command.exception.AbstractoTemplatedException;
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece; import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
import dev.sheldan.abstracto.core.command.handler.provided.RoleParameterHandler; import dev.sheldan.abstracto.core.command.handler.provided.RoleParameterHandler;
@@ -20,7 +22,7 @@ public class RoleParameterHandlerImpl implements RoleParameterHandler {
} }
@Override @Override
public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Class clazz, Message context) { public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Parameter param, Message context, Command command) {
String inputString = (String) input.getValue(); String inputString = (String) input.getValue();
Matcher matcher = Message.MentionType.ROLE.getPattern().matcher(inputString); Matcher matcher = Message.MentionType.ROLE.getPattern().matcher(inputString);
if(matcher.matches()) { if(matcher.matches()) {

View File

@@ -0,0 +1,28 @@
package dev.sheldan.abstracto.core.command.handler;
import dev.sheldan.abstracto.core.command.Command;
import dev.sheldan.abstracto.core.command.CommandConstants;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
import dev.sheldan.abstracto.core.command.handler.provided.StringParameterHandler;
import net.dv8tion.jda.api.entities.Message;
import org.springframework.stereotype.Component;
@Component
public class StringParameterHandlerImpl implements StringParameterHandler {
@Override
public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Parameter param, Message context, Command command) {
return input.getValue().toString();
}
@Override
public boolean handles(Class clazz) {
return clazz.equals(String.class);
}
@Override
public Integer getPriority() {
return CommandConstants.CORE_HANDLER_PRIORITY;
}
}

View File

@@ -1,6 +1,8 @@
package dev.sheldan.abstracto.core.command.handler; package dev.sheldan.abstracto.core.command.handler;
import dev.sheldan.abstracto.core.command.Command;
import dev.sheldan.abstracto.core.command.CommandConstants; import dev.sheldan.abstracto.core.command.CommandConstants;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.exception.AbstractoTemplatedException; import dev.sheldan.abstracto.core.command.exception.AbstractoTemplatedException;
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece; import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
import dev.sheldan.abstracto.core.command.handler.provided.TextChannelParameterHandler; import dev.sheldan.abstracto.core.command.handler.provided.TextChannelParameterHandler;
@@ -20,7 +22,7 @@ public class TextChannelParameterHandlerImpl implements TextChannelParameterHand
} }
@Override @Override
public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Class clazz, Message context) { public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Parameter param, Message context, Command command) {
String inputString = (String) input.getValue(); String inputString = (String) input.getValue();
Matcher matcher = Message.MentionType.CHANNEL.getPattern().matcher(inputString); Matcher matcher = Message.MentionType.CHANNEL.getPattern().matcher(inputString);
if(matcher.matches()) { if(matcher.matches()) {

View File

@@ -7,6 +7,7 @@ import dev.sheldan.abstracto.core.command.condition.CommandCondition;
import dev.sheldan.abstracto.core.command.condition.ConditionResult; import dev.sheldan.abstracto.core.command.condition.ConditionResult;
import dev.sheldan.abstracto.core.command.condition.ConditionalCommand; import dev.sheldan.abstracto.core.command.condition.ConditionalCommand;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration; import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.config.Parameters; import dev.sheldan.abstracto.core.command.config.Parameters;
import dev.sheldan.abstracto.core.command.execution.CommandContext; import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.UnParsedCommandParameter; import dev.sheldan.abstracto.core.command.execution.UnParsedCommandParameter;
@@ -179,6 +180,21 @@ public class CommandServiceBean implements CommandService {
return commandReceivedHandler.getParsedParameters(unParsedParameter, command, messageContainingContent); return commandReceivedHandler.getParsedParameters(unParsedParameter, command, messageContainingContent);
} }
@Override
public Parameter cloneParameter(Parameter parameter) {
return Parameter
.builder()
.optional(parameter.isOptional())
.type(parameter.getType())
.remainder(parameter.isRemainder())
.name(parameter.getName())
.templated(parameter.getTemplated())
.description(parameter.getDescription())
.validators(parameter.getValidators())
.isListParam(parameter.isListParam())
.build();
}
private ConditionResult checkConditions(CommandContext commandContext, Command command, List<CommandCondition> conditions) { private ConditionResult checkConditions(CommandContext commandContext, Command command, List<CommandCondition> conditions) {
if(conditions != null) { if(conditions != null) {
for (CommandCondition condition : conditions) { for (CommandCondition condition : conditions) {

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