Compare commits

..

20 Commits

Author SHA1 Message Date
Sheldan
3eaffaef87 [maven-release-plugin] prepare release abstracto-application-1.4.17 2023-02-04 14:52:20 +01:00
Sheldan
b3a943e155 [AB-20] adding level up notification configuration possibility 2023-01-28 13:13:38 +01:00
Sheldan
06dd4af131 [maven-release-plugin] prepare for next development iteration 2023-01-12 01:37:16 +01:00
Sheldan
0d51469975 [maven-release-plugin] prepare release abstracto-application-1.4.16 2023-01-12 01:37:12 +01:00
Sheldan
aa10c88588 [AB-81] adding support for choices in slash command parameters 2023-01-12 01:34:30 +01:00
Sheldan
db27f64832 [AB-80] fixing not cleaning up emote record when changing emote 2023-01-10 19:15:27 +01:00
Sheldan
3903039aac [AB-79] fixing test 2022-12-27 13:12:10 +01:00
Sheldan
41f42ee110 [AB-79] fix not applying role for re-joining users upon sync 2022-12-27 13:03:59 +01:00
Sheldan
74f54e1257 [maven-release-plugin] prepare for next development iteration 2022-12-21 13:27:21 +01:00
Sheldan
a72e48f690 [maven-release-plugin] prepare release abstracto-application-1.4.15 2022-12-21 13:27:16 +01:00
Sheldan
a813af8b1f [AB-xxx] fixing issue of not providing percentage to rank correctly 2022-12-21 01:34:32 +01:00
Sheldan
abee7b2732 [AB-xxx] providing more information in the rank model 2022-12-20 22:15:05 +01:00
Sheldan
4c71ffbb7e [maven-release-plugin] prepare for next development iteration 2022-12-10 16:54:36 +01:00
Sheldan
18050e2a8a [maven-release-plugin] prepare release abstracto-application-1.4.14 2022-12-10 16:54:32 +01:00
Sheldan
a0d83763d4 [AB-78] fixing users with previous experience not awarding the experience role if they join and are pending 2022-12-10 15:44:09 +01:00
Sheldan
0461c8e4ec [AB-77] deferring the reply for report with context interactions
do not defer the interaction all the time for modal interactions
2022-12-10 12:59:47 +01:00
Sheldan
072f32975a [maven-release-plugin] prepare for next development iteration 2022-12-03 20:17:11 +01:00
Sheldan
6810d28c50 [maven-release-plugin] prepare release abstracto-application-1.4.13 2022-12-03 20:16:57 +01:00
Sheldan
650a9099c4 [AB-66] fixing not reducing the bid on mines
fixing reaction report sometimes running into a timeout
2022-12-03 20:14:18 +01:00
Sheldan
1217e03725 [maven-release-plugin] prepare for next development iteration 2022-12-02 21:20:57 +01:00
108 changed files with 558 additions and 152 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -23,8 +23,8 @@ import java.security.SecureRandom;
import java.util.*;
import java.util.stream.Collectors;
import static dev.sheldan.abstracto.entertainment.config.EconomyFeatureConfig.MINES_MINIMUM_MINES_RATIO;
import static dev.sheldan.abstracto.entertainment.config.GamesFeatureConfig.MINES_CREDITS_FACTOR;
import static dev.sheldan.abstracto.entertainment.config.GamesFeatureConfig.MINES_MINIMUM_MINES_RATIO;
@Component
public class GameServiceBean implements GameService {
@@ -134,6 +134,7 @@ public class GameServiceBean implements GameService {
.build();
Optional<EconomyUser> economyUserOptional = economyUserManagementService.getUser(serverUser);
if(economyUserOptional.isPresent()) {
economyService.addCredits(economyUserOptional.get(), -credits);
economyService.addCredits(economyUserOptional.get(), creditChange);
}
mineBoard.setCreditChange(creditChange);

View File

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

View File

@@ -13,7 +13,6 @@ public class EconomyFeatureConfig implements FeatureConfig {
public static final String PAYDAY_CREDITS_CONFIG_KEY = "paydayCredits";
public static final String PAYDAY_COOLDOWN_CONFIG_KEY = "paydayCooldown";
public static final String SLOTS_COOLDOWN_CONFIG_KEY = "slotsCooldown";
public static final String MINES_MINIMUM_MINES_RATIO = "minesMinMineRatio";
@Override
public FeatureDefinition getFeature() {
@@ -22,6 +21,6 @@ public class EconomyFeatureConfig implements FeatureConfig {
@Override
public List<String> getRequiredSystemConfigKeys() {
return Arrays.asList(PAYDAY_CREDITS_CONFIG_KEY, PAYDAY_COOLDOWN_CONFIG_KEY, SLOTS_COOLDOWN_CONFIG_KEY, MINES_MINIMUM_MINES_RATIO);
return Arrays.asList(PAYDAY_CREDITS_CONFIG_KEY, PAYDAY_COOLDOWN_CONFIG_KEY, SLOTS_COOLDOWN_CONFIG_KEY);
}
}

View File

@@ -11,6 +11,7 @@ import java.util.List;
public class GamesFeatureConfig implements FeatureConfig {
public static final String MINES_CREDITS_FACTOR = "minesCreditsFactor";
public static final String MINES_MINIMUM_MINES_RATIO = "minesMinMineRatio";
@Override
public FeatureDefinition getFeature() {
@@ -19,7 +20,7 @@ public class GamesFeatureConfig implements FeatureConfig {
@Override
public List<String> getRequiredSystemConfigKeys() {
return Arrays.asList(MINES_CREDITS_FACTOR);
return Arrays.asList(MINES_CREDITS_FACTOR, MINES_MINIMUM_MINES_RATIO);
}
}

View File

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

View File

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

View File

@@ -0,0 +1,103 @@
package dev.sheldan.abstracto.experience.command;
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.CommandContext;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.interaction.InteractionService;
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
import dev.sheldan.abstracto.experience.config.ExperienceFeatureDefinition;
import dev.sheldan.abstracto.experience.config.ExperienceSlashCommandNames;
import dev.sheldan.abstracto.experience.service.AUserExperienceService;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@Component
public class ExpLevelUpNotification extends AbstractConditionableCommand {
private static final String FLAG_PARAMETER = "newValue";
private static final String EXP_LEVEL_UP_NOTIFICATION_COMMAND = "expLevelUpNotification";
private static final String EXP_LEVEL_UP_NOTIFICATION_RESPONSE = "expLevelUpNotification_response";
@Autowired
private UserInServerManagementService userInServerManagementService;
@Autowired
private AUserExperienceService aUserExperienceService;
@Autowired
private InteractionService interactionService;
@Autowired
private SlashCommandParameterService slashCommandParameterService;
@Override
public CommandResult execute(CommandContext commandContext) {
Boolean newValue = (Boolean) commandContext.getParameters().getParameters().get(0);
updateExpLevelNotification(commandContext.getAuthor(), newValue);
return CommandResult.fromSuccess();
}
@Override
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
Boolean newValue = slashCommandParameterService.getCommandOption(FLAG_PARAMETER, event, Boolean.class);
updateExpLevelNotification(event.getMember(), newValue);
return interactionService.replyEmbed(EXP_LEVEL_UP_NOTIFICATION_RESPONSE, event)
.thenApply(interactionHook -> CommandResult.fromSuccess());
}
private void updateExpLevelNotification(Member member, Boolean newValue) {
AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(member);
aUserExperienceService.setLevelUpNotification(aUserInAServer, newValue);
}
@Override
public FeatureDefinition getFeature() {
return ExperienceFeatureDefinition.EXPERIENCE;
}
@Override
public CommandConfiguration getConfiguration() {
Parameter memberParameter = Parameter
.builder()
.name(FLAG_PARAMETER)
.templated(true)
.type(Boolean.class)
.build();
List<Parameter> parameters = Arrays.asList(memberParameter);
HelpInfo helpInfo = HelpInfo
.builder()
.templated(true)
.build();
SlashCommandConfig slashCommandConfig = SlashCommandConfig
.builder()
.enabled(true)
.rootCommandName(ExperienceSlashCommandNames.EXPERIENCE)
.commandName(EXP_LEVEL_UP_NOTIFICATION_COMMAND)
.build();
return CommandConfiguration.builder()
.name(EXP_LEVEL_UP_NOTIFICATION_COMMAND)
.module(ExperienceModuleDefinition.EXPERIENCE)
.slashCommandConfig(slashCommandConfig)
.causesReaction(true)
.supportsEmbedException(true)
.templated(true)
.parameters(parameters)
.help(helpInfo)
.build();
}
}

View File

@@ -104,7 +104,17 @@ public class Rank extends AbstractConditionableCommand {
AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(toRender);
AUserExperience experienceObj = userExperienceManagementService.findUserInServer(aUserInAServer);
log.info("Rendering rank for user {} in server {}.", toRender.getId(), toRender.getGuild().getId());
rankModel.setExperienceToNextLevel(experienceLevelService.calculateExperienceToNextLevel(experienceObj.getCurrentLevel().getLevel(), experienceObj.getExperience()));
Long currentExpNeeded = experienceObj.getCurrentLevel().getExperienceNeeded();
Long experienceNeededToNextLevel = experienceLevelService.calculateExperienceToNextLevel(experienceObj.getCurrentLevel().getLevel(), experienceObj.getExperience());
Long nextLevelExperience = experienceLevelService.calculateNextLevel(experienceObj.getCurrentLevel().getLevel()).getExperienceNeeded();
Long levelExperience = nextLevelExperience - currentExpNeeded;
Long inLevelExperience = experienceObj.getExperience() - currentExpNeeded;
rankModel.setExperienceForCurrentLevel(currentExpNeeded);
rankModel.setCurrentLevelPercentage(((float) inLevelExperience / levelExperience) * 100);
rankModel.setLevelExperience(levelExperience);
rankModel.setExperienceToNextLevel(experienceNeededToNextLevel);
rankModel.setInLevelExperience(inLevelExperience);
rankModel.setNextLevelExperience(nextLevelExperience);
return templateService.renderEmbedTemplate(RANK_POST_EMBED_TEMPLATE, rankModel, toRender.getGuild().getIdLong());
}

View File

@@ -37,12 +37,16 @@ public class JoiningUserRoleListener implements AsyncJoinListener {
@Override
public DefaultListenerResult execute(MemberJoinModel model) {
if(model.getMember().isPending()) {
log.info("Joining member {} in guild {} is still pending - ignoring for experience role assignment.", model.getJoiningUser().getUserId(), model.getJoiningUser().getServerId());
return DefaultListenerResult.IGNORED;
}
Optional<AUserInAServer> userInAServerOptional = userInServerManagementService.loadUserOptional(model.getServerId(), model.getJoiningUser().getUserId());
userInAServerOptional.ifPresent(aUserInAServer -> {
Optional<AUserExperience> userExperienceOptional = userExperienceManagementService.findByUserInServerIdOptional(aUserInAServer.getUserInServerId());
if(userExperienceOptional.isPresent()) {
log.info("User {} joined {} with previous experience. Setting up experience role again (if necessary).", model.getJoiningUser().getUserId(), model.getServerId());
userExperienceService.syncForSingleUser(userExperienceOptional.get(), model.getMember()).thenAccept(result ->
userExperienceService.syncForSingleUser(userExperienceOptional.get(), model.getMember(), true).thenAccept(result ->
log.info("Finished re-assigning experience for re-joining user {} in server {}.", model.getJoiningUser().getUserId(), model.getServerId())
);
} else {

View File

@@ -0,0 +1,60 @@
package dev.sheldan.abstracto.experience.listener;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
import dev.sheldan.abstracto.core.listener.async.jda.AsyncUpdatePendingListener;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.models.listener.MemberUpdatePendingModel;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
import dev.sheldan.abstracto.experience.config.ExperienceFeatureDefinition;
import dev.sheldan.abstracto.experience.model.database.AUserExperience;
import dev.sheldan.abstracto.experience.service.AUserExperienceService;
import dev.sheldan.abstracto.experience.service.management.UserExperienceManagementService;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.Member;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Optional;
/**
* If a {@link Member member} updates the pending status, this {@link AsyncUpdatePendingListener listener} retrieves the previously stored {@link AUserExperience experience} and gives the
* member the necessary {@link net.dv8tion.jda.api.entities.Role role} according to the current configuration, if any
*/
@Component
@Slf4j
public class MemberPendingRoleListener implements AsyncUpdatePendingListener {
@Autowired
private UserExperienceManagementService userExperienceManagementService;
@Autowired
private AUserExperienceService userExperienceService;
@Autowired
private UserInServerManagementService userInServerManagementService;
@Override
public DefaultListenerResult execute(MemberUpdatePendingModel model) {
Optional<AUserInAServer> userInAServerOptional = userInServerManagementService.loadUserOptional(model.getServerId(), model.getUser().getUserId());
userInAServerOptional.ifPresent(aUserInAServer -> {
Optional<AUserExperience> userExperienceOptional = userExperienceManagementService.findByUserInServerIdOptional(aUserInAServer.getUserInServerId());
if(userExperienceOptional.isPresent()) {
log.info("User {} updated pending status {} with previous experience. Setting up experience role again (if necessary).", model.getUser().getUserId(), model.getServerId());
userExperienceService.syncForSingleUser(userExperienceOptional.get(), model.getMember(), true).thenAccept(result ->
log.info("Finished re-assigning experience for update pending user {} in server {}.", model.getUser().getUserId(), model.getServerId())
);
} else {
log.info("Member updating pending {} in server {} does not have any previous experience. Not setting up anything.", model.getUser().getUserId(), model.getServerId());
}
});
return DefaultListenerResult.PROCESSED;
}
@Override
public FeatureDefinition getFeature() {
return ExperienceFeatureDefinition.EXPERIENCE;
}
}

View File

@@ -252,17 +252,17 @@ public class AUserExperienceServiceBean implements AUserExperienceService {
public CompletableFuture<Void> syncUser(Member member, List<AExperienceRole> roles) {
AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(member);
AUserExperience userExperience = userExperienceManagementService.findByUserInServerId(aUserInAServer.getUserInServerId());
return calculateAndApplyExperienceRole(userExperience, member, roles);
return calculateAndApplyExperienceRole(userExperience, member, roles, false);
}
@Override
public CompletableFuture<Void> syncForSingleUser(AUserExperience userExperience, Member member) {
public CompletableFuture<Void> syncForSingleUser(AUserExperience userExperience, Member member, boolean forceRoles) {
List<AExperienceRole> roles = experienceRoleManagementService.getExperienceRolesForServer(userExperience.getServer());
roles.sort(Comparator.comparing(role -> role.getLevel().getLevel()));
return calculateAndApplyExperienceRole(userExperience, member, roles);
return calculateAndApplyExperienceRole(userExperience, member, roles, forceRoles);
}
private CompletableFuture<Void> calculateAndApplyExperienceRole(AUserExperience userExperience, Member member, List<AExperienceRole> roles) {
private CompletableFuture<Void> calculateAndApplyExperienceRole(AUserExperience userExperience, Member member, List<AExperienceRole> roles, boolean forceRoles) {
AExperienceRole calculatedNewRole = experienceRoleService.calculateRole(roles, userExperience.getCurrentLevel().getLevel());
Long oldRoleId = userExperience.getCurrentExperienceRole() != null && userExperience.getCurrentExperienceRole().getRole() != null ? userExperience.getCurrentExperienceRole().getRole().getId() : null;
Long newRoleId = calculatedNewRole != null ? calculatedNewRole.getRole().getId() : null;
@@ -270,15 +270,15 @@ public class AUserExperienceServiceBean implements AUserExperienceService {
userExperience.setCurrentExperienceRole(calculatedNewRole);
CompletableFuture<Void> returningFuture;
if(!Objects.equals(oldRoleId, newRoleId)) {
if(!Objects.equals(oldRoleId, newRoleId) || forceRoles) {
CompletableFuture<Void> addingFuture;
if(oldRoleId != null) {
if(oldRoleId != null || forceRoles) {
addingFuture = roleService.removeRoleFromMemberAsync(member, oldRoleId);
} else {
addingFuture = CompletableFuture.completedFuture(null);
}
CompletableFuture<Void> removingFeature;
if(newRoleId != null) {
if(newRoleId != null || forceRoles) {
removingFeature = roleService.addRoleToMemberAsync(member, newRoleId);
} else {
removingFeature = CompletableFuture.completedFuture(null);
@@ -340,7 +340,9 @@ public class AUserExperienceServiceBean implements AUserExperienceService {
Long newRoleId = calculatedNewRole != null ? calculatedNewRole.getRole().getId() : null;
result.setOldRoleId(oldRoleId);
result.setNewRoleId(newRoleId);
if(message != null && featureModeService.featureModeActive(ExperienceFeatureDefinition.EXPERIENCE, serverId, ExperienceFeatureMode.LEVEL_UP_NOTIFICATION)) {
if(message != null
&& aUserExperience.getLevelUpNotification()
&& featureModeService.featureModeActive(ExperienceFeatureDefinition.EXPERIENCE, serverId, ExperienceFeatureMode.LEVEL_UP_NOTIFICATION)) {
LevelUpNotificationModel model = LevelUpNotificationModel
.builder()
.memberDisplay(MemberDisplay.fromMember(member))
@@ -429,6 +431,13 @@ public class AUserExperienceServiceBean implements AUserExperienceService {
userExperience.setExperienceGainDisabled(false);
}
@Override
public void setLevelUpNotification(AUserInAServer aUserInAServer, Boolean newValue) {
Optional<AUserExperience> aUserExperienceOptional = userExperienceManagementService.findByUserInServerIdOptional(aUserInAServer.getUserInServerId());
AUserExperience aUserExperience = aUserExperienceOptional.orElseGet(() -> userExperienceManagementService.createUserInServer(aUserInAServer));
aUserExperience.setLevelUpNotification(newValue);
}
/**
* Renders a {@link MessageToSend messageToSend} to be used as a status message for the ongoing user synchronization
* @param current The amount of users which have been synced

View File

@@ -57,9 +57,14 @@ public class ExperienceLevelServiceBean implements ExperienceLevelService {
@Override
public Long calculateExperienceToNextLevel(Integer level, Long currentExperience) {
AExperienceLevel nextLevel = experienceLevelManagementService.getLevelOptional(level + 1)
.orElseThrow(() -> new AbstractoRunTimeException(String.format("Could not find level %s", level)));
AExperienceLevel nextLevel = calculateNextLevel(level);
return nextLevel.getExperienceNeeded() - currentExperience;
}
@Override
public AExperienceLevel calculateNextLevel(Integer level) {
return experienceLevelManagementService.getLevelOptional(level + 1)
.orElseThrow(() -> new AbstractoRunTimeException(String.format("Could not find level %s", level)));
}
}

View File

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

View File

@@ -0,0 +1,19 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
<property name="experienceModule" value="(SELECT id FROM module WHERE name = 'experience')"/>
<property name="experienceFeature" value="(SELECT id FROM feature WHERE key = 'experience')"/>
<changeSet author="Sheldan" id="experience-expLevelUpNotification_command">
<insert tableName="command">
<column name="name" value="expLevelUpNotification"/>
<column name="module_id" valueComputed="${experienceModule}"/>
<column name="feature_id" valueComputed="${experienceFeature}"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

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

View File

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

View File

@@ -0,0 +1,15 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
<changeSet author="Sheldan" id="user_experience-add_level_up_notification">
<addColumn tableName="user_experience">
<column name="level_up_notification" type="BOOLEAN" defaultValueBoolean="true"/>
</addColumn>
</changeSet>
</databaseChangeLog>

View File

@@ -9,4 +9,5 @@
<include file="1.0-experience/collection.xml" relativeToChangelogFile="true"/>
<include file="1.2.15/collection.xml" relativeToChangelogFile="true"/>
<include file="1.4.8/collection.xml" relativeToChangelogFile="true"/>
<include file="1.4.17/collection.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -67,7 +67,7 @@ public class JoiningUserRoleListenerTest {
public void testUserWithExperienceRejoining() {
AUserExperience experience = Mockito.mock(AUserExperience.class);
when(userExperienceManagementService.findByUserInServerIdOptional(USER_IN_SERVER_ID)).thenReturn(Optional.of(experience));
when(userExperienceService.syncForSingleUser(experience, member)).thenReturn(CompletableFuture.completedFuture(null));
when(userExperienceService.syncForSingleUser(experience, member, true)).thenReturn(CompletableFuture.completedFuture(null));
when(model.getMember()).thenReturn(member);
DefaultListenerResult result = testUnit.execute(model);
Assert.assertEquals(DefaultListenerResult.PROCESSED, result);
@@ -75,9 +75,18 @@ public class JoiningUserRoleListenerTest {
@Test
public void testUserWithOutExperienceRejoining() {
when(model.getMember()).thenReturn(member);
when(userExperienceManagementService.findByUserInServerIdOptional(USER_IN_SERVER_ID)).thenReturn(Optional.empty());
testUnit.execute(model);
verify(userExperienceService, times(0)).syncForSingleUser(any(), any());
verify(userExperienceService, times(0)).syncForSingleUser(any(), any(), eq(true));
}
@Test
public void testPendingUserJoining() {
when(member.isPending()).thenReturn(true);
when(model.getMember()).thenReturn(member);
testUnit.execute(model);
verify(userExperienceService, times(0)).syncForSingleUser(any(), any(), eq(true));
}
}

View File

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

View File

@@ -60,6 +60,9 @@ public class AUserExperience implements Serializable {
@Column(name = "experience_gain_disabled", nullable = false)
private Boolean experienceGainDisabled = false;
@Column(name = "level_up_notification")
private Boolean levelUpNotification;
/**
* The {@link AExperienceLevel level} which the user currently has.
*/

View File

@@ -23,6 +23,26 @@ public class RankModel {
* The necessary experience to the next level up.
*/
private Long experienceToNextLevel;
/**
* Total experience needed for this level
*/
private Long experienceForCurrentLevel;
/**
* Percentage of progress within this level
*/
private Float currentLevelPercentage;
/**
* The total amount of experience needed for this level
*/
private Long levelExperience;
/**
* The experience which has been reached _within_ this level
*/
private Long inLevelExperience;
/**
* The experience needed to reach the next level
*/
private Long nextLevelExperience;
/**
* The member to show the rank for
*/

View File

@@ -44,7 +44,7 @@ public interface AUserExperienceService {
CompletableFuture<Void> syncUserRolesWithFeedback(AServer server, MessageChannel messageChannel);
CompletableFuture<Void> syncForSingleUser(AUserExperience userExperience, Member member);
CompletableFuture<Void> syncForSingleUser(AUserExperience userExperience, Member member, boolean changeRoles);
/**
* Loads the desired page of the ordered complete leaderboard from the {@link AServer} and returns the information as a {@link LeaderBoard}
@@ -75,6 +75,7 @@ public interface AUserExperienceService {
* @param userInAServer The {@link AUserInAServer} to enable experience for
*/
void enableExperienceForUser(AUserInAServer userInAServer);
void setLevelUpNotification(AUserInAServer aUserInAServer, Boolean newValue);
boolean experienceGainEnabledInChannel(MessageChannel messageChannel);

View File

@@ -1,5 +1,7 @@
package dev.sheldan.abstracto.experience.service;
import dev.sheldan.abstracto.experience.model.database.AExperienceLevel;
/**
* Service responsible for operations on {@link dev.sheldan.abstracto.experience.model.database.AExperienceLevel experienceLevel}
* This includes creating and calculations.
@@ -20,6 +22,7 @@ public interface ExperienceLevelService {
* @return The amount of experience required necessary to reach the next level
*/
Long calculateExperienceToNextLevel(Integer level, Long currentExperience);
AExperienceLevel calculateNextLevel(Integer level);
/**
* Calculates the required experience to reach this level. This calculated experience is relative, in the sense that

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -33,33 +33,32 @@ public class ReportContextCommandListener implements MessageContextCommandListen
@Override
public DefaultListenerResult execute(MessageContextInteractionModel model) {
Message targetMessage = model.getEvent().getTarget();
if(targetMessage.getAuthor().getIdLong() == model.getEvent().getUser().getIdLong()) {
interactionService.replyEmbed(ReactionReportServiceBean.REACTION_REPORT_OWN_MESSAGE_RESPONSE_TEMPLATE, new Object(), model.getEvent());
return DefaultListenerResult.IGNORED;
}
ServerUser userReporting = ServerUser
.builder()
.serverId(model.getServerId())
.userId(model.getEvent().getUser().getIdLong())
.isBot(model.getEvent().getUser().isBot())
.build();
if(!reactionReportService.allowedToReport(userReporting)) {
log.info("User {} was reported on message {} in server {} within the cooldown. Ignoring.",
targetMessage.getAuthor().getIdLong(), targetMessage.getIdLong(), targetMessage.getGuild().getIdLong());
interactionService.replyEmbed(ReactionReportServiceBean.REACTION_REPORT_COOLDOWN_RESPONSE_TEMPLATE, new Object(), model.getEvent());
return DefaultListenerResult.IGNORED;
}
reactionReportService.createReactionReport(targetMessage, userReporting, null).exceptionally(throwable -> {
log.error("Failed to create reaction report in server {} on message {} in channel {} with interaction.",
model.getServerId(), targetMessage.getIdLong(), model.getEvent().getChannel().getIdLong(), throwable);
return null;
model.getEvent().deferReply(true).queue(interactionHook -> {
Message targetMessage = model.getEvent().getTarget();
if(targetMessage.getAuthor().getIdLong() == model.getEvent().getUser().getIdLong()) {
interactionService.sendMessageToInteraction(ReactionReportServiceBean.REACTION_REPORT_OWN_MESSAGE_RESPONSE_TEMPLATE, new Object(), interactionHook);
return;
}
ServerUser userReporting = ServerUser
.builder()
.serverId(model.getServerId())
.userId(model.getEvent().getUser().getIdLong())
.isBot(model.getEvent().getUser().isBot())
.build();
if(!reactionReportService.allowedToReport(userReporting)) {
log.info("User {} was reported on message {} in server {} within the cooldown. Ignoring.",
targetMessage.getAuthor().getIdLong(), targetMessage.getIdLong(), targetMessage.getGuild().getIdLong());
interactionService.sendMessageToInteraction(ReactionReportServiceBean.REACTION_REPORT_COOLDOWN_RESPONSE_TEMPLATE, new Object(),interactionHook);
return;
}
reactionReportService.createReactionReport(targetMessage, userReporting, null).exceptionally(throwable -> {
log.error("Failed to create reaction report in server {} on message {} in channel {} with interaction.",
model.getServerId(), targetMessage.getIdLong(), model.getEvent().getChannel().getIdLong(), throwable);
return null;
});
interactionService.sendMessageToInteraction(REACTION_REPORT_RESPONSE_TEMPLATE, new Object(), interactionHook);
});
interactionService.replyEmbed(REACTION_REPORT_RESPONSE_TEMPLATE, new Object(), model.getEvent());
return DefaultListenerResult.PROCESSED;
}

View File

@@ -17,6 +17,7 @@ import net.dv8tion.jda.api.interactions.modals.ModalMapping;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import static dev.sheldan.abstracto.moderation.service.ReactionReportServiceBean.REACTION_REPORT_FAILURE_RESPONSE_TEMPLATE;
import static dev.sheldan.abstracto.moderation.service.ReactionReportServiceBean.REACTION_REPORT_RESPONSE_TEMPLATE;
@Component
@@ -46,27 +47,35 @@ public class ReportContextModalListener implements ModalInteractionListener {
.map(ModalMapping::getAsString)
.findFirst()
.orElse(null);
messageCache.getMessageFromCache(payload.getServerId(), payload.getChannelId(), payload.getMessageId()).thenAccept(cachedMessage -> {
ServerUser userReporting = ServerUser
.builder()
.serverId(model.getServerId())
.userId(cachedMessage.getAuthor().getAuthorId())
.isBot(cachedMessage.getAuthor().getIsBot())
.build();
reactionReportService.createReactionReport(cachedMessage, userReporting, context)
.thenAccept(unused -> {
interactionService.replyEmbed(REACTION_REPORT_RESPONSE_TEMPLATE, new Object(), model.getEvent());
log.info("Handled modal for message report with id {} in guild {} in channel {} on message {}",
model.getEvent().getModalId(), payload.getServerId(), payload.getChannelId(), payload.getMessageId());
componentPayloadManagementService.deletePayload(payload.getModalId());
}).exceptionally(throwable -> {
log.error("Failed to create reaction report in server {} on message {} in channel {} with interaction.",
model.getServerId(), cachedMessage.getMessageId(), model.getEvent().getChannel().getIdLong(), throwable);
model.getEvent().deferReply(true).queue(interactionHook -> {
messageCache.getMessageFromCache(payload.getServerId(), payload.getChannelId(), payload.getMessageId()).thenAccept(cachedMessage -> {
ServerUser userReporting = ServerUser
.builder()
.serverId(model.getServerId())
.userId(cachedMessage.getAuthor().getAuthorId())
.isBot(cachedMessage.getAuthor().getIsBot())
.build();
reactionReportService.createReactionReport(cachedMessage, userReporting, context)
.thenAccept(unused -> {
interactionService.sendMessageToInteraction(REACTION_REPORT_RESPONSE_TEMPLATE, new Object(), interactionHook);
log.info("Handled modal for message report with id {} in guild {} in channel {} on message {}",
model.getEvent().getModalId(), payload.getServerId(), payload.getChannelId(), payload.getMessageId());
componentPayloadManagementService.deletePayload(payload.getModalId());
}).exceptionally(throwable -> {
interactionService.sendMessageToInteraction(REACTION_REPORT_FAILURE_RESPONSE_TEMPLATE, new Object(), interactionHook);
log.error("Failed to create reaction report in server {} on message {} in channel {} with interaction.",
model.getServerId(), cachedMessage.getMessageId(), model.getEvent().getChannel().getIdLong(), throwable);
return null;
});
}).exceptionally(throwable -> {
interactionService.sendMessageToInteraction(REACTION_REPORT_FAILURE_RESPONSE_TEMPLATE, new Object(), interactionHook);
log.error("Failed to load reported message for reporting message {} in channel {} with context.",
model.getEvent().getMessage().getIdLong(), model.getEvent().getChannel().getIdLong(), throwable);
return null;
});
}).exceptionally(throwable -> {
log.error("Failed to load reported message.", throwable);
return null;
}, throwable -> {
log.error("Failed to acknowledge modal interaction for report context modal listener in guild {} on message {}.", model.getServerId(),
model.getEvent().getMessage() != null ? model.getEvent().getMessage().getIdLong() : 0, throwable);
});
return ModalInteractionListenerResult.ACKNOWLEDGED;

View File

@@ -71,6 +71,7 @@ public class ReactionReportServiceBean implements ReactionReportService {
private static final String REACTION_REPORT_TEMPLATE_KEY = "reactionReport_notification";
public static final String REACTION_REPORT_MODAL_ORIGIN = "reportMessageModal";
public static final String REACTION_REPORT_RESPONSE_TEMPLATE = "reactionReport_response";
public static final String REACTION_REPORT_FAILURE_RESPONSE_TEMPLATE = "reactionReport_failure_response";
public static final String REACTION_REPORT_COOLDOWN_RESPONSE_TEMPLATE = "reactionReport_cooldown_response";
public static final String REACTION_REPORT_OWN_MESSAGE_RESPONSE_TEMPLATE = "reactionReport_own_message_response";

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>voice-channel-context</artifactId>
<version>1.4.12</version>
<version>1.4.17</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>voice-channel-context</artifactId>
<version>1.4.12</version>
<version>1.4.17</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

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

View File

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

View File

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

View File

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

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.abstracto.core</groupId>
<artifactId>core</artifactId>
<version>1.4.12</version>
<version>1.4.17</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>

View File

@@ -22,6 +22,11 @@ public class ListenerExecutorConfig {
return executorService.setupExecutorFor("joinListener");
}
@Bean(name = "memberPendingUpdateExecutor")
public TaskExecutor memberPendingUpdateExecutor() {
return executorService.setupExecutorFor("memberPendingUpdateListener");
}
@Bean(name = "leaveListenerExecutor")
public TaskExecutor leaveListenerExecutor() {
return executorService.setupExecutorFor("leaveListener");

View File

@@ -106,6 +106,7 @@ public class InteractionServiceBean implements InteractionService {
if(messageToSend.getEphemeral()) {
Interaction interaction = interactionHook.getInteraction();
interactionHook.setEphemeral(messageToSend.getEphemeral());
log.info("Sending ephemeral message to interaction in guild {} in channel {} for user {}.",
interaction.getGuild().getIdLong(), interaction.getChannel().getId(),
interaction.getMember().getIdLong());

View File

@@ -62,8 +62,6 @@ public class ModalInteractionListenerBean extends ListenerAdapter {
@Override
public void onModalInteraction(@Nonnull ModalInteractionEvent event) {
if(listenerList == null) return;
// TODO remove this and make this configurable
event.deferEdit().queue();
CompletableFuture.runAsync(() -> self.executeListenerLogic(event), modalInteractionExecutor).exceptionally(throwable -> {
log.error("Failed to execute listener logic in modal interaction event.", throwable);
return null;

View File

@@ -124,14 +124,18 @@ public class SlashCommandServiceBean implements SlashCommandService {
for (OptionType type : types) {
String parameterName = slashCommandParameterService.getFullQualifiedParameterName(parameter.getSlashCompatibleName(), type) + "_" + i;
String parameterDescription = isTemplated ? templateService.renderSimpleTemplate(internalCommandName + "_parameter_" + parameter.getName()) : parameter.getDescription();
optionalParameters.add(new OptionData(type, parameterName, parameterDescription, false));
OptionData optionData = new OptionData(type, parameterName, parameterDescription, false);
addChoices(optionData, parameter, internalCommandName, isTemplated);
optionalParameters.add(optionData);
}
}
} else {
types.forEach(type -> {
String parameterName = slashCommandParameterService.getFullQualifiedParameterName(parameter.getSlashCompatibleName(), type);
String parameterDescription = isTemplated ? templateService.renderSimpleTemplate(internalCommandName + "_parameter_" + parameter.getName()) : parameter.getDescription();
optionalParameters.add(new OptionData(type, parameterName, parameterDescription, false));
OptionData optionData = new OptionData(type, parameterName, parameterDescription, false);
addChoices(optionData, parameter, internalCommandName, isTemplated);
optionalParameters.add(optionData);
});
}
} else {
@@ -139,10 +143,14 @@ public class SlashCommandServiceBean implements SlashCommandService {
String parameterDescription = isTemplated ? templateService.renderSimpleTemplate(internalCommandName + "_parameter_" + parameter.getName()) : parameter.getDescription();
if(parameter.isListParam()) {
for (int i = 0; i < parameter.getListSize(); i++) {
optionalParameters.add(new OptionData(type, parameter.getSlashCompatibleName() + "_" + i, parameterDescription, false));
OptionData optionData = new OptionData(type, parameter.getSlashCompatibleName() + "_" + i, parameterDescription, false);
addChoices(optionData, parameter, internalCommandName, isTemplated);
optionalParameters.add(optionData);
}
} else {
requiredParameters.add(new OptionData(type, parameter.getSlashCompatibleName(), parameterDescription, !parameter.isOptional(), parameter.getSupportsAutoComplete()));
OptionData optionData = new OptionData(type, parameter.getSlashCompatibleName(), parameterDescription, !parameter.isOptional(), parameter.getSupportsAutoComplete());
addChoices(optionData, parameter, internalCommandName, isTemplated);
requiredParameters.add(optionData);
}
}
});
@@ -150,6 +158,13 @@ public class SlashCommandServiceBean implements SlashCommandService {
return requiredParameters;
}
private void addChoices(OptionData optionData, Parameter parameter, String commandName, boolean isTemplated) {
parameter.getChoices().forEach(choiceKey -> {
String value = isTemplated ? templateService.renderSimpleTemplate(commandName + "_parameter_" + parameter.getName() + "_choice_" + choiceKey) : choiceKey;
optionData.addChoice(value, choiceKey);
});
}
private boolean shouldParameterBeCreated(Parameter parameter, Long serverId) {
if(parameter.getDependentFeatures().isEmpty()) {
return true;

View File

@@ -0,0 +1,53 @@
package dev.sheldan.abstracto.core.listener.async.jda;
import dev.sheldan.abstracto.core.listener.ListenerService;
import dev.sheldan.abstracto.core.models.ServerUser;
import dev.sheldan.abstracto.core.models.listener.MemberUpdatePendingModel;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.events.guild.member.update.GuildMemberUpdatePendingEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.task.TaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Nonnull;
import java.util.List;
@Component
@Slf4j
public class AsyncMemberPendingUpdateListenerBean extends ListenerAdapter {
@Autowired(required = false)
private List<AsyncUpdatePendingListener> listenerList;
@Autowired
@Qualifier("memberPendingUpdateExecutor")
private TaskExecutor memberPendingUpdateListenerExecutor;
@Autowired
private ListenerService listenerService;
@Override
@Transactional
public void onGuildMemberUpdatePending(@Nonnull GuildMemberUpdatePendingEvent event) {
if(listenerList == null) return;
MemberUpdatePendingModel model = getModel(event);
listenerList.forEach(joinListener -> listenerService.executeFeatureAwareListener(joinListener, model, memberPendingUpdateListenerExecutor));
}
private MemberUpdatePendingModel getModel(GuildMemberUpdatePendingEvent event) {
ServerUser serverUser = ServerUser
.builder()
.serverId(event.getGuild().getIdLong())
.userId(event.getUser().getIdLong())
.isBot(event.getUser().isBot())
.build();
return MemberUpdatePendingModel
.builder()
.user(serverUser)
.member(event.getMember())
.build();
}
}

View File

@@ -166,6 +166,7 @@ public class EmoteServiceBean implements EmoteService {
.builder()
.fake(true)
.custom(false)
.animated(false)
.emoteKey(emoteText)
.build();
}

View File

@@ -122,10 +122,6 @@ public class RoleServiceBean implements RoleService {
}
private CompletableFuture<Void> addRoleToUserAsync(Guild guild, Long userId, ARole role) {
if(role.getDeleted()) {
log.warn("Not possible to add role to user. Role {} was marked as deleted.", role.getId());
throw new RoleDeletedException(role);
}
Role roleById = guild.getRoleById(role.getId());
if(roleById != null) {
log.info("Adding role {} to user {} in server {}.", role.getId(), userId, guild.getId());

View File

@@ -160,15 +160,16 @@ public class EmoteManagementServiceBean implements EmoteManagementService {
if(fakeEmote.getCustom()) {
log.debug("Setting existing emote (a: {}, c: {}, id: {}, discord id: {}) to new custom emote configuration: new id {}, animated {}.",
emoteBeingSet.getAnimated(), emoteBeingSet.getCustom(), emoteBeingSet.getId(), emoteBeingSet.getEmoteId(), fakeEmote.getEmoteId(), fakeEmote.getAnimated());
emoteBeingSet.setCustom(fakeEmote.getCustom());
emoteBeingSet.setEmoteId(fakeEmote.getEmoteId());
emoteBeingSet.setEmoteKey(fakeEmote.getEmoteKey());
emoteBeingSet.setAnimated(fakeEmote.getAnimated());
} else {
log.debug("Setting existing emote (a: {}, c: {}, id: {}, discord id: {}) to new default emote {}.",
emoteBeingSet.getAnimated(), emoteBeingSet.getCustom(), emoteBeingSet.getId(), emoteBeingSet.getEmoteId(), fakeEmote.getEmoteKey());
emoteBeingSet.setCustom(false);
emoteBeingSet.setEmoteKey(fakeEmote.getEmoteKey());
emoteBeingSet.setEmoteId(null);
emoteBeingSet.setAnimated(false);
}
emoteBeingSet.setCustom(fakeEmote.getCustom());
emoteBeingSet.setEmoteKey(fakeEmote.getEmoteKey());
return emoteBeingSet;
}
}

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.abstracto.core</groupId>
<artifactId>core</artifactId>
<version>1.4.12</version>
<version>1.4.17</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>

View File

@@ -37,6 +37,8 @@ public class Parameter implements Serializable {
// these are the features which potentially require this parameter
@Builder.Default
private List<String> dependentFeatures = new ArrayList<>();
@Builder.Default
private List<String> choices = new ArrayList<>();
public String getSlashCompatibleName() {
return name.toLowerCase(Locale.ROOT);

View File

@@ -0,0 +1,8 @@
package dev.sheldan.abstracto.core.listener.async.jda;
import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
import dev.sheldan.abstracto.core.listener.FeatureAwareListener;
import dev.sheldan.abstracto.core.models.listener.MemberUpdatePendingModel;
public interface AsyncUpdatePendingListener extends FeatureAwareListener<MemberUpdatePendingModel, DefaultListenerResult> {
}

View File

@@ -0,0 +1,21 @@
package dev.sheldan.abstracto.core.models.listener;
import dev.sheldan.abstracto.core.listener.FeatureAwareListenerModel;
import dev.sheldan.abstracto.core.models.ServerUser;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import net.dv8tion.jda.api.entities.Member;
@Getter
@Setter
@Builder
public class MemberUpdatePendingModel implements FeatureAwareListenerModel {
private ServerUser user;
private Member member;
@Override
public Long getServerId() {
return user.getServerId();
}
}

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>core</artifactId>
<groupId>dev.sheldan.abstracto.core</groupId>
<version>1.4.12</version>
<version>1.4.17</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>core</artifactId>
<groupId>dev.sheldan.abstracto.core</groupId>
<version>1.4.12</version>
<version>1.4.17</version>
</parent>
<modelVersion>4.0.0</modelVersion>

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