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
* [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)
* [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.

View File

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

View File

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

View File

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

View File

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

View File

@@ -43,7 +43,7 @@ public class LoveCalc extends AbstractConditionableCommand {
model.setFirstPart(firstPart);
model.setSecondPart(secondPart);
return FutureUtils.toSingleFutureGeneric(channelService.sendEmbedTemplateInTextChannelList(LOVE_CALC_RESPONSE_TEMPLATE_KEY, model, commandContext.getChannel()))
.thenApply(unused -> CommandResult.fromIgnored());
.thenApply(unused -> CommandResult.fromSuccess());
}
@Override
@@ -58,7 +58,6 @@ public class LoveCalc extends AbstractConditionableCommand {
.module(EntertainmentModuleDefinition.ENTERTAINMENT)
.templated(true)
.supportsEmbedException(true)
.causesReaction(true)
.parameters(parameters)
.help(helpInfo)
.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) {
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/pro dbchangelog-3.8.xsd" >
<include file="1.0-entertainment/collection.xml" relativeToChangelogFile="true"/>
<include file="1.2.8-entertainment/collection.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>entertainment</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.2.7</version>
<version>1.2.8</version>
</parent>
<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);
boolean executeRoulette(Member memberExecuting);
String takeChoice(List<String> choices, Member memberExecuting);
String createMockText(String text, Member memberExecuting, Member mockedUser);
}

View File

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

View File

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

View File

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

