mirror of
https://github.com/Sheldan/abstracto.git
synced 2026-01-09 10:47:16 +00:00
Compare commits
17 Commits
v1.6.13
...
feature/in
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bd00f6d248 | ||
|
|
0d5b7c5855 | ||
|
|
c791c063e3 | ||
|
|
d293d764db | ||
|
|
a7cd674cdd | ||
|
|
0abefe64e9 | ||
|
|
d1267605c1 | ||
|
|
b4ffea341c | ||
|
|
507c755809 | ||
|
|
9e0e92a530 | ||
|
|
d078b3fa87 | ||
|
|
71b7dd2383 | ||
|
|
ea0384490e | ||
|
|
b5dbc0b1ed | ||
|
|
e265eb6760 | ||
|
|
2f18b7431d | ||
|
|
2d8827fa81 |
2
.env
2
.env
@@ -1,2 +1,2 @@
|
||||
REGISTRY_PREFIX=harbor.sheldan.dev/abstracto/
|
||||
VERSION=1.6.12
|
||||
VERSION=1.6.16
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>anti-raid</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@ import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
|
||||
import dev.sheldan.abstracto.core.listener.async.jda.AsyncMessageReceivedListener;
|
||||
import dev.sheldan.abstracto.core.models.listener.MessageReceivedModel;
|
||||
import io.micrometer.tracing.Span;
|
||||
import io.micrometer.tracing.Tracer;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.channel.ChannelType;
|
||||
@@ -19,13 +21,22 @@ public class MassPingMessageListener implements AsyncMessageReceivedListener {
|
||||
@Autowired
|
||||
private MassPingService massPingService;
|
||||
|
||||
@Autowired
|
||||
private Tracer tracer;
|
||||
|
||||
@Override
|
||||
public DefaultListenerResult execute(MessageReceivedModel model) {
|
||||
Message message = model.getMessage();
|
||||
if(message.getAuthor().isBot() || message.isWebhookMessage() || !message.isFromGuild() || !message.isFromType(ChannelType.TEXT)) {
|
||||
return DefaultListenerResult.IGNORED;
|
||||
Span newSpan = tracer.nextSpan().name("mass-ping-filter");
|
||||
try (Tracer.SpanInScope ws = this.tracer.withSpan(newSpan.start())) {
|
||||
Message message = model.getMessage();
|
||||
if (message.getAuthor().isBot() || message.isWebhookMessage() || !message.isFromGuild() || !message.isFromType(ChannelType.TEXT)) {
|
||||
newSpan.end();
|
||||
return DefaultListenerResult.IGNORED;
|
||||
}
|
||||
massPingService.processMessage(message).whenComplete((unused, throwable) -> {
|
||||
newSpan.end();
|
||||
});
|
||||
}
|
||||
massPingService.processMessage(message);
|
||||
return DefaultListenerResult.PROCESSED;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>anti-raid</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>assignable-roles</artifactId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>assignable-roles</artifactId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>assignable-roles-int</artifactId>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>custom-command</artifactId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>custom-command</artifactId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>dynamic-activity</artifactId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>dynamic-activity</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>entertainment</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>entertainment</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>experience-tracking</artifactId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -97,7 +97,7 @@ public class LeaderBoardCommand extends AbstractConditionableCommand {
|
||||
} else {
|
||||
leaderBoard = userExperienceService.findLeaderBoardData(server, page);
|
||||
}
|
||||
List<CompletableFuture> futures = new ArrayList<>();
|
||||
List<CompletableFuture<?>> futures = new ArrayList<>();
|
||||
CompletableFuture<List<LeaderBoardEntryModel>> completableFutures = converter.fromLeaderBoard(leaderBoard, actorUser.getGuild().getIdLong());
|
||||
futures.add(completableFutures);
|
||||
log.info("Rendering leaderboard for page {} in server {} for user {}.", page, actorUser.getId(), actorUser.getGuild().getId());
|
||||
|
||||
@@ -27,6 +27,8 @@ import dev.sheldan.abstracto.experience.service.ExperienceLevelService;
|
||||
import dev.sheldan.abstracto.experience.service.management.UserExperienceManagementService;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import io.micrometer.tracing.Span;
|
||||
import io.micrometer.tracing.Tracer;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
@@ -83,11 +85,14 @@ public class Rank extends AbstractConditionableCommand {
|
||||
@Value("${abstracto.experience.leaderboard.externalUrl}")
|
||||
private String leaderboardExternalURL;
|
||||
|
||||
@Autowired
|
||||
private Tracer tracer;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
|
||||
List<Object> parameters = commandContext.getParameters().getParameters();
|
||||
Member targetMember = !parameters.isEmpty() ? (Member) parameters.get(0) : commandContext.getAuthor();
|
||||
if(!targetMember.getGuild().equals(commandContext.getGuild())) {
|
||||
if (!targetMember.getGuild().equals(commandContext.getGuild())) {
|
||||
throw new EntityGuildMismatchException();
|
||||
}
|
||||
AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(targetMember);
|
||||
@@ -97,10 +102,13 @@ public class Rank extends AbstractConditionableCommand {
|
||||
.builder()
|
||||
.member(targetMember)
|
||||
.build();
|
||||
Span span = tracer.currentSpan();
|
||||
return future.thenCompose(leaderBoardEntryModel -> {
|
||||
try (Tracer.SpanInScope ws = tracer.withSpan(span)) {
|
||||
MessageToSend messageToSend = self.renderMessageToSend(targetMember, rankModel, leaderBoardEntryModel.get(0));
|
||||
return FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, commandContext.getChannel()));
|
||||
}).thenApply(result -> CommandResult.fromIgnored());
|
||||
}
|
||||
}).thenApply(result -> CommandResult.fromIgnored());
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@@ -133,7 +141,7 @@ public class Rank extends AbstractConditionableCommand {
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
||||
Member targetMember;
|
||||
if(slashCommandParameterService.hasCommandOption(MEMBER_PARAMETER, event)) {
|
||||
if (slashCommandParameterService.hasCommandOption(MEMBER_PARAMETER, event)) {
|
||||
targetMember = slashCommandParameterService.getCommandOption(MEMBER_PARAMETER, event, Member.class);
|
||||
} else {
|
||||
targetMember = event.getMember();
|
||||
@@ -145,9 +153,12 @@ public class Rank extends AbstractConditionableCommand {
|
||||
.builder()
|
||||
.member(targetMember)
|
||||
.build();
|
||||
Span span = tracer.currentSpan();
|
||||
return future.thenCompose(leaderBoardEntryModel -> {
|
||||
MessageToSend messageToSend = self.renderMessageToSend(targetMember, rankModel, leaderBoardEntryModel.get(0));
|
||||
return interactionService.replyMessageToSend(messageToSend, event);
|
||||
try (Tracer.SpanInScope ws = tracer.withSpan(span)) {
|
||||
MessageToSend messageToSend = self.renderMessageToSend(targetMember, rankModel, leaderBoardEntryModel.get(0));
|
||||
return interactionService.replyMessageToSend(messageToSend, event);
|
||||
}
|
||||
}).thenApply(result -> CommandResult.fromIgnored());
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,8 @@ import dev.sheldan.abstracto.core.service.MemberService;
|
||||
import dev.sheldan.abstracto.experience.model.LeaderBoard;
|
||||
import dev.sheldan.abstracto.experience.model.LeaderBoardEntry;
|
||||
import dev.sheldan.abstracto.experience.model.template.LeaderBoardEntryModel;
|
||||
import dev.sheldan.abstracto.experience.service.management.UserExperienceManagementService;
|
||||
import io.micrometer.tracing.Span;
|
||||
import io.micrometer.tracing.Tracer;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -29,10 +30,7 @@ public class LeaderBoardModelConverter {
|
||||
private MemberService memberService;
|
||||
|
||||
@Autowired
|
||||
private UserExperienceManagementService userExperienceManagementService;
|
||||
|
||||
@Autowired
|
||||
private LeaderBoardModelConverter self;
|
||||
private Tracer tracer;
|
||||
|
||||
/**
|
||||
* Converts the complete {@link LeaderBoard leaderBoard} into a list of {@link LeaderBoardEntryModel leaderbaordEntryModels} which contain additional
|
||||
@@ -62,12 +60,15 @@ public class LeaderBoardModelConverter {
|
||||
.build();
|
||||
})
|
||||
.collect(Collectors.toMap(LeaderBoardEntryModel::getUserId, Function.identity()));
|
||||
Span span = tracer.currentSpan();
|
||||
return memberService.getMembersInServerAsync(serverId, userIds).thenApply(members -> {
|
||||
members.forEach(member -> models.get(member.getIdLong()).setMember(member));
|
||||
return new ArrayList<>(models.values())
|
||||
.stream()
|
||||
.sorted(Comparator.comparing(LeaderBoardEntryModel::getRank)).
|
||||
collect(Collectors.toList());
|
||||
try (Tracer.SpanInScope ws = tracer.withSpan(span)) {
|
||||
members.forEach(member -> models.get(member.getIdLong()).setMember(member));
|
||||
return new ArrayList<>(models.values())
|
||||
.stream()
|
||||
.sorted(Comparator.comparing(LeaderBoardEntryModel::getRank)).
|
||||
collect(Collectors.toList());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@ import dev.sheldan.abstracto.core.listener.sync.jda.MessageReceivedListener;
|
||||
import dev.sheldan.abstracto.core.models.listener.MessageReceivedModel;
|
||||
import dev.sheldan.abstracto.experience.config.ExperienceFeatureDefinition;
|
||||
import dev.sheldan.abstracto.experience.service.AUserExperienceService;
|
||||
import io.micrometer.tracing.Span;
|
||||
import io.micrometer.tracing.Tracer;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -23,17 +25,26 @@ public class ExperienceTrackerListener implements AsyncMessageReceivedListener {
|
||||
@Autowired
|
||||
private AUserExperienceService userExperienceService;
|
||||
|
||||
@Autowired
|
||||
private Tracer tracer;
|
||||
|
||||
@Override
|
||||
public DefaultListenerResult execute(MessageReceivedModel model) {
|
||||
Message message = model.getMessage();
|
||||
if(!message.isFromGuild() || message.isWebhookMessage() || message.getType().isSystem() || message.getAuthor().isBot()) {
|
||||
return DefaultListenerResult.IGNORED;
|
||||
}
|
||||
if(userExperienceService.experienceGainEnabledInChannel(message.getChannel())) {
|
||||
userExperienceService.addExperience(message.getMember(), model.getMessage());
|
||||
return DefaultListenerResult.PROCESSED;
|
||||
} else {
|
||||
return DefaultListenerResult.IGNORED;
|
||||
Span newSpan = tracer.nextSpan().name("experience-tracker");
|
||||
try (Tracer.SpanInScope ws = this.tracer.withSpan(newSpan.start())) {
|
||||
Message message = model.getMessage();
|
||||
if(!message.isFromGuild() || message.isWebhookMessage() || message.getType().isSystem() || message.getAuthor().isBot()) {
|
||||
newSpan.end();
|
||||
return DefaultListenerResult.IGNORED;
|
||||
}
|
||||
if(userExperienceService.experienceGainEnabledInChannel(message.getChannel())) {
|
||||
userExperienceService.addExperience(message.getMember(), model.getMessage()).whenComplete((unused, throwable) -> {
|
||||
newSpan.end();
|
||||
});
|
||||
return DefaultListenerResult.PROCESSED;
|
||||
} else {
|
||||
return DefaultListenerResult.IGNORED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package dev.sheldan.abstracto.experience.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.metric.service.MetricUtils;
|
||||
import dev.sheldan.abstracto.core.models.database.*;
|
||||
import dev.sheldan.abstracto.core.models.template.display.MemberDisplay;
|
||||
import dev.sheldan.abstracto.core.models.template.display.RoleDisplay;
|
||||
@@ -25,6 +26,8 @@ import dev.sheldan.abstracto.experience.service.management.DisabledExpRoleManage
|
||||
import dev.sheldan.abstracto.experience.service.management.ExperienceLevelManagementService;
|
||||
import dev.sheldan.abstracto.experience.service.management.ExperienceRoleManagementService;
|
||||
import dev.sheldan.abstracto.experience.service.management.UserExperienceManagementService;
|
||||
import io.micrometer.tracing.Span;
|
||||
import io.micrometer.tracing.Tracer;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
@@ -114,8 +117,11 @@ public class AUserExperienceServiceBean implements AUserExperienceService {
|
||||
@Qualifier("experienceUpdateExecutor")
|
||||
private TaskExecutor experienceUpdateExecutor;
|
||||
|
||||
@Autowired
|
||||
private Tracer tracer;
|
||||
|
||||
@Override
|
||||
public void addExperience(Member member, Message message) {
|
||||
public CompletableFuture<Void> addExperience(Member member, Message message) {
|
||||
runTimeExperienceService.takeLock();
|
||||
try {
|
||||
Map<Long, Map<Long, Instant>> runtimeExperience = runTimeExperienceService.getRuntimeExperience();
|
||||
@@ -141,7 +147,7 @@ public class AUserExperienceServiceBean implements AUserExperienceService {
|
||||
// we store when the user is eligible for experience _again_
|
||||
Long maxSeconds = configService.getLongValueOrConfigDefault(EXP_COOLDOWN_SECONDS_KEY, serverId);
|
||||
serverExperience.put(userId, Instant.now().plus(maxSeconds, ChronoUnit.SECONDS));
|
||||
CompletableFuture.runAsync(() -> self.addExperienceToMember(member, message), experienceUpdateExecutor).exceptionally(throwable -> {
|
||||
return CompletableFuture.runAsync(() -> self.addExperienceToMember(member, message), MetricUtils.wrapExecutor(experienceUpdateExecutor)).exceptionally(throwable -> {
|
||||
log.error("Failed to add experience to member {} in server {}.", message.getAuthor().getId(), message.getGuild().getIdLong(), throwable);
|
||||
return null;
|
||||
});
|
||||
@@ -149,6 +155,7 @@ public class AUserExperienceServiceBean implements AUserExperienceService {
|
||||
} finally {
|
||||
runTimeExperienceService.releaseLock();
|
||||
}
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
|
||||
|
||||
@@ -297,61 +304,69 @@ public class AUserExperienceServiceBean implements AUserExperienceService {
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void addExperienceToMember(Member member, Message message) {
|
||||
long serverId = member.getGuild().getIdLong();
|
||||
AServer server = serverManagementService.loadOrCreate(serverId);
|
||||
List<ADisabledExpRole> disabledExpRoles = disabledExpRoleManagementService.getDisabledRolesForServer(server);
|
||||
List<ARole> disabledRoles = disabledExpRoles
|
||||
public CompletableFuture<Void> addExperienceToMember(Member member, Message message) {
|
||||
CompletableFuture<Void> notificationFuture = CompletableFuture.completedFuture(null);
|
||||
CompletableFuture<Void> levelActionFuture = CompletableFuture.completedFuture(null);
|
||||
CompletableFuture<Void> roleFuture = CompletableFuture.completedFuture(null);
|
||||
Span newSpan = tracer.nextSpan().name("experience-adding");
|
||||
try (Tracer.SpanInScope ws = this.tracer.withSpan(newSpan.start())) {
|
||||
long serverId = member.getGuild().getIdLong();
|
||||
AServer server = serverManagementService.loadOrCreate(serverId);
|
||||
List<ADisabledExpRole> disabledExpRoles = disabledExpRoleManagementService.getDisabledRolesForServer(server);
|
||||
List<ARole> disabledRoles = disabledExpRoles
|
||||
.stream()
|
||||
.map(ADisabledExpRole::getRole)
|
||||
.collect(Collectors.toList());
|
||||
if(roleService.hasAnyOfTheRoles(member, disabledRoles)) {
|
||||
log.debug("User {} has a experience disable role in server {} - not giving any experience.", member.getIdLong(), serverId);
|
||||
return;
|
||||
}
|
||||
AUserInAServer userInAServer = userInServerManagementService.loadOrCreateUser(member);
|
||||
Long userInServerId = userInAServer.getUserInServerId();
|
||||
Optional<AUserExperience> aUserExperienceOptional = userExperienceManagementService.findByUserInServerIdOptional(userInAServer.getUserInServerId());
|
||||
AUserExperience aUserExperience = aUserExperienceOptional.orElseGet(() -> userExperienceManagementService.createUserInServer(userInAServer));
|
||||
if(Boolean.FALSE.equals(aUserExperience.getExperienceGainDisabled())) {
|
||||
List<AExperienceLevel> levels = experienceLevelManagementService.getLevelConfig();
|
||||
levels.sort(Comparator.comparing(AExperienceLevel::getExperienceNeeded));
|
||||
if (roleService.hasAnyOfTheRoles(member, disabledRoles)) {
|
||||
log.debug("User {} has a experience disable role in server {} - not giving any experience.", member.getIdLong(), serverId);
|
||||
newSpan.end();
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
AUserInAServer userInAServer = userInServerManagementService.loadOrCreateUser(member);
|
||||
Long userInServerId = userInAServer.getUserInServerId();
|
||||
Optional<AUserExperience> aUserExperienceOptional = userExperienceManagementService.findByUserInServerIdOptional(userInAServer.getUserInServerId());
|
||||
AUserExperience aUserExperience = aUserExperienceOptional.orElseGet(() -> userExperienceManagementService.createUserInServer(userInAServer));
|
||||
if (Boolean.FALSE.equals(aUserExperience.getExperienceGainDisabled())) {
|
||||
List<AExperienceLevel> levels = experienceLevelManagementService.getLevelConfig();
|
||||
levels.sort(Comparator.comparing(AExperienceLevel::getExperienceNeeded));
|
||||
|
||||
Long minExp = configService.getLongValueOrConfigDefault(ExperienceFeatureConfig.MIN_EXP_KEY, serverId);
|
||||
Long maxExp = configService.getLongValueOrConfigDefault(ExperienceFeatureConfig.MAX_EXP_KEY, serverId);
|
||||
Double multiplier = configService.getDoubleValueOrConfigDefault(ExperienceFeatureConfig.EXP_MULTIPLIER_KEY, serverId);
|
||||
Long experienceRange = maxExp - minExp + 1;
|
||||
Long gainedExperience = (secureRandom.nextInt(experienceRange.intValue()) + minExp);
|
||||
gainedExperience = (long) Math.floor(gainedExperience * multiplier);
|
||||
Long minExp = configService.getLongValueOrConfigDefault(ExperienceFeatureConfig.MIN_EXP_KEY, serverId);
|
||||
Long maxExp = configService.getLongValueOrConfigDefault(ExperienceFeatureConfig.MAX_EXP_KEY, serverId);
|
||||
Double multiplier = configService.getDoubleValueOrConfigDefault(ExperienceFeatureConfig.EXP_MULTIPLIER_KEY, serverId);
|
||||
Long experienceRange = maxExp - minExp + 1;
|
||||
Long gainedExperience = (secureRandom.nextInt(experienceRange.intValue()) + minExp);
|
||||
gainedExperience = (long) Math.floor(gainedExperience * multiplier);
|
||||
|
||||
List<AExperienceRole> roles = experienceRoleManagementService.getExperienceRolesForServer(server);
|
||||
roles.sort(Comparator.comparing(role -> role.getLevel().getLevel()));
|
||||
List<AExperienceRole> roles = experienceRoleManagementService.getExperienceRolesForServer(server);
|
||||
roles.sort(Comparator.comparing(role -> role.getLevel().getLevel()));
|
||||
|
||||
log.debug("Handling {}. The user gains {}.", userInServerId, gainedExperience);
|
||||
log.debug("Handling {}. The user gains {}.", userInServerId, gainedExperience);
|
||||
|
||||
Long oldExperience = aUserExperience.getExperience();
|
||||
Long newExperienceCount = oldExperience + gainedExperience;
|
||||
aUserExperience.setExperience(newExperienceCount);
|
||||
AExperienceLevel newLevel = calculateLevel(levels, newExperienceCount);
|
||||
RoleCalculationResult result = RoleCalculationResult
|
||||
Long oldExperience = aUserExperience.getExperience();
|
||||
Long newExperienceCount = oldExperience + gainedExperience;
|
||||
aUserExperience.setExperience(newExperienceCount);
|
||||
AExperienceLevel newLevel = calculateLevel(levels, newExperienceCount);
|
||||
RoleCalculationResult result = RoleCalculationResult
|
||||
.builder()
|
||||
.build();
|
||||
boolean userChangesLevel = !Objects.equals(newLevel.getLevel(), aUserExperience.getCurrentLevel().getLevel());
|
||||
Integer oldLevel = aUserExperience.getCurrentLevel() != null ? aUserExperience.getCurrentLevel().getLevel() : 0;
|
||||
if(userChangesLevel) {
|
||||
log.info("User {} in server {} changed level. New {}, Old {}.", member.getIdLong(),
|
||||
boolean userChangesLevel = !Objects.equals(newLevel.getLevel(), aUserExperience.getCurrentLevel().getLevel());
|
||||
Integer oldLevel = aUserExperience.getCurrentLevel() != null ? aUserExperience.getCurrentLevel().getLevel() : 0;
|
||||
if (userChangesLevel) {
|
||||
log.info("User {} in server {} changed level. New {}, Old {}.", member.getIdLong(),
|
||||
member.getGuild().getIdLong(), newLevel.getLevel(),
|
||||
oldLevel);
|
||||
aUserExperience.setCurrentLevel(newLevel);
|
||||
AExperienceRole calculatedNewRole = experienceRoleService.calculateRole(roles, newLevel.getLevel());
|
||||
Long oldRoleId = aUserExperience.getCurrentExperienceRole() != null && aUserExperience.getCurrentExperienceRole().getRole() != null ? aUserExperience.getCurrentExperienceRole().getRole().getId() : null;
|
||||
Long newRoleId = calculatedNewRole != null && calculatedNewRole.getRole() != null ? calculatedNewRole.getRole().getId() : null;
|
||||
result.setOldRoleId(oldRoleId);
|
||||
result.setNewRoleId(newRoleId);
|
||||
if(message != null
|
||||
aUserExperience.setCurrentLevel(newLevel);
|
||||
AExperienceRole calculatedNewRole = experienceRoleService.calculateRole(roles, newLevel.getLevel());
|
||||
Long oldRoleId = aUserExperience.getCurrentExperienceRole() != null && aUserExperience.getCurrentExperienceRole().getRole() != null ?
|
||||
aUserExperience.getCurrentExperienceRole().getRole().getId() : null;
|
||||
Long newRoleId = calculatedNewRole != null && calculatedNewRole.getRole() != null ? calculatedNewRole.getRole().getId() : null;
|
||||
result.setOldRoleId(oldRoleId);
|
||||
result.setNewRoleId(newRoleId);
|
||||
if (message != null
|
||||
&& aUserExperience.getLevelUpNotification()
|
||||
&& featureModeService.featureModeActive(ExperienceFeatureDefinition.EXPERIENCE, serverId, ExperienceFeatureMode.LEVEL_UP_NOTIFICATION)) {
|
||||
LevelUpNotificationModel model = LevelUpNotificationModel
|
||||
&&
|
||||
featureModeService.featureModeActive(ExperienceFeatureDefinition.EXPERIENCE, serverId, ExperienceFeatureMode.LEVEL_UP_NOTIFICATION)) {
|
||||
LevelUpNotificationModel model = LevelUpNotificationModel
|
||||
.builder()
|
||||
.memberDisplay(MemberDisplay.fromMember(member))
|
||||
.oldExperience(oldExperience)
|
||||
@@ -361,59 +376,71 @@ public class AUserExperienceServiceBean implements AUserExperienceService {
|
||||
.newRole(oldRoleId != null ? RoleDisplay.fromRole(oldRoleId) : null)
|
||||
.newRole(newRoleId != null ? RoleDisplay.fromRole(newRoleId) : null)
|
||||
.build();
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate("experience_level_up_notification", model, serverId);
|
||||
FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, message.getChannel())).thenAccept(unused -> {
|
||||
log.info("Sent level up notification to user {} in server {} in channel {}.", member.getIdLong(), serverId, message.getChannel().getIdLong());
|
||||
}).exceptionally(throwable -> {
|
||||
log.warn("Failed to send level up notification to user {} in server {} in channel {}.", member.getIdLong(), serverId, message.getChannel().getIdLong());
|
||||
return null;
|
||||
});
|
||||
}
|
||||
aUserExperience.setCurrentExperienceRole(calculatedNewRole);
|
||||
}
|
||||
aUserExperience.setMessageCount(aUserExperience.getMessageCount() + 1L);
|
||||
if(userChangesLevel && featureModeService.featureModeActive(ExperienceFeatureDefinition.EXPERIENCE, server, ExperienceFeatureMode.LEVEL_ACTION)) {
|
||||
levelActionService.applyLevelActionsToUser(aUserExperience, oldLevel)
|
||||
.thenAccept(unused -> {
|
||||
log.info("Executed level actions for user {}.", userInServerId);
|
||||
})
|
||||
.exceptionally(throwable -> {
|
||||
log.warn("Failed to execute level actions for user {}.", userInServerId, throwable);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
if(aUserExperienceOptional.isEmpty()) {
|
||||
userExperienceManagementService.saveUser(aUserExperience);
|
||||
}
|
||||
if(!Objects.equals(result.getOldRoleId(), result.getNewRoleId())) {
|
||||
if(result.getOldRoleId() != null && result.getNewRoleId() != null) {
|
||||
roleService.updateRolesIds(member, Arrays.asList(result.getOldRoleId()), Arrays.asList(result.getNewRoleId())).thenAccept(unused -> {
|
||||
log.debug("Removed role {} from and added role {} to member {} in server {}.", result.getOldRoleId(), result.getNewRoleId(), member.getIdLong(), member.getGuild().getIdLong());
|
||||
}).exceptionally(throwable -> {
|
||||
log.warn("Failed to remove role {} from and add role {} to member {} in server {}.", result.getOldRoleId(), result.getNewRoleId(), member.getIdLong(), member.getGuild().getIdLong(), throwable);
|
||||
return null;
|
||||
});
|
||||
} else {
|
||||
if(result.getOldRoleId() != null) {
|
||||
roleService.removeRoleFromMemberAsync(member, result.getOldRoleId()).thenAccept(unused -> {
|
||||
log.debug("Removed role {} from member {} in server {}.", result.getOldRoleId(), member.getIdLong(), member.getGuild().getIdLong());
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate("experience_level_up_notification", model, serverId);
|
||||
FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, message.getChannel())).thenAccept(unused -> {
|
||||
log.info("Sent level up notification to user {} in server {} in channel {}.", member.getIdLong(), serverId,
|
||||
message.getChannel().getIdLong());
|
||||
}).exceptionally(throwable -> {
|
||||
log.warn("Failed to remove role {} from member {} in server {}.", result.getOldRoleId(), member.getIdLong(), member.getGuild().getIdLong(), throwable);
|
||||
log.warn("Failed to send level up notification to user {} in server {} in channel {}.", member.getIdLong(), serverId,
|
||||
message.getChannel().getIdLong());
|
||||
return null;
|
||||
});
|
||||
}
|
||||
if(result.getNewRoleId() != null) {
|
||||
roleService.addRoleToMemberAsync(member, result.getNewRoleId()).thenAccept(unused -> {
|
||||
log.debug("Added role {} to member {} in server {}.", result.getNewRoleId(), member.getIdLong(), member.getGuild().getIdLong());
|
||||
}).exceptionally(throwable -> {
|
||||
log.warn("Failed to add role {} to member {} in server {}.", result.getOldRoleId(), member.getIdLong(), member.getGuild().getIdLong(), throwable);
|
||||
aUserExperience.setCurrentExperienceRole(calculatedNewRole);
|
||||
}
|
||||
aUserExperience.setMessageCount(aUserExperience.getMessageCount() + 1L);
|
||||
if (userChangesLevel &&
|
||||
featureModeService.featureModeActive(ExperienceFeatureDefinition.EXPERIENCE, server, ExperienceFeatureMode.LEVEL_ACTION)) {
|
||||
levelActionService.applyLevelActionsToUser(aUserExperience, oldLevel)
|
||||
.thenAccept(unused -> {
|
||||
log.info("Executed level actions for user {}.", userInServerId);
|
||||
})
|
||||
.exceptionally(throwable -> {
|
||||
log.warn("Failed to execute level actions for user {}.", userInServerId, throwable);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
if (aUserExperienceOptional.isEmpty()) {
|
||||
userExperienceManagementService.saveUser(aUserExperience);
|
||||
}
|
||||
if (!Objects.equals(result.getOldRoleId(), result.getNewRoleId())) {
|
||||
if (result.getOldRoleId() != null && result.getNewRoleId() != null) {
|
||||
roleService.updateRolesIds(member, Arrays.asList(result.getOldRoleId()), Arrays.asList(result.getNewRoleId())).thenAccept(unused -> {
|
||||
log.debug("Removed role {} from and added role {} to member {} in server {}.", result.getOldRoleId(), result.getNewRoleId(),
|
||||
member.getIdLong(), member.getGuild().getIdLong());
|
||||
}).exceptionally(throwable -> {
|
||||
log.warn("Failed to remove role {} from and add role {} to member {} in server {}.", result.getOldRoleId(), result.getNewRoleId(),
|
||||
member.getIdLong(), member.getGuild().getIdLong(), throwable);
|
||||
return null;
|
||||
});
|
||||
} else {
|
||||
if (result.getOldRoleId() != null) {
|
||||
roleService.removeRoleFromMemberAsync(member, result.getOldRoleId()).thenAccept(unused -> {
|
||||
log.debug("Removed role {} from member {} in server {}.", result.getOldRoleId(), member.getIdLong(),
|
||||
member.getGuild().getIdLong());
|
||||
}).exceptionally(throwable -> {
|
||||
log.warn("Failed to remove role {} from member {} in server {}.", result.getOldRoleId(), member.getIdLong(),
|
||||
member.getGuild().getIdLong(), throwable);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
if (result.getNewRoleId() != null) {
|
||||
roleService.addRoleToMemberAsync(member, result.getNewRoleId()).thenAccept(unused -> {
|
||||
log.debug("Added role {} to member {} in server {}.", result.getNewRoleId(), member.getIdLong(), member.getGuild().getIdLong());
|
||||
}).exceptionally(throwable -> {
|
||||
log.warn("Failed to add role {} to member {} in server {}.", result.getOldRoleId(), member.getIdLong(),
|
||||
member.getGuild().getIdLong(), throwable);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.debug("Experience gain was disabled. User did not gain any experience.");
|
||||
}
|
||||
} else {
|
||||
log.debug("Experience gain was disabled. User did not gain any experience.");
|
||||
return CompletableFuture.allOf(notificationFuture, levelActionFuture, roleFuture).whenComplete((unused, throwable) -> {
|
||||
newSpan.end();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>experience-tracking</artifactId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ import java.util.concurrent.CompletableFuture;
|
||||
*/
|
||||
public interface AUserExperienceService {
|
||||
String EXPERIENCE_GAIN_CHANNEL_GROUP_KEY = "experienceGain";
|
||||
void addExperience(Member member, Message message);
|
||||
CompletableFuture<Void> addExperience(Member member, Message message);
|
||||
|
||||
/**
|
||||
* Calculates the appropriate level for the given experience amount according to the given {@link AExperienceLevel levels}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>giveaway</artifactId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>giveaway-impl</artifactId>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>giveaway</artifactId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>giveaway-int</artifactId>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>giveaway</artifactId>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>image-generation</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>image-generation-impl</artifactId>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>image-generation</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>image-generation-int</artifactId>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>image-generation</artifactId>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>invite-filter</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@ import dev.sheldan.abstracto.core.models.listener.MessageReceivedModel;
|
||||
import dev.sheldan.abstracto.invitefilter.config.InviteFilterFeatureDefinition;
|
||||
import dev.sheldan.abstracto.invitefilter.service.InviteLinkFilterService;
|
||||
import dev.sheldan.abstracto.invitefilter.service.InviteLinkFilterServiceBean;
|
||||
import io.micrometer.tracing.Span;
|
||||
import io.micrometer.tracing.Tracer;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -24,6 +26,9 @@ public class InviteLinkFilterListener implements AsyncMessageReceivedListener {
|
||||
@Autowired
|
||||
private InviteLinkFilterServiceBean filterServiceBean;
|
||||
|
||||
@Autowired
|
||||
private Tracer tracer;
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return InviteFilterFeatureDefinition.INVITE_FILTER;
|
||||
@@ -31,31 +36,40 @@ public class InviteLinkFilterListener implements AsyncMessageReceivedListener {
|
||||
|
||||
@Override
|
||||
public DefaultListenerResult execute(MessageReceivedModel model) {
|
||||
Message message = model.getMessage();
|
||||
Span newSpan = tracer.nextSpan().name("invite-filter");
|
||||
try (Tracer.SpanInScope ws = this.tracer.withSpan(newSpan.start())) {
|
||||
Message message = model.getMessage();
|
||||
|
||||
if(!message.isFromGuild() || message.isWebhookMessage() || message.getType().isSystem()) {
|
||||
return DefaultListenerResult.IGNORED;
|
||||
if (!message.isFromGuild() || message.isWebhookMessage() || message.getType().isSystem()) {
|
||||
newSpan.end();
|
||||
return DefaultListenerResult.IGNORED;
|
||||
}
|
||||
|
||||
List<String> foundInvites = inviteLinkFilterService.findInvitesInMessage(message);
|
||||
|
||||
if (foundInvites.isEmpty()) {
|
||||
newSpan.end();
|
||||
return DefaultListenerResult.IGNORED;
|
||||
}
|
||||
|
||||
if (!inviteLinkFilterService.isInviteFilterActiveInChannel(message.getChannel())) {
|
||||
newSpan.end();
|
||||
return DefaultListenerResult.IGNORED;
|
||||
}
|
||||
|
||||
if (inviteLinkFilterService.isMemberImmuneAgainstInviteFilter(message.getMember())) {
|
||||
log.info("Not checking for invites in message, because author {} in channel {} in guild {} is immune against invite filter.",
|
||||
message.getMember().getIdLong(), message.getGuild().getIdLong(), message.getChannel().getIdLong());
|
||||
newSpan.end();
|
||||
return DefaultListenerResult.IGNORED;
|
||||
}
|
||||
|
||||
// only to reduce code duplication, the interface is too concrete
|
||||
filterServiceBean.resolveAndCheckInvites(message, foundInvites).whenComplete((unused, throwable) -> {
|
||||
newSpan.end();
|
||||
});
|
||||
|
||||
return DefaultListenerResult.PROCESSED;
|
||||
}
|
||||
|
||||
List<String> foundInvites = inviteLinkFilterService.findInvitesInMessage(message);
|
||||
|
||||
if(foundInvites.isEmpty()){
|
||||
return DefaultListenerResult.IGNORED;
|
||||
}
|
||||
|
||||
if(!inviteLinkFilterService.isInviteFilterActiveInChannel(message.getChannel())) {
|
||||
return DefaultListenerResult.IGNORED;
|
||||
}
|
||||
|
||||
if(inviteLinkFilterService.isMemberImmuneAgainstInviteFilter(message.getMember())) {
|
||||
log.info("Not checking for invites in message, because author {} in channel {} in guild {} is immune against invite filter.",
|
||||
message.getMember().getIdLong(), message.getGuild().getIdLong(), message.getChannel().getIdLong());
|
||||
return DefaultListenerResult.IGNORED;
|
||||
}
|
||||
|
||||
// only to reduce code duplication, the interface is too concrete
|
||||
filterServiceBean.resolveAndCheckInvites(message, foundInvites);
|
||||
|
||||
return DefaultListenerResult.PROCESSED;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -303,12 +303,13 @@ public class InviteLinkFilterServiceBean implements InviteLinkFilterService {
|
||||
return foundInvites;
|
||||
}
|
||||
|
||||
public void resolveAndCheckInvites(Message message, List<String> foundInvites) {
|
||||
public CompletableFuture<Void> resolveAndCheckInvites(Message message, List<String> foundInvites) {
|
||||
List<CompletableFuture<Invite>> inviteList = new ArrayList<>();
|
||||
JDA jda = message.getJDA();
|
||||
foundInvites.forEach(s -> inviteList.add(resolveInvite(jda, s)));
|
||||
|
||||
CompletableFutureList<Invite> list = new CompletableFutureList<>(inviteList);
|
||||
CompletableFuture<Void> returningFuture = new CompletableFuture<>();
|
||||
list.getMainFuture().whenComplete((unused, throwable) -> {
|
||||
List<Invite> invites = list.getObjects();
|
||||
Long serverId = message.getGuild().getIdLong();
|
||||
@@ -353,24 +354,31 @@ public class InviteLinkFilterServiceBean implements InviteLinkFilterService {
|
||||
}
|
||||
if(toDelete) {
|
||||
metricService.incrementCounter(MESSAGE_INVITE_FILTERED);
|
||||
messageService.deleteMessage(message);
|
||||
|
||||
CompletableFuture<Void> deletionFuture = messageService.deleteMessage(message);
|
||||
CompletableFuture<Void> notificationFuture = CompletableFuture.completedFuture(null);
|
||||
boolean trackUsages = featureModeService.featureModeActive(InviteFilterFeatureDefinition.INVITE_FILTER, serverId, InviteFilterMode.TRACK_USES);
|
||||
if(trackUsages) {
|
||||
targetServers.forEach((targetServerId, serverName) -> storeFilteredInviteLinkUsage(targetServerId, serverName, author));
|
||||
}
|
||||
boolean sendNotification = featureModeService.featureModeActive(InviteFilterFeatureDefinition.INVITE_FILTER, serverId, InviteFilterMode.FILTER_NOTIFICATIONS);
|
||||
if(sendNotification) {
|
||||
sendDeletionNotification(deletedInvites, message)
|
||||
notificationFuture = sendDeletionNotification(deletedInvites, message)
|
||||
.thenAccept(unused1 -> log.info("Sent invite deletion notification.")).exceptionally(throwable1 -> {
|
||||
log.error("Failed to send invite deletion notification.");
|
||||
return null;
|
||||
});
|
||||
}
|
||||
CompletableFuture.allOf(deletionFuture, notificationFuture).whenComplete((unused1, throwable1) -> {
|
||||
returningFuture.complete(null);
|
||||
});
|
||||
}
|
||||
}).exceptionally(throwable -> {
|
||||
log.error("Invite matching failed.", throwable);
|
||||
returningFuture.complete(null);
|
||||
return null;
|
||||
});
|
||||
return returningFuture;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>invite-filter</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>moderation-int</artifactId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>link-embed</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>link-embed</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>logging</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
|
||||
import dev.sheldan.abstracto.core.listener.async.jda.AsyncLeaveListener;
|
||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
||||
import dev.sheldan.abstracto.core.models.listener.MemberLeaveModel;
|
||||
import dev.sheldan.abstracto.core.models.template.display.RoleDisplay;
|
||||
import dev.sheldan.abstracto.core.models.template.display.UserDisplay;
|
||||
import dev.sheldan.abstracto.core.service.PostTargetService;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
@@ -13,6 +14,7 @@ import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import dev.sheldan.abstracto.logging.config.LoggingFeatureDefinition;
|
||||
import dev.sheldan.abstracto.logging.config.LoggingPostTarget;
|
||||
import dev.sheldan.abstracto.logging.model.template.MemberLeaveLogModel;
|
||||
import java.util.List;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -41,10 +43,17 @@ public class LeaveLogger implements AsyncLeaveListener {
|
||||
.userId(listenerModel.getUser().getIdLong())
|
||||
.serverId(listenerModel.getServerId())
|
||||
.build();
|
||||
List<RoleDisplay> roles = listenerModel
|
||||
.getMember()
|
||||
.getRoles()
|
||||
.stream()
|
||||
.map(RoleDisplay::fromRole)
|
||||
.toList();
|
||||
MemberLeaveLogModel model = MemberLeaveLogModel
|
||||
.builder()
|
||||
.leavingUser(leavingUser)
|
||||
.user(UserDisplay.fromUser(listenerModel.getUser()))
|
||||
.roles(roles)
|
||||
.build();
|
||||
log.debug("Logging leave event for user {} in server {}.", listenerModel.getUser().getIdLong(), listenerModel.getServerId());
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(USER_LEAVE_TEMPLATE, model, listenerModel.getServerId());
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>logging</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package dev.sheldan.abstracto.logging.model.template;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.ServerUser;
|
||||
import dev.sheldan.abstracto.core.models.template.display.RoleDisplay;
|
||||
import dev.sheldan.abstracto.core.models.template.display.UserDisplay;
|
||||
import java.util.List;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
@@ -12,4 +14,5 @@ import lombok.Setter;
|
||||
public class MemberLeaveLogModel {
|
||||
private ServerUser leavingUser;
|
||||
private UserDisplay user;
|
||||
private List<RoleDisplay> roles;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>moderation</artifactId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>moderation</artifactId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>modmail</artifactId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>modmail</artifactId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto</groupId>
|
||||
<artifactId>abstracto-application</artifactId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>profanity-filter</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -9,6 +9,8 @@ import dev.sheldan.abstracto.core.service.ProfanityService;
|
||||
import dev.sheldan.abstracto.profanityfilter.config.ProfanityFilterFeatureDefinition;
|
||||
import dev.sheldan.abstracto.profanityfilter.service.ProfanityFilterService;
|
||||
import dev.sheldan.abstracto.profanityfilter.service.ProfanityFilterServiceBean;
|
||||
import io.micrometer.tracing.Span;
|
||||
import io.micrometer.tracing.Tracer;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -29,25 +31,35 @@ public class ProfanityMessageReceivedListener implements AsyncMessageReceivedLis
|
||||
@Autowired
|
||||
private ProfanityFilterServiceBean profanityFilterServiceBean;
|
||||
|
||||
@Autowired
|
||||
private Tracer tracer;
|
||||
|
||||
@Override
|
||||
public DefaultListenerResult execute(MessageReceivedModel model) {
|
||||
Message message = model.getMessage();
|
||||
if(message.isWebhookMessage() || message.getType().isSystem() || !message.isFromGuild()) {
|
||||
return DefaultListenerResult.IGNORED;
|
||||
}
|
||||
Span newSpan = tracer.nextSpan().name("profanity-filter");
|
||||
try (Tracer.SpanInScope ws = this.tracer.withSpan(newSpan.start())) {
|
||||
Message message = model.getMessage();
|
||||
if (message.isWebhookMessage() || message.getType().isSystem() || !message.isFromGuild()) {
|
||||
newSpan.end();
|
||||
return DefaultListenerResult.IGNORED;
|
||||
}
|
||||
|
||||
if(profanityFilterService.isImmuneAgainstProfanityFilter(message.getMember())) {
|
||||
log.debug("Not checking for profanities in message, because author {} in channel {} in guild {} is immune against profanity filter.",
|
||||
message.getMember().getIdLong(), message.getGuild().getIdLong(), message.getChannel().getIdLong());
|
||||
return DefaultListenerResult.IGNORED;
|
||||
}
|
||||
if (profanityFilterService.isImmuneAgainstProfanityFilter(message.getMember())) {
|
||||
log.debug("Not checking for profanities in message, because author {} in channel {} in guild {} is immune against profanity filter.",
|
||||
message.getMember().getIdLong(), message.getGuild().getIdLong(), message.getChannel().getIdLong());
|
||||
newSpan.end();
|
||||
return DefaultListenerResult.IGNORED;
|
||||
}
|
||||
|
||||
Long serverId = model.getServerId();
|
||||
Optional<ProfanityRegex> potentialProfanityGroup = profanityService.getProfanityRegex(message.getContentRaw(), serverId);
|
||||
if(potentialProfanityGroup.isPresent()) {
|
||||
ProfanityRegex foundProfanityGroup = potentialProfanityGroup.get();
|
||||
profanityFilterServiceBean.handleProfaneMessage(message, foundProfanityGroup);
|
||||
return DefaultListenerResult.PROCESSED;
|
||||
Long serverId = model.getServerId();
|
||||
Optional<ProfanityRegex> potentialProfanityGroup = profanityService.getProfanityRegex(message.getContentRaw(), serverId);
|
||||
if (potentialProfanityGroup.isPresent()) {
|
||||
ProfanityRegex foundProfanityGroup = potentialProfanityGroup.get();
|
||||
profanityFilterServiceBean.handleProfaneMessage(message, foundProfanityGroup).whenComplete((unused, throwable) -> {
|
||||
newSpan.end();
|
||||
});
|
||||
return DefaultListenerResult.PROCESSED;
|
||||
}
|
||||
}
|
||||
return DefaultListenerResult.IGNORED;
|
||||
}
|
||||
|
||||
@@ -238,22 +238,23 @@ public class ProfanityFilterServiceBean implements ProfanityFilterService {
|
||||
return roleImmunityService.isImmune(member, PROFANITY_FILTER_EFFECT_KEY);
|
||||
}
|
||||
|
||||
public void handleProfaneMessage(Message message, ProfanityRegex foundProfanityGroup) {
|
||||
public CompletableFuture<Void> handleProfaneMessage(Message message, ProfanityRegex foundProfanityGroup) {
|
||||
metricService.incrementCounter(PROFANITIES_DETECTED_METRIC);
|
||||
if(featureModeService.featureModeActive(ProfanityFilterFeatureDefinition.PROFANITY_FILTER, message.getGuild().getIdLong(), ProfanityFilterMode.PROFANITY_REPORT)) {
|
||||
createProfanityReport(message, foundProfanityGroup).exceptionally(throwable -> {
|
||||
return createProfanityReport(message, foundProfanityGroup).exceptionally(throwable -> {
|
||||
log.error("Failed to report or persist profanities in server {} for message {} in channel {}.",
|
||||
message.getGuild().getIdLong(), message.getChannel().getIdLong(), message.getIdLong(), throwable);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
if(featureModeService.featureModeActive(ProfanityFilterFeatureDefinition.PROFANITY_FILTER, message.getGuild().getIdLong(), ProfanityFilterMode.AUTO_DELETE_PROFANITIES)) {
|
||||
messageService.deleteMessage(message).exceptionally(throwable -> {
|
||||
return messageService.deleteMessage(message).exceptionally(throwable -> {
|
||||
log.error("Failed to delete profanity message with id {} in channel {} in server {}.",
|
||||
message.getIdLong(), message.getChannel().getIdLong(), message.getGuild().getIdLong(), throwable);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>profanity-filter</artifactId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>remind</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>remind</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>repost-detection</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>repost-detection</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>starboard</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -8,6 +8,8 @@ import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.models.database.PostTarget;
|
||||
import dev.sheldan.abstracto.core.models.property.SystemConfigProperty;
|
||||
import dev.sheldan.abstracto.core.models.template.display.MemberDisplay;
|
||||
import dev.sheldan.abstracto.core.models.template.display.UserDisplay;
|
||||
import dev.sheldan.abstracto.core.service.*;
|
||||
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.DefaultConfigManagementService;
|
||||
@@ -148,22 +150,43 @@ public class StarboardServiceBean implements StarboardService {
|
||||
|
||||
|
||||
private CompletableFuture<StarboardPostModel> buildStarboardPostModel(CachedMessage message, Integer starCount) {
|
||||
return userService.retrieveUserForId(message.getAuthor().getAuthorId())
|
||||
.thenApply(user -> createStarboardModel(message, starCount, user))
|
||||
CompletableFuture<User> userFuture = userService.retrieveUserForId(message.getAuthor().getAuthorId());
|
||||
CompletableFuture<Member> memberFuture = memberService.retrieveMemberInServer(message.getAuthorAsServerUser());
|
||||
CompletableFuture<StarboardPostModel> returnedFuture = new CompletableFuture<>();
|
||||
FutureUtils.toSingleFuture(List.of(userFuture, memberFuture))
|
||||
.whenComplete((any, error) -> {
|
||||
User user = null;
|
||||
if(!userFuture.isCompletedExceptionally()) {
|
||||
user = userFuture.join();
|
||||
} else {
|
||||
log.warn("Failed to retrieve user for author {} of starboard post.", message.getAuthor().getAuthorId());
|
||||
}
|
||||
Member member = null;
|
||||
if(!memberFuture.isCompletedExceptionally()) {
|
||||
member = memberFuture.join();
|
||||
} else {
|
||||
log.warn("Failed to retrieve user for author {} of starboard post.", message.getAuthor().getAuthorId());
|
||||
}
|
||||
StarboardPostModel starboardModel = createStarboardModel(message, starCount, user, member);
|
||||
returnedFuture.complete(starboardModel);
|
||||
})
|
||||
.exceptionally(throwable -> {
|
||||
log.warn("Failed to retrieve user for author {} of starboard post.", message.getAuthor().getAuthorId(), throwable);
|
||||
return createStarboardModel(message, starCount, null);
|
||||
log.warn("Complete failure when handling creation starboard post of message {}.", message.getMessageId(), throwable);
|
||||
returnedFuture.completeExceptionally(throwable);
|
||||
return null;
|
||||
});
|
||||
return returnedFuture;
|
||||
}
|
||||
|
||||
private StarboardPostModel createStarboardModel(CachedMessage message, Integer starCount, net.dv8tion.jda.api.entities.User user) {
|
||||
private StarboardPostModel createStarboardModel(CachedMessage message, Integer starCount, net.dv8tion.jda.api.entities.User user, Member member) {
|
||||
Optional<GuildMessageChannel> channel = channelService.getMessageChannelFromServerOptional(message.getServerId(), message.getChannelId());
|
||||
Optional<Guild> guild = guildService.getGuildByIdOptional(message.getServerId());
|
||||
String starLevelEmote = getAppropriateEmote(message.getServerId(), starCount);
|
||||
return StarboardPostModel
|
||||
.builder()
|
||||
.message(message)
|
||||
.author(user)
|
||||
.authorUser(user != null ? UserDisplay.fromUser(user) : null)
|
||||
.authorMember(member != null ? MemberDisplay.fromMember(member) : null)
|
||||
.sourceChannelId(message.getChannelId())
|
||||
.channel(channel.orElse(null))
|
||||
.starCount(starCount)
|
||||
@@ -214,7 +237,7 @@ public class StarboardServiceBean implements StarboardService {
|
||||
int count = 3;
|
||||
List<CompletableFuture<StarStatsUser>> topStarGiverFutures = starboardPostReactorManagementService.retrieveTopStarGiver(serverId, count);
|
||||
List<CompletableFuture<StarStatsUser>> topStarReceiverFutures = starboardPostReactorManagementService.retrieveTopStarReceiver(serverId, count);
|
||||
List<CompletableFuture> allFutures = new ArrayList<>();
|
||||
List<CompletableFuture<?>> allFutures = new ArrayList<>();
|
||||
allFutures.addAll(topStarGiverFutures);
|
||||
allFutures.addAll(topStarReceiverFutures);
|
||||
return FutureUtils.toSingleFuture(allFutures).thenApply(aVoid -> {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>starboard</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -2,17 +2,19 @@ package dev.sheldan.abstracto.starboard.model.template;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
|
||||
import dev.sheldan.abstracto.core.models.context.ServerContext;
|
||||
import dev.sheldan.abstracto.core.models.template.display.MemberDisplay;
|
||||
import dev.sheldan.abstracto.core.models.template.display.UserDisplay;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
import net.dv8tion.jda.api.entities.User;
|
||||
import net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@SuperBuilder
|
||||
public class StarboardPostModel extends ServerContext {
|
||||
private User author;
|
||||
private UserDisplay authorUser;
|
||||
private MemberDisplay authorMember;
|
||||
private GuildMessageChannel channel;
|
||||
private Long sourceChannelId;
|
||||
private CachedMessage message;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>statistic</artifactId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -8,6 +8,8 @@ import dev.sheldan.abstracto.core.service.GuildService;
|
||||
import dev.sheldan.abstracto.statistic.config.StatisticFeatureDefinition;
|
||||
import dev.sheldan.abstracto.statistic.emote.model.database.UsedEmoteType;
|
||||
import dev.sheldan.abstracto.statistic.emote.service.TrackedEmoteService;
|
||||
import io.micrometer.tracing.Span;
|
||||
import io.micrometer.tracing.Tracer;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.emoji.CustomEmoji;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -30,13 +32,13 @@ public class EmoteTrackingListener implements AsyncMessageReceivedListener {
|
||||
@Autowired
|
||||
private GuildService guildService;
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return StatisticFeatureDefinition.EMOTE_TRACKING;
|
||||
}
|
||||
@Autowired
|
||||
private Tracer tracer;
|
||||
|
||||
@Override
|
||||
public DefaultListenerResult execute(MessageReceivedModel model) {
|
||||
Span newSpan = tracer.nextSpan().name("experience-tracker");
|
||||
try (Tracer.SpanInScope ws = this.tracer.withSpan(newSpan.start())) {
|
||||
Message message = model.getMessage();
|
||||
if(!message.isFromGuild() || message.isWebhookMessage() || message.getType().isSystem()) {
|
||||
return DefaultListenerResult.IGNORED;
|
||||
@@ -50,5 +52,15 @@ public class EmoteTrackingListener implements AsyncMessageReceivedListener {
|
||||
trackedEmoteService.addEmoteToRuntimeStorage(groupedEmotes.get(0), guildService.getGuildById(model.getServerId()), (long) groupedEmotes.size(), UsedEmoteType.MESSAGE)
|
||||
);
|
||||
return DefaultListenerResult.PROCESSED;
|
||||
} finally {
|
||||
newSpan.end();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return StatisticFeatureDefinition.EMOTE_TRACKING;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>statistic</artifactId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>sticky-roles</artifactId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>sticky-roles-impl</artifactId>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>sticky-roles</artifactId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>sticky-roles-int</artifactId>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>suggestion</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>suggestion</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>twitch</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>twitch</artifactId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>utility</artifactId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>utility</artifactId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>voice-channel-context</artifactId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>voice-channel-context</artifactId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>abstracto-modules</artifactId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>webservices</artifactId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ public class WikipediaServiceBean implements WikipediaService {
|
||||
Response response = okHttpClient.newCall(request).execute();
|
||||
if(!response.isSuccessful()) {
|
||||
if(log.isDebugEnabled()) {
|
||||
log.error("Failed to retrieve wikipedia summary. Response had code {} with body {}.",
|
||||
log.debug("Failed to retrieve wikipedia summary. Response had code {} with body {}.",
|
||||
response.code(), response.body());
|
||||
}
|
||||
throw new WikipediaRequestException(response.code());
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>webservices</artifactId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto</groupId>
|
||||
<artifactId>abstracto-application</artifactId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.core</groupId>
|
||||
<artifactId>core</artifactId>
|
||||
<version>1.6.13</version>
|
||||
<version>1.6.17-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
@@ -182,10 +182,8 @@ public class CommandReceivedHandler extends ListenerAdapter {
|
||||
}
|
||||
|
||||
public UnParsedCommandResult getUnparsedCommandResult(Message message) {
|
||||
String contentStripped = message.getContentRaw();
|
||||
List<String> parameters = Arrays.asList(contentStripped.split(" "));
|
||||
UnParsedCommandParameter unParsedParameter = new UnParsedCommandParameter(contentStripped, message);
|
||||
String commandName = commandManager.getCommandName(parameters.get(0), message.getGuild().getIdLong());
|
||||
String commandName = getCommandName(message);
|
||||
UnParsedCommandParameter unParsedParameter = new UnParsedCommandParameter(message.getContentRaw(), message);
|
||||
Command foundCommand = commandManager.findCommandByParameters(commandName, unParsedParameter, message.getGuild().getIdLong()).orElse(null);
|
||||
return UnParsedCommandResult
|
||||
.builder()
|
||||
@@ -194,13 +192,9 @@ public class CommandReceivedHandler extends ListenerAdapter {
|
||||
.build();
|
||||
}
|
||||
|
||||
public CompletableFuture<CommandParseResult> getParametersFromMessage(Message message) {
|
||||
UnParsedCommandResult result = getUnparsedCommandResult(message);
|
||||
return getParsedParameters(result.getParameter(), result.getCommand(), message).thenApply(foundParameters -> CommandParseResult
|
||||
.builder()
|
||||
.command(result.getCommand())
|
||||
.parameters(foundParameters)
|
||||
.build());
|
||||
public String getCommandName(Message message) {
|
||||
List<String> parameters = Arrays.asList( message.getContentRaw().split(" "));
|
||||
return commandManager.getCommandName(parameters.get(0), message.getGuild().getIdLong());
|
||||
}
|
||||
|
||||
public CompletableFuture<CommandParseResult> getParametersFromMessage(Message message, UnParsedCommandResult result) {
|
||||
@@ -432,7 +426,7 @@ public class CommandReceivedHandler extends ListenerAdapter {
|
||||
Parameter param = parameters.get(0);
|
||||
CommandParameterIterators iterators = new CommandParameterIterators(channelIterator, emoteIterator, memberIterator, roleIterator);
|
||||
Set<CommandParameterHandler> usedParameterHandler = findNecessaryCommandParameterHandlers(parameters, unParsedCommandParameter);
|
||||
List<CompletableFuture> futures = new ArrayList<>();
|
||||
List<CompletableFuture<?>> futures = new ArrayList<>();
|
||||
// the actual parameters which were handled, might not coincide with the unparsed parameters
|
||||
// because we might ignore some parameters (for example referenced messages) in case the command does not use this as a parameter
|
||||
int parsedParameter = 0;
|
||||
@@ -449,7 +443,7 @@ public class CommandReceivedHandler extends ListenerAdapter {
|
||||
.getDependentFeatures()
|
||||
.stream()
|
||||
.map(s -> featureConfigService.getFeatureEnum(s))
|
||||
.collect(Collectors.toList());
|
||||
.toList();
|
||||
boolean parameterActiveForFeatures = false;
|
||||
for (FeatureDefinition featureDefinition : featureDefinitions) {
|
||||
if(featureFlagService.getFeatureFlagValue(featureDefinition, message.getGuild().getIdLong())) {
|
||||
@@ -466,7 +460,7 @@ public class CommandReceivedHandler extends ListenerAdapter {
|
||||
try {
|
||||
if (handler.handles(param.getType(), value)) {
|
||||
if (handler.async()) {
|
||||
CompletableFuture future = handler.handleAsync(value, iterators, param, message, command);
|
||||
CompletableFuture<?> future = handler.handleAsync(value, iterators, param, message, command);
|
||||
futures.add(future);
|
||||
parsedParameters.add(ParseResult.builder().parameter(param).result(future).build());
|
||||
} else {
|
||||
@@ -494,11 +488,11 @@ public class CommandReceivedHandler extends ListenerAdapter {
|
||||
combinedFuture.thenAccept(aVoid -> {
|
||||
List<Object> allParamResults = parsedParameters.stream().map(o -> {
|
||||
if (o.getResult() instanceof CompletableFuture) {
|
||||
return ((CompletableFuture) o.getResult()).join();
|
||||
return ((CompletableFuture<?>) o.getResult()).join();
|
||||
} else {
|
||||
return o.getResult();
|
||||
}
|
||||
}).collect(Collectors.toList());
|
||||
}).toList();
|
||||
List<ParseResult> parseResults = new ArrayList<>();
|
||||
for (int i = 0; i < allParamResults.size(); i++) {
|
||||
if (allParamResults.get(i) != null) {
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
package dev.sheldan.abstracto.core.commands.utility;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.Command;
|
||||
import dev.sheldan.abstracto.core.command.CommandAlternative;
|
||||
import dev.sheldan.abstracto.core.command.CommandReceivedHandler;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.command.config.features.CoreFeatureMode;
|
||||
import dev.sheldan.abstracto.core.command.execution.UnParsedCommandParameter;
|
||||
import dev.sheldan.abstracto.core.command.service.CommandManager;
|
||||
import dev.sheldan.abstracto.core.config.FeatureMode;
|
||||
import dev.sheldan.abstracto.core.config.ListenerPriority;
|
||||
import dev.sheldan.abstracto.core.models.template.commands.SlashCommandSuggestionModel;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.service.FeatureFlagService;
|
||||
import dev.sheldan.abstracto.core.service.FeatureModeService;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import java.util.Optional;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class SlashCommandSuggestor implements CommandAlternative {
|
||||
|
||||
@Autowired
|
||||
private FeatureModeService featureModeService;
|
||||
|
||||
@Autowired
|
||||
private CommandManager commandManager;
|
||||
|
||||
@Autowired
|
||||
private CommandReceivedHandler commandReceivedHandler;
|
||||
|
||||
@Autowired
|
||||
private FeatureFlagService featureFlagService;
|
||||
|
||||
@Autowired
|
||||
private TemplateService templateService;
|
||||
|
||||
@Autowired
|
||||
private ChannelService channelService;
|
||||
|
||||
public static final String SUGGESTION_TEMPLATE_KEY = "slash_command_suggestion";
|
||||
|
||||
@Override
|
||||
public Integer getPriority() {
|
||||
return ListenerPriority.MEDIUM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldExecute(UnParsedCommandParameter parameter, Guild guild, Message message) {
|
||||
boolean featureModeActive = featureModeService.featureModeActive(CoreFeatureDefinition.CORE_FEATURE, guild.getIdLong(), CoreFeatureMode.SUGGEST_SLASH_COMMANDS);
|
||||
if(!featureModeActive) {
|
||||
return false;
|
||||
}
|
||||
String commandName = commandReceivedHandler.getCommandName(message);
|
||||
Long guildId = message.getGuildIdLong();
|
||||
Optional<Command> potentialCommand = commandManager.getCommandByNameOptional(commandName, true, guildId);
|
||||
return potentialCommand.isPresent() && potentialCommand.get().getConfiguration().isSlashCommandOnly();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(UnParsedCommandParameter parameter, Message message) {
|
||||
String commandName = commandReceivedHandler.getCommandName(message);
|
||||
Long guildId = message.getGuildIdLong();
|
||||
Optional<Command> potentialCommand = commandManager.getCommandByNameOptional(commandName, true, guildId);
|
||||
// limitation to not check conditions if command is executable, I dont want to completely built the entire command context, as that would require
|
||||
// to parse the parameters, therefore the major checks should suffice
|
||||
if(potentialCommand.isPresent()) {
|
||||
Command command = potentialCommand.get();
|
||||
if(command.getConfiguration().isSlashCommandOnly()) {
|
||||
boolean featureAvailable = featureFlagService.getFeatureFlagValue(command.getFeature(), guildId);
|
||||
if(featureAvailable) {
|
||||
boolean shouldNotifyUser = command.getFeatureModeLimitations().isEmpty();
|
||||
for (FeatureMode featureModeLimitation : command.getFeatureModeLimitations()) {
|
||||
if(featureModeService.featureModeActive(command.getFeature(), guildId, featureModeLimitation)) {
|
||||
shouldNotifyUser = true;
|
||||
}
|
||||
}
|
||||
if(shouldNotifyUser) {
|
||||
notifyUser(message, command, commandName, guildId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyUser(Message message, Command command, String commandName, Long guildId) {
|
||||
String path = command.getConfiguration().getSlashCommandConfig().getSlashCommandPath();
|
||||
SlashCommandSuggestionModel model = SlashCommandSuggestionModel
|
||||
.builder()
|
||||
.slashCommandPath(path)
|
||||
.build();
|
||||
Long userId = message.getAuthor().getIdLong();
|
||||
log.info("Suggesting slash command for command {} to user {}.", commandName, userId);
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(SUGGESTION_TEMPLATE_KEY, model, guildId);
|
||||
FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, message.getChannel()))
|
||||
.thenAccept(unused -> {
|
||||
log.debug("Successfully suggested command.");
|
||||
}).exceptionally(throwable -> {
|
||||
log.warn("Failed to suggest slash command for command {} to user {}", commandName, userId);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,6 @@ import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.typeadapters.RuntimeTypeAdapterFactory;
|
||||
import dev.sheldan.abstracto.core.logging.OkHttpLogger;
|
||||
import dev.sheldan.abstracto.core.metric.OkHttpMetrics;
|
||||
import dev.sheldan.abstracto.core.service.BotService;
|
||||
import dev.sheldan.abstracto.core.templating.model.messagecomponents.ActionRowButtonConfig;
|
||||
import dev.sheldan.abstracto.core.templating.model.messagecomponents.ActionRowItemConfig;
|
||||
import dev.sheldan.abstracto.core.templating.model.messagecomponents.ComponentConfig;
|
||||
@@ -37,15 +36,15 @@ import java.util.List;
|
||||
@Configuration
|
||||
public class CoreConfig {
|
||||
|
||||
@Autowired
|
||||
private BotService botService;
|
||||
|
||||
@Autowired
|
||||
private OkHttpMetrics okHttpMetrics;
|
||||
|
||||
@Autowired
|
||||
private OkHttpLogger okHttpLogger;
|
||||
|
||||
@Autowired
|
||||
private OkHttpUserAgentSetter okHttpUserAgentSetter;
|
||||
|
||||
@Autowired
|
||||
private List<CustomJsonSerializer> customJsonSerializers;
|
||||
|
||||
@@ -95,6 +94,7 @@ public class CoreConfig {
|
||||
return new OkHttpClient.Builder()
|
||||
.addInterceptor(okHttpMetrics)
|
||||
.addInterceptor(okHttpLogger)
|
||||
.addInterceptor(okHttpUserAgentSetter)
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
@@ -207,4 +207,9 @@ public class ListenerExecutorConfig {
|
||||
return executorService.setupExecutorFor("voiceChatLeftListener");
|
||||
}
|
||||
|
||||
@Bean(name = "genericExecutor")
|
||||
public TaskExecutor genericExecutor() {
|
||||
return executorService.setupExecutorFor("genericExecutor");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
package dev.sheldan.abstracto.core.config;
|
||||
|
||||
import java.io.IOException;
|
||||
import okhttp3.Interceptor;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class OkHttpUserAgentSetter implements Interceptor {
|
||||
|
||||
@Value("${abstracto.okhttp.useragent}")
|
||||
private String userAgent;
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Response intercept(@NotNull Chain chain) throws IOException {
|
||||
Request originalRequest = chain.request();
|
||||
Request requestWithUserAgent = originalRequest.newBuilder()
|
||||
.header("User-Agent", userAgent)
|
||||
.build();
|
||||
return chain.proceed(requestWithUserAgent);
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,8 @@ import dev.sheldan.abstracto.core.templating.model.AttachedFile;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.utils.ContextUtils;
|
||||
import io.micrometer.tracing.Span;
|
||||
import io.micrometer.tracing.Tracer;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||
@@ -58,6 +60,9 @@ public class InteractionServiceBean implements InteractionService {
|
||||
@Autowired
|
||||
private TemplateService templateService;
|
||||
|
||||
@Autowired
|
||||
private Tracer tracer;
|
||||
|
||||
public static final CounterMetric EPHEMERAL_MESSAGES_SEND = CounterMetric
|
||||
.builder()
|
||||
.name(DISCORD_API_INTERACTION_METRIC)
|
||||
@@ -259,84 +264,88 @@ public class InteractionServiceBean implements InteractionService {
|
||||
}
|
||||
|
||||
public CompletableFuture<InteractionHook> replyMessageToSend(MessageToSend messageToSend, IReplyCallback callback) {
|
||||
ReplyCallbackAction action = null;
|
||||
if(messageToSend.getUseComponentsV2()) {
|
||||
action = callback.replyComponents(messageToSend.getComponents()).useComponentsV2();
|
||||
} else {
|
||||
if(messageToSend.getMessages() != null && !messageToSend.getMessages().isEmpty()) {
|
||||
metricService.incrementCounter(MESSAGE_SEND_METRIC);
|
||||
action = callback.reply(messageToSend.getMessages().get(0));
|
||||
}
|
||||
if(messageToSend.getEmbeds() != null && !messageToSend.getEmbeds().isEmpty()) {
|
||||
if(action != null) {
|
||||
action = action.addEmbeds(messageToSend.getEmbeds().subList(0, Math.min(10, messageToSend.getEmbeds().size())));
|
||||
} else {
|
||||
action = callback.replyEmbeds(messageToSend.getEmbeds());
|
||||
}
|
||||
}
|
||||
if(messageToSend.hasFilesToSend()) {
|
||||
List<FileUpload> attachedFiles = messageToSend
|
||||
.getAttachedFiles()
|
||||
.stream()
|
||||
.map(AttachedFile::convertToFileUpload)
|
||||
.collect(Collectors.toList());
|
||||
if(action != null) {
|
||||
action.setFiles(attachedFiles);
|
||||
} else {
|
||||
Span newSpan = tracer.nextSpan().name("send-message-to-interaction");
|
||||
try (Tracer.SpanInScope ws = this.tracer.withSpan(newSpan.start())) {
|
||||
ReplyCallbackAction action = null;
|
||||
if (messageToSend.getUseComponentsV2()) {
|
||||
action = callback.replyComponents(messageToSend.getComponents()).useComponentsV2();
|
||||
} else {
|
||||
if (messageToSend.getMessages() != null && !messageToSend.getMessages().isEmpty()) {
|
||||
metricService.incrementCounter(MESSAGE_SEND_METRIC);
|
||||
action = callback.replyFiles(attachedFiles);
|
||||
action = callback.reply(messageToSend.getMessages().get(0));
|
||||
}
|
||||
}
|
||||
// this should be last, because we are "faking" a message, by inserting a ., in case there has not been a reply yet
|
||||
// we could also throw an exception, but we are allowing this to go through
|
||||
List<ActionRow> actionRows = messageToSend.getActionRows();
|
||||
if(actionRows != null && !actionRows.isEmpty()) {
|
||||
if(action == null) {
|
||||
action = callback.reply(".");
|
||||
}
|
||||
action = action.setComponents(actionRows);
|
||||
AServer server;
|
||||
if(ContextUtils.isGuildKnown(callback)) {
|
||||
server = serverManagementService.loadServer(callback.getGuild().getIdLong());
|
||||
} else {
|
||||
server = null;
|
||||
}
|
||||
actionRows.forEach(components -> components.forEach(component -> {
|
||||
if(component instanceof ActionComponent) {
|
||||
String id = ((ActionComponent)component).getId();
|
||||
MessageToSend.ComponentConfig payload = messageToSend.getComponentPayloads().get(id);
|
||||
if(payload != null && payload.getPersistCallback()) {
|
||||
componentPayloadManagementService.createPayload(id, payload.getPayload(), payload.getPayloadType(), payload.getComponentOrigin(), server, payload.getComponentType());
|
||||
}
|
||||
if (messageToSend.getEmbeds() != null && !messageToSend.getEmbeds().isEmpty()) {
|
||||
if (action != null) {
|
||||
action = action.addEmbeds(messageToSend.getEmbeds().subList(0, Math.min(10, messageToSend.getEmbeds().size())));
|
||||
} else {
|
||||
action = callback.replyEmbeds(messageToSend.getEmbeds());
|
||||
}
|
||||
}));
|
||||
}
|
||||
if (messageToSend.hasFilesToSend()) {
|
||||
List<FileUpload> attachedFiles = messageToSend
|
||||
.getAttachedFiles()
|
||||
.stream()
|
||||
.map(AttachedFile::convertToFileUpload)
|
||||
.collect(Collectors.toList());
|
||||
if (action != null) {
|
||||
action.setFiles(attachedFiles);
|
||||
} else {
|
||||
metricService.incrementCounter(MESSAGE_SEND_METRIC);
|
||||
action = callback.replyFiles(attachedFiles);
|
||||
}
|
||||
}
|
||||
// this should be last, because we are "faking" a message, by inserting a ., in case there has not been a reply yet
|
||||
// we could also throw an exception, but we are allowing this to go through
|
||||
List<ActionRow> actionRows = messageToSend.getActionRows();
|
||||
if (actionRows != null && !actionRows.isEmpty()) {
|
||||
if (action == null) {
|
||||
action = callback.reply(".");
|
||||
}
|
||||
action = action.setComponents(actionRows);
|
||||
AServer server;
|
||||
if (ContextUtils.isGuildKnown(callback)) {
|
||||
server = serverManagementService.loadServer(callback.getGuild().getIdLong());
|
||||
} else {
|
||||
server = null;
|
||||
}
|
||||
actionRows.forEach(components -> components.forEach(component -> {
|
||||
if (component instanceof ActionComponent) {
|
||||
String id = ((ActionComponent) component).getId();
|
||||
MessageToSend.ComponentConfig payload = messageToSend.getComponentPayloads().get(id);
|
||||
if (payload != null && payload.getPersistCallback()) {
|
||||
componentPayloadManagementService.createPayload(id, payload.getPayload(), payload.getPayloadType(),
|
||||
payload.getComponentOrigin(), server, payload.getComponentType());
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(messageToSend.getEphemeral()) {
|
||||
if(ContextUtils.hasGuild(callback)) {
|
||||
log.info("Sending ephemeral message to interaction in guild {} in channel {} for user {}.",
|
||||
if (messageToSend.getEphemeral()) {
|
||||
if (ContextUtils.hasGuild(callback)) {
|
||||
log.info("Sending ephemeral message to interaction in guild {} in channel {} for user {}.",
|
||||
callback.getGuild().getIdLong(), callback.getChannel().getId(),
|
||||
callback.getUser().getIdLong());
|
||||
} else {
|
||||
log.info("Sending ephemeral message to user {}.", callback.getUser().getIdLong());
|
||||
} else {
|
||||
log.info("Sending ephemeral message to user {}.", callback.getUser().getIdLong());
|
||||
}
|
||||
metricService.incrementCounter(EPHEMERAL_MESSAGES_SEND);
|
||||
if (action != null) {
|
||||
action = action.setEphemeral(messageToSend.getEphemeral());
|
||||
}
|
||||
}
|
||||
metricService.incrementCounter(EPHEMERAL_MESSAGES_SEND);
|
||||
if(action != null) {
|
||||
action = action.setEphemeral(messageToSend.getEphemeral());
|
||||
if (ContextUtils.isGuildKnown(callback)) {
|
||||
Set<Message.MentionType> allowedMentions = allowedMentionService.getAllowedMentionsFor(callback.getMessageChannel(), messageToSend);
|
||||
if (action != null) {
|
||||
action = action.setAllowedMentions(allowedMentions);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(ContextUtils.isGuildKnown(callback)) {
|
||||
Set<Message.MentionType> allowedMentions = allowedMentionService.getAllowedMentionsFor(callback.getMessageChannel(), messageToSend);
|
||||
if (action != null) {
|
||||
action = action.setAllowedMentions(allowedMentions);
|
||||
}
|
||||
}
|
||||
|
||||
if(action == null) {
|
||||
throw new AbstractoRunTimeException("The callback did not result in any message.");
|
||||
if (action == null) {
|
||||
throw new AbstractoRunTimeException("The callback did not result in any message.");
|
||||
}
|
||||
return action.submit();
|
||||
}
|
||||
return action.submit();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.google.gson.Gson;
|
||||
import dev.sheldan.abstracto.core.config.FeatureConfig;
|
||||
import dev.sheldan.abstracto.core.interaction.InteractionResult;
|
||||
import dev.sheldan.abstracto.core.interaction.button.ButtonPostInteractionExecution;
|
||||
import dev.sheldan.abstracto.core.metric.service.MetricUtils;
|
||||
import dev.sheldan.abstracto.core.models.database.ComponentPayload;
|
||||
import dev.sheldan.abstracto.core.interaction.button.ButtonPayload;
|
||||
import dev.sheldan.abstracto.core.service.FeatureConfigService;
|
||||
@@ -63,7 +64,7 @@ public class SyncButtonClickedListenerBean extends ListenerAdapter {
|
||||
@Override
|
||||
public void onButtonInteraction(@Nonnull ButtonInteractionEvent event) {
|
||||
if(listenerList == null) return;
|
||||
CompletableFuture.runAsync(() -> self.executeListenerLogic(event), buttonClickedExecutor).exceptionally(throwable -> {
|
||||
CompletableFuture.runAsync(() -> self.executeListenerLogic(event), MetricUtils.wrapExecutor(buttonClickedExecutor)).exceptionally(throwable -> {
|
||||
log.error("Failed to execute listener logic in async button event.", throwable);
|
||||
return null;
|
||||
});
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user