[AB-203] restructuring listeners to use more common code and common interfaces for listeners and models

restructuring entity listener to be async and added models
fixing usage of repository save method
adding interface dependencies to bundle dependency management
This commit is contained in:
Sheldan
2021-03-21 10:58:31 +01:00
parent cfe7786d4d
commit b4e36efafb
241 changed files with 3521 additions and 2049 deletions

View File

@@ -5,8 +5,10 @@ import dev.sheldan.abstracto.assignableroles.model.database.AssignableRolePlace;
import dev.sheldan.abstracto.assignableroles.model.database.AssignableRolePlacePost;
import dev.sheldan.abstracto.assignableroles.service.management.AssignableRolePlacePostManagementService;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
import dev.sheldan.abstracto.core.listener.async.jda.AsyncMessageDeletedListener;
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
import dev.sheldan.abstracto.core.models.listener.MessageDeletedModel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@@ -20,24 +22,26 @@ public class AssignablePostDeletedListener implements AsyncMessageDeletedListene
@Autowired
private AssignableRolePlacePostManagementService service;
/**
* This method deletes one individual {@link AssignableRolePlacePost post}, because its message has been deleted
* @param messageBefore The {@link CachedMessage message} which was deleted
*/
@Override
public void execute(CachedMessage messageBefore) {
Optional<AssignableRolePlacePost> messageOptional = service.findByMessageIdOptional(messageBefore.getMessageId());
messageOptional.ifPresent(post -> {
AssignableRolePlace assignablePlace = post.getAssignablePlace();
log.info("Post {} has been deleted in server {} in channel {}, we are removing a post from place {}.", post.getId(), messageBefore.getServerId(), messageBefore.getChannelId(), assignablePlace.getKey());
post.getAssignableRoles().forEach(assignableRole -> assignableRole.setAssignableRolePlacePost(null));
assignablePlace.getMessagePosts().remove(post);
});
}
@Override
public FeatureDefinition getFeature() {
return AssignableRoleFeatureDefinition.ASSIGNABLE_ROLES;
}
/**
* This method deletes one individual {@link AssignableRolePlacePost post}, because its message has been deleted
* @param model The {@link MessageDeletedModel message} containing the {@link CachedMessage cachedMessage} which was deleted
*/
@Override
public DefaultListenerResult execute(MessageDeletedModel model) {
Optional<AssignableRolePlacePost> messageOptional = service.findByMessageIdOptional(model.getCachedMessage().getMessageId());
messageOptional.ifPresent(post -> {
AssignableRolePlace assignablePlace = post.getAssignablePlace();
log.info("Post {} has been deleted in server {} in channel {}, we are removing a post from place {}.",
post.getId(), model.getServerId(), model.getCachedMessage().getChannelId(), assignablePlace.getKey());
post.getAssignableRoles().forEach(assignableRole -> assignableRole.setAssignableRolePlacePost(null));
assignablePlace.getMessagePosts().remove(post);
});
return DefaultListenerResult.PROCESSED;
}
}

View File

@@ -12,17 +12,18 @@ import dev.sheldan.abstracto.assignableroles.service.management.AssignableRolePl
import dev.sheldan.abstracto.assignableroles.service.management.AssignableRolePlacePostManagementService;
import dev.sheldan.abstracto.assignableroles.service.management.AssignedRoleUserManagementService;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
import dev.sheldan.abstracto.core.listener.async.jda.AsyncReactionAddedListener;
import dev.sheldan.abstracto.core.models.ServerUser;
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
import dev.sheldan.abstracto.core.models.cache.CachedReaction;
import dev.sheldan.abstracto.core.models.cache.CachedReactions;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.models.listener.ReactionAddedModel;
import dev.sheldan.abstracto.core.service.EmoteService;
import dev.sheldan.abstracto.core.service.MemberService;
import dev.sheldan.abstracto.core.service.ReactionService;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.MessageReaction;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
@@ -69,69 +70,32 @@ public class AssignablePostReactionAdded implements AsyncReactionAddedListener {
@Autowired
private MemberService memberService;
/**
* Determines if the {@link net.dv8tion.jda.api.entities.Message message} a reaction was added to, belongs to a
* {@link AssignableRolePlacePost post}.
* If the {@link AssignableRolePlacePost post} belong to an inactive {@link AssignableRolePlace place} this method
* will automatically remove the reaction, self reactions are ignored. Otherwise the logic according to the configuration
* of the {@link AssignableRolePlace place} will be executed.
* @param message The {@link CachedMessage message} on which a reaction was added
* @param cachedReaction The {@link CachedReaction reaction} which was added
* @param serverUser The {@link ServerUser serverUser} who added the reaction
*/
@Override
public void executeReactionAdded(CachedMessage message, CachedReactions cachedReaction, ServerUser serverUser) {
Optional<AssignableRolePlacePost> messageOptional = service.findByMessageIdOptional(message.getMessageId());
if(messageOptional.isPresent()) {
AssignableRolePlacePost assignablePlacePost = messageOptional.get();
if(cachedReaction.getSelf()) {
log.info("Ignoring self reaction on assignable role post in server {}.", message.getServerId());
return;
}
CachedReaction specificReaction = cachedReaction.getReactionForSpecificUser(serverUser);
Long assignableRolePlacePostId = assignablePlacePost.getId();
if(assignablePlacePost.getAssignablePlace().getActive()) {
log.info("User {} added reaction to assignable role place {} in server {}. Handling added event.", serverUser.getUserId(), assignablePlacePost.getId(), serverUser.getServerId());
addAppropriateRoles(specificReaction, assignablePlacePost, serverUser, message);
} else {
reactionService.removeReactionFromMessage(specificReaction, message).exceptionally(throwable -> {
log.error("Failed to remove reaction on place post {} because place is inactive.", assignableRolePlacePostId, throwable);
return null;
});
log.trace("Reaction for assignable place {} in sever {} was added, but place is inactive.", assignablePlacePost.getAssignablePlace().getKey(), serverUser.getServerId());
}
}
}
/**
* Iterates over all {@link AssignableRole assignableRoles} of the post and checks which {@link AssignableRole assignableRole}
* is identified by the added {@link CachedReaction reaction}. If there is no valid reaction, the {@link net.dv8tion.jda.api.entities.MessageReaction reaction}
* is identified by the added {@link MessageReaction reaction}. If there is no valid reaction, the {@link net.dv8tion.jda.api.entities.MessageReaction reaction}
* will be removed again. In case the {@link AssignableRolePlace place} is configured to have unique roles, this will remove the existing
* {@link net.dv8tion.jda.api.entities.MessageReaction reaction} and the assigned {@link net.dv8tion.jda.api.entities.Role role}.
* Afterwards the appropriate {@link net.dv8tion.jda.api.entities.Role role} will be added and the update
* will be stored in the database.
* @param cachedReaction The {@link CachedReaction reaction} which was added
* @param assignablePlacePost The {@link AssignableRolePlacePost post} onto which the {@link CachedReaction reaction} was added to
* @param serverUser The {@link ServerUser serverUser} who added the {@link CachedReaction reaction}
* @param message The {@link CachedMessage message} onto which the {@link net.dv8tion.jda.api.entities.MessageReaction reaction}
* was added
* @param assignablePlacePost The {@link AssignableRolePlacePost post} onto which the {@link MessageReaction reaction} was added to
* @param model The {@link ReactionAddedModel model} containing information about who added which reaction where
*/
private void addAppropriateRoles(CachedReaction cachedReaction, AssignableRolePlacePost assignablePlacePost, ServerUser serverUser, CachedMessage message) {
private void addAppropriateRoles(AssignableRolePlacePost assignablePlacePost, ReactionAddedModel model) {
boolean validReaction = false;
AssignableRolePlace assignableRolePlace = assignablePlacePost.getAssignablePlace();
List<CompletableFuture<Void>> futures = new ArrayList<>();
for (AssignableRole assignableRole : assignablePlacePost.getAssignableRoles()) {
log.trace("Checking emote {} if it was reaction for assignable role place.", assignableRole.getEmote().getId());
if (emoteService.compareCachedEmoteWithAEmote(cachedReaction.getEmote(), assignableRole.getEmote())) {
if (emoteService.isReactionEmoteAEmote(model.getReaction().getReactionEmote(), assignableRole.getEmote())) {
if(assignableRolePlace.getUniqueRoles()) {
log.trace("Assignable role place {} has unique roles configured. Removing existing reactions and roles.", assignableRolePlace.getId());
Optional<AssignedRoleUser> byUserInServer = assignedRoleUserManagementService.findByUserInServerOptional(serverUser);
Optional<AssignedRoleUser> byUserInServer = assignedRoleUserManagementService.findByUserInServerOptional(model.getUserReacting());
byUserInServer.ifPresent(user -> futures.add(assignableRolePlaceService.removeExistingReactionsAndRoles(assignableRolePlace, user)));
}
Long assignableRoleId = assignableRole.getId();
log.info("User added {} reaction {} and gets assignable role {} in server {}.", serverUser.getUserId(), assignableRole.getEmote().getId(), assignableRoleId, serverUser.getServerId());
CompletableFuture<Void> roleAdditionFuture = assignableRoleServiceBean.assignAssignableRoleToUser(assignableRoleId, serverUser);
log.info("User added {} reaction {} and gets assignable role {} in server {}.", model.getUserReacting().getUserId(), assignableRole.getEmote().getId(), assignableRoleId, model.getServerId());
CompletableFuture<Void> roleAdditionFuture = assignableRoleServiceBean.assignAssignableRoleToUser(assignableRoleId, model.getUserReacting());
futures.add(CompletableFuture.allOf(roleAdditionFuture));
validReaction = true;
@@ -140,11 +104,11 @@ public class AssignablePostReactionAdded implements AsyncReactionAddedListener {
}
if(!validReaction) {
log.trace("Reaction was not found in the configuration of assignable role place {}, removing reaction.", assignableRolePlace.getId());
futures.add(reactionService.removeReaction(message, cachedReaction.getEmote(), serverUser));
futures.add(reactionService.removeReactionFromMessage(model.getReaction(), model.getMessage(), model.getMemberReacting().getUser()));
}
Long assignableRolePlaceId = assignableRolePlace.getId();
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).thenAccept(aVoid ->
self.updateStoredAssignableRoles(assignableRolePlaceId, serverUser, cachedReaction)
self.updateStoredAssignableRoles(assignableRolePlaceId, model.getUserReacting(), model.getReaction())
).exceptionally(throwable -> {
log.error("Failed to add role or remove emote for assignable role place {}.", assignableRolePlaceId, throwable);
return null;
@@ -155,17 +119,17 @@ public class AssignablePostReactionAdded implements AsyncReactionAddedListener {
* Persists the {@link AssignableRole role} changes for the user who added a reaction in the database
* @param assignableRolePlaceId The ID of the {@link AssignableRolePlace place}
* @param serverUser The {@link ServerUser serverUser} who added the {@link net.dv8tion.jda.api.entities.MessageReaction reaction}
* @param cachedReaction The {@link CachedReaction reaction} wich was added
* @param reaction The {@link CachedReaction reaction} wich was added
*/
@Transactional
public void updateStoredAssignableRoles(Long assignableRolePlaceId, ServerUser serverUser, CachedReaction cachedReaction) {
public void updateStoredAssignableRoles(Long assignableRolePlaceId, ServerUser serverUser, MessageReaction reaction) {
AssignableRolePlace place = assignableRolePlaceManagementService.findByPlaceId(assignableRolePlaceId);
AUserInAServer userInAServer = userInServerManagementService.loadOrCreateUser(serverUser);
if(place.getUniqueRoles()) {
log.trace("Assignable role place {} has unique roles. Deleting all existing references.", assignableRolePlaceId);
assignableRoleServiceBean.clearAllRolesOfUserInPlace(place, userInAServer);
}
AssignableRole role = assignableRoleManagementService.getRoleForReactionEmote(cachedReaction.getEmote(), place);
AssignableRole role = assignableRoleManagementService.getRoleForReactionEmote(reaction.getReactionEmote(), place);
log.info("Adding role to assignable role {} to user {} in server {}.", role.getId(), userInAServer.getUserReference().getId(), userInAServer.getServerReference().getId());
assignableRoleServiceBean.addRoleToUser(role.getId(), userInAServer);
@@ -176,4 +140,36 @@ public class AssignablePostReactionAdded implements AsyncReactionAddedListener {
return AssignableRoleFeatureDefinition.ASSIGNABLE_ROLES;
}
/**
* Determines if the {@link net.dv8tion.jda.api.entities.Message message} a reaction was added to, belongs to a
* {@link AssignableRolePlacePost post}.
* If the {@link AssignableRolePlacePost post} belong to an inactive {@link AssignableRolePlace place} this method
* will automatically remove the reaction, self reactions are ignored. Otherwise the logic according to the configuration
* of the {@link AssignableRolePlace place} will be executed.
* @param model The {@link ReactionAddedModel message} which contains information about the added reaction
*/
@Override
public DefaultListenerResult execute(ReactionAddedModel model) {
MessageReaction reaction = model.getReaction();
Optional<AssignableRolePlacePost> messageOptional = service.findByMessageIdOptional(model.getMessage().getMessageId());
if(messageOptional.isPresent()) {
AssignableRolePlacePost assignablePlacePost = messageOptional.get();
if(reaction.isSelf()) {
log.info("Ignoring self reaction on assignable role post in server {}.", model.getServerId());
return DefaultListenerResult.IGNORED;
}
Long assignableRolePlacePostId = assignablePlacePost.getId();
if(assignablePlacePost.getAssignablePlace().getActive()) {
log.info("User {} added reaction to assignable role place {} in server {}. Handling added event.", model.getUserReacting().getUserId(), assignablePlacePost.getId(), model.getServerId());
addAppropriateRoles(assignablePlacePost, model);
} else {
reactionService.removeReactionFromMessage(model.getReaction(), model.getMessage()).exceptionally(throwable -> {
log.error("Failed to remove reaction on place post {} because place is inactive.", assignableRolePlacePostId, throwable);
return null;
});
log.trace("Reaction for assignable place {} in sever {} was added, but place is inactive.", assignablePlacePost.getAssignablePlace().getKey(), model.getServerId());
}
}
return DefaultListenerResult.PROCESSED;
}
}

View File

@@ -6,10 +6,10 @@ import dev.sheldan.abstracto.assignableroles.model.database.AssignableRolePlaceP
import dev.sheldan.abstracto.assignableroles.service.AssignableRoleService;
import dev.sheldan.abstracto.assignableroles.service.management.AssignableRolePlacePostManagementService;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
import dev.sheldan.abstracto.core.listener.async.jda.AsyncReactionRemovedListener;
import dev.sheldan.abstracto.core.models.ServerUser;
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
import dev.sheldan.abstracto.core.models.cache.CachedReactions;
import dev.sheldan.abstracto.core.models.listener.ReactionRemovedModel;
import dev.sheldan.abstracto.core.service.EmoteService;
import dev.sheldan.abstracto.core.service.RoleService;
import lombok.extern.slf4j.Slf4j;
@@ -45,31 +45,37 @@ public class AssignablePostReactionRemoved implements AsyncReactionRemovedListen
* If the {@link AssignableRolePlacePost post} belong to an inactive {@link AssignableRolePlace place} this method ignores the removal.
* Otherwise the logic according to the configuration
* of the {@link AssignableRolePlace place} will be executed.
* @param message The {@link CachedMessage message} on which a reaction was added
* @param reactions All the reactions which are currently known to be on the {@link CachedMessage message}
* @param userRemoving The {@link ServerUser serverUser} which removed a {@link net.dv8tion.jda.api.entities.MessageReaction reaction}
* @param model The {@link ReactionRemovedModel model} containing the information which reaction was placed where
*/
@Override
public void executeReactionRemoved(CachedMessage message, CachedReactions reactions, ServerUser userRemoving) {
public DefaultListenerResult execute(ReactionRemovedModel model) {
CachedMessage message = model.getMessage();
Optional<AssignableRolePlacePost> messageOptional = service.findByMessageIdOptional(message.getMessageId());
if(messageOptional.isPresent()) {
AssignableRolePlacePost assignablePlacePost = messageOptional.get();
if(assignablePlacePost.getAssignablePlace().getActive()) {
assignablePlacePost.getAssignableRoles().forEach(assignableRole -> {
if(emoteService.compareCachedEmoteWithAEmote(reactions.getEmote(), assignableRole.getEmote())) {
if(emoteService.isReactionEmoteAEmote(model.getReaction().getReactionEmote(), assignableRole.getEmote())) {
Long assignableRoleId = assignableRole.getId();
log.info("Removing assignable role {} for user {} in server {} from assignable role place {}.", assignableRoleId,
userRemoving.getUserId(), userRemoving.getServerId(), assignablePlacePost.getAssignablePlace().getId());
assignableRoleService.fullyRemoveAssignableRoleFromUser(assignableRole, userRemoving).exceptionally(throwable -> {
log.error("Failed to remove assignable role {} from user {} in server {}.", assignableRoleId, userRemoving.getUserId(), userRemoving.getServerId(), throwable);
model.getUserRemoving().getUserId(), model.getServerId(), assignablePlacePost.getAssignablePlace().getId());
assignableRoleService.fullyRemoveAssignableRoleFromUser(assignableRole, model.getUserRemoving()).exceptionally(throwable -> {
log.error("Failed to remove assignable role {} from user {} in server {}.", assignableRoleId, model.getUserRemoving().getUserId(), model.getServerId(), throwable);
return null;
});
}
});
return DefaultListenerResult.PROCESSED;
} else {
log.trace("Reaction for assignable place {} in sever {} was added, but place is inactive.", assignablePlacePost.getAssignablePlace().getKey(), userRemoving.getServerId());
log.trace("Reaction for assignable place {} in sever {} was added, but place is inactive.", assignablePlacePost.getAssignablePlace().getKey(), model.getServerId());
return DefaultListenerResult.PROCESSED;
}
} else {
return DefaultListenerResult.IGNORED;
}
}
}

View File

@@ -13,6 +13,7 @@ import dev.sheldan.abstracto.core.service.EmoteService;
import dev.sheldan.abstracto.core.service.management.EmoteManagementService;
import dev.sheldan.abstracto.core.service.management.RoleManagementService;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.MessageReaction;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@@ -95,4 +96,16 @@ public class AssignableRoleManagementServiceBean implements AssignableRoleManage
}
throw new AbstractoRunTimeException("Role for reaction was not found.");
}
@Override
public AssignableRole getRoleForReactionEmote(MessageReaction.ReactionEmote cachedEmote, AssignableRolePlace assignableRolePlace) {
for (AssignableRolePlacePost post : assignableRolePlace.getMessagePosts()) {
for (AssignableRole assignableRole : post.getAssignableRoles()) {
if (emoteService.isReactionEmoteAEmote(cachedEmote, assignableRole.getEmote())) {
return assignableRole;
}
}
}
throw new AbstractoRunTimeException("Role for reaction was not found.");
}
}

View File

@@ -28,9 +28,8 @@ public class AssignableRolePlaceManagementServiceBean implements AssignableRoleP
.text(text)
.key(name)
.build();
repository.save(place);
log.info("Creating assignable role place in channel {} on server {}.", channel.getId(), channel.getServer().getId());
return place;
return repository.save(place);
}
@Override