View File

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

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>link-embed</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.2.7</version>
<version>1.2.8</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -38,6 +38,12 @@
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>dev.sheldan.abstracto.scheduling</groupId>
<artifactId>scheduling-int</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>dev.sheldan.abstracto.core</groupId>
<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 org.springframework.data.jpa.repository.JpaRepository;
import java.time.Instant;
import java.util.List;
public interface EmbeddedMessageRepository extends JpaRepository<EmbeddedMessage, Long> {
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;
import dev.sheldan.abstracto.core.models.ServerChannelMessage;
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
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.templating.model.MessageToSend;
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.database.EmbeddedMessage;
import dev.sheldan.abstracto.linkembed.service.management.MessageEmbedPostManagementService;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.TextChannel;
import net.dv8tion.jda.api.entities.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@Component
@Slf4j
@@ -68,6 +78,15 @@ public class MessageEmbedServiceBean implements MessageEmbedService {
@Autowired
private ReactionService reactionService;
@Autowired
private MessageService messageService;
@Autowired
private EmoteService emoteService;
@Value("${abstracto.feature.linkEmbed.removalDays}")
private Long embedRemovalDays;
@Override
public List<MessageEmbedLink> getLinksInMessage(String message) {
List<MessageEmbedLink> links = new ArrayList<>();
@@ -97,7 +116,6 @@ public class MessageEmbedServiceBean implements MessageEmbedService {
linksToEmbed.forEach(messageEmbedLink ->
messageCache.getMessageFromCache(messageEmbedLink.getServerId(), messageEmbedLink.getChannelId(), messageEmbedLink.getMessageId())
.thenAccept(cachedMessage -> self.embedLink(cachedMessage, target, userEmbeddingUserInServerId, embeddingMessage)
).exceptionally(throwable -> {
log.error("Message embedding from cache failed for message {}.", messageEmbedLink.getMessageId(), throwable);
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
public CompletableFuture<Void> sendEmbeddingMessage(CachedMessage cachedMessage, TextChannel target, Long userEmbeddingUserInServerId, MessageEmbeddedModel messageEmbeddedModel) {
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)
).exceptionally(throwable -> {
log.warn("Failed to retrieve author for user {}.", embeddedMessage.getAuthor().getAuthorId(), throwable);
self.loadMessageEmbedModel(message, embeddedMessage, null);
return null;
return self.loadMessageEmbedModel(message, embeddedMessage, null);
});
}

View File

@@ -16,6 +16,8 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.time.Instant;
import java.util.List;
import java.util.Optional;
@Component
@@ -76,4 +78,15 @@ public class MessageEmbedPostManagementServiceBean implements MessageEmbedPostMa
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.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/pro dbchangelog-3.8.xsd" >
<include file="1.0-link-embed/collection.xml" relativeToChangelogFile="true"/>
<include file="1.2.8-link-embed/collection.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

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

View File

@@ -12,4 +12,5 @@ public interface MessageEmbedService {
List<MessageEmbedLink> getLinksInMessage(String message);
void embedLinks(List<MessageEmbedLink> linksToEmbed, 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 net.dv8tion.jda.api.entities.Message;
import java.time.Instant;
import java.util.List;
import java.util.Optional;
public interface MessageEmbedPostManagementService {
void createMessageEmbed(CachedMessage embeddedMessage, Message messageContainingEmbed, AUserInAServer cause);
Optional<EmbeddedMessage> findEmbeddedPostByMessageId(Long messageId);
void deleteEmbeddedMessage(EmbeddedMessage embeddedMessage);
List<EmbeddedMessage> getEmbeddedMessagesOlderThan(Instant date);
void deleteEmbeddedMessagesViaId(List<Long> embeddingMessageId);
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>remind</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.2.7</version>
<version>1.2.8</version>
</parent>
<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.ContextConverter;
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.service.ChannelService;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
import dev.sheldan.abstracto.core.utils.FutureUtils;
import dev.sheldan.abstracto.remind.config.RemindFeatureDefinition;
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.service.management.ReminderManagementService;
import lombok.extern.slf4j.Slf4j;
@@ -42,7 +44,20 @@ public class Reminders extends AbstractConditionableCommand {
AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(commandContext.getAuthor());
List<Reminder> activeReminders = reminderManagementService.getActiveRemindersForUser(aUserInAServer);
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());
return FutureUtils.toSingleFutureGeneric(channelService.sendEmbedTemplateInTextChannelList(REMINDERS_RESPONSE_TEMPLATE, model, commandContext.getChannel()))
.thenApply(aVoid -> CommandResult.fromIgnored());

View File

@@ -27,7 +27,7 @@ public class ReminderJob extends QuartzJobBean {
log.info("Executing reminder job for reminder {}", reminderId);
reminderService.executeReminder(reminderId);
} 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
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
.builder()
.user(user.getUserReference())
@@ -80,8 +85,8 @@ public class RemindServiceBean implements ReminderService {
.guild(user.getServerReference())
.channel(channel)
.build();
Instant remindAt = Instant.now().plusNanos(remindIn.toNanos());
Reminder reminder = reminderManagementService.createReminder(aServerAChannelAUser, remindText, remindAt, message.getIdLong());
Instant remindAt = Instant.now().plusMillis(remindIn.toMillis());
Reminder reminder = reminderManagementService.createReminder(aServerAChannelAUser, remindText, remindAt, messageId);
log.info("Creating reminder for user {} in guild {} due at {}.",
user.getUserReference().getId(), user.getServerReference().getId(), remindAt);
@@ -96,7 +101,7 @@ public class RemindServiceBean implements ReminderService {
}, remindIn.toNanos(), TimeUnit.NANOSECONDS);
} else {
HashMap<Object, Object> parameters = new HashMap<>();
parameters.put("reminderId", reminder.getId());
parameters.put("reminderId", reminder.getId().toString());
JobParameters jobParameters = JobParameters.builder().parameters(parameters).build();
String triggerKey = schedulerService.executeJobWithParametersOnce("reminderJob", "utility", jobParameters, Date.from(reminder.getTargetDate()));
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.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.service.ChannelService;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
@@ -37,6 +39,9 @@ public class RemindersTest {
@Mock
private UserInServerManagementService userInServerManagementService;
@Mock
private AChannel channel;
@Captor
private ArgumentCaptor<RemindersModel> modelCaptor;
@@ -44,7 +49,9 @@ public class RemindersTest {
public void testExecuteCommand() {
CommandContext context = CommandTestUtilities.getNoParameters();
Reminder reminder = Mockito.mock(Reminder.class);
when(reminder.getChannel()).thenReturn(channel);
Reminder secondReminder = Mockito.mock(Reminder.class);
when(secondReminder.getChannel()).thenReturn(channel);
List<Reminder> reminders = Arrays.asList(reminder, secondReminder);
AUserInAServer user = Mockito.mock(AUserInAServer.class);
when(userInServerManagementService.loadOrCreateUser(context.getAuthor())).thenReturn(user);
@@ -52,8 +59,8 @@ public class RemindersTest {
CompletableFuture<CommandResult> result = testUnit.executeAsync(context);
verify(channelService, times(1)).sendEmbedTemplateInTextChannelList(eq(Reminders.REMINDERS_RESPONSE_TEMPLATE), modelCaptor.capture(), eq(context.getChannel()));
RemindersModel usedModel = modelCaptor.getValue();
Assert.assertEquals(reminder, usedModel.getReminders().get(0));
Assert.assertEquals(secondReminder, usedModel.getReminders().get(1));
Assert.assertEquals(reminder, usedModel.getReminders().get(0).getReminder());
Assert.assertEquals(secondReminder, usedModel.getReminders().get(1).getReminder());
Assert.assertEquals(reminders.size(), usedModel.getReminders().size());
CommandTestUtilities.checkSuccessfulCompletionAsync(result);
}

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>remind</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.2.7</version>
<version>1.2.8</version>
</parent>
<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;
import dev.sheldan.abstracto.core.models.context.UserInitiatedServerContext;
import dev.sheldan.abstracto.remind.model.database.Reminder;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.SuperBuilder;
import java.util.ArrayList;
import java.util.List;
@Getter
@Setter
@SuperBuilder
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 {
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 unRemind(Long reminderId, AUserInAServer userInAServer);
}

View File

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

View File

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

View File

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

View File

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

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>starboard</artifactId>
<groupId>dev.sheldan.abstracto.modules</groupId>
<version>1.2.7</version>
<version>1.2.8</version>
</parent>
<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) {
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) {
AUserInAServer author = userInServerManagementService.loadOrCreateUser(message.getServerId(), message.getAuthor().getAuthorId());
List<AUserInAServer> userExceptAuthor = getUsersExcept(reaction.getUsers(), author);
@@ -78,7 +83,7 @@ public abstract class StarboardListener {
if (userExceptAuthor.size() >= starMinimum) {
log.info("Post reached starboard minimum. Message {} in channel {} in server {} will be starred/updated.",
message.getMessageId(), message.getChannelId(), message.getServerId());
if(starboardPostOptional.isPresent()) {
if(starboardPostExists) {
updateStarboardPost(message, userAddingReaction, adding, starboardPostOptional.get(), userExceptAuthor);
} else {
metricService.incrementCounter(STARBOARD_STARS_THRESHOLD_REACHED);
@@ -89,14 +94,14 @@ public abstract class StarboardListener {
});
}
} else {
if(starboardPostOptional.isPresent()) {
if(starboardPostExists) {
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);
starboardPostOptional.ifPresent(starboardPost -> completelyRemoveStarboardPost(starboardPost, userReacting));
}
}
} else {
if(starboardPostOptional.isPresent()) {
if(starboardPostExists) {
log.info("Removing starboard post for message {} in channel {} in server {}", message.getMessageId(), message.getChannelId(), message.getServerId());
starboardPostOptional.ifPresent(starboardPost -> completelyRemoveStarboardPost(starboardPost, userReacting));
}

View File

@@ -165,6 +165,18 @@ public class StarAddedListenerTest {
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() {
when(userInServerActing.getUserReference()).thenReturn(userActing);
when(userActing.getId()).thenReturn(USER_ACTING_ID);

View File

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

View File

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

View File

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

View File

@@ -1,9 +1,12 @@
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.handler.CommandParameterHandler;
import dev.sheldan.abstracto.core.command.handler.CommandParameterIterators;
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.service.TrackedEmoteService;
import net.dv8tion.jda.api.entities.Emote;
@@ -24,6 +27,9 @@ public class TrackedEmoteParameterHandler implements CommandParameterHandler {
@Autowired
private TrackedEmoteService trackedEmoteService;
@Autowired
private CommandService commandService;
/**
* This {@link CommandParameterHandler} only handles {@link TrackedEmote}
* @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 iterators The {@link CommandParameterIterators} containing all available iterators to directly retrieve JDA related
* 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 command
* @return A faked {@link TrackedEmote} based on the given input or from {@link CommandParameterIterators} directly. This {@link TrackedEmote}
* does not need to actually exist.
*/
@Override
public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Class clazz, Message context) {
Emote emote = (Emote) emoteParameterHandler.handle(input, iterators, Emote.class, context);
public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Parameter param, Message context, Command command) {
Parameter cloned = commandService.cloneParameter(param);
cloned.setType(Emote.class);
Emote emote = (Emote) emoteParameterHandler.handle(input, iterators, cloned, context, command);
if(emote != null) {
return trackedEmoteService.getFakeTrackedEmote(emote, context.getGuild());
} else {

View File

@@ -1,9 +1,12 @@
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.handler.CommandParameterHandler;
import dev.sheldan.abstracto.core.command.handler.CommandParameterIterators;
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.model.database.TrackedEmote;
import dev.sheldan.abstracto.statistic.emote.service.TrackedEmoteService;
@@ -28,6 +31,9 @@ public class TrackedEmoteParameterParameterHandler implements CommandParameterHa
@Autowired
private TrackedEmoteService trackedEmoteService;
@Autowired
private CommandService commandService;
/**
* This {@link CommandParameterHandler} only handles {@link TrackEmoteParameter}
* @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 iterators The {@link CommandParameterIterators} containing all available iterators to directly retrieve JDA related
* 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 command
* @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}.
*/
@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();
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) {
parameter.setEmote(emote);
parameter.setTrackedEmote(trackedEmoteService.getFakeTrackedEmote(emote, context.getGuild()));

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>webservices</artifactId>
<version>1.2.7</version>
<version>1.2.8</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>webservices</artifactId>
<version>1.2.7</version>
<version>1.2.8</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

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

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.abstracto.core</groupId>
<artifactId>core</artifactId>
<version>1.2.7</version>
<version>1.2.8</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<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.ParameterValidator;
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.IncorrectParameterException;
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
// the parameters are going from left to right anyway
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()) {
boolean validate = parameterValidator.validate(parameters.getParameters().get(i));
if(!validate) {
@@ -243,37 +244,36 @@ public class CommandReceivedHandler extends ListenerAdapter {
}
public CompletableFuture<Parameters> getParsedParameters(UnParsedCommandParameter unParsedCommandParameter, Command command, Message message){
List<Object> parsedParameters = new ArrayList<>();
if(command.getConfiguration().getParameters() == null || command.getConfiguration().getParameters().isEmpty()) {
return CompletableFuture.completedFuture(Parameters.builder().parameters(parsedParameters).build());
List<ParseResult> parsedParameters = new ArrayList<>();
List<Parameter> parameters = command.getConfiguration().getParameters();
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());
Iterator<TextChannel> channelIterator = message.getMentionedChannels().iterator();
Iterator<Emote> emoteIterator = message.getEmotesBag().iterator();
Iterator<Member> memberIterator = message.getMentionedMembers().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);
boolean reminderActive = false;
List<CompletableFuture> futures = new ArrayList<>();
for (int i = 0; i < unParsedCommandParameter.getParameters().size(); i++) {
if(i < command.getConfiguration().getParameters().size() && !param.isRemainder()) {
param = command.getConfiguration().getParameters().get(i);
if(i < parameters.size() && !param.isRemainder()) {
param = parameters.get(i);
} else {
reminderActive = true;
param = parameters.get(parameters.size() - 1);
}
UnparsedCommandParameterPiece value = unParsedCommandParameter.getParameters().get(i);
boolean handlerMatched = false;
for (CommandParameterHandler handler : parameterHandlers) {
try {
if (handler.handles(param.getType())) {
handlerMatched = true;
if (handler.async()) {
CompletableFuture future = handler.handleAsync(value, iterators, param.getType(), message);
CompletableFuture future = handler.handleAsync(value, iterators, param, message, command);
futures.add(future);
parsedParameters.add(future);
parsedParameters.add(ParseResult.builder().parameter(param).result(future).build());
} 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;
}
@@ -285,44 +285,30 @@ public class CommandReceivedHandler extends ListenerAdapter {
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()) {
CompletableFuture<Parameters> multipleFuturesFuture = new CompletableFuture<>();
CompletableFuture<Void> combinedFuture = FutureUtils.toSingleFuture(futures);
combinedFuture.thenAccept(aVoid -> {
List<Object> usableParameters = parsedParameters.stream().map(o -> {
if(o instanceof CompletableFuture) {
return ((CompletableFuture) o).join();
List<Object> allParamResults = parsedParameters.stream().map(o -> {
if(o.getResult() instanceof CompletableFuture) {
return ((CompletableFuture) o.getResult()).join();
} else {
return o;
return o.getResult();
}
}).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 -> {
@@ -331,11 +317,38 @@ public class CommandReceivedHandler extends ListenerAdapter {
});
return multipleFuturesFuture;
} else {
Parameters parameters = Parameters.builder().parameters(parsedParameters).build();
return CompletableFuture.completedFuture(parameters);
Parameters resultParameters = Parameters.builder().parameters(extractParametersFromParsed(parsedParameters)).build();
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
public void postConstruct() {
metricService.registerCounter(COMMANDS_PROCESSED_COUNTER, "Commands processed");

View File

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

View File

@@ -1,9 +1,12 @@
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.AEmoteParameterHandler;
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.service.EmoteService;
import net.dv8tion.jda.api.entities.Emote;
@@ -20,14 +23,19 @@ public class AEmoteParameterHandlerImpl implements AEmoteParameterHandler {
@Autowired
private EmoteService emoteService;
@Autowired
private CommandService commandService;
@Override
public boolean handles(Class clazz) {
return clazz.equals(AEmote.class);
}
@Override
public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Class clazz, Message context) {
Emote emote = (Emote) emoteParameterHandler.handle(input, iterators, Emote.class, context);
public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Parameter param, Message context, Command command) {
Parameter cloned = commandService.cloneParameter(param);
cloned.setType(Emote.class);
Emote emote = (Emote) emoteParameterHandler.handle(input, iterators, cloned, context, command);
if(emote != null) {
return emoteService.getFakeEmoteFromEmote(emote);
} else {

View File

@@ -1,9 +1,12 @@
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.ARoleParameterHandler;
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.service.RoleService;
import net.dv8tion.jda.api.entities.Message;
@@ -20,14 +23,19 @@ public class ARoleParameterHandlerImpl implements ARoleParameterHandler {
@Autowired
private RoleService roleService;
@Autowired
private CommandService commandService;
@Override
public boolean handles(Class clazz) {
return clazz.equals(ARole.class);
}
@Override
public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Class clazz, Message context) {
Role role = (Role) roleParameterHandler.handle(input, iterators, Role.class, context);
public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Parameter param, Message context, Command command) {
Parameter cloned = commandService.cloneParameter(param);
cloned.setType(Role.class);
Role role = (Role) roleParameterHandler.handle(input, iterators, cloned, context, command);
return roleService.getFakeRoleFromRole(role);
}

View File

@@ -1,9 +1,12 @@
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.AUserInAServerParameterHandler;
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.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
@@ -23,10 +26,15 @@ public class AUserInAServerParameterHandlerImpl implements AUserInAServerParamet
@Autowired
private UserInServerManagementService userInServerManagementService;
@Autowired
private CommandService commandService;
@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<>();
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 {
AUserInAServer actualInstance;
if (throwable == null) {

View File

@@ -1,6 +1,8 @@
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.BooleanParameterHandler;
import net.dv8tion.jda.api.entities.Message;
@@ -14,7 +16,7 @@ public class BooleanParameterHandlerImpl implements BooleanParameterHandler {
}
@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());
}

View File

@@ -1,6 +1,8 @@
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.ChannelGroupNotFoundException;
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
import dev.sheldan.abstracto.core.command.handler.provided.ChannelGroupParameterHandler;
@@ -23,7 +25,7 @@ public class ChannelGroupParameterHandlerImpl implements ChannelGroupParameterHa
private ServerManagementService serverManagementService;
@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());
String inputString = (String) input.getValue();
AChannelGroup actualInstance = channelGroupManagementService.findByNameAndServerOptional(inputString, server)

View File

@@ -1,6 +1,8 @@
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.ChannelGroupTypeParameterHandler;
import dev.sheldan.abstracto.core.models.database.ChannelGroupType;
@@ -25,7 +27,7 @@ public class ChannelGroupTypeParameterHandlerImpl implements ChannelGroupTypePar
}
@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());
return ChannelGroupType
.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;
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.CommandParameterKey;
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
import dev.sheldan.abstracto.core.command.handler.provided.CommandKeyParameterHandler;
@@ -16,8 +18,8 @@ public class CommandKeyParameterHandlerImpl implements CommandKeyParameterHandle
}
@Override
public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Class clazz, Message context) {
return CommandParameterKey.getEnumFromKey(clazz, (String) input.getValue());
public Object handle(UnparsedCommandParameterPiece input, CommandParameterIterators iterators, Parameter param, Message context, Command command) {
return CommandParameterKey.getEnumFromKey(param.getType(), (String) input.getValue());
}
@Override

View File

@@ -1,6 +1,8 @@
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.DoubleParameterHandler;
import net.dv8tion.jda.api.entities.Message;
@@ -14,7 +16,7 @@ public class DoubleParameterHandlerImpl implements DoubleParameterHandler {
}
@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());
}

View File

@@ -1,6 +1,8 @@
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.DurationParameterHandler;
import dev.sheldan.abstracto.core.utils.ParseUtils;
@@ -17,7 +19,7 @@ public class DurationParameterHandlerImpl implements DurationParameterHandler {
}
@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());
}

View File

@@ -1,6 +1,8 @@
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.EmoteParameterHandler;
import net.dv8tion.jda.api.entities.Emote;
@@ -19,7 +21,7 @@ public class EmoteParameterHandlerImpl implements EmoteParameterHandler {
}
@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();
Matcher matcher = Message.MentionType.EMOTE.getPattern().matcher(inputString);
if(matcher.matches()) {

View File

@@ -1,6 +1,8 @@
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.NoAttachmentFoundException;
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
import dev.sheldan.abstracto.core.command.handler.provided.FileParameterHandler;
@@ -25,7 +27,7 @@ public class FileParameterHandlerImpl implements FileParameterHandler {
}
@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()) {
throw new NoAttachmentFoundException();
}

View File

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

View File

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

View File

@@ -1,6 +1,8 @@
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.IntegerParameterHandler;
import net.dv8tion.jda.api.entities.Message;
@@ -15,7 +17,7 @@ public class IntegerParameterHandlerImpl implements IntegerParameterHandler {
}
@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());
}

View File

@@ -1,6 +1,8 @@
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.LongParameterHandler;
import net.dv8tion.jda.api.entities.Message;
@@ -15,7 +17,7 @@ public class LongParameterHandlerImpl implements LongParameterHandler {
}
@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());
}

View File

@@ -1,6 +1,8 @@
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.AbstractoTemplatedException;
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
import dev.sheldan.abstracto.core.command.handler.provided.MemberParameterHandler;
@@ -26,7 +28,7 @@ public class MemberParameterHandlerImpl implements MemberParameterHandler {
}
@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();
Matcher matcher = Message.MentionType.USER.getPattern().matcher(inputString);
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;
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.AbstractoTemplatedException;
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
import dev.sheldan.abstracto.core.command.handler.provided.RoleParameterHandler;
@@ -20,7 +22,7 @@ public class RoleParameterHandlerImpl implements RoleParameterHandler {
}
@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();
Matcher matcher = Message.MentionType.ROLE.getPattern().matcher(inputString);
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;
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.AbstractoTemplatedException;
import dev.sheldan.abstracto.core.command.execution.UnparsedCommandParameterPiece;
import dev.sheldan.abstracto.core.command.handler.provided.TextChannelParameterHandler;
@@ -20,7 +22,7 @@ public class TextChannelParameterHandlerImpl implements TextChannelParameterHand
}
@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();
Matcher matcher = Message.MentionType.CHANNEL.getPattern().matcher(inputString);
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.ConditionalCommand;
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.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.UnParsedCommandParameter;
@@ -179,6 +180,21 @@ public class CommandServiceBean implements CommandService {
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) {
if(conditions != null) {
for (CommandCondition condition : conditions) {

